(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
var asn1 = exports;

asn1.bignum = require('bn.js');

asn1.define = require('./asn1/api').define;
asn1.base = require('./asn1/base');
asn1.constants = require('./asn1/constants');
asn1.decoders = require('./asn1/decoders');
asn1.encoders = require('./asn1/encoders');

},{"./asn1/api":2,"./asn1/base":4,"./asn1/constants":8,"./asn1/decoders":10,"./asn1/encoders":13,"bn.js":16}],2:[function(require,module,exports){
var asn1 = require('../asn1');
var inherits = require('inherits');

var api = exports;

api.define = function define(name, body) {
  return new Entity(name, body);
};

function Entity(name, body) {
  this.name = name;
  this.body = body;

  this.decoders = {};
  this.encoders = {};
};

Entity.prototype._createNamed = function createNamed(base) {
  var named;
  try {
    named = require('vm').runInThisContext(
      '(function ' + this.name + '(entity) {\n' +
      '  this._initNamed(entity);\n' +
      '})'
    );
  } catch (e) {
    named = function (entity) {
      this._initNamed(entity);
    };
  }
  inherits(named, base);
  named.prototype._initNamed = function initnamed(entity) {
    base.call(this, entity);
  };

  return new named(this);
};

Entity.prototype._getDecoder = function _getDecoder(enc) {
  enc = enc || 'der';
  // Lazily create decoder
  if (!this.decoders.hasOwnProperty(enc))
    this.decoders[enc] = this._createNamed(asn1.decoders[enc]);
  return this.decoders[enc];
};

Entity.prototype.decode = function decode(data, enc, options) {
  return this._getDecoder(enc).decode(data, options);
};

Entity.prototype._getEncoder = function _getEncoder(enc) {
  enc = enc || 'der';
  // Lazily create encoder
  if (!this.encoders.hasOwnProperty(enc))
    this.encoders[enc] = this._createNamed(asn1.encoders[enc]);
  return this.encoders[enc];
};

Entity.prototype.encode = function encode(data, enc, /* internal */ reporter) {
  return this._getEncoder(enc).encode(data, reporter);
};

},{"../asn1":1,"inherits":94,"vm":136}],3:[function(require,module,exports){
var inherits = require('inherits');
var Reporter = require('../base').Reporter;
var Buffer = require('buffer').Buffer;

function DecoderBuffer(base, options) {
  Reporter.call(this, options);
  if (!Buffer.isBuffer(base)) {
    this.error('Input not Buffer');
    return;
  }

  this.base = base;
  this.offset = 0;
  this.length = base.length;
}
inherits(DecoderBuffer, Reporter);
exports.DecoderBuffer = DecoderBuffer;

DecoderBuffer.prototype.save = function save() {
  return { offset: this.offset, reporter: Reporter.prototype.save.call(this) };
};

DecoderBuffer.prototype.restore = function restore(save) {
  // Return skipped data
  var res = new DecoderBuffer(this.base);
  res.offset = save.offset;
  res.length = this.offset;

  this.offset = save.offset;
  Reporter.prototype.restore.call(this, save.reporter);

  return res;
};

DecoderBuffer.prototype.isEmpty = function isEmpty() {
  return this.offset === this.length;
};

DecoderBuffer.prototype.readUInt8 = function readUInt8(fail) {
  if (this.offset + 1 <= this.length)
    return this.base.readUInt8(this.offset++, true);
  else
    return this.error(fail || 'DecoderBuffer overrun');
}

DecoderBuffer.prototype.skip = function skip(bytes, fail) {
  if (!(this.offset + bytes <= this.length))
    return this.error(fail || 'DecoderBuffer overrun');

  var res = new DecoderBuffer(this.base);

  // Share reporter state
  res._reporterState = this._reporterState;

  res.offset = this.offset;
  res.length = this.offset + bytes;
  this.offset += bytes;
  return res;
}

DecoderBuffer.prototype.raw = function raw(save) {
  return this.base.slice(save ? save.offset : this.offset, this.length);
}

function EncoderBuffer(value, reporter) {
  if (Array.isArray(value)) {
    this.length = 0;
    this.value = value.map(function(item) {
      if (!(item instanceof EncoderBuffer))
        item = new EncoderBuffer(item, reporter);
      this.length += item.length;
      return item;
    }, this);
  } else if (typeof value === 'number') {
    if (!(0 <= value && value <= 0xff))
      return reporter.error('non-byte EncoderBuffer value');
    this.value = value;
    this.length = 1;
  } else if (typeof value === 'string') {
    this.value = value;
    this.length = Buffer.byteLength(value);
  } else if (Buffer.isBuffer(value)) {
    this.value = value;
    this.length = value.length;
  } else {
    return reporter.error('Unsupported type: ' + typeof value);
  }
}
exports.EncoderBuffer = EncoderBuffer;

EncoderBuffer.prototype.join = function join(out, offset) {
  if (!out)
    out = new Buffer(this.length);
  if (!offset)
    offset = 0;

  if (this.length === 0)
    return out;

  if (Array.isArray(this.value)) {
    this.value.forEach(function(item) {
      item.join(out, offset);
      offset += item.length;
    });
  } else {
    if (typeof this.value === 'number')
      out[offset] = this.value;
    else if (typeof this.value === 'string')
      out.write(this.value, offset);
    else if (Buffer.isBuffer(this.value))
      this.value.copy(out, offset);
    offset += this.length;
  }

  return out;
};

},{"../base":4,"buffer":45,"inherits":94}],4:[function(require,module,exports){
var base = exports;

base.Reporter = require('./reporter').Reporter;
base.DecoderBuffer = require('./buffer').DecoderBuffer;
base.EncoderBuffer = require('./buffer').EncoderBuffer;
base.Node = require('./node');

},{"./buffer":3,"./node":5,"./reporter":6}],5:[function(require,module,exports){
var Reporter = require('../base').Reporter;
var EncoderBuffer = require('../base').EncoderBuffer;
var DecoderBuffer = require('../base').DecoderBuffer;
var assert = require('minimalistic-assert');

// Supported tags
var tags = [
  'seq', 'seqof', 'set', 'setof', 'objid', 'bool',
  'gentime', 'utctime', 'null_', 'enum', 'int', 'objDesc',
  'bitstr', 'bmpstr', 'charstr', 'genstr', 'graphstr', 'ia5str', 'iso646str',
  'numstr', 'octstr', 'printstr', 't61str', 'unistr', 'utf8str', 'videostr'
];

// Public methods list
var methods = [
  'key', 'obj', 'use', 'optional', 'explicit', 'implicit', 'def', 'choice',
  'any', 'contains'
].concat(tags);

// Overrided methods list
var overrided = [
  '_peekTag', '_decodeTag', '_use',
  '_decodeStr', '_decodeObjid', '_decodeTime',
  '_decodeNull', '_decodeInt', '_decodeBool', '_decodeList',

  '_encodeComposite', '_encodeStr', '_encodeObjid', '_encodeTime',
  '_encodeNull', '_encodeInt', '_encodeBool'
];

function Node(enc, parent) {
  var state = {};
  this._baseState = state;

  state.enc = enc;

  state.parent = parent || null;
  state.children = null;

  // State
  state.tag = null;
  state.args = null;
  state.reverseArgs = null;
  state.choice = null;
  state.optional = false;
  state.any = false;
  state.obj = false;
  state.use = null;
  state.useDecoder = null;
  state.key = null;
  state['default'] = null;
  state.explicit = null;
  state.implicit = null;
  state.contains = null;

  // Should create new instance on each method
  if (!state.parent) {
    state.children = [];
    this._wrap();
  }
}
module.exports = Node;

var stateProps = [
  'enc', 'parent', 'children', 'tag', 'args', 'reverseArgs', 'choice',
  'optional', 'any', 'obj', 'use', 'alteredUse', 'key', 'default', 'explicit',
  'implicit', 'contains'
];

Node.prototype.clone = function clone() {
  var state = this._baseState;
  var cstate = {};
  stateProps.forEach(function(prop) {
    cstate[prop] = state[prop];
  });
  var res = new this.constructor(cstate.parent);
  res._baseState = cstate;
  return res;
};

Node.prototype._wrap = function wrap() {
  var state = this._baseState;
  methods.forEach(function(method) {
    this[method] = function _wrappedMethod() {
      var clone = new this.constructor(this);
      state.children.push(clone);
      return clone[method].apply(clone, arguments);
    };
  }, this);
};

Node.prototype._init = function init(body) {
  var state = this._baseState;

  assert(state.parent === null);
  body.call(this);

  // Filter children
  state.children = state.children.filter(function(child) {
    return child._baseState.parent === this;
  }, this);
  assert.equal(state.children.length, 1, 'Root node can have only one child');
};

Node.prototype._useArgs = function useArgs(args) {
  var state = this._baseState;

  // Filter children and args
  var children = args.filter(function(arg) {
    return arg instanceof this.constructor;
  }, this);
  args = args.filter(function(arg) {
    return !(arg instanceof this.constructor);
  }, this);

  if (children.length !== 0) {
    assert(state.children === null);
    state.children = children;

    // Replace parent to maintain backward link
    children.forEach(function(child) {
      child._baseState.parent = this;
    }, this);
  }
  if (args.length !== 0) {
    assert(state.args === null);
    state.args = args;
    state.reverseArgs = args.map(function(arg) {
      if (typeof arg !== 'object' || arg.constructor !== Object)
        return arg;

      var res = {};
      Object.keys(arg).forEach(function(key) {
        if (key == (key | 0))
          key |= 0;
        var value = arg[key];
        res[value] = key;
      });
      return res;
    });
  }
};

//
// Overrided methods
//

overrided.forEach(function(method) {
  Node.prototype[method] = function _overrided() {
    var state = this._baseState;
    throw new Error(method + ' not implemented for encoding: ' + state.enc);
  };
});

//
// Public methods
//

tags.forEach(function(tag) {
  Node.prototype[tag] = function _tagMethod() {
    var state = this._baseState;
    var args = Array.prototype.slice.call(arguments);

    assert(state.tag === null);
    state.tag = tag;

    this._useArgs(args);

    return this;
  };
});

Node.prototype.use = function use(item) {
  assert(item);
  var state = this._baseState;

  assert(state.use === null);
  state.use = item;

  return this;
};

Node.prototype.optional = function optional() {
  var state = this._baseState;

  state.optional = true;

  return this;
};

Node.prototype.def = function def(val) {
  var state = this._baseState;

  assert(state['default'] === null);
  state['default'] = val;
  state.optional = true;

  return this;
};

Node.prototype.explicit = function explicit(num) {
  var state = this._baseState;

  assert(state.explicit === null && state.implicit === null);
  state.explicit = num;

  return this;
};

Node.prototype.implicit = function implicit(num) {
  var state = this._baseState;

  assert(state.explicit === null && state.implicit === null);
  state.implicit = num;

  return this;
};

Node.prototype.obj = function obj() {
  var state = this._baseState;
  var args = Array.prototype.slice.call(arguments);

  state.obj = true;

  if (args.length !== 0)
    this._useArgs(args);

  return this;
};

Node.prototype.key = function key(newKey) {
  var state = this._baseState;

  assert(state.key === null);
  state.key = newKey;

  return this;
};

Node.prototype.any = function any() {
  var state = this._baseState;

  state.any = true;

  return this;
};

Node.prototype.choice = function choice(obj) {
  var state = this._baseState;

  assert(state.choice === null);
  state.choice = obj;
  this._useArgs(Object.keys(obj).map(function(key) {
    return obj[key];
  }));

  return this;
};

Node.prototype.contains = function contains(item) {
  var state = this._baseState;

  assert(state.use === null);
  state.contains = item;

  return this;
};

//
// Decoding
//

Node.prototype._decode = function decode(input, options) {
  var state = this._baseState;

  // Decode root node
  if (state.parent === null)
    return input.wrapResult(state.children[0]._decode(input, options));

  var result = state['default'];
  var present = true;

  var prevKey = null;
  if (state.key !== null)
    prevKey = input.enterKey(state.key);

  // Check if tag is there
  if (state.optional) {
    var tag = null;
    if (state.explicit !== null)
      tag = state.explicit;
    else if (state.implicit !== null)
      tag = state.implicit;
    else if (state.tag !== null)
      tag = state.tag;

    if (tag === null && !state.any) {
      // Trial and Error
      var save = input.save();
      try {
        if (state.choice === null)
          this._decodeGeneric(state.tag, input, options);
        else
          this._decodeChoice(input, options);
        present = true;
      } catch (e) {
        present = false;
      }
      input.restore(save);
    } else {
      present = this._peekTag(input, tag, state.any);

      if (input.isError(present))
        return present;
    }
  }

  // Push object on stack
  var prevObj;
  if (state.obj && present)
    prevObj = input.enterObject();

  if (present) {
    // Unwrap explicit values
    if (state.explicit !== null) {
      var explicit = this._decodeTag(input, state.explicit);
      if (input.isError(explicit))
        return explicit;
      input = explicit;
    }

    var start = input.offset;

    // Unwrap implicit and normal values
    if (state.use === null && state.choice === null) {
      if (state.any)
        var save = input.save();
      var body = this._decodeTag(
        input,
        state.implicit !== null ? state.implicit : state.tag,
        state.any
      );
      if (input.isError(body))
        return body;

      if (state.any)
        result = input.raw(save);
      else
        input = body;
    }

    if (options && options.track && state.tag !== null)
      options.track(input.path(), start, input.length, 'tagged');

    if (options && options.track && state.tag !== null)
      options.track(input.path(), input.offset, input.length, 'content');

    // Select proper method for tag
    if (state.any)
      result = result;
    else if (state.choice === null)
      result = this._decodeGeneric(state.tag, input, options);
    else
      result = this._decodeChoice(input, options);

    if (input.isError(result))
      return result;

    // Decode children
    if (!state.any && state.choice === null && state.children !== null) {
      state.children.forEach(function decodeChildren(child) {
        // NOTE: We are ignoring errors here, to let parser continue with other
        // parts of encoded data
        child._decode(input, options);
      });
    }

    // Decode contained/encoded by schema, only in bit or octet strings
    if (state.contains && (state.tag === 'octstr' || state.tag === 'bitstr')) {
      var data = new DecoderBuffer(result);
      result = this._getUse(state.contains, input._reporterState.obj)
          ._decode(data, options);
    }
  }

  // Pop object
  if (state.obj && present)
    result = input.leaveObject(prevObj);

  // Set key
  if (state.key !== null && (result !== null || present === true))
    input.leaveKey(prevKey, state.key, result);
  else if (prevKey !== null)
    input.exitKey(prevKey);

  return result;
};

Node.prototype._decodeGeneric = function decodeGeneric(tag, input, options) {
  var state = this._baseState;

  if (tag === 'seq' || tag === 'set')
    return null;
  if (tag === 'seqof' || tag === 'setof')
    return this._decodeList(input, tag, state.args[0], options);
  else if (/str$/.test(tag))
    return this._decodeStr(input, tag, options);
  else if (tag === 'objid' && state.args)
    return this._decodeObjid(input, state.args[0], state.args[1], options);
  else if (tag === 'objid')
    return this._decodeObjid(input, null, null, options);
  else if (tag === 'gentime' || tag === 'utctime')
    return this._decodeTime(input, tag, options);
  else if (tag === 'null_')
    return this._decodeNull(input, options);
  else if (tag === 'bool')
    return this._decodeBool(input, options);
  else if (tag === 'objDesc')
    return this._decodeStr(input, tag, options);
  else if (tag === 'int' || tag === 'enum')
    return this._decodeInt(input, state.args && state.args[0], options);

  if (state.use !== null) {
    return this._getUse(state.use, input._reporterState.obj)
        ._decode(input, options);
  } else {
    return input.error('unknown tag: ' + tag);
  }
};

Node.prototype._getUse = function _getUse(entity, obj) {

  var state = this._baseState;
  // Create altered use decoder if implicit is set
  state.useDecoder = this._use(entity, obj);
  assert(state.useDecoder._baseState.parent === null);
  state.useDecoder = state.useDecoder._baseState.children[0];
  if (state.implicit !== state.useDecoder._baseState.implicit) {
    state.useDecoder = state.useDecoder.clone();
    state.useDecoder._baseState.implicit = state.implicit;
  }
  return state.useDecoder;
};

Node.prototype._decodeChoice = function decodeChoice(input, options) {
  var state = this._baseState;
  var result = null;
  var match = false;

  Object.keys(state.choice).some(function(key) {
    var save = input.save();
    var node = state.choice[key];
    try {
      var value = node._decode(input, options);
      if (input.isError(value))
        return false;

      result = { type: key, value: value };
      match = true;
    } catch (e) {
      input.restore(save);
      return false;
    }
    return true;
  }, this);

  if (!match)
    return input.error('Choice not matched');

  return result;
};

//
// Encoding
//

Node.prototype._createEncoderBuffer = function createEncoderBuffer(data) {
  return new EncoderBuffer(data, this.reporter);
};

Node.prototype._encode = function encode(data, reporter, parent) {
  var state = this._baseState;
  if (state['default'] !== null && state['default'] === data)
    return;

  var result = this._encodeValue(data, reporter, parent);
  if (result === undefined)
    return;

  if (this._skipDefault(result, reporter, parent))
    return;

  return result;
};

Node.prototype._encodeValue = function encode(data, reporter, parent) {
  var state = this._baseState;

  // Decode root node
  if (state.parent === null)
    return state.children[0]._encode(data, reporter || new Reporter());

  var result = null;

  // Set reporter to share it with a child class
  this.reporter = reporter;

  // Check if data is there
  if (state.optional && data === undefined) {
    if (state['default'] !== null)
      data = state['default']
    else
      return;
  }

  // Encode children first
  var content = null;
  var primitive = false;
  if (state.any) {
    // Anything that was given is translated to buffer
    result = this._createEncoderBuffer(data);
  } else if (state.choice) {
    result = this._encodeChoice(data, reporter);
  } else if (state.contains) {
    content = this._getUse(state.contains, parent)._encode(data, reporter);
    primitive = true;
  } else if (state.children) {
    content = state.children.map(function(child) {
      if (child._baseState.tag === 'null_')
        return child._encode(null, reporter, data);

      if (child._baseState.key === null)
        return reporter.error('Child should have a key');
      var prevKey = reporter.enterKey(child._baseState.key);

      if (typeof data !== 'object')
        return reporter.error('Child expected, but input is not object');

      var res = child._encode(data[child._baseState.key], reporter, data);
      reporter.leaveKey(prevKey);

      return res;
    }, this).filter(function(child) {
      return child;
    });
    content = this._createEncoderBuffer(content);
  } else {
    if (state.tag === 'seqof' || state.tag === 'setof') {
      // TODO(indutny): this should be thrown on DSL level
      if (!(state.args && state.args.length === 1))
        return reporter.error('Too many args for : ' + state.tag);

      if (!Array.isArray(data))
        return reporter.error('seqof/setof, but data is not Array');

      var child = this.clone();
      child._baseState.implicit = null;
      content = this._createEncoderBuffer(data.map(function(item) {
        var state = this._baseState;

        return this._getUse(state.args[0], data)._encode(item, reporter);
      }, child));
    } else if (state.use !== null) {
      result = this._getUse(state.use, parent)._encode(data, reporter);
    } else {
      content = this._encodePrimitive(state.tag, data);
      primitive = true;
    }
  }

  // Encode data itself
  var result;
  if (!state.any && state.choice === null) {
    var tag = state.implicit !== null ? state.implicit : state.tag;
    var cls = state.implicit === null ? 'universal' : 'context';

    if (tag === null) {
      if (state.use === null)
        reporter.error('Tag could be ommited only for .use()');
    } else {
      if (state.use === null)
        result = this._encodeComposite(tag, primitive, cls, content);
    }
  }

  // Wrap in explicit
  if (state.explicit !== null)
    result = this._encodeComposite(state.explicit, false, 'context', result);

  return result;
};

Node.prototype._encodeChoice = function encodeChoice(data, reporter) {
  var state = this._baseState;

  var node = state.choice[data.type];
  if (!node) {
    assert(
        false,
        data.type + ' not found in ' +
            JSON.stringify(Object.keys(state.choice)));
  }
  return node._encode(data.value, reporter);
};

Node.prototype._encodePrimitive = function encodePrimitive(tag, data) {
  var state = this._baseState;

  if (/str$/.test(tag))
    return this._encodeStr(data, tag);
  else if (tag === 'objid' && state.args)
    return this._encodeObjid(data, state.reverseArgs[0], state.args[1]);
  else if (tag === 'objid')
    return this._encodeObjid(data, null, null);
  else if (tag === 'gentime' || tag === 'utctime')
    return this._encodeTime(data, tag);
  else if (tag === 'null_')
    return this._encodeNull();
  else if (tag === 'int' || tag === 'enum')
    return this._encodeInt(data, state.args && state.reverseArgs[0]);
  else if (tag === 'bool')
    return this._encodeBool(data);
  else if (tag === 'objDesc')
    return this._encodeStr(data, tag);
  else
    throw new Error('Unsupported tag: ' + tag);
};

Node.prototype._isNumstr = function isNumstr(str) {
  return /^[0-9 ]*$/.test(str);
};

Node.prototype._isPrintstr = function isPrintstr(str) {
  return /^[A-Za-z0-9 '\(\)\+,\-\.\/:=\?]*$/.test(str);
};

},{"../base":4,"minimalistic-assert":97}],6:[function(require,module,exports){
var inherits = require('inherits');

function Reporter(options) {
  this._reporterState = {
    obj: null,
    path: [],
    options: options || {},
    errors: []
  };
}
exports.Reporter = Reporter;

Reporter.prototype.isError = function isError(obj) {
  return obj instanceof ReporterError;
};

Reporter.prototype.save = function save() {
  var state = this._reporterState;

  return { obj: state.obj, pathLen: state.path.length };
};

Reporter.prototype.restore = function restore(data) {
  var state = this._reporterState;

  state.obj = data.obj;
  state.path = state.path.slice(0, data.pathLen);
};

Reporter.prototype.enterKey = function enterKey(key) {
  return this._reporterState.path.push(key);
};

Reporter.prototype.exitKey = function exitKey(index) {
  var state = this._reporterState;

  state.path = state.path.slice(0, index - 1);
};

Reporter.prototype.leaveKey = function leaveKey(index, key, value) {
  var state = this._reporterState;

  this.exitKey(index);
  if (state.obj !== null)
    state.obj[key] = value;
};

Reporter.prototype.path = function path() {
  return this._reporterState.path.join('/');
};

Reporter.prototype.enterObject = function enterObject() {
  var state = this._reporterState;

  var prev = state.obj;
  state.obj = {};
  return prev;
};

Reporter.prototype.leaveObject = function leaveObject(prev) {
  var state = this._reporterState;

  var now = state.obj;
  state.obj = prev;
  return now;
};

Reporter.prototype.error = function error(msg) {
  var err;
  var state = this._reporterState;

  var inherited = msg instanceof ReporterError;
  if (inherited) {
    err = msg;
  } else {
    err = new ReporterError(state.path.map(function(elem) {
      return '[' + JSON.stringify(elem) + ']';
    }).join(''), msg.message || msg, msg.stack);
  }

  if (!state.options.partial)
    throw err;

  if (!inherited)
    state.errors.push(err);

  return err;
};

Reporter.prototype.wrapResult = function wrapResult(result) {
  var state = this._reporterState;
  if (!state.options.partial)
    return result;

  return {
    result: this.isError(result) ? null : result,
    errors: state.errors
  };
};

function ReporterError(path, msg) {
  this.path = path;
  this.rethrow(msg);
};
inherits(ReporterError, Error);

ReporterError.prototype.rethrow = function rethrow(msg) {
  this.message = msg + ' at: ' + (this.path || '(shallow)');
  if (Error.captureStackTrace)
    Error.captureStackTrace(this, ReporterError);

  if (!this.stack) {
    try {
      // IE only adds stack when thrown
      throw new Error(this.message);
    } catch (e) {
      this.stack = e.stack;
    }
  }
  return this;
};

},{"inherits":94}],7:[function(require,module,exports){
var constants = require('../constants');

exports.tagClass = {
  0: 'universal',
  1: 'application',
  2: 'context',
  3: 'private'
};
exports.tagClassByName = constants._reverse(exports.tagClass);

exports.tag = {
  0x00: 'end',
  0x01: 'bool',
  0x02: 'int',
  0x03: 'bitstr',
  0x04: 'octstr',
  0x05: 'null_',
  0x06: 'objid',
  0x07: 'objDesc',
  0x08: 'external',
  0x09: 'real',
  0x0a: 'enum',
  0x0b: 'embed',
  0x0c: 'utf8str',
  0x0d: 'relativeOid',
  0x10: 'seq',
  0x11: 'set',
  0x12: 'numstr',
  0x13: 'printstr',
  0x14: 't61str',
  0x15: 'videostr',
  0x16: 'ia5str',
  0x17: 'utctime',
  0x18: 'gentime',
  0x19: 'graphstr',
  0x1a: 'iso646str',
  0x1b: 'genstr',
  0x1c: 'unistr',
  0x1d: 'charstr',
  0x1e: 'bmpstr'
};
exports.tagByName = constants._reverse(exports.tag);

},{"../constants":8}],8:[function(require,module,exports){
var constants = exports;

// Helper
constants._reverse = function reverse(map) {
  var res = {};

  Object.keys(map).forEach(function(key) {
    // Convert key to integer if it is stringified
    if ((key | 0) == key)
      key = key | 0;

    var value = map[key];
    res[value] = key;
  });

  return res;
};

constants.der = require('./der');

},{"./der":7}],9:[function(require,module,exports){
var inherits = require('inherits');

var asn1 = require('../../asn1');
var base = asn1.base;
var bignum = asn1.bignum;

// Import DER constants
var der = asn1.constants.der;

function DERDecoder(entity) {
  this.enc = 'der';
  this.name = entity.name;
  this.entity = entity;

  // Construct base tree
  this.tree = new DERNode();
  this.tree._init(entity.body);
};
module.exports = DERDecoder;

DERDecoder.prototype.decode = function decode(data, options) {
  if (!(data instanceof base.DecoderBuffer))
    data = new base.DecoderBuffer(data, options);

  return this.tree._decode(data, options);
};

// Tree methods

function DERNode(parent) {
  base.Node.call(this, 'der', parent);
}
inherits(DERNode, base.Node);

DERNode.prototype._peekTag = function peekTag(buffer, tag, any) {
  if (buffer.isEmpty())
    return false;

  var state = buffer.save();
  var decodedTag = derDecodeTag(buffer, 'Failed to peek tag: "' + tag + '"');
  if (buffer.isError(decodedTag))
    return decodedTag;

  buffer.restore(state);

  return decodedTag.tag === tag || decodedTag.tagStr === tag ||
    (decodedTag.tagStr + 'of') === tag || any;
};

DERNode.prototype._decodeTag = function decodeTag(buffer, tag, any) {
  var decodedTag = derDecodeTag(buffer,
                                'Failed to decode tag of "' + tag + '"');
  if (buffer.isError(decodedTag))
    return decodedTag;

  var len = derDecodeLen(buffer,
                         decodedTag.primitive,
                         'Failed to get length of "' + tag + '"');

  // Failure
  if (buffer.isError(len))
    return len;

  if (!any &&
      decodedTag.tag !== tag &&
      decodedTag.tagStr !== tag &&
      decodedTag.tagStr + 'of' !== tag) {
    return buffer.error('Failed to match tag: "' + tag + '"');
  }

  if (decodedTag.primitive || len !== null)
    return buffer.skip(len, 'Failed to match body of: "' + tag + '"');

  // Indefinite length... find END tag
  var state = buffer.save();
  var res = this._skipUntilEnd(
      buffer,
      'Failed to skip indefinite length body: "' + this.tag + '"');
  if (buffer.isError(res))
    return res;

  len = buffer.offset - state.offset;
  buffer.restore(state);
  return buffer.skip(len, 'Failed to match body of: "' + tag + '"');
};

DERNode.prototype._skipUntilEnd = function skipUntilEnd(buffer, fail) {
  while (true) {
    var tag = derDecodeTag(buffer, fail);
    if (buffer.isError(tag))
      return tag;
    var len = derDecodeLen(buffer, tag.primitive, fail);
    if (buffer.isError(len))
      return len;

    var res;
    if (tag.primitive || len !== null)
      res = buffer.skip(len)
    else
      res = this._skipUntilEnd(buffer, fail);

    // Failure
    if (buffer.isError(res))
      return res;

    if (tag.tagStr === 'end')
      break;
  }
};

DERNode.prototype._decodeList = function decodeList(buffer, tag, decoder,
                                                    options) {
  var result = [];
  while (!buffer.isEmpty()) {
    var possibleEnd = this._peekTag(buffer, 'end');
    if (buffer.isError(possibleEnd))
      return possibleEnd;

    var res = decoder.decode(buffer, 'der', options);
    if (buffer.isError(res) && possibleEnd)
      break;
    result.push(res);
  }
  return result;
};

DERNode.prototype._decodeStr = function decodeStr(buffer, tag) {
  if (tag === 'bitstr') {
    var unused = buffer.readUInt8();
    if (buffer.isError(unused))
      return unused;
    return { unused: unused, data: buffer.raw() };
  } else if (tag === 'bmpstr') {
    var raw = buffer.raw();
    if (raw.length % 2 === 1)
      return buffer.error('Decoding of string type: bmpstr length mismatch');

    var str = '';
    for (var i = 0; i < raw.length / 2; i++) {
      str += String.fromCharCode(raw.readUInt16BE(i * 2));
    }
    return str;
  } else if (tag === 'numstr') {
    var numstr = buffer.raw().toString('ascii');
    if (!this._isNumstr(numstr)) {
      return buffer.error('Decoding of string type: ' +
                          'numstr unsupported characters');
    }
    return numstr;
  } else if (tag === 'octstr') {
    return buffer.raw();
  } else if (tag === 'objDesc') {
    return buffer.raw();
  } else if (tag === 'printstr') {
    var printstr = buffer.raw().toString('ascii');
    if (!this._isPrintstr(printstr)) {
      return buffer.error('Decoding of string type: ' +
                          'printstr unsupported characters');
    }
    return printstr;
  } else if (/str$/.test(tag)) {
    return buffer.raw().toString();
  } else {
    return buffer.error('Decoding of string type: ' + tag + ' unsupported');
  }
};

DERNode.prototype._decodeObjid = function decodeObjid(buffer, values, relative) {
  var result;
  var identifiers = [];
  var ident = 0;
  while (!buffer.isEmpty()) {
    var subident = buffer.readUInt8();
    ident <<= 7;
    ident |= subident & 0x7f;
    if ((subident & 0x80) === 0) {
      identifiers.push(ident);
      ident = 0;
    }
  }
  if (subident & 0x80)
    identifiers.push(ident);

  var first = (identifiers[0] / 40) | 0;
  var second = identifiers[0] % 40;

  if (relative)
    result = identifiers;
  else
    result = [first, second].concat(identifiers.slice(1));

  if (values) {
    var tmp = values[result.join(' ')];
    if (tmp === undefined)
      tmp = values[result.join('.')];
    if (tmp !== undefined)
      result = tmp;
  }

  return result;
};

DERNode.prototype._decodeTime = function decodeTime(buffer, tag) {
  var str = buffer.raw().toString();
  if (tag === 'gentime') {
    var year = str.slice(0, 4) | 0;
    var mon = str.slice(4, 6) | 0;
    var day = str.slice(6, 8) | 0;
    var hour = str.slice(8, 10) | 0;
    var min = str.slice(10, 12) | 0;
    var sec = str.slice(12, 14) | 0;
  } else if (tag === 'utctime') {
    var year = str.slice(0, 2) | 0;
    var mon = str.slice(2, 4) | 0;
    var day = str.slice(4, 6) | 0;
    var hour = str.slice(6, 8) | 0;
    var min = str.slice(8, 10) | 0;
    var sec = str.slice(10, 12) | 0;
    if (year < 70)
      year = 2000 + year;
    else
      year = 1900 + year;
  } else {
    return buffer.error('Decoding ' + tag + ' time is not supported yet');
  }

  return Date.UTC(year, mon - 1, day, hour, min, sec, 0);
};

DERNode.prototype._decodeNull = function decodeNull(buffer) {
  return null;
};

DERNode.prototype._decodeBool = function decodeBool(buffer) {
  var res = buffer.readUInt8();
  if (buffer.isError(res))
    return res;
  else
    return res !== 0;
};

DERNode.prototype._decodeInt = function decodeInt(buffer, values) {
  // Bigint, return as it is (assume big endian)
  var raw = buffer.raw();
  var res = new bignum(raw);

  if (values)
    res = values[res.toString(10)] || res;

  return res;
};

DERNode.prototype._use = function use(entity, obj) {
  if (typeof entity === 'function')
    entity = entity(obj);
  return entity._getDecoder('der').tree;
};

// Utility methods

function derDecodeTag(buf, fail) {
  var tag = buf.readUInt8(fail);
  if (buf.isError(tag))
    return tag;

  var cls = der.tagClass[tag >> 6];
  var primitive = (tag & 0x20) === 0;

  // Multi-octet tag - load
  if ((tag & 0x1f) === 0x1f) {
    var oct = tag;
    tag = 0;
    while ((oct & 0x80) === 0x80) {
      oct = buf.readUInt8(fail);
      if (buf.isError(oct))
        return oct;

      tag <<= 7;
      tag |= oct & 0x7f;
    }
  } else {
    tag &= 0x1f;
  }
  var tagStr = der.tag[tag];

  return {
    cls: cls,
    primitive: primitive,
    tag: tag,
    tagStr: tagStr
  };
}

function derDecodeLen(buf, primitive, fail) {
  var len = buf.readUInt8(fail);
  if (buf.isError(len))
    return len;

  // Indefinite form
  if (!primitive && len === 0x80)
    return null;

  // Definite form
  if ((len & 0x80) === 0) {
    // Short form
    return len;
  }

  // Long form
  var num = len & 0x7f;
  if (num >= 4)
    return buf.error('length octect is too long');

  len = 0;
  for (var i = 0; i < num; i++) {
    len <<= 8;
    var j = buf.readUInt8(fail);
    if (buf.isError(j))
      return j;
    len |= j;
  }

  return len;
}

},{"../../asn1":1,"inherits":94}],10:[function(require,module,exports){
var decoders = exports;

decoders.der = require('./der');
decoders.pem = require('./pem');

},{"./der":9,"./pem":11}],11:[function(require,module,exports){
var inherits = require('inherits');
var Buffer = require('buffer').Buffer;

var DERDecoder = require('./der');

function PEMDecoder(entity) {
  DERDecoder.call(this, entity);
  this.enc = 'pem';
};
inherits(PEMDecoder, DERDecoder);
module.exports = PEMDecoder;

PEMDecoder.prototype.decode = function decode(data, options) {
  var lines = data.toString().split(/[\r\n]+/g);

  var label = options.label.toUpperCase();

  var re = /^-----(BEGIN|END) ([^-]+)-----$/;
  var start = -1;
  var end = -1;
  for (var i = 0; i < lines.length; i++) {
    var match = lines[i].match(re);
    if (match === null)
      continue;

    if (match[2] !== label)
      continue;

    if (start === -1) {
      if (match[1] !== 'BEGIN')
        break;
      start = i;
    } else {
      if (match[1] !== 'END')
        break;
      end = i;
      break;
    }
  }
  if (start === -1 || end === -1)
    throw new Error('PEM section not found for: ' + label);

  var base64 = lines.slice(start + 1, end).join('');
  // Remove excessive symbols
  base64.replace(/[^a-z0-9\+\/=]+/gi, '');

  var input = new Buffer(base64, 'base64');
  return DERDecoder.prototype.decode.call(this, input, options);
};

},{"./der":9,"buffer":45,"inherits":94}],12:[function(require,module,exports){
var inherits = require('inherits');
var Buffer = require('buffer').Buffer;

var asn1 = require('../../asn1');
var base = asn1.base;

// Import DER constants
var der = asn1.constants.der;

function DEREncoder(entity) {
  this.enc = 'der';
  this.name = entity.name;
  this.entity = entity;

  // Construct base tree
  this.tree = new DERNode();
  this.tree._init(entity.body);
};
module.exports = DEREncoder;

DEREncoder.prototype.encode = function encode(data, reporter) {
  return this.tree._encode(data, reporter).join();
};

// Tree methods

function DERNode(parent) {
  base.Node.call(this, 'der', parent);
}
inherits(DERNode, base.Node);

DERNode.prototype._encodeComposite = function encodeComposite(tag,
                                                              primitive,
                                                              cls,
                                                              content) {
  var encodedTag = encodeTag(tag, primitive, cls, this.reporter);

  // Short form
  if (content.length < 0x80) {
    var header = new Buffer(2);
    header[0] = encodedTag;
    header[1] = content.length;
    return this._createEncoderBuffer([ header, content ]);
  }

  // Long form
  // Count octets required to store length
  var lenOctets = 1;
  for (var i = content.length; i >= 0x100; i >>= 8)
    lenOctets++;

  var header = new Buffer(1 + 1 + lenOctets);
  header[0] = encodedTag;
  header[1] = 0x80 | lenOctets;

  for (var i = 1 + lenOctets, j = content.length; j > 0; i--, j >>= 8)
    header[i] = j & 0xff;

  return this._createEncoderBuffer([ header, content ]);
};

DERNode.prototype._encodeStr = function encodeStr(str, tag) {
  if (tag === 'bitstr') {
    return this._createEncoderBuffer([ str.unused | 0, str.data ]);
  } else if (tag === 'bmpstr') {
    var buf = new Buffer(str.length * 2);
    for (var i = 0; i < str.length; i++) {
      buf.writeUInt16BE(str.charCodeAt(i), i * 2);
    }
    return this._createEncoderBuffer(buf);
  } else if (tag === 'numstr') {
    if (!this._isNumstr(str)) {
      return this.reporter.error('Encoding of string type: numstr supports ' +
                                 'only digits and space');
    }
    return this._createEncoderBuffer(str);
  } else if (tag === 'printstr') {
    if (!this._isPrintstr(str)) {
      return this.reporter.error('Encoding of string type: printstr supports ' +
                                 'only latin upper and lower case letters, ' +
                                 'digits, space, apostrophe, left and rigth ' +
                                 'parenthesis, plus sign, comma, hyphen, ' +
                                 'dot, slash, colon, equal sign, ' +
                                 'question mark');
    }
    return this._createEncoderBuffer(str);
  } else if (/str$/.test(tag)) {
    return this._createEncoderBuffer(str);
  } else if (tag === 'objDesc') {
    return this._createEncoderBuffer(str);
  } else {
    return this.reporter.error('Encoding of string type: ' + tag +
                               ' unsupported');
  }
};

DERNode.prototype._encodeObjid = function encodeObjid(id, values, relative) {
  if (typeof id === 'string') {
    if (!values)
      return this.reporter.error('string objid given, but no values map found');
    if (!values.hasOwnProperty(id))
      return this.reporter.error('objid not found in values map');
    id = values[id].split(/[\s\.]+/g);
    for (var i = 0; i < id.length; i++)
      id[i] |= 0;
  } else if (Array.isArray(id)) {
    id = id.slice();
    for (var i = 0; i < id.length; i++)
      id[i] |= 0;
  }

  if (!Array.isArray(id)) {
    return this.reporter.error('objid() should be either array or string, ' +
                               'got: ' + JSON.stringify(id));
  }

  if (!relative) {
    if (id[1] >= 40)
      return this.reporter.error('Second objid identifier OOB');
    id.splice(0, 2, id[0] * 40 + id[1]);
  }

  // Count number of octets
  var size = 0;
  for (var i = 0; i < id.length; i++) {
    var ident = id[i];
    for (size++; ident >= 0x80; ident >>= 7)
      size++;
  }

  var objid = new Buffer(size);
  var offset = objid.length - 1;
  for (var i = id.length - 1; i >= 0; i--) {
    var ident = id[i];
    objid[offset--] = ident & 0x7f;
    while ((ident >>= 7) > 0)
      objid[offset--] = 0x80 | (ident & 0x7f);
  }

  return this._createEncoderBuffer(objid);
};

function two(num) {
  if (num < 10)
    return '0' + num;
  else
    return num;
}

DERNode.prototype._encodeTime = function encodeTime(time, tag) {
  var str;
  var date = new Date(time);

  if (tag === 'gentime') {
    str = [
      two(date.getFullYear()),
      two(date.getUTCMonth() + 1),
      two(date.getUTCDate()),
      two(date.getUTCHours()),
      two(date.getUTCMinutes()),
      two(date.getUTCSeconds()),
      'Z'
    ].join('');
  } else if (tag === 'utctime') {
    str = [
      two(date.getFullYear() % 100),
      two(date.getUTCMonth() + 1),
      two(date.getUTCDate()),
      two(date.getUTCHours()),
      two(date.getUTCMinutes()),
      two(date.getUTCSeconds()),
      'Z'
    ].join('');
  } else {
    this.reporter.error('Encoding ' + tag + ' time is not supported yet');
  }

  return this._encodeStr(str, 'octstr');
};

DERNode.prototype._encodeNull = function encodeNull() {
  return this._createEncoderBuffer('');
};

DERNode.prototype._encodeInt = function encodeInt(num, values) {
  if (typeof num === 'string') {
    if (!values)
      return this.reporter.error('String int or enum given, but no values map');
    if (!values.hasOwnProperty(num)) {
      return this.reporter.error('Values map doesn\'t contain: ' +
                                 JSON.stringify(num));
    }
    num = values[num];
  }

  // Bignum, assume big endian
  if (typeof num !== 'number' && !Buffer.isBuffer(num)) {
    var numArray = num.toArray();
    if (!num.sign && numArray[0] & 0x80) {
      numArray.unshift(0);
    }
    num = new Buffer(numArray);
  }

  if (Buffer.isBuffer(num)) {
    var size = num.length;
    if (num.length === 0)
      size++;

    var out = new Buffer(size);
    num.copy(out);
    if (num.length === 0)
      out[0] = 0
    return this._createEncoderBuffer(out);
  }

  if (num < 0x80)
    return this._createEncoderBuffer(num);

  if (num < 0x100)
    return this._createEncoderBuffer([0, num]);

  var size = 1;
  for (var i = num; i >= 0x100; i >>= 8)
    size++;

  var out = new Array(size);
  for (var i = out.length - 1; i >= 0; i--) {
    out[i] = num & 0xff;
    num >>= 8;
  }
  if(out[0] & 0x80) {
    out.unshift(0);
  }

  return this._createEncoderBuffer(new Buffer(out));
};

DERNode.prototype._encodeBool = function encodeBool(value) {
  return this._createEncoderBuffer(value ? 0xff : 0);
};

DERNode.prototype._use = function use(entity, obj) {
  if (typeof entity === 'function')
    entity = entity(obj);
  return entity._getEncoder('der').tree;
};

DERNode.prototype._skipDefault = function skipDefault(dataBuffer, reporter, parent) {
  var state = this._baseState;
  var i;
  if (state['default'] === null)
    return false;

  var data = dataBuffer.join();
  if (state.defaultBuffer === undefined)
    state.defaultBuffer = this._encodeValue(state['default'], reporter, parent).join();

  if (data.length !== state.defaultBuffer.length)
    return false;

  for (i=0; i < data.length; i++)
    if (data[i] !== state.defaultBuffer[i])
      return false;

  return true;
};

// Utility methods

function encodeTag(tag, primitive, cls, reporter) {
  var res;

  if (tag === 'seqof')
    tag = 'seq';
  else if (tag === 'setof')
    tag = 'set';

  if (der.tagByName.hasOwnProperty(tag))
    res = der.tagByName[tag];
  else if (typeof tag === 'number' && (tag | 0) === tag)
    res = tag;
  else
    return reporter.error('Unknown tag: ' + tag);

  if (res >= 0x1f)
    return reporter.error('Multi-octet tag encoding unsupported');

  if (!primitive)
    res |= 0x20;

  res |= (der.tagClassByName[cls || 'universal'] << 6);

  return res;
}

},{"../../asn1":1,"buffer":45,"inherits":94}],13:[function(require,module,exports){
var encoders = exports;

encoders.der = require('./der');
encoders.pem = require('./pem');

},{"./der":12,"./pem":14}],14:[function(require,module,exports){
var inherits = require('inherits');

var DEREncoder = require('./der');

function PEMEncoder(entity) {
  DEREncoder.call(this, entity);
  this.enc = 'pem';
};
inherits(PEMEncoder, DEREncoder);
module.exports = PEMEncoder;

PEMEncoder.prototype.encode = function encode(data, options) {
  var buf = DEREncoder.prototype.encode.call(this, data);

  var p = buf.toString('base64');
  var out = [ '-----BEGIN ' + options.label + '-----' ];
  for (var i = 0; i < p.length; i += 64)
    out.push(p.slice(i, i + 64));
  out.push('-----END ' + options.label + '-----');
  return out.join('\n');
};

},{"./der":12,"inherits":94}],15:[function(require,module,exports){
'use strict'

exports.byteLength = byteLength
exports.toByteArray = toByteArray
exports.fromByteArray = fromByteArray

var lookup = []
var revLookup = []
var Arr = typeof Uint8Array !== 'undefined' ? Uint8Array : Array

var code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
for (var i = 0, len = code.length; i < len; ++i) {
  lookup[i] = code[i]
  revLookup[code.charCodeAt(i)] = i
}

revLookup['-'.charCodeAt(0)] = 62
revLookup['_'.charCodeAt(0)] = 63

function placeHoldersCount (b64) {
  var len = b64.length
  if (len % 4 > 0) {
    throw new Error('Invalid string. Length must be a multiple of 4')
  }

  // the number of equal signs (place holders)
  // if there are two placeholders, than the two characters before it
  // represent one byte
  // if there is only one, then the three characters before it represent 2 bytes
  // this is just a cheap hack to not do indexOf twice
  return b64[len - 2] === '=' ? 2 : b64[len - 1] === '=' ? 1 : 0
}

function byteLength (b64) {
  // base64 is 4/3 + up to two characters of the original data
  return b64.length * 3 / 4 - placeHoldersCount(b64)
}

function toByteArray (b64) {
  var i, j, l, tmp, placeHolders, arr
  var len = b64.length
  placeHolders = placeHoldersCount(b64)

  arr = new Arr(len * 3 / 4 - placeHolders)

  // if there are placeholders, only get up to the last complete 4 chars
  l = placeHolders > 0 ? len - 4 : len

  var L = 0

  for (i = 0, j = 0; i < l; i += 4, j += 3) {
    tmp = (revLookup[b64.charCodeAt(i)] << 18) | (revLookup[b64.charCodeAt(i + 1)] << 12) | (revLookup[b64.charCodeAt(i + 2)] << 6) | revLookup[b64.charCodeAt(i + 3)]
    arr[L++] = (tmp >> 16) & 0xFF
    arr[L++] = (tmp >> 8) & 0xFF
    arr[L++] = tmp & 0xFF
  }

  if (placeHolders === 2) {
    tmp = (revLookup[b64.charCodeAt(i)] << 2) | (revLookup[b64.charCodeAt(i + 1)] >> 4)
    arr[L++] = tmp & 0xFF
  } else if (placeHolders === 1) {
    tmp = (revLookup[b64.charCodeAt(i)] << 10) | (revLookup[b64.charCodeAt(i + 1)] << 4) | (revLookup[b64.charCodeAt(i + 2)] >> 2)
    arr[L++] = (tmp >> 8) & 0xFF
    arr[L++] = tmp & 0xFF
  }

  return arr
}

function tripletToBase64 (num) {
  return lookup[num >> 18 & 0x3F] + lookup[num >> 12 & 0x3F] + lookup[num >> 6 & 0x3F] + lookup[num & 0x3F]
}

function encodeChunk (uint8, start, end) {
  var tmp
  var output = []
  for (var i = start; i < end; i += 3) {
    tmp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2])
    output.push(tripletToBase64(tmp))
  }
  return output.join('')
}

function fromByteArray (uint8) {
  var tmp
  var len = uint8.length
  var extraBytes = len % 3 // if we have 1 byte left, pad 2 bytes
  var output = ''
  var parts = []
  var maxChunkLength = 16383 // must be multiple of 3

  // go through the array every three bytes, we'll deal with trailing stuff later
  for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) {
    parts.push(encodeChunk(uint8, i, (i + maxChunkLength) > len2 ? len2 : (i + maxChunkLength)))
  }

  // pad the end with zeros, but make sure to not forget the extra bytes
  if (extraBytes === 1) {
    tmp = uint8[len - 1]
    output += lookup[tmp >> 2]
    output += lookup[(tmp << 4) & 0x3F]
    output += '=='
  } else if (extraBytes === 2) {
    tmp = (uint8[len - 2] << 8) + (uint8[len - 1])
    output += lookup[tmp >> 10]
    output += lookup[(tmp >> 4) & 0x3F]
    output += lookup[(tmp << 2) & 0x3F]
    output += '='
  }

  parts.push(output)

  return parts.join('')
}

},{}],16:[function(require,module,exports){
(function (module, exports) {
  'use strict';

  // Utils
  function assert (val, msg) {
    if (!val) throw new Error(msg || 'Assertion failed');
  }

  // Could use `inherits` module, but don't want to move from single file
  // architecture yet.
  function inherits (ctor, superCtor) {
    ctor.super_ = superCtor;
    var TempCtor = function () {};
    TempCtor.prototype = superCtor.prototype;
    ctor.prototype = new TempCtor();
    ctor.prototype.constructor = ctor;
  }

  // BN

  function BN (number, base, endian) {
    if (BN.isBN(number)) {
      return number;
    }

    this.negative = 0;
    this.words = null;
    this.length = 0;

    // Reduction context
    this.red = null;

    if (number !== null) {
      if (base === 'le' || base === 'be') {
        endian = base;
        base = 10;
      }

      this._init(number || 0, base || 10, endian || 'be');
    }
  }
  if (typeof module === 'object') {
    module.exports = BN;
  } else {
    exports.BN = BN;
  }

  BN.BN = BN;
  BN.wordSize = 26;

  var Buffer;
  try {
    Buffer = require('buf' + 'fer').Buffer;
  } catch (e) {
  }

  BN.isBN = function isBN (num) {
    if (num instanceof BN) {
      return true;
    }

    return num !== null && typeof num === 'object' &&
      num.constructor.wordSize === BN.wordSize && Array.isArray(num.words);
  };

  BN.max = function max (left, right) {
    if (left.cmp(right) > 0) return left;
    return right;
  };

  BN.min = function min (left, right) {
    if (left.cmp(right) < 0) return left;
    return right;
  };

  BN.prototype._init = function init (number, base, endian) {
    if (typeof number === 'number') {
      return this._initNumber(number, base, endian);
    }

    if (typeof number === 'object') {
      return this._initArray(number, base, endian);
    }

    if (base === 'hex') {
      base = 16;
    }
    assert(base === (base | 0) && base >= 2 && base <= 36);

    number = number.toString().replace(/\s+/g, '');
    var start = 0;
    if (number[0] === '-') {
      start++;
    }

    if (base === 16) {
      this._parseHex(number, start);
    } else {
      this._parseBase(number, base, start);
    }

    if (number[0] === '-') {
      this.negative = 1;
    }

    this.strip();

    if (endian !== 'le') return;

    this._initArray(this.toArray(), base, endian);
  };

  BN.prototype._initNumber = function _initNumber (number, base, endian) {
    if (number < 0) {
      this.negative = 1;
      number = -number;
    }
    if (number < 0x4000000) {
      this.words = [ number & 0x3ffffff ];
      this.length = 1;
    } else if (number < 0x10000000000000) {
      this.words = [
        number & 0x3ffffff,
        (number / 0x4000000) & 0x3ffffff
      ];
      this.length = 2;
    } else {
      assert(number < 0x20000000000000); // 2 ^ 53 (unsafe)
      this.words = [
        number & 0x3ffffff,
        (number / 0x4000000) & 0x3ffffff,
        1
      ];
      this.length = 3;
    }

    if (endian !== 'le') return;

    // Reverse the bytes
    this._initArray(this.toArray(), base, endian);
  };

  BN.prototype._initArray = function _initArray (number, base, endian) {
    // Perhaps a Uint8Array
    assert(typeof number.length === 'number');
    if (number.length <= 0) {
      this.words = [ 0 ];
      this.length = 1;
      return this;
    }

    this.length = Math.ceil(number.length / 3);
    this.words = new Array(this.length);
    for (var i = 0; i < this.length; i++) {
      this.words[i] = 0;
    }

    var j, w;
    var off = 0;
    if (endian === 'be') {
      for (i = number.length - 1, j = 0; i >= 0; i -= 3) {
        w = number[i] | (number[i - 1] << 8) | (number[i - 2] << 16);
        this.words[j] |= (w << off) & 0x3ffffff;
        this.words[j + 1] = (w >>> (26 - off)) & 0x3ffffff;
        off += 24;
        if (off >= 26) {
          off -= 26;
          j++;
        }
      }
    } else if (endian === 'le') {
      for (i = 0, j = 0; i < number.length; i += 3) {
        w = number[i] | (number[i + 1] << 8) | (number[i + 2] << 16);
        this.words[j] |= (w << off) & 0x3ffffff;
        this.words[j + 1] = (w >>> (26 - off)) & 0x3ffffff;
        off += 24;
        if (off >= 26) {
          off -= 26;
          j++;
        }
      }
    }
    return this.strip();
  };

  function parseHex (str, start, end) {
    var r = 0;
    var len = Math.min(str.length, end);
    for (var i = start; i < len; i++) {
      var c = str.charCodeAt(i) - 48;

      r <<= 4;

      // 'a' - 'f'
      if (c >= 49 && c <= 54) {
        r |= c - 49 + 0xa;

      // 'A' - 'F'
      } else if (c >= 17 && c <= 22) {
        r |= c - 17 + 0xa;

      // '0' - '9'
      } else {
        r |= c & 0xf;
      }
    }
    return r;
  }

  BN.prototype._parseHex = function _parseHex (number, start) {
    // Create possibly bigger array to ensure that it fits the number
    this.length = Math.ceil((number.length - start) / 6);
    this.words = new Array(this.length);
    for (var i = 0; i < this.length; i++) {
      this.words[i] = 0;
    }

    var j, w;
    // Scan 24-bit chunks and add them to the number
    var off = 0;
    for (i = number.length - 6, j = 0; i >= start; i -= 6) {
      w = parseHex(number, i, i + 6);
      this.words[j] |= (w << off) & 0x3ffffff;
      // NOTE: `0x3fffff` is intentional here, 26bits max shift + 24bit hex limb
      this.words[j + 1] |= w >>> (26 - off) & 0x3fffff;
      off += 24;
      if (off >= 26) {
        off -= 26;
        j++;
      }
    }
    if (i + 6 !== start) {
      w = parseHex(number, start, i + 6);
      this.words[j] |= (w << off) & 0x3ffffff;
      this.words[j + 1] |= w >>> (26 - off) & 0x3fffff;
    }
    this.strip();
  };

  function parseBase (str, start, end, mul) {
    var r = 0;
    var len = Math.min(str.length, end);
    for (var i = start; i < len; i++) {
      var c = str.charCodeAt(i) - 48;

      r *= mul;

      // 'a'
      if (c >= 49) {
        r += c - 49 + 0xa;

      // 'A'
      } else if (c >= 17) {
        r += c - 17 + 0xa;

      // '0' - '9'
      } else {
        r += c;
      }
    }
    return r;
  }

  BN.prototype._parseBase = function _parseBase (number, base, start) {
    // Initialize as zero
    this.words = [ 0 ];
    this.length = 1;

    // Find length of limb in base
    for (var limbLen = 0, limbPow = 1; limbPow <= 0x3ffffff; limbPow *= base) {
      limbLen++;
    }
    limbLen--;
    limbPow = (limbPow / base) | 0;

    var total = number.length - start;
    var mod = total % limbLen;
    var end = Math.min(total, total - mod) + start;

    var word = 0;
    for (var i = start; i < end; i += limbLen) {
      word = parseBase(number, i, i + limbLen, base);

      this.imuln(limbPow);
      if (this.words[0] + word < 0x4000000) {
        this.words[0] += word;
      } else {
        this._iaddn(word);
      }
    }

    if (mod !== 0) {
      var pow = 1;
      word = parseBase(number, i, number.length, base);

      for (i = 0; i < mod; i++) {
        pow *= base;
      }

      this.imuln(pow);
      if (this.words[0] + word < 0x4000000) {
        this.words[0] += word;
      } else {
        this._iaddn(word);
      }
    }
  };

  BN.prototype.copy = function copy (dest) {
    dest.words = new Array(this.length);
    for (var i = 0; i < this.length; i++) {
      dest.words[i] = this.words[i];
    }
    dest.length = this.length;
    dest.negative = this.negative;
    dest.red = this.red;
  };

  BN.prototype.clone = function clone () {
    var r = new BN(null);
    this.copy(r);
    return r;
  };

  BN.prototype._expand = function _expand (size) {
    while (this.length < size) {
      this.words[this.length++] = 0;
    }
    return this;
  };

  // Remove leading `0` from `this`
  BN.prototype.strip = function strip () {
    while (this.length > 1 && this.words[this.length - 1] === 0) {
      this.length--;
    }
    return this._normSign();
  };

  BN.prototype._normSign = function _normSign () {
    // -0 = 0
    if (this.length === 1 && this.words[0] === 0) {
      this.negative = 0;
    }
    return this;
  };

  BN.prototype.inspect = function inspect () {
    return (this.red ? '<BN-R: ' : '<BN: ') + this.toString(16) + '>';
  };

  /*

  var zeros = [];
  var groupSizes = [];
  var groupBases = [];

  var s = '';
  var i = -1;
  while (++i < BN.wordSize) {
    zeros[i] = s;
    s += '0';
  }
  groupSizes[0] = 0;
  groupSizes[1] = 0;
  groupBases[0] = 0;
  groupBases[1] = 0;
  var base = 2 - 1;
  while (++base < 36 + 1) {
    var groupSize = 0;
    var groupBase = 1;
    while (groupBase < (1 << BN.wordSize) / base) {
      groupBase *= base;
      groupSize += 1;
    }
    groupSizes[base] = groupSize;
    groupBases[base] = groupBase;
  }

  */

  var zeros = [
    '',
    '0',
    '00',
    '000',
    '0000',
    '00000',
    '000000',
    '0000000',
    '00000000',
    '000000000',
    '0000000000',
    '00000000000',
    '000000000000',
    '0000000000000',
    '00000000000000',
    '000000000000000',
    '0000000000000000',
    '00000000000000000',
    '000000000000000000',
    '0000000000000000000',
    '00000000000000000000',
    '000000000000000000000',
    '0000000000000000000000',
    '00000000000000000000000',
    '000000000000000000000000',
    '0000000000000000000000000'
  ];

  var groupSizes = [
    0, 0,
    25, 16, 12, 11, 10, 9, 8,
    8, 7, 7, 7, 7, 6, 6,
    6, 6, 6, 6, 6, 5, 5,
    5, 5, 5, 5, 5, 5, 5,
    5, 5, 5, 5, 5, 5, 5
  ];

  var groupBases = [
    0, 0,
    33554432, 43046721, 16777216, 48828125, 60466176, 40353607, 16777216,
    43046721, 10000000, 19487171, 35831808, 62748517, 7529536, 11390625,
    16777216, 24137569, 34012224, 47045881, 64000000, 4084101, 5153632,
    6436343, 7962624, 9765625, 11881376, 14348907, 17210368, 20511149,
    24300000, 28629151, 33554432, 39135393, 45435424, 52521875, 60466176
  ];

  BN.prototype.toString = function toString (base, padding) {
    base = base || 10;
    padding = padding | 0 || 1;

    var out;
    if (base === 16 || base === 'hex') {
      out = '';
      var off = 0;
      var carry = 0;
      for (var i = 0; i < this.length; i++) {
        var w = this.words[i];
        var word = (((w << off) | carry) & 0xffffff).toString(16);
        carry = (w >>> (24 - off)) & 0xffffff;
        if (carry !== 0 || i !== this.length - 1) {
          out = zeros[6 - word.length] + word + out;
        } else {
          out = word + out;
        }
        off += 2;
        if (off >= 26) {
          off -= 26;
          i--;
        }
      }
      if (carry !== 0) {
        out = carry.toString(16) + out;
      }
      while (out.length % padding !== 0) {
        out = '0' + out;
      }
      if (this.negative !== 0) {
        out = '-' + out;
      }
      return out;
    }

    if (base === (base | 0) && base >= 2 && base <= 36) {
      // var groupSize = Math.floor(BN.wordSize * Math.LN2 / Math.log(base));
      var groupSize = groupSizes[base];
      // var groupBase = Math.pow(base, groupSize);
      var groupBase = groupBases[base];
      out = '';
      var c = this.clone();
      c.negative = 0;
      while (!c.isZero()) {
        var r = c.modn(groupBase).toString(base);
        c = c.idivn(groupBase);

        if (!c.isZero()) {
          out = zeros[groupSize - r.length] + r + out;
        } else {
          out = r + out;
        }
      }
      if (this.isZero()) {
        out = '0' + out;
      }
      while (out.length % padding !== 0) {
        out = '0' + out;
      }
      if (this.negative !== 0) {
        out = '-' + out;
      }
      return out;
    }

    assert(false, 'Base should be between 2 and 36');
  };

  BN.prototype.toNumber = function toNumber () {
    var ret = this.words[0];
    if (this.length === 2) {
      ret += this.words[1] * 0x4000000;
    } else if (this.length === 3 && this.words[2] === 0x01) {
      // NOTE: at this stage it is known that the top bit is set
      ret += 0x10000000000000 + (this.words[1] * 0x4000000);
    } else if (this.length > 2) {
      assert(false, 'Number can only safely store up to 53 bits');
    }
    return (this.negative !== 0) ? -ret : ret;
  };

  BN.prototype.toJSON = function toJSON () {
    return this.toString(16);
  };

  BN.prototype.toBuffer = function toBuffer (endian, length) {
    assert(typeof Buffer !== 'undefined');
    return this.toArrayLike(Buffer, endian, length);
  };

  BN.prototype.toArray = function toArray (endian, length) {
    return this.toArrayLike(Array, endian, length);
  };

  BN.prototype.toArrayLike = function toArrayLike (ArrayType, endian, length) {
    var byteLength = this.byteLength();
    var reqLength = length || Math.max(1, byteLength);
    assert(byteLength <= reqLength, 'byte array longer than desired length');
    assert(reqLength > 0, 'Requested array length <= 0');

    this.strip();
    var littleEndian = endian === 'le';
    var res = new ArrayType(reqLength);

    var b, i;
    var q = this.clone();
    if (!littleEndian) {
      // Assume big-endian
      for (i = 0; i < reqLength - byteLength; i++) {
        res[i] = 0;
      }

      for (i = 0; !q.isZero(); i++) {
        b = q.andln(0xff);
        q.iushrn(8);

        res[reqLength - i - 1] = b;
      }
    } else {
      for (i = 0; !q.isZero(); i++) {
        b = q.andln(0xff);
        q.iushrn(8);

        res[i] = b;
      }

      for (; i < reqLength; i++) {
        res[i] = 0;
      }
    }

    return res;
  };

  if (Math.clz32) {
    BN.prototype._countBits = function _countBits (w) {
      return 32 - Math.clz32(w);
    };
  } else {
    BN.prototype._countBits = function _countBits (w) {
      var t = w;
      var r = 0;
      if (t >= 0x1000) {
        r += 13;
        t >>>= 13;
      }
      if (t >= 0x40) {
        r += 7;
        t >>>= 7;
      }
      if (t >= 0x8) {
        r += 4;
        t >>>= 4;
      }
      if (t >= 0x02) {
        r += 2;
        t >>>= 2;
      }
      return r + t;
    };
  }

  BN.prototype._zeroBits = function _zeroBits (w) {
    // Short-cut
    if (w === 0) return 26;

    var t = w;
    var r = 0;
    if ((t & 0x1fff) === 0) {
      r += 13;
      t >>>= 13;
    }
    if ((t & 0x7f) === 0) {
      r += 7;
      t >>>= 7;
    }
    if ((t & 0xf) === 0) {
      r += 4;
      t >>>= 4;
    }
    if ((t & 0x3) === 0) {
      r += 2;
      t >>>= 2;
    }
    if ((t & 0x1) === 0) {
      r++;
    }
    return r;
  };

  // Return number of used bits in a BN
  BN.prototype.bitLength = function bitLength () {
    var w = this.words[this.length - 1];
    var hi = this._countBits(w);
    return (this.length - 1) * 26 + hi;
  };

  function toBitArray (num) {
    var w = new Array(num.bitLength());

    for (var bit = 0; bit < w.length; bit++) {
      var off = (bit / 26) | 0;
      var wbit = bit % 26;

      w[bit] = (num.words[off] & (1 << wbit)) >>> wbit;
    }

    return w;
  }

  // Number of trailing zero bits
  BN.prototype.zeroBits = function zeroBits () {
    if (this.isZero()) return 0;

    var r = 0;
    for (var i = 0; i < this.length; i++) {
      var b = this._zeroBits(this.words[i]);
      r += b;
      if (b !== 26) break;
    }
    return r;
  };

  BN.prototype.byteLength = function byteLength () {
    return Math.ceil(this.bitLength() / 8);
  };

  BN.prototype.toTwos = function toTwos (width) {
    if (this.negative !== 0) {
      return this.abs().inotn(width).iaddn(1);
    }
    return this.clone();
  };

  BN.prototype.fromTwos = function fromTwos (width) {
    if (this.testn(width - 1)) {
      return this.notn(width).iaddn(1).ineg();
    }
    return this.clone();
  };

  BN.prototype.isNeg = function isNeg () {
    return this.negative !== 0;
  };

  // Return negative clone of `this`
  BN.prototype.neg = function neg () {
    return this.clone().ineg();
  };

  BN.prototype.ineg = function ineg () {
    if (!this.isZero()) {
      this.negative ^= 1;
    }

    return this;
  };

  // Or `num` with `this` in-place
  BN.prototype.iuor = function iuor (num) {
    while (this.length < num.length) {
      this.words[this.length++] = 0;
    }

    for (var i = 0; i < num.length; i++) {
      this.words[i] = this.words[i] | num.words[i];
    }

    return this.strip();
  };

  BN.prototype.ior = function ior (num) {
    assert((this.negative | num.negative) === 0);
    return this.iuor(num);
  };

  // Or `num` with `this`
  BN.prototype.or = function or (num) {
    if (this.length > num.length) return this.clone().ior(num);
    return num.clone().ior(this);
  };

  BN.prototype.uor = function uor (num) {
    if (this.length > num.length) return this.clone().iuor(num);
    return num.clone().iuor(this);
  };

  // And `num` with `this` in-place
  BN.prototype.iuand = function iuand (num) {
    // b = min-length(num, this)
    var b;
    if (this.length > num.length) {
      b = num;
    } else {
      b = this;
    }

    for (var i = 0; i < b.length; i++) {
      this.words[i] = this.words[i] & num.words[i];
    }

    this.length = b.length;

    return this.strip();
  };

  BN.prototype.iand = function iand (num) {
    assert((this.negative | num.negative) === 0);
    return this.iuand(num);
  };

  // And `num` with `this`
  BN.prototype.and = function and (num) {
    if (this.length > num.length) return this.clone().iand(num);
    return num.clone().iand(this);
  };

  BN.prototype.uand = function uand (num) {
    if (this.length > num.length) return this.clone().iuand(num);
    return num.clone().iuand(this);
  };

  // Xor `num` with `this` in-place
  BN.prototype.iuxor = function iuxor (num) {
    // a.length > b.length
    var a;
    var b;
    if (this.length > num.length) {
      a = this;
      b = num;
    } else {
      a = num;
      b = this;
    }

    for (var i = 0; i < b.length; i++) {
      this.words[i] = a.words[i] ^ b.words[i];
    }

    if (this !== a) {
      for (; i < a.length; i++) {
        this.words[i] = a.words[i];
      }
    }

    this.length = a.length;

    return this.strip();
  };

  BN.prototype.ixor = function ixor (num) {
    assert((this.negative | num.negative) === 0);
    return this.iuxor(num);
  };

  // Xor `num` with `this`
  BN.prototype.xor = function xor (num) {
    if (this.length > num.length) return this.clone().ixor(num);
    return num.clone().ixor(this);
  };

  BN.prototype.uxor = function uxor (num) {
    if (this.length > num.length) return this.clone().iuxor(num);
    return num.clone().iuxor(this);
  };

  // Not ``this`` with ``width`` bitwidth
  BN.prototype.inotn = function inotn (width) {
    assert(typeof width === 'number' && width >= 0);

    var bytesNeeded = Math.ceil(width / 26) | 0;
    var bitsLeft = width % 26;

    // Extend the buffer with leading zeroes
    this._expand(bytesNeeded);

    if (bitsLeft > 0) {
      bytesNeeded--;
    }

    // Handle complete words
    for (var i = 0; i < bytesNeeded; i++) {
      this.words[i] = ~this.words[i] & 0x3ffffff;
    }

    // Handle the residue
    if (bitsLeft > 0) {
      this.words[i] = ~this.words[i] & (0x3ffffff >> (26 - bitsLeft));
    }

    // And remove leading zeroes
    return this.strip();
  };

  BN.prototype.notn = function notn (width) {
    return this.clone().inotn(width);
  };

  // Set `bit` of `this`
  BN.prototype.setn = function setn (bit, val) {
    assert(typeof bit === 'number' && bit >= 0);

    var off = (bit / 26) | 0;
    var wbit = bit % 26;

    this._expand(off + 1);

    if (val) {
      this.words[off] = this.words[off] | (1 << wbit);
    } else {
      this.words[off] = this.words[off] & ~(1 << wbit);
    }

    return this.strip();
  };

  // Add `num` to `this` in-place
  BN.prototype.iadd = function iadd (num) {
    var r;

    // negative + positive
    if (this.negative !== 0 && num.negative === 0) {
      this.negative = 0;
      r = this.isub(num);
      this.negative ^= 1;
      return this._normSign();

    // positive + negative
    } else if (this.negative === 0 && num.negative !== 0) {
      num.negative = 0;
      r = this.isub(num);
      num.negative = 1;
      return r._normSign();
    }

    // a.length > b.length
    var a, b;
    if (this.length > num.length) {
      a = this;
      b = num;
    } else {
      a = num;
      b = this;
    }

    var carry = 0;
    for (var i = 0; i < b.length; i++) {
      r = (a.words[i] | 0) + (b.words[i] | 0) + carry;
      this.words[i] = r & 0x3ffffff;
      carry = r >>> 26;
    }
    for (; carry !== 0 && i < a.length; i++) {
      r = (a.words[i] | 0) + carry;
      this.words[i] = r & 0x3ffffff;
      carry = r >>> 26;
    }

    this.length = a.length;
    if (carry !== 0) {
      this.words[this.length] = carry;
      this.length++;
    // Copy the rest of the words
    } else if (a !== this) {
      for (; i < a.length; i++) {
        this.words[i] = a.words[i];
      }
    }

    return this;
  };

  // Add `num` to `this`
  BN.prototype.add = function add (num) {
    var res;
    if (num.negative !== 0 && this.negative === 0) {
      num.negative = 0;
      res = this.sub(num);
      num.negative ^= 1;
      return res;
    } else if (num.negative === 0 && this.negative !== 0) {
      this.negative = 0;
      res = num.sub(this);
      this.negative = 1;
      return res;
    }

    if (this.length > num.length) return this.clone().iadd(num);

    return num.clone().iadd(this);
  };

  // Subtract `num` from `this` in-place
  BN.prototype.isub = function isub (num) {
    // this - (-num) = this + num
    if (num.negative !== 0) {
      num.negative = 0;
      var r = this.iadd(num);
      num.negative = 1;
      return r._normSign();

    // -this - num = -(this + num)
    } else if (this.negative !== 0) {
      this.negative = 0;
      this.iadd(num);
      this.negative = 1;
      return this._normSign();
    }

    // At this point both numbers are positive
    var cmp = this.cmp(num);

    // Optimization - zeroify
    if (cmp === 0) {
      this.negative = 0;
      this.length = 1;
      this.words[0] = 0;
      return this;
    }

    // a > b
    var a, b;
    if (cmp > 0) {
      a = this;
      b = num;
    } else {
      a = num;
      b = this;
    }

    var carry = 0;
    for (var i = 0; i < b.length; i++) {
      r = (a.words[i] | 0) - (b.words[i] | 0) + carry;
      carry = r >> 26;
      this.words[i] = r & 0x3ffffff;
    }
    for (; carry !== 0 && i < a.length; i++) {
      r = (a.words[i] | 0) + carry;
      carry = r >> 26;
      this.words[i] = r & 0x3ffffff;
    }

    // Copy rest of the words
    if (carry === 0 && i < a.length && a !== this) {
      for (; i < a.length; i++) {
        this.words[i] = a.words[i];
      }
    }

    this.length = Math.max(this.length, i);

    if (a !== this) {
      this.negative = 1;
    }

    return this.strip();
  };

  // Subtract `num` from `this`
  BN.prototype.sub = function sub (num) {
    return this.clone().isub(num);
  };

  function smallMulTo (self, num, out) {
    out.negative = num.negative ^ self.negative;
    var len = (self.length + num.length) | 0;
    out.length = len;
    len = (len - 1) | 0;

    // Peel one iteration (compiler can't do it, because of code complexity)
    var a = self.words[0] | 0;
    var b = num.words[0] | 0;
    var r = a * b;

    var lo = r & 0x3ffffff;
    var carry = (r / 0x4000000) | 0;
    out.words[0] = lo;

    for (var k = 1; k < len; k++) {
      // Sum all words with the same `i + j = k` and accumulate `ncarry`,
      // note that ncarry could be >= 0x3ffffff
      var ncarry = carry >>> 26;
      var rword = carry & 0x3ffffff;
      var maxJ = Math.min(k, num.length - 1);
      for (var j = Math.max(0, k - self.length + 1); j <= maxJ; j++) {
        var i = (k - j) | 0;
        a = self.words[i] | 0;
        b = num.words[j] | 0;
        r = a * b + rword;
        ncarry += (r / 0x4000000) | 0;
        rword = r & 0x3ffffff;
      }
      out.words[k] = rword | 0;
      carry = ncarry | 0;
    }
    if (carry !== 0) {
      out.words[k] = carry | 0;
    } else {
      out.length--;
    }

    return out.strip();
  }

  // TODO(indutny): it may be reasonable to omit it for users who don't need
  // to work with 256-bit numbers, otherwise it gives 20% improvement for 256-bit
  // multiplication (like elliptic secp256k1).
  var comb10MulTo = function comb10MulTo (self, num, out) {
    var a = self.words;
    var b = num.words;
    var o = out.words;
    var c = 0;
    var lo;
    var mid;
    var hi;
    var a0 = a[0] | 0;
    var al0 = a0 & 0x1fff;
    var ah0 = a0 >>> 13;
    var a1 = a[1] | 0;
    var al1 = a1 & 0x1fff;
    var ah1 = a1 >>> 13;
    var a2 = a[2] | 0;
    var al2 = a2 & 0x1fff;
    var ah2 = a2 >>> 13;
    var a3 = a[3] | 0;
    var al3 = a3 & 0x1fff;
    var ah3 = a3 >>> 13;
    var a4 = a[4] | 0;
    var al4 = a4 & 0x1fff;
    var ah4 = a4 >>> 13;
    var a5 = a[5] | 0;
    var al5 = a5 & 0x1fff;
    var ah5 = a5 >>> 13;
    var a6 = a[6] | 0;
    var al6 = a6 & 0x1fff;
    var ah6 = a6 >>> 13;
    var a7 = a[7] | 0;
    var al7 = a7 & 0x1fff;
    var ah7 = a7 >>> 13;
    var a8 = a[8] | 0;
    var al8 = a8 & 0x1fff;
    var ah8 = a8 >>> 13;
    var a9 = a[9] | 0;
    var al9 = a9 & 0x1fff;
    var ah9 = a9 >>> 13;
    var b0 = b[0] | 0;
    var bl0 = b0 & 0x1fff;
    var bh0 = b0 >>> 13;
    var b1 = b[1] | 0;
    var bl1 = b1 & 0x1fff;
    var bh1 = b1 >>> 13;
    var b2 = b[2] | 0;
    var bl2 = b2 & 0x1fff;
    var bh2 = b2 >>> 13;
    var b3 = b[3] | 0;
    var bl3 = b3 & 0x1fff;
    var bh3 = b3 >>> 13;
    var b4 = b[4] | 0;
    var bl4 = b4 & 0x1fff;
    var bh4 = b4 >>> 13;
    var b5 = b[5] | 0;
    var bl5 = b5 & 0x1fff;
    var bh5 = b5 >>> 13;
    var b6 = b[6] | 0;
    var bl6 = b6 & 0x1fff;
    var bh6 = b6 >>> 13;
    var b7 = b[7] | 0;
    var bl7 = b7 & 0x1fff;
    var bh7 = b7 >>> 13;
    var b8 = b[8] | 0;
    var bl8 = b8 & 0x1fff;
    var bh8 = b8 >>> 13;
    var b9 = b[9] | 0;
    var bl9 = b9 & 0x1fff;
    var bh9 = b9 >>> 13;

    out.negative = self.negative ^ num.negative;
    out.length = 19;
    /* k = 0 */
    lo = Math.imul(al0, bl0);
    mid = Math.imul(al0, bh0);
    mid = (mid + Math.imul(ah0, bl0)) | 0;
    hi = Math.imul(ah0, bh0);
    var w0 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
    c = (((hi + (mid >>> 13)) | 0) + (w0 >>> 26)) | 0;
    w0 &= 0x3ffffff;
    /* k = 1 */
    lo = Math.imul(al1, bl0);
    mid = Math.imul(al1, bh0);
    mid = (mid + Math.imul(ah1, bl0)) | 0;
    hi = Math.imul(ah1, bh0);
    lo = (lo + Math.imul(al0, bl1)) | 0;
    mid = (mid + Math.imul(al0, bh1)) | 0;
    mid = (mid + Math.imul(ah0, bl1)) | 0;
    hi = (hi + Math.imul(ah0, bh1)) | 0;
    var w1 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
    c = (((hi + (mid >>> 13)) | 0) + (w1 >>> 26)) | 0;
    w1 &= 0x3ffffff;
    /* k = 2 */
    lo = Math.imul(al2, bl0);
    mid = Math.imul(al2, bh0);
    mid = (mid + Math.imul(ah2, bl0)) | 0;
    hi = Math.imul(ah2, bh0);
    lo = (lo + Math.imul(al1, bl1)) | 0;
    mid = (mid + Math.imul(al1, bh1)) | 0;
    mid = (mid + Math.imul(ah1, bl1)) | 0;
    hi = (hi + Math.imul(ah1, bh1)) | 0;
    lo = (lo + Math.imul(al0, bl2)) | 0;
    mid = (mid + Math.imul(al0, bh2)) | 0;
    mid = (mid + Math.imul(ah0, bl2)) | 0;
    hi = (hi + Math.imul(ah0, bh2)) | 0;
    var w2 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
    c = (((hi + (mid >>> 13)) | 0) + (w2 >>> 26)) | 0;
    w2 &= 0x3ffffff;
    /* k = 3 */
    lo = Math.imul(al3, bl0);
    mid = Math.imul(al3, bh0);
    mid = (mid + Math.imul(ah3, bl0)) | 0;
    hi = Math.imul(ah3, bh0);
    lo = (lo + Math.imul(al2, bl1)) | 0;
    mid = (mid + Math.imul(al2, bh1)) | 0;
    mid = (mid + Math.imul(ah2, bl1)) | 0;
    hi = (hi + Math.imul(ah2, bh1)) | 0;
    lo = (lo + Math.imul(al1, bl2)) | 0;
    mid = (mid + Math.imul(al1, bh2)) | 0;
    mid = (mid + Math.imul(ah1, bl2)) | 0;
    hi = (hi + Math.imul(ah1, bh2)) | 0;
    lo = (lo + Math.imul(al0, bl3)) | 0;
    mid = (mid + Math.imul(al0, bh3)) | 0;
    mid = (mid + Math.imul(ah0, bl3)) | 0;
    hi = (hi + Math.imul(ah0, bh3)) | 0;
    var w3 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
    c = (((hi + (mid >>> 13)) | 0) + (w3 >>> 26)) | 0;
    w3 &= 0x3ffffff;
    /* k = 4 */
    lo = Math.imul(al4, bl0);
    mid = Math.imul(al4, bh0);
    mid = (mid + Math.imul(ah4, bl0)) | 0;
    hi = Math.imul(ah4, bh0);
    lo = (lo + Math.imul(al3, bl1)) | 0;
    mid = (mid + Math.imul(al3, bh1)) | 0;
    mid = (mid + Math.imul(ah3, bl1)) | 0;
    hi = (hi + Math.imul(ah3, bh1)) | 0;
    lo = (lo + Math.imul(al2, bl2)) | 0;
    mid = (mid + Math.imul(al2, bh2)) | 0;
    mid = (mid + Math.imul(ah2, bl2)) | 0;
    hi = (hi + Math.imul(ah2, bh2)) | 0;
    lo = (lo + Math.imul(al1, bl3)) | 0;
    mid = (mid + Math.imul(al1, bh3)) | 0;
    mid = (mid + Math.imul(ah1, bl3)) | 0;
    hi = (hi + Math.imul(ah1, bh3)) | 0;
    lo = (lo + Math.imul(al0, bl4)) | 0;
    mid = (mid + Math.imul(al0, bh4)) | 0;
    mid = (mid + Math.imul(ah0, bl4)) | 0;
    hi = (hi + Math.imul(ah0, bh4)) | 0;
    var w4 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
    c = (((hi + (mid >>> 13)) | 0) + (w4 >>> 26)) | 0;
    w4 &= 0x3ffffff;
    /* k = 5 */
    lo = Math.imul(al5, bl0);
    mid = Math.imul(al5, bh0);
    mid = (mid + Math.imul(ah5, bl0)) | 0;
    hi = Math.imul(ah5, bh0);
    lo = (lo + Math.imul(al4, bl1)) | 0;
    mid = (mid + Math.imul(al4, bh1)) | 0;
    mid = (mid + Math.imul(ah4, bl1)) | 0;
    hi = (hi + Math.imul(ah4, bh1)) | 0;
    lo = (lo + Math.imul(al3, bl2)) | 0;
    mid = (mid + Math.imul(al3, bh2)) | 0;
    mid = (mid + Math.imul(ah3, bl2)) | 0;
    hi = (hi + Math.imul(ah3, bh2)) | 0;
    lo = (lo + Math.imul(al2, bl3)) | 0;
    mid = (mid + Math.imul(al2, bh3)) | 0;
    mid = (mid + Math.imul(ah2, bl3)) | 0;
    hi = (hi + Math.imul(ah2, bh3)) | 0;
    lo = (lo + Math.imul(al1, bl4)) | 0;
    mid = (mid + Math.imul(al1, bh4)) | 0;
    mid = (mid + Math.imul(ah1, bl4)) | 0;
    hi = (hi + Math.imul(ah1, bh4)) | 0;
    lo = (lo + Math.imul(al0, bl5)) | 0;
    mid = (mid + Math.imul(al0, bh5)) | 0;
    mid = (mid + Math.imul(ah0, bl5)) | 0;
    hi = (hi + Math.imul(ah0, bh5)) | 0;
    var w5 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
    c = (((hi + (mid >>> 13)) | 0) + (w5 >>> 26)) | 0;
    w5 &= 0x3ffffff;
    /* k = 6 */
    lo = Math.imul(al6, bl0);
    mid = Math.imul(al6, bh0);
    mid = (mid + Math.imul(ah6, bl0)) | 0;
    hi = Math.imul(ah6, bh0);
    lo = (lo + Math.imul(al5, bl1)) | 0;
    mid = (mid + Math.imul(al5, bh1)) | 0;
    mid = (mid + Math.imul(ah5, bl1)) | 0;
    hi = (hi + Math.imul(ah5, bh1)) | 0;
    lo = (lo + Math.imul(al4, bl2)) | 0;
    mid = (mid + Math.imul(al4, bh2)) | 0;
    mid = (mid + Math.imul(ah4, bl2)) | 0;
    hi = (hi + Math.imul(ah4, bh2)) | 0;
    lo = (lo + Math.imul(al3, bl3)) | 0;
    mid = (mid + Math.imul(al3, bh3)) | 0;
    mid = (mid + Math.imul(ah3, bl3)) | 0;
    hi = (hi + Math.imul(ah3, bh3)) | 0;
    lo = (lo + Math.imul(al2, bl4)) | 0;
    mid = (mid + Math.imul(al2, bh4)) | 0;
    mid = (mid + Math.imul(ah2, bl4)) | 0;
    hi = (hi + Math.imul(ah2, bh4)) | 0;
    lo = (lo + Math.imul(al1, bl5)) | 0;
    mid = (mid + Math.imul(al1, bh5)) | 0;
    mid = (mid + Math.imul(ah1, bl5)) | 0;
    hi = (hi + Math.imul(ah1, bh5)) | 0;
    lo = (lo + Math.imul(al0, bl6)) | 0;
    mid = (mid + Math.imul(al0, bh6)) | 0;
    mid = (mid + Math.imul(ah0, bl6)) | 0;
    hi = (hi + Math.imul(ah0, bh6)) | 0;
    var w6 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
    c = (((hi + (mid >>> 13)) | 0) + (w6 >>> 26)) | 0;
    w6 &= 0x3ffffff;
    /* k = 7 */
    lo = Math.imul(al7, bl0);
    mid = Math.imul(al7, bh0);
    mid = (mid + Math.imul(ah7, bl0)) | 0;
    hi = Math.imul(ah7, bh0);
    lo = (lo + Math.imul(al6, bl1)) | 0;
    mid = (mid + Math.imul(al6, bh1)) | 0;
    mid = (mid + Math.imul(ah6, bl1)) | 0;
    hi = (hi + Math.imul(ah6, bh1)) | 0;
    lo = (lo + Math.imul(al5, bl2)) | 0;
    mid = (mid + Math.imul(al5, bh2)) | 0;
    mid = (mid + Math.imul(ah5, bl2)) | 0;
    hi = (hi + Math.imul(ah5, bh2)) | 0;
    lo = (lo + Math.imul(al4, bl3)) | 0;
    mid = (mid + Math.imul(al4, bh3)) | 0;
    mid = (mid + Math.imul(ah4, bl3)) | 0;
    hi = (hi + Math.imul(ah4, bh3)) | 0;
    lo = (lo + Math.imul(al3, bl4)) | 0;
    mid = (mid + Math.imul(al3, bh4)) | 0;
    mid = (mid + Math.imul(ah3, bl4)) | 0;
    hi = (hi + Math.imul(ah3, bh4)) | 0;
    lo = (lo + Math.imul(al2, bl5)) | 0;
    mid = (mid + Math.imul(al2, bh5)) | 0;
    mid = (mid + Math.imul(ah2, bl5)) | 0;
    hi = (hi + Math.imul(ah2, bh5)) | 0;
    lo = (lo + Math.imul(al1, bl6)) | 0;
    mid = (mid + Math.imul(al1, bh6)) | 0;
    mid = (mid + Math.imul(ah1, bl6)) | 0;
    hi = (hi + Math.imul(ah1, bh6)) | 0;
    lo = (lo + Math.imul(al0, bl7)) | 0;
    mid = (mid + Math.imul(al0, bh7)) | 0;
    mid = (mid + Math.imul(ah0, bl7)) | 0;
    hi = (hi + Math.imul(ah0, bh7)) | 0;
    var w7 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
    c = (((hi + (mid >>> 13)) | 0) + (w7 >>> 26)) | 0;
    w7 &= 0x3ffffff;
    /* k = 8 */
    lo = Math.imul(al8, bl0);
    mid = Math.imul(al8, bh0);
    mid = (mid + Math.imul(ah8, bl0)) | 0;
    hi = Math.imul(ah8, bh0);
    lo = (lo + Math.imul(al7, bl1)) | 0;
    mid = (mid + Math.imul(al7, bh1)) | 0;
    mid = (mid + Math.imul(ah7, bl1)) | 0;
    hi = (hi + Math.imul(ah7, bh1)) | 0;
    lo = (lo + Math.imul(al6, bl2)) | 0;
    mid = (mid + Math.imul(al6, bh2)) | 0;
    mid = (mid + Math.imul(ah6, bl2)) | 0;
    hi = (hi + Math.imul(ah6, bh2)) | 0;
    lo = (lo + Math.imul(al5, bl3)) | 0;
    mid = (mid + Math.imul(al5, bh3)) | 0;
    mid = (mid + Math.imul(ah5, bl3)) | 0;
    hi = (hi + Math.imul(ah5, bh3)) | 0;
    lo = (lo + Math.imul(al4, bl4)) | 0;
    mid = (mid + Math.imul(al4, bh4)) | 0;
    mid = (mid + Math.imul(ah4, bl4)) | 0;
    hi = (hi + Math.imul(ah4, bh4)) | 0;
    lo = (lo + Math.imul(al3, bl5)) | 0;
    mid = (mid + Math.imul(al3, bh5)) | 0;
    mid = (mid + Math.imul(ah3, bl5)) | 0;
    hi = (hi + Math.imul(ah3, bh5)) | 0;
    lo = (lo + Math.imul(al2, bl6)) | 0;
    mid = (mid + Math.imul(al2, bh6)) | 0;
    mid = (mid + Math.imul(ah2, bl6)) | 0;
    hi = (hi + Math.imul(ah2, bh6)) | 0;
    lo = (lo + Math.imul(al1, bl7)) | 0;
    mid = (mid + Math.imul(al1, bh7)) | 0;
    mid = (mid + Math.imul(ah1, bl7)) | 0;
    hi = (hi + Math.imul(ah1, bh7)) | 0;
    lo = (lo + Math.imul(al0, bl8)) | 0;
    mid = (mid + Math.imul(al0, bh8)) | 0;
    mid = (mid + Math.imul(ah0, bl8)) | 0;
    hi = (hi + Math.imul(ah0, bh8)) | 0;
    var w8 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
    c = (((hi + (mid >>> 13)) | 0) + (w8 >>> 26)) | 0;
    w8 &= 0x3ffffff;
    /* k = 9 */
    lo = Math.imul(al9, bl0);
    mid = Math.imul(al9, bh0);
    mid = (mid + Math.imul(ah9, bl0)) | 0;
    hi = Math.imul(ah9, bh0);
    lo = (lo + Math.imul(al8, bl1)) | 0;
    mid = (mid + Math.imul(al8, bh1)) | 0;
    mid = (mid + Math.imul(ah8, bl1)) | 0;
    hi = (hi + Math.imul(ah8, bh1)) | 0;
    lo = (lo + Math.imul(al7, bl2)) | 0;
    mid = (mid + Math.imul(al7, bh2)) | 0;
    mid = (mid + Math.imul(ah7, bl2)) | 0;
    hi = (hi + Math.imul(ah7, bh2)) | 0;
    lo = (lo + Math.imul(al6, bl3)) | 0;
    mid = (mid + Math.imul(al6, bh3)) | 0;
    mid = (mid + Math.imul(ah6, bl3)) | 0;
    hi = (hi + Math.imul(ah6, bh3)) | 0;
    lo = (lo + Math.imul(al5, bl4)) | 0;
    mid = (mid + Math.imul(al5, bh4)) | 0;
    mid = (mid + Math.imul(ah5, bl4)) | 0;
    hi = (hi + Math.imul(ah5, bh4)) | 0;
    lo = (lo + Math.imul(al4, bl5)) | 0;
    mid = (mid + Math.imul(al4, bh5)) | 0;
    mid = (mid + Math.imul(ah4, bl5)) | 0;
    hi = (hi + Math.imul(ah4, bh5)) | 0;
    lo = (lo + Math.imul(al3, bl6)) | 0;
    mid = (mid + Math.imul(al3, bh6)) | 0;
    mid = (mid + Math.imul(ah3, bl6)) | 0;
    hi = (hi + Math.imul(ah3, bh6)) | 0;
    lo = (lo + Math.imul(al2, bl7)) | 0;
    mid = (mid + Math.imul(al2, bh7)) | 0;
    mid = (mid + Math.imul(ah2, bl7)) | 0;
    hi = (hi + Math.imul(ah2, bh7)) | 0;
    lo = (lo + Math.imul(al1, bl8)) | 0;
    mid = (mid + Math.imul(al1, bh8)) | 0;
    mid = (mid + Math.imul(ah1, bl8)) | 0;
    hi = (hi + Math.imul(ah1, bh8)) | 0;
    lo = (lo + Math.imul(al0, bl9)) | 0;
    mid = (mid + Math.imul(al0, bh9)) | 0;
    mid = (mid + Math.imul(ah0, bl9)) | 0;
    hi = (hi + Math.imul(ah0, bh9)) | 0;
    var w9 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
    c = (((hi + (mid >>> 13)) | 0) + (w9 >>> 26)) | 0;
    w9 &= 0x3ffffff;
    /* k = 10 */
    lo = Math.imul(al9, bl1);
    mid = Math.imul(al9, bh1);
    mid = (mid + Math.imul(ah9, bl1)) | 0;
    hi = Math.imul(ah9, bh1);
    lo = (lo + Math.imul(al8, bl2)) | 0;
    mid = (mid + Math.imul(al8, bh2)) | 0;
    mid = (mid + Math.imul(ah8, bl2)) | 0;
    hi = (hi + Math.imul(ah8, bh2)) | 0;
    lo = (lo + Math.imul(al7, bl3)) | 0;
    mid = (mid + Math.imul(al7, bh3)) | 0;
    mid = (mid + Math.imul(ah7, bl3)) | 0;
    hi = (hi + Math.imul(ah7, bh3)) | 0;
    lo = (lo + Math.imul(al6, bl4)) | 0;
    mid = (mid + Math.imul(al6, bh4)) | 0;
    mid = (mid + Math.imul(ah6, bl4)) | 0;
    hi = (hi + Math.imul(ah6, bh4)) | 0;
    lo = (lo + Math.imul(al5, bl5)) | 0;
    mid = (mid + Math.imul(al5, bh5)) | 0;
    mid = (mid + Math.imul(ah5, bl5)) | 0;
    hi = (hi + Math.imul(ah5, bh5)) | 0;
    lo = (lo + Math.imul(al4, bl6)) | 0;
    mid = (mid + Math.imul(al4, bh6)) | 0;
    mid = (mid + Math.imul(ah4, bl6)) | 0;
    hi = (hi + Math.imul(ah4, bh6)) | 0;
    lo = (lo + Math.imul(al3, bl7)) | 0;
    mid = (mid + Math.imul(al3, bh7)) | 0;
    mid = (mid + Math.imul(ah3, bl7)) | 0;
    hi = (hi + Math.imul(ah3, bh7)) | 0;
    lo = (lo + Math.imul(al2, bl8)) | 0;
    mid = (mid + Math.imul(al2, bh8)) | 0;
    mid = (mid + Math.imul(ah2, bl8)) | 0;
    hi = (hi + Math.imul(ah2, bh8)) | 0;
    lo = (lo + Math.imul(al1, bl9)) | 0;
    mid = (mid + Math.imul(al1, bh9)) | 0;
    mid = (mid + Math.imul(ah1, bl9)) | 0;
    hi = (hi + Math.imul(ah1, bh9)) | 0;
    var w10 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
    c = (((hi + (mid >>> 13)) | 0) + (w10 >>> 26)) | 0;
    w10 &= 0x3ffffff;
    /* k = 11 */
    lo = Math.imul(al9, bl2);
    mid = Math.imul(al9, bh2);
    mid = (mid + Math.imul(ah9, bl2)) | 0;
    hi = Math.imul(ah9, bh2);
    lo = (lo + Math.imul(al8, bl3)) | 0;
    mid = (mid + Math.imul(al8, bh3)) | 0;
    mid = (mid + Math.imul(ah8, bl3)) | 0;
    hi = (hi + Math.imul(ah8, bh3)) | 0;
    lo = (lo + Math.imul(al7, bl4)) | 0;
    mid = (mid + Math.imul(al7, bh4)) | 0;
    mid = (mid + Math.imul(ah7, bl4)) | 0;
    hi = (hi + Math.imul(ah7, bh4)) | 0;
    lo = (lo + Math.imul(al6, bl5)) | 0;
    mid = (mid + Math.imul(al6, bh5)) | 0;
    mid = (mid + Math.imul(ah6, bl5)) | 0;
    hi = (hi + Math.imul(ah6, bh5)) | 0;
    lo = (lo + Math.imul(al5, bl6)) | 0;
    mid = (mid + Math.imul(al5, bh6)) | 0;
    mid = (mid + Math.imul(ah5, bl6)) | 0;
    hi = (hi + Math.imul(ah5, bh6)) | 0;
    lo = (lo + Math.imul(al4, bl7)) | 0;
    mid = (mid + Math.imul(al4, bh7)) | 0;
    mid = (mid + Math.imul(ah4, bl7)) | 0;
    hi = (hi + Math.imul(ah4, bh7)) | 0;
    lo = (lo + Math.imul(al3, bl8)) | 0;
    mid = (mid + Math.imul(al3, bh8)) | 0;
    mid = (mid + Math.imul(ah3, bl8)) | 0;
    hi = (hi + Math.imul(ah3, bh8)) | 0;
    lo = (lo + Math.imul(al2, bl9)) | 0;
    mid = (mid + Math.imul(al2, bh9)) | 0;
    mid = (mid + Math.imul(ah2, bl9)) | 0;
    hi = (hi + Math.imul(ah2, bh9)) | 0;
    var w11 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
    c = (((hi + (mid >>> 13)) | 0) + (w11 >>> 26)) | 0;
    w11 &= 0x3ffffff;
    /* k = 12 */
    lo = Math.imul(al9, bl3);
    mid = Math.imul(al9, bh3);
    mid = (mid + Math.imul(ah9, bl3)) | 0;
    hi = Math.imul(ah9, bh3);
    lo = (lo + Math.imul(al8, bl4)) | 0;
    mid = (mid + Math.imul(al8, bh4)) | 0;
    mid = (mid + Math.imul(ah8, bl4)) | 0;
    hi = (hi + Math.imul(ah8, bh4)) | 0;
    lo = (lo + Math.imul(al7, bl5)) | 0;
    mid = (mid + Math.imul(al7, bh5)) | 0;
    mid = (mid + Math.imul(ah7, bl5)) | 0;
    hi = (hi + Math.imul(ah7, bh5)) | 0;
    lo = (lo + Math.imul(al6, bl6)) | 0;
    mid = (mid + Math.imul(al6, bh6)) | 0;
    mid = (mid + Math.imul(ah6, bl6)) | 0;
    hi = (hi + Math.imul(ah6, bh6)) | 0;
    lo = (lo + Math.imul(al5, bl7)) | 0;
    mid = (mid + Math.imul(al5, bh7)) | 0;
    mid = (mid + Math.imul(ah5, bl7)) | 0;
    hi = (hi + Math.imul(ah5, bh7)) | 0;
    lo = (lo + Math.imul(al4, bl8)) | 0;
    mid = (mid + Math.imul(al4, bh8)) | 0;
    mid = (mid + Math.imul(ah4, bl8)) | 0;
    hi = (hi + Math.imul(ah4, bh8)) | 0;
    lo = (lo + Math.imul(al3, bl9)) | 0;
    mid = (mid + Math.imul(al3, bh9)) | 0;
    mid = (mid + Math.imul(ah3, bl9)) | 0;
    hi = (hi + Math.imul(ah3, bh9)) | 0;
    var w12 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
    c = (((hi + (mid >>> 13)) | 0) + (w12 >>> 26)) | 0;
    w12 &= 0x3ffffff;
    /* k = 13 */
    lo = Math.imul(al9, bl4);
    mid = Math.imul(al9, bh4);
    mid = (mid + Math.imul(ah9, bl4)) | 0;
    hi = Math.imul(ah9, bh4);
    lo = (lo + Math.imul(al8, bl5)) | 0;
    mid = (mid + Math.imul(al8, bh5)) | 0;
    mid = (mid + Math.imul(ah8, bl5)) | 0;
    hi = (hi + Math.imul(ah8, bh5)) | 0;
    lo = (lo + Math.imul(al7, bl6)) | 0;
    mid = (mid + Math.imul(al7, bh6)) | 0;
    mid = (mid + Math.imul(ah7, bl6)) | 0;
    hi = (hi + Math.imul(ah7, bh6)) | 0;
    lo = (lo + Math.imul(al6, bl7)) | 0;
    mid = (mid + Math.imul(al6, bh7)) | 0;
    mid = (mid + Math.imul(ah6, bl7)) | 0;
    hi = (hi + Math.imul(ah6, bh7)) | 0;
    lo = (lo + Math.imul(al5, bl8)) | 0;
    mid = (mid + Math.imul(al5, bh8)) | 0;
    mid = (mid + Math.imul(ah5, bl8)) | 0;
    hi = (hi + Math.imul(ah5, bh8)) | 0;
    lo = (lo + Math.imul(al4, bl9)) | 0;
    mid = (mid + Math.imul(al4, bh9)) | 0;
    mid = (mid + Math.imul(ah4, bl9)) | 0;
    hi = (hi + Math.imul(ah4, bh9)) | 0;
    var w13 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
    c = (((hi + (mid >>> 13)) | 0) + (w13 >>> 26)) | 0;
    w13 &= 0x3ffffff;
    /* k = 14 */
    lo = Math.imul(al9, bl5);
    mid = Math.imul(al9, bh5);
    mid = (mid + Math.imul(ah9, bl5)) | 0;
    hi = Math.imul(ah9, bh5);
    lo = (lo + Math.imul(al8, bl6)) | 0;
    mid = (mid + Math.imul(al8, bh6)) | 0;
    mid = (mid + Math.imul(ah8, bl6)) | 0;
    hi = (hi + Math.imul(ah8, bh6)) | 0;
    lo = (lo + Math.imul(al7, bl7)) | 0;
    mid = (mid + Math.imul(al7, bh7)) | 0;
    mid = (mid + Math.imul(ah7, bl7)) | 0;
    hi = (hi + Math.imul(ah7, bh7)) | 0;
    lo = (lo + Math.imul(al6, bl8)) | 0;
    mid = (mid + Math.imul(al6, bh8)) | 0;
    mid = (mid + Math.imul(ah6, bl8)) | 0;
    hi = (hi + Math.imul(ah6, bh8)) | 0;
    lo = (lo + Math.imul(al5, bl9)) | 0;
    mid = (mid + Math.imul(al5, bh9)) | 0;
    mid = (mid + Math.imul(ah5, bl9)) | 0;
    hi = (hi + Math.imul(ah5, bh9)) | 0;
    var w14 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
    c = (((hi + (mid >>> 13)) | 0) + (w14 >>> 26)) | 0;
    w14 &= 0x3ffffff;
    /* k = 15 */
    lo = Math.imul(al9, bl6);
    mid = Math.imul(al9, bh6);
    mid = (mid + Math.imul(ah9, bl6)) | 0;
    hi = Math.imul(ah9, bh6);
    lo = (lo + Math.imul(al8, bl7)) | 0;
    mid = (mid + Math.imul(al8, bh7)) | 0;
    mid = (mid + Math.imul(ah8, bl7)) | 0;
    hi = (hi + Math.imul(ah8, bh7)) | 0;
    lo = (lo + Math.imul(al7, bl8)) | 0;
    mid = (mid + Math.imul(al7, bh8)) | 0;
    mid = (mid + Math.imul(ah7, bl8)) | 0;
    hi = (hi + Math.imul(ah7, bh8)) | 0;
    lo = (lo + Math.imul(al6, bl9)) | 0;
    mid = (mid + Math.imul(al6, bh9)) | 0;
    mid = (mid + Math.imul(ah6, bl9)) | 0;
    hi = (hi + Math.imul(ah6, bh9)) | 0;
    var w15 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
    c = (((hi + (mid >>> 13)) | 0) + (w15 >>> 26)) | 0;
    w15 &= 0x3ffffff;
    /* k = 16 */
    lo = Math.imul(al9, bl7);
    mid = Math.imul(al9, bh7);
    mid = (mid + Math.imul(ah9, bl7)) | 0;
    hi = Math.imul(ah9, bh7);
    lo = (lo + Math.imul(al8, bl8)) | 0;
    mid = (mid + Math.imul(al8, bh8)) | 0;
    mid = (mid + Math.imul(ah8, bl8)) | 0;
    hi = (hi + Math.imul(ah8, bh8)) | 0;
    lo = (lo + Math.imul(al7, bl9)) | 0;
    mid = (mid + Math.imul(al7, bh9)) | 0;
    mid = (mid + Math.imul(ah7, bl9)) | 0;
    hi = (hi + Math.imul(ah7, bh9)) | 0;
    var w16 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
    c = (((hi + (mid >>> 13)) | 0) + (w16 >>> 26)) | 0;
    w16 &= 0x3ffffff;
    /* k = 17 */
    lo = Math.imul(al9, bl8);
    mid = Math.imul(al9, bh8);
    mid = (mid + Math.imul(ah9, bl8)) | 0;
    hi = Math.imul(ah9, bh8);
    lo = (lo + Math.imul(al8, bl9)) | 0;
    mid = (mid + Math.imul(al8, bh9)) | 0;
    mid = (mid + Math.imul(ah8, bl9)) | 0;
    hi = (hi + Math.imul(ah8, bh9)) | 0;
    var w17 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
    c = (((hi + (mid >>> 13)) | 0) + (w17 >>> 26)) | 0;
    w17 &= 0x3ffffff;
    /* k = 18 */
    lo = Math.imul(al9, bl9);
    mid = Math.imul(al9, bh9);
    mid = (mid + Math.imul(ah9, bl9)) | 0;
    hi = Math.imul(ah9, bh9);
    var w18 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
    c = (((hi + (mid >>> 13)) | 0) + (w18 >>> 26)) | 0;
    w18 &= 0x3ffffff;
    o[0] = w0;
    o[1] = w1;
    o[2] = w2;
    o[3] = w3;
    o[4] = w4;
    o[5] = w5;
    o[6] = w6;
    o[7] = w7;
    o[8] = w8;
    o[9] = w9;
    o[10] = w10;
    o[11] = w11;
    o[12] = w12;
    o[13] = w13;
    o[14] = w14;
    o[15] = w15;
    o[16] = w16;
    o[17] = w17;
    o[18] = w18;
    if (c !== 0) {
      o[19] = c;
      out.length++;
    }
    return out;
  };

  // Polyfill comb
  if (!Math.imul) {
    comb10MulTo = smallMulTo;
  }

  function bigMulTo (self, num, out) {
    out.negative = num.negative ^ self.negative;
    out.length = self.length + num.length;

    var carry = 0;
    var hncarry = 0;
    for (var k = 0; k < out.length - 1; k++) {
      // Sum all words with the same `i + j = k` and accumulate `ncarry`,
      // note that ncarry could be >= 0x3ffffff
      var ncarry = hncarry;
      hncarry = 0;
      var rword = carry & 0x3ffffff;
      var maxJ = Math.min(k, num.length - 1);
      for (var j = Math.max(0, k - self.length + 1); j <= maxJ; j++) {
        var i = k - j;
        var a = self.words[i] | 0;
        var b = num.words[j] | 0;
        var r = a * b;

        var lo = r & 0x3ffffff;
        ncarry = (ncarry + ((r / 0x4000000) | 0)) | 0;
        lo = (lo + rword) | 0;
        rword = lo & 0x3ffffff;
        ncarry = (ncarry + (lo >>> 26)) | 0;

        hncarry += ncarry >>> 26;
        ncarry &= 0x3ffffff;
      }
      out.words[k] = rword;
      carry = ncarry;
      ncarry = hncarry;
    }
    if (carry !== 0) {
      out.words[k] = carry;
    } else {
      out.length--;
    }

    return out.strip();
  }

  function jumboMulTo (self, num, out) {
    var fftm = new FFTM();
    return fftm.mulp(self, num, out);
  }

  BN.prototype.mulTo = function mulTo (num, out) {
    var res;
    var len = this.length + num.length;
    if (this.length === 10 && num.length === 10) {
      res = comb10MulTo(this, num, out);
    } else if (len < 63) {
      res = smallMulTo(this, num, out);
    } else if (len < 1024) {
      res = bigMulTo(this, num, out);
    } else {
      res = jumboMulTo(this, num, out);
    }

    return res;
  };

  // Cooley-Tukey algorithm for FFT
  // slightly revisited to rely on looping instead of recursion

  function FFTM (x, y) {
    this.x = x;
    this.y = y;
  }

  FFTM.prototype.makeRBT = function makeRBT (N) {
    var t = new Array(N);
    var l = BN.prototype._countBits(N) - 1;
    for (var i = 0; i < N; i++) {
      t[i] = this.revBin(i, l, N);
    }

    return t;
  };

  // Returns binary-reversed representation of `x`
  FFTM.prototype.revBin = function revBin (x, l, N) {
    if (x === 0 || x === N - 1) return x;

    var rb = 0;
    for (var i = 0; i < l; i++) {
      rb |= (x & 1) << (l - i - 1);
      x >>= 1;
    }

    return rb;
  };

  // Performs "tweedling" phase, therefore 'emulating'
  // behaviour of the recursive algorithm
  FFTM.prototype.permute = function permute (rbt, rws, iws, rtws, itws, N) {
    for (var i = 0; i < N; i++) {
      rtws[i] = rws[rbt[i]];
      itws[i] = iws[rbt[i]];
    }
  };

  FFTM.prototype.transform = function transform (rws, iws, rtws, itws, N, rbt) {
    this.permute(rbt, rws, iws, rtws, itws, N);

    for (var s = 1; s < N; s <<= 1) {
      var l = s << 1;

      var rtwdf = Math.cos(2 * Math.PI / l);
      var itwdf = Math.sin(2 * Math.PI / l);

      for (var p = 0; p < N; p += l) {
        var rtwdf_ = rtwdf;
        var itwdf_ = itwdf;

        for (var j = 0; j < s; j++) {
          var re = rtws[p + j];
          var ie = itws[p + j];

          var ro = rtws[p + j + s];
          var io = itws[p + j + s];

          var rx = rtwdf_ * ro - itwdf_ * io;

          io = rtwdf_ * io + itwdf_ * ro;
          ro = rx;

          rtws[p + j] = re + ro;
          itws[p + j] = ie + io;

          rtws[p + j + s] = re - ro;
          itws[p + j + s] = ie - io;

          /* jshint maxdepth : false */
          if (j !== l) {
            rx = rtwdf * rtwdf_ - itwdf * itwdf_;

            itwdf_ = rtwdf * itwdf_ + itwdf * rtwdf_;
            rtwdf_ = rx;
          }
        }
      }
    }
  };

  FFTM.prototype.guessLen13b = function guessLen13b (n, m) {
    var N = Math.max(m, n) | 1;
    var odd = N & 1;
    var i = 0;
    for (N = N / 2 | 0; N; N = N >>> 1) {
      i++;
    }

    return 1 << i + 1 + odd;
  };

  FFTM.prototype.conjugate = function conjugate (rws, iws, N) {
    if (N <= 1) return;

    for (var i = 0; i < N / 2; i++) {
      var t = rws[i];

      rws[i] = rws[N - i - 1];
      rws[N - i - 1] = t;

      t = iws[i];

      iws[i] = -iws[N - i - 1];
      iws[N - i - 1] = -t;
    }
  };

  FFTM.prototype.normalize13b = function normalize13b (ws, N) {
    var carry = 0;
    for (var i = 0; i < N / 2; i++) {
      var w = Math.round(ws[2 * i + 1] / N) * 0x2000 +
        Math.round(ws[2 * i] / N) +
        carry;

      ws[i] = w & 0x3ffffff;

      if (w < 0x4000000) {
        carry = 0;
      } else {
        carry = w / 0x4000000 | 0;
      }
    }

    return ws;
  };

  FFTM.prototype.convert13b = function convert13b (ws, len, rws, N) {
    var carry = 0;
    for (var i = 0; i < len; i++) {
      carry = carry + (ws[i] | 0);

      rws[2 * i] = carry & 0x1fff; carry = carry >>> 13;
      rws[2 * i + 1] = carry & 0x1fff; carry = carry >>> 13;
    }

    // Pad with zeroes
    for (i = 2 * len; i < N; ++i) {
      rws[i] = 0;
    }

    assert(carry === 0);
    assert((carry & ~0x1fff) === 0);
  };

  FFTM.prototype.stub = function stub (N) {
    var ph = new Array(N);
    for (var i = 0; i < N; i++) {
      ph[i] = 0;
    }

    return ph;
  };

  FFTM.prototype.mulp = function mulp (x, y, out) {
    var N = 2 * this.guessLen13b(x.length, y.length);

    var rbt = this.makeRBT(N);

    var _ = this.stub(N);

    var rws = new Array(N);
    var rwst = new Array(N);
    var iwst = new Array(N);

    var nrws = new Array(N);
    var nrwst = new Array(N);
    var niwst = new Array(N);

    var rmws = out.words;
    rmws.length = N;

    this.convert13b(x.words, x.length, rws, N);
    this.convert13b(y.words, y.length, nrws, N);

    this.transform(rws, _, rwst, iwst, N, rbt);
    this.transform(nrws, _, nrwst, niwst, N, rbt);

    for (var i = 0; i < N; i++) {
      var rx = rwst[i] * nrwst[i] - iwst[i] * niwst[i];
      iwst[i] = rwst[i] * niwst[i] + iwst[i] * nrwst[i];
      rwst[i] = rx;
    }

    this.conjugate(rwst, iwst, N);
    this.transform(rwst, iwst, rmws, _, N, rbt);
    this.conjugate(rmws, _, N);
    this.normalize13b(rmws, N);

    out.negative = x.negative ^ y.negative;
    out.length = x.length + y.length;
    return out.strip();
  };

  // Multiply `this` by `num`
  BN.prototype.mul = function mul (num) {
    var out = new BN(null);
    out.words = new Array(this.length + num.length);
    return this.mulTo(num, out);
  };

  // Multiply employing FFT
  BN.prototype.mulf = function mulf (num) {
    var out = new BN(null);
    out.words = new Array(this.length + num.length);
    return jumboMulTo(this, num, out);
  };

  // In-place Multiplication
  BN.prototype.imul = function imul (num) {
    return this.clone().mulTo(num, this);
  };

  BN.prototype.imuln = function imuln (num) {
    assert(typeof num === 'number');
    assert(num < 0x4000000);

    // Carry
    var carry = 0;
    for (var i = 0; i < this.length; i++) {
      var w = (this.words[i] | 0) * num;
      var lo = (w & 0x3ffffff) + (carry & 0x3ffffff);
      carry >>= 26;
      carry += (w / 0x4000000) | 0;
      // NOTE: lo is 27bit maximum
      carry += lo >>> 26;
      this.words[i] = lo & 0x3ffffff;
    }

    if (carry !== 0) {
      this.words[i] = carry;
      this.length++;
    }

    return this;
  };

  BN.prototype.muln = function muln (num) {
    return this.clone().imuln(num);
  };

  // `this` * `this`
  BN.prototype.sqr = function sqr () {
    return this.mul(this);
  };

  // `this` * `this` in-place
  BN.prototype.isqr = function isqr () {
    return this.imul(this.clone());
  };

  // Math.pow(`this`, `num`)
  BN.prototype.pow = function pow (num) {
    var w = toBitArray(num);
    if (w.length === 0) return new BN(1);

    // Skip leading zeroes
    var res = this;
    for (var i = 0; i < w.length; i++, res = res.sqr()) {
      if (w[i] !== 0) break;
    }

    if (++i < w.length) {
      for (var q = res.sqr(); i < w.length; i++, q = q.sqr()) {
        if (w[i] === 0) continue;

        res = res.mul(q);
      }
    }

    return res;
  };

  // Shift-left in-place
  BN.prototype.iushln = function iushln (bits) {
    assert(typeof bits === 'number' && bits >= 0);
    var r = bits % 26;
    var s = (bits - r) / 26;
    var carryMask = (0x3ffffff >>> (26 - r)) << (26 - r);
    var i;

    if (r !== 0) {
      var carry = 0;

      for (i = 0; i < this.length; i++) {
        var newCarry = this.words[i] & carryMask;
        var c = ((this.words[i] | 0) - newCarry) << r;
        this.words[i] = c | carry;
        carry = newCarry >>> (26 - r);
      }

      if (carry) {
        this.words[i] = carry;
        this.length++;
      }
    }

    if (s !== 0) {
      for (i = this.length - 1; i >= 0; i--) {
        this.words[i + s] = this.words[i];
      }

      for (i = 0; i < s; i++) {
        this.words[i] = 0;
      }

      this.length += s;
    }

    return this.strip();
  };

  BN.prototype.ishln = function ishln (bits) {
    // TODO(indutny): implement me
    assert(this.negative === 0);
    return this.iushln(bits);
  };

  // Shift-right in-place
  // NOTE: `hint` is a lowest bit before trailing zeroes
  // NOTE: if `extended` is present - it will be filled with destroyed bits
  BN.prototype.iushrn = function iushrn (bits, hint, extended) {
    assert(typeof bits === 'number' && bits >= 0);
    var h;
    if (hint) {
      h = (hint - (hint % 26)) / 26;
    } else {
      h = 0;
    }

    var r = bits % 26;
    var s = Math.min((bits - r) / 26, this.length);
    var mask = 0x3ffffff ^ ((0x3ffffff >>> r) << r);
    var maskedWords = extended;

    h -= s;
    h = Math.max(0, h);

    // Extended mode, copy masked part
    if (maskedWords) {
      for (var i = 0; i < s; i++) {
        maskedWords.words[i] = this.words[i];
      }
      maskedWords.length = s;
    }

    if (s === 0) {
      // No-op, we should not move anything at all
    } else if (this.length > s) {
      this.length -= s;
      for (i = 0; i < this.length; i++) {
        this.words[i] = this.words[i + s];
      }
    } else {
      this.words[0] = 0;
      this.length = 1;
    }

    var carry = 0;
    for (i = this.length - 1; i >= 0 && (carry !== 0 || i >= h); i--) {
      var word = this.words[i] | 0;
      this.words[i] = (carry << (26 - r)) | (word >>> r);
      carry = word & mask;
    }

    // Push carried bits as a mask
    if (maskedWords && carry !== 0) {
      maskedWords.words[maskedWords.length++] = carry;
    }

    if (this.length === 0) {
      this.words[0] = 0;
      this.length = 1;
    }

    return this.strip();
  };

  BN.prototype.ishrn = function ishrn (bits, hint, extended) {
    // TODO(indutny): implement me
    assert(this.negative === 0);
    return this.iushrn(bits, hint, extended);
  };

  // Shift-left
  BN.prototype.shln = function shln (bits) {
    return this.clone().ishln(bits);
  };

  BN.prototype.ushln = function ushln (bits) {
    return this.clone().iushln(bits);
  };

  // Shift-right
  BN.prototype.shrn = function shrn (bits) {
    return this.clone().ishrn(bits);
  };

  BN.prototype.ushrn = function ushrn (bits) {
    return this.clone().iushrn(bits);
  };

  // Test if n bit is set
  BN.prototype.testn = function testn (bit) {
    assert(typeof bit === 'number' && bit >= 0);
    var r = bit % 26;
    var s = (bit - r) / 26;
    var q = 1 << r;

    // Fast case: bit is much higher than all existing words
    if (this.length <= s) return false;

    // Check bit and return
    var w = this.words[s];

    return !!(w & q);
  };

  // Return only lowers bits of number (in-place)
  BN.prototype.imaskn = function imaskn (bits) {
    assert(typeof bits === 'number' && bits >= 0);
    var r = bits % 26;
    var s = (bits - r) / 26;

    assert(this.negative === 0, 'imaskn works only with positive numbers');

    if (this.length <= s) {
      return this;
    }

    if (r !== 0) {
      s++;
    }
    this.length = Math.min(s, this.length);

    if (r !== 0) {
      var mask = 0x3ffffff ^ ((0x3ffffff >>> r) << r);
      this.words[this.length - 1] &= mask;
    }

    return this.strip();
  };

  // Return only lowers bits of number
  BN.prototype.maskn = function maskn (bits) {
    return this.clone().imaskn(bits);
  };

  // Add plain number `num` to `this`
  BN.prototype.iaddn = function iaddn (num) {
    assert(typeof num === 'number');
    assert(num < 0x4000000);
    if (num < 0) return this.isubn(-num);

    // Possible sign change
    if (this.negative !== 0) {
      if (this.length === 1 && (this.words[0] | 0) < num) {
        this.words[0] = num - (this.words[0] | 0);
        this.negative = 0;
        return this;
      }

      this.negative = 0;
      this.isubn(num);
      this.negative = 1;
      return this;
    }

    // Add without checks
    return this._iaddn(num);
  };

  BN.prototype._iaddn = function _iaddn (num) {
    this.words[0] += num;

    // Carry
    for (var i = 0; i < this.length && this.words[i] >= 0x4000000; i++) {
      this.words[i] -= 0x4000000;
      if (i === this.length - 1) {
        this.words[i + 1] = 1;
      } else {
        this.words[i + 1]++;
      }
    }
    this.length = Math.max(this.length, i + 1);

    return this;
  };

  // Subtract plain number `num` from `this`
  BN.prototype.isubn = function isubn (num) {
    assert(typeof num === 'number');
    assert(num < 0x4000000);
    if (num < 0) return this.iaddn(-num);

    if (this.negative !== 0) {
      this.negative = 0;
      this.iaddn(num);
      this.negative = 1;
      return this;
    }

    this.words[0] -= num;

    if (this.length === 1 && this.words[0] < 0) {
      this.words[0] = -this.words[0];
      this.negative = 1;
    } else {
      // Carry
      for (var i = 0; i < this.length && this.words[i] < 0; i++) {
        this.words[i] += 0x4000000;
        this.words[i + 1] -= 1;
      }
    }

    return this.strip();
  };

  BN.prototype.addn = function addn (num) {
    return this.clone().iaddn(num);
  };

  BN.prototype.subn = function subn (num) {
    return this.clone().isubn(num);
  };

  BN.prototype.iabs = function iabs () {
    this.negative = 0;

    return this;
  };

  BN.prototype.abs = function abs () {
    return this.clone().iabs();
  };

  BN.prototype._ishlnsubmul = function _ishlnsubmul (num, mul, shift) {
    var len = num.length + shift;
    var i;

    this._expand(len);

    var w;
    var carry = 0;
    for (i = 0; i < num.length; i++) {
      w = (this.words[i + shift] | 0) + carry;
      var right = (num.words[i] | 0) * mul;
      w -= right & 0x3ffffff;
      carry = (w >> 26) - ((right / 0x4000000) | 0);
      this.words[i + shift] = w & 0x3ffffff;
    }
    for (; i < this.length - shift; i++) {
      w = (this.words[i + shift] | 0) + carry;
      carry = w >> 26;
      this.words[i + shift] = w & 0x3ffffff;
    }

    if (carry === 0) return this.strip();

    // Subtraction overflow
    assert(carry === -1);
    carry = 0;
    for (i = 0; i < this.length; i++) {
      w = -(this.words[i] | 0) + carry;
      carry = w >> 26;
      this.words[i] = w & 0x3ffffff;
    }
    this.negative = 1;

    return this.strip();
  };

  BN.prototype._wordDiv = function _wordDiv (num, mode) {
    var shift = this.length - num.length;

    var a = this.clone();
    var b = num;

    // Normalize
    var bhi = b.words[b.length - 1] | 0;
    var bhiBits = this._countBits(bhi);
    shift = 26 - bhiBits;
    if (shift !== 0) {
      b = b.ushln(shift);
      a.iushln(shift);
      bhi = b.words[b.length - 1] | 0;
    }

    // Initialize quotient
    var m = a.length - b.length;
    var q;

    if (mode !== 'mod') {
      q = new BN(null);
      q.length = m + 1;
      q.words = new Array(q.length);
      for (var i = 0; i < q.length; i++) {
        q.words[i] = 0;
      }
    }

    var diff = a.clone()._ishlnsubmul(b, 1, m);
    if (diff.negative === 0) {
      a = diff;
      if (q) {
        q.words[m] = 1;
      }
    }

    for (var j = m - 1; j >= 0; j--) {
      var qj = (a.words[b.length + j] | 0) * 0x4000000 +
        (a.words[b.length + j - 1] | 0);

      // NOTE: (qj / bhi) is (0x3ffffff * 0x4000000 + 0x3ffffff) / 0x2000000 max
      // (0x7ffffff)
      qj = Math.min((qj / bhi) | 0, 0x3ffffff);

      a._ishlnsubmul(b, qj, j);
      while (a.negative !== 0) {
        qj--;
        a.negative = 0;
        a._ishlnsubmul(b, 1, j);
        if (!a.isZero()) {
          a.negative ^= 1;
        }
      }
      if (q) {
        q.words[j] = qj;
      }
    }
    if (q) {
      q.strip();
    }
    a.strip();

    // Denormalize
    if (mode !== 'div' && shift !== 0) {
      a.iushrn(shift);
    }

    return {
      div: q || null,
      mod: a
    };
  };

  // NOTE: 1) `mode` can be set to `mod` to request mod only,
  //       to `div` to request div only, or be absent to
  //       request both div & mod
  //       2) `positive` is true if unsigned mod is requested
  BN.prototype.divmod = function divmod (num, mode, positive) {
    assert(!num.isZero());

    if (this.isZero()) {
      return {
        div: new BN(0),
        mod: new BN(0)
      };
    }

    var div, mod, res;
    if (this.negative !== 0 && num.negative === 0) {
      res = this.neg().divmod(num, mode);

      if (mode !== 'mod') {
        div = res.div.neg();
      }

      if (mode !== 'div') {
        mod = res.mod.neg();
        if (positive && mod.negative !== 0) {
          mod.iadd(num);
        }
      }

      return {
        div: div,
        mod: mod
      };
    }

    if (this.negative === 0 && num.negative !== 0) {
      res = this.divmod(num.neg(), mode);

      if (mode !== 'mod') {
        div = res.div.neg();
      }

      return {
        div: div,
        mod: res.mod
      };
    }

    if ((this.negative & num.negative) !== 0) {
      res = this.neg().divmod(num.neg(), mode);

      if (mode !== 'div') {
        mod = res.mod.neg();
        if (positive && mod.negative !== 0) {
          mod.isub(num);
        }
      }

      return {
        div: res.div,
        mod: mod
      };
    }

    // Both numbers are positive at this point

    // Strip both numbers to approximate shift value
    if (num.length > this.length || this.cmp(num) < 0) {
      return {
        div: new BN(0),
        mod: this
      };
    }

    // Very short reduction
    if (num.length === 1) {
      if (mode === 'div') {
        return {
          div: this.divn(num.words[0]),
          mod: null
        };
      }

      if (mode === 'mod') {
        return {
          div: null,
          mod: new BN(this.modn(num.words[0]))
        };
      }

      return {
        div: this.divn(num.words[0]),
        mod: new BN(this.modn(num.words[0]))
      };
    }

    return this._wordDiv(num, mode);
  };

  // Find `this` / `num`
  BN.prototype.div = function div (num) {
    return this.divmod(num, 'div', false).div;
  };

  // Find `this` % `num`
  BN.prototype.mod = function mod (num) {
    return this.divmod(num, 'mod', false).mod;
  };

  BN.prototype.umod = function umod (num) {
    return this.divmod(num, 'mod', true).mod;
  };

  // Find Round(`this` / `num`)
  BN.prototype.divRound = function divRound (num) {
    var dm = this.divmod(num);

    // Fast case - exact division
    if (dm.mod.isZero()) return dm.div;

    var mod = dm.div.negative !== 0 ? dm.mod.isub(num) : dm.mod;

    var half = num.ushrn(1);
    var r2 = num.andln(1);
    var cmp = mod.cmp(half);

    // Round down
    if (cmp < 0 || r2 === 1 && cmp === 0) return dm.div;

    // Round up
    return dm.div.negative !== 0 ? dm.div.isubn(1) : dm.div.iaddn(1);
  };

  BN.prototype.modn = function modn (num) {
    assert(num <= 0x3ffffff);
    var p = (1 << 26) % num;

    var acc = 0;
    for (var i = this.length - 1; i >= 0; i--) {
      acc = (p * acc + (this.words[i] | 0)) % num;
    }

    return acc;
  };

  // In-place division by number
  BN.prototype.idivn = function idivn (num) {
    assert(num <= 0x3ffffff);

    var carry = 0;
    for (var i = this.length - 1; i >= 0; i--) {
      var w = (this.words[i] | 0) + carry * 0x4000000;
      this.words[i] = (w / num) | 0;
      carry = w % num;
    }

    return this.strip();
  };

  BN.prototype.divn = function divn (num) {
    return this.clone().idivn(num);
  };

  BN.prototype.egcd = function egcd (p) {
    assert(p.negative === 0);
    assert(!p.isZero());

    var x = this;
    var y = p.clone();

    if (x.negative !== 0) {
      x = x.umod(p);
    } else {
      x = x.clone();
    }

    // A * x + B * y = x
    var A = new BN(1);
    var B = new BN(0);

    // C * x + D * y = y
    var C = new BN(0);
    var D = new BN(1);

    var g = 0;

    while (x.isEven() && y.isEven()) {
      x.iushrn(1);
      y.iushrn(1);
      ++g;
    }

    var yp = y.clone();
    var xp = x.clone();

    while (!x.isZero()) {
      for (var i = 0, im = 1; (x.words[0] & im) === 0 && i < 26; ++i, im <<= 1);
      if (i > 0) {
        x.iushrn(i);
        while (i-- > 0) {
          if (A.isOdd() || B.isOdd()) {
            A.iadd(yp);
            B.isub(xp);
          }

          A.iushrn(1);
          B.iushrn(1);
        }
      }

      for (var j = 0, jm = 1; (y.words[0] & jm) === 0 && j < 26; ++j, jm <<= 1);
      if (j > 0) {
        y.iushrn(j);
        while (j-- > 0) {
          if (C.isOdd() || D.isOdd()) {
            C.iadd(yp);
            D.isub(xp);
          }

          C.iushrn(1);
          D.iushrn(1);
        }
      }

      if (x.cmp(y) >= 0) {
        x.isub(y);
        A.isub(C);
        B.isub(D);
      } else {
        y.isub(x);
        C.isub(A);
        D.isub(B);
      }
    }

    return {
      a: C,
      b: D,
      gcd: y.iushln(g)
    };
  };

  // This is reduced incarnation of the binary EEA
  // above, designated to invert members of the
  // _prime_ fields F(p) at a maximal speed
  BN.prototype._invmp = function _invmp (p) {
    assert(p.negative === 0);
    assert(!p.isZero());

    var a = this;
    var b = p.clone();

    if (a.negative !== 0) {
      a = a.umod(p);
    } else {
      a = a.clone();
    }

    var x1 = new BN(1);
    var x2 = new BN(0);

    var delta = b.clone();

    while (a.cmpn(1) > 0 && b.cmpn(1) > 0) {
      for (var i = 0, im = 1; (a.words[0] & im) === 0 && i < 26; ++i, im <<= 1);
      if (i > 0) {
        a.iushrn(i);
        while (i-- > 0) {
          if (x1.isOdd()) {
            x1.iadd(delta);
          }

          x1.iushrn(1);
        }
      }

      for (var j = 0, jm = 1; (b.words[0] & jm) === 0 && j < 26; ++j, jm <<= 1);
      if (j > 0) {
        b.iushrn(j);
        while (j-- > 0) {
          if (x2.isOdd()) {
            x2.iadd(delta);
          }

          x2.iushrn(1);
        }
      }

      if (a.cmp(b) >= 0) {
        a.isub(b);
        x1.isub(x2);
      } else {
        b.isub(a);
        x2.isub(x1);
      }
    }

    var res;
    if (a.cmpn(1) === 0) {
      res = x1;
    } else {
      res = x2;
    }

    if (res.cmpn(0) < 0) {
      res.iadd(p);
    }

    return res;
  };

  BN.prototype.gcd = function gcd (num) {
    if (this.isZero()) return num.abs();
    if (num.isZero()) return this.abs();

    var a = this.clone();
    var b = num.clone();
    a.negative = 0;
    b.negative = 0;

    // Remove common factor of two
    for (var shift = 0; a.isEven() && b.isEven(); shift++) {
      a.iushrn(1);
      b.iushrn(1);
    }

    do {
      while (a.isEven()) {
        a.iushrn(1);
      }
      while (b.isEven()) {
        b.iushrn(1);
      }

      var r = a.cmp(b);
      if (r < 0) {
        // Swap `a` and `b` to make `a` always bigger than `b`
        var t = a;
        a = b;
        b = t;
      } else if (r === 0 || b.cmpn(1) === 0) {
        break;
      }

      a.isub(b);
    } while (true);

    return b.iushln(shift);
  };

  // Invert number in the field F(num)
  BN.prototype.invm = function invm (num) {
    return this.egcd(num).a.umod(num);
  };

  BN.prototype.isEven = function isEven () {
    return (this.words[0] & 1) === 0;
  };

  BN.prototype.isOdd = function isOdd () {
    return (this.words[0] & 1) === 1;
  };

  // And first word and num
  BN.prototype.andln = function andln (num) {
    return this.words[0] & num;
  };

  // Increment at the bit position in-line
  BN.prototype.bincn = function bincn (bit) {
    assert(typeof bit === 'number');
    var r = bit % 26;
    var s = (bit - r) / 26;
    var q = 1 << r;

    // Fast case: bit is much higher than all existing words
    if (this.length <= s) {
      this._expand(s + 1);
      this.words[s] |= q;
      return this;
    }

    // Add bit and propagate, if needed
    var carry = q;
    for (var i = s; carry !== 0 && i < this.length; i++) {
      var w = this.words[i] | 0;
      w += carry;
      carry = w >>> 26;
      w &= 0x3ffffff;
      this.words[i] = w;
    }
    if (carry !== 0) {
      this.words[i] = carry;
      this.length++;
    }
    return this;
  };

  BN.prototype.isZero = function isZero () {
    return this.length === 1 && this.words[0] === 0;
  };

  BN.prototype.cmpn = function cmpn (num) {
    var negative = num < 0;

    if (this.negative !== 0 && !negative) return -1;
    if (this.negative === 0 && negative) return 1;

    this.strip();

    var res;
    if (this.length > 1) {
      res = 1;
    } else {
      if (negative) {
        num = -num;
      }

      assert(num <= 0x3ffffff, 'Number is too big');

      var w = this.words[0] | 0;
      res = w === num ? 0 : w < num ? -1 : 1;
    }
    if (this.negative !== 0) return -res | 0;
    return res;
  };

  // Compare two numbers and return:
  // 1 - if `this` > `num`
  // 0 - if `this` == `num`
  // -1 - if `this` < `num`
  BN.prototype.cmp = function cmp (num) {
    if (this.negative !== 0 && num.negative === 0) return -1;
    if (this.negative === 0 && num.negative !== 0) return 1;

    var res = this.ucmp(num);
    if (this.negative !== 0) return -res | 0;
    return res;
  };

  // Unsigned comparison
  BN.prototype.ucmp = function ucmp (num) {
    // At this point both numbers have the same sign
    if (this.length > num.length) return 1;
    if (this.length < num.length) return -1;

    var res = 0;
    for (var i = this.length - 1; i >= 0; i--) {
      var a = this.words[i] | 0;
      var b = num.words[i] | 0;

      if (a === b) continue;
      if (a < b) {
        res = -1;
      } else if (a > b) {
        res = 1;
      }
      break;
    }
    return res;
  };

  BN.prototype.gtn = function gtn (num) {
    return this.cmpn(num) === 1;
  };

  BN.prototype.gt = function gt (num) {
    return this.cmp(num) === 1;
  };

  BN.prototype.gten = function gten (num) {
    return this.cmpn(num) >= 0;
  };

  BN.prototype.gte = function gte (num) {
    return this.cmp(num) >= 0;
  };

  BN.prototype.ltn = function ltn (num) {
    return this.cmpn(num) === -1;
  };

  BN.prototype.lt = function lt (num) {
    return this.cmp(num) === -1;
  };

  BN.prototype.lten = function lten (num) {
    return this.cmpn(num) <= 0;
  };

  BN.prototype.lte = function lte (num) {
    return this.cmp(num) <= 0;
  };

  BN.prototype.eqn = function eqn (num) {
    return this.cmpn(num) === 0;
  };

  BN.prototype.eq = function eq (num) {
    return this.cmp(num) === 0;
  };

  //
  // A reduce context, could be using montgomery or something better, depending
  // on the `m` itself.
  //
  BN.red = function red (num) {
    return new Red(num);
  };

  BN.prototype.toRed = function toRed (ctx) {
    assert(!this.red, 'Already a number in reduction context');
    assert(this.negative === 0, 'red works only with positives');
    return ctx.convertTo(this)._forceRed(ctx);
  };

  BN.prototype.fromRed = function fromRed () {
    assert(this.red, 'fromRed works only with numbers in reduction context');
    return this.red.convertFrom(this);
  };

  BN.prototype._forceRed = function _forceRed (ctx) {
    this.red = ctx;
    return this;
  };

  BN.prototype.forceRed = function forceRed (ctx) {
    assert(!this.red, 'Already a number in reduction context');
    return this._forceRed(ctx);
  };

  BN.prototype.redAdd = function redAdd (num) {
    assert(this.red, 'redAdd works only with red numbers');
    return this.red.add(this, num);
  };

  BN.prototype.redIAdd = function redIAdd (num) {
    assert(this.red, 'redIAdd works only with red numbers');
    return this.red.iadd(this, num);
  };

  BN.prototype.redSub = function redSub (num) {
    assert(this.red, 'redSub works only with red numbers');
    return this.red.sub(this, num);
  };

  BN.prototype.redISub = function redISub (num) {
    assert(this.red, 'redISub works only with red numbers');
    return this.red.isub(this, num);
  };

  BN.prototype.redShl = function redShl (num) {
    assert(this.red, 'redShl works only with red numbers');
    return this.red.shl(this, num);
  };

  BN.prototype.redMul = function redMul (num) {
    assert(this.red, 'redMul works only with red numbers');
    this.red._verify2(this, num);
    return this.red.mul(this, num);
  };

  BN.prototype.redIMul = function redIMul (num) {
    assert(this.red, 'redMul works only with red numbers');
    this.red._verify2(this, num);
    return this.red.imul(this, num);
  };

  BN.prototype.redSqr = function redSqr () {
    assert(this.red, 'redSqr works only with red numbers');
    this.red._verify1(this);
    return this.red.sqr(this);
  };

  BN.prototype.redISqr = function redISqr () {
    assert(this.red, 'redISqr works only with red numbers');
    this.red._verify1(this);
    return this.red.isqr(this);
  };

  // Square root over p
  BN.prototype.redSqrt = function redSqrt () {
    assert(this.red, 'redSqrt works only with red numbers');
    this.red._verify1(this);
    return this.red.sqrt(this);
  };

  BN.prototype.redInvm = function redInvm () {
    assert(this.red, 'redInvm works only with red numbers');
    this.red._verify1(this);
    return this.red.invm(this);
  };

  // Return negative clone of `this` % `red modulo`
  BN.prototype.redNeg = function redNeg () {
    assert(this.red, 'redNeg works only with red numbers');
    this.red._verify1(this);
    return this.red.neg(this);
  };

  BN.prototype.redPow = function redPow (num) {
    assert(this.red && !num.red, 'redPow(normalNum)');
    this.red._verify1(this);
    return this.red.pow(this, num);
  };

  // Prime numbers with efficient reduction
  var primes = {
    k256: null,
    p224: null,
    p192: null,
    p25519: null
  };

  // Pseudo-Mersenne prime
  function MPrime (name, p) {
    // P = 2 ^ N - K
    this.name = name;
    this.p = new BN(p, 16);
    this.n = this.p.bitLength();
    this.k = new BN(1).iushln(this.n).isub(this.p);

    this.tmp = this._tmp();
  }

  MPrime.prototype._tmp = function _tmp () {
    var tmp = new BN(null);
    tmp.words = new Array(Math.ceil(this.n / 13));
    return tmp;
  };

  MPrime.prototype.ireduce = function ireduce (num) {
    // Assumes that `num` is less than `P^2`
    // num = HI * (2 ^ N - K) + HI * K + LO = HI * K + LO (mod P)
    var r = num;
    var rlen;

    do {
      this.split(r, this.tmp);
      r = this.imulK(r);
      r = r.iadd(this.tmp);
      rlen = r.bitLength();
    } while (rlen > this.n);

    var cmp = rlen < this.n ? -1 : r.ucmp(this.p);
    if (cmp === 0) {
      r.words[0] = 0;
      r.length = 1;
    } else if (cmp > 0) {
      r.isub(this.p);
    } else {
      r.strip();
    }

    return r;
  };

  MPrime.prototype.split = function split (input, out) {
    input.iushrn(this.n, 0, out);
  };

  MPrime.prototype.imulK = function imulK (num) {
    return num.imul(this.k);
  };

  function K256 () {
    MPrime.call(
      this,
      'k256',
      'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffc2f');
  }
  inherits(K256, MPrime);

  K256.prototype.split = function split (input, output) {
    // 256 = 9 * 26 + 22
    var mask = 0x3fffff;

    var outLen = Math.min(input.length, 9);
    for (var i = 0; i < outLen; i++) {
      output.words[i] = input.words[i];
    }
    output.length = outLen;

    if (input.length <= 9) {
      input.words[0] = 0;
      input.length = 1;
      return;
    }

    // Shift by 9 limbs
    var prev = input.words[9];
    output.words[output.length++] = prev & mask;

    for (i = 10; i < input.length; i++) {
      var next = input.words[i] | 0;
      input.words[i - 10] = ((next & mask) << 4) | (prev >>> 22);
      prev = next;
    }
    prev >>>= 22;
    input.words[i - 10] = prev;
    if (prev === 0 && input.length > 10) {
      input.length -= 10;
    } else {
      input.length -= 9;
    }
  };

  K256.prototype.imulK = function imulK (num) {
    // K = 0x1000003d1 = [ 0x40, 0x3d1 ]
    num.words[num.length] = 0;
    num.words[num.length + 1] = 0;
    num.length += 2;

    // bounded at: 0x40 * 0x3ffffff + 0x3d0 = 0x100000390
    var lo = 0;
    for (var i = 0; i < num.length; i++) {
      var w = num.words[i] | 0;
      lo += w * 0x3d1;
      num.words[i] = lo & 0x3ffffff;
      lo = w * 0x40 + ((lo / 0x4000000) | 0);
    }

    // Fast length reduction
    if (num.words[num.length - 1] === 0) {
      num.length--;
      if (num.words[num.length - 1] === 0) {
        num.length--;
      }
    }
    return num;
  };

  function P224 () {
    MPrime.call(
      this,
      'p224',
      'ffffffff ffffffff ffffffff ffffffff 00000000 00000000 00000001');
  }
  inherits(P224, MPrime);

  function P192 () {
    MPrime.call(
      this,
      'p192',
      'ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff');
  }
  inherits(P192, MPrime);

  function P25519 () {
    // 2 ^ 255 - 19
    MPrime.call(
      this,
      '25519',
      '7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed');
  }
  inherits(P25519, MPrime);

  P25519.prototype.imulK = function imulK (num) {
    // K = 0x13
    var carry = 0;
    for (var i = 0; i < num.length; i++) {
      var hi = (num.words[i] | 0) * 0x13 + carry;
      var lo = hi & 0x3ffffff;
      hi >>>= 26;

      num.words[i] = lo;
      carry = hi;
    }
    if (carry !== 0) {
      num.words[num.length++] = carry;
    }
    return num;
  };

  // Exported mostly for testing purposes, use plain name instead
  BN._prime = function prime (name) {
    // Cached version of prime
    if (primes[name]) return primes[name];

    var prime;
    if (name === 'k256') {
      prime = new K256();
    } else if (name === 'p224') {
      prime = new P224();
    } else if (name === 'p192') {
      prime = new P192();
    } else if (name === 'p25519') {
      prime = new P25519();
    } else {
      throw new Error('Unknown prime ' + name);
    }
    primes[name] = prime;

    return prime;
  };

  //
  // Base reduction engine
  //
  function Red (m) {
    if (typeof m === 'string') {
      var prime = BN._prime(m);
      this.m = prime.p;
      this.prime = prime;
    } else {
      assert(m.gtn(1), 'modulus must be greater than 1');
      this.m = m;
      this.prime = null;
    }
  }

  Red.prototype._verify1 = function _verify1 (a) {
    assert(a.negative === 0, 'red works only with positives');
    assert(a.red, 'red works only with red numbers');
  };

  Red.prototype._verify2 = function _verify2 (a, b) {
    assert((a.negative | b.negative) === 0, 'red works only with positives');
    assert(a.red && a.red === b.red,
      'red works only with red numbers');
  };

  Red.prototype.imod = function imod (a) {
    if (this.prime) return this.prime.ireduce(a)._forceRed(this);
    return a.umod(this.m)._forceRed(this);
  };

  Red.prototype.neg = function neg (a) {
    if (a.isZero()) {
      return a.clone();
    }

    return this.m.sub(a)._forceRed(this);
  };

  Red.prototype.add = function add (a, b) {
    this._verify2(a, b);

    var res = a.add(b);
    if (res.cmp(this.m) >= 0) {
      res.isub(this.m);
    }
    return res._forceRed(this);
  };

  Red.prototype.iadd = function iadd (a, b) {
    this._verify2(a, b);

    var res = a.iadd(b);
    if (res.cmp(this.m) >= 0) {
      res.isub(this.m);
    }
    return res;
  };

  Red.prototype.sub = function sub (a, b) {
    this._verify2(a, b);

    var res = a.sub(b);
    if (res.cmpn(0) < 0) {
      res.iadd(this.m);
    }
    return res._forceRed(this);
  };

  Red.prototype.isub = function isub (a, b) {
    this._verify2(a, b);

    var res = a.isub(b);
    if (res.cmpn(0) < 0) {
      res.iadd(this.m);
    }
    return res;
  };

  Red.prototype.shl = function shl (a, num) {
    this._verify1(a);
    return this.imod(a.ushln(num));
  };

  Red.prototype.imul = function imul (a, b) {
    this._verify2(a, b);
    return this.imod(a.imul(b));
  };

  Red.prototype.mul = function mul (a, b) {
    this._verify2(a, b);
    return this.imod(a.mul(b));
  };

  Red.prototype.isqr = function isqr (a) {
    return this.imul(a, a.clone());
  };

  Red.prototype.sqr = function sqr (a) {
    return this.mul(a, a);
  };

  Red.prototype.sqrt = function sqrt (a) {
    if (a.isZero()) return a.clone();

    var mod3 = this.m.andln(3);
    assert(mod3 % 2 === 1);

    // Fast case
    if (mod3 === 3) {
      var pow = this.m.add(new BN(1)).iushrn(2);
      return this.pow(a, pow);
    }

    // Tonelli-Shanks algorithm (Totally unoptimized and slow)
    //
    // Find Q and S, that Q * 2 ^ S = (P - 1)
    var q = this.m.subn(1);
    var s = 0;
    while (!q.isZero() && q.andln(1) === 0) {
      s++;
      q.iushrn(1);
    }
    assert(!q.isZero());

    var one = new BN(1).toRed(this);
    var nOne = one.redNeg();

    // Find quadratic non-residue
    // NOTE: Max is such because of generalized Riemann hypothesis.
    var lpow = this.m.subn(1).iushrn(1);
    var z = this.m.bitLength();
    z = new BN(2 * z * z).toRed(this);

    while (this.pow(z, lpow).cmp(nOne) !== 0) {
      z.redIAdd(nOne);
    }

    var c = this.pow(z, q);
    var r = this.pow(a, q.addn(1).iushrn(1));
    var t = this.pow(a, q);
    var m = s;
    while (t.cmp(one) !== 0) {
      var tmp = t;
      for (var i = 0; tmp.cmp(one) !== 0; i++) {
        tmp = tmp.redSqr();
      }
      assert(i < m);
      var b = this.pow(c, new BN(1).iushln(m - i - 1));

      r = r.redMul(b);
      c = b.redSqr();
      t = t.redMul(c);
      m = i;
    }

    return r;
  };

  Red.prototype.invm = function invm (a) {
    var inv = a._invmp(this.m);
    if (inv.negative !== 0) {
      inv.negative = 0;
      return this.imod(inv).redNeg();
    } else {
      return this.imod(inv);
    }
  };

  Red.prototype.pow = function pow (a, num) {
    if (num.isZero()) return new BN(1);
    if (num.cmpn(1) === 0) return a.clone();

    var windowSize = 4;
    var wnd = new Array(1 << windowSize);
    wnd[0] = new BN(1).toRed(this);
    wnd[1] = a;
    for (var i = 2; i < wnd.length; i++) {
      wnd[i] = this.mul(wnd[i - 1], a);
    }

    var res = wnd[0];
    var current = 0;
    var currentLen = 0;
    var start = num.bitLength() % 26;
    if (start === 0) {
      start = 26;
    }

    for (i = num.length - 1; i >= 0; i--) {
      var word = num.words[i];
      for (var j = start - 1; j >= 0; j--) {
        var bit = (word >> j) & 1;
        if (res !== wnd[0]) {
          res = this.sqr(res);
        }

        if (bit === 0 && current === 0) {
          currentLen = 0;
          continue;
        }

        current <<= 1;
        current |= bit;
        currentLen++;
        if (currentLen !== windowSize && (i !== 0 || j !== 0)) continue;

        res = this.mul(res, wnd[current]);
        currentLen = 0;
        current = 0;
      }
      start = 26;
    }

    return res;
  };

  Red.prototype.convertTo = function convertTo (num) {
    var r = num.umod(this.m);

    return r === num ? r.clone() : r;
  };

  Red.prototype.convertFrom = function convertFrom (num) {
    var res = num.clone();
    res.red = null;
    return res;
  };

  //
  // Montgomery method engine
  //

  BN.mont = function mont (num) {
    return new Mont(num);
  };

  function Mont (m) {
    Red.call(this, m);

    this.shift = this.m.bitLength();
    if (this.shift % 26 !== 0) {
      this.shift += 26 - (this.shift % 26);
    }

    this.r = new BN(1).iushln(this.shift);
    this.r2 = this.imod(this.r.sqr());
    this.rinv = this.r._invmp(this.m);

    this.minv = this.rinv.mul(this.r).isubn(1).div(this.m);
    this.minv = this.minv.umod(this.r);
    this.minv = this.r.sub(this.minv);
  }
  inherits(Mont, Red);

  Mont.prototype.convertTo = function convertTo (num) {
    return this.imod(num.ushln(this.shift));
  };

  Mont.prototype.convertFrom = function convertFrom (num) {
    var r = this.imod(num.mul(this.rinv));
    r.red = null;
    return r;
  };

  Mont.prototype.imul = function imul (a, b) {
    if (a.isZero() || b.isZero()) {
      a.words[0] = 0;
      a.length = 1;
      return a;
    }

    var t = a.imul(b);
    var c = t.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m);
    var u = t.isub(c).iushrn(this.shift);
    var res = u;

    if (u.cmp(this.m) >= 0) {
      res = u.isub(this.m);
    } else if (u.cmpn(0) < 0) {
      res = u.iadd(this.m);
    }

    return res._forceRed(this);
  };

  Mont.prototype.mul = function mul (a, b) {
    if (a.isZero() || b.isZero()) return new BN(0)._forceRed(this);

    var t = a.mul(b);
    var c = t.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m);
    var u = t.isub(c).iushrn(this.shift);
    var res = u;
    if (u.cmp(this.m) >= 0) {
      res = u.isub(this.m);
    } else if (u.cmpn(0) < 0) {
      res = u.iadd(this.m);
    }

    return res._forceRed(this);
  };

  Mont.prototype.invm = function invm (a) {
    // (AR)^-1 * R^2 = (A^-1 * R^-1) * R^2 = A^-1 * R
    var res = this.imod(a._invmp(this.m).mul(this.r2));
    return res._forceRed(this);
  };
})(typeof module === 'undefined' || module, this);

},{}],17:[function(require,module,exports){
var r;

module.exports = function rand(len) {
  if (!r)
    r = new Rand(null);

  return r.generate(len);
};

function Rand(rand) {
  this.rand = rand;
}
module.exports.Rand = Rand;

Rand.prototype.generate = function generate(len) {
  return this._rand(len);
};

if (typeof window === 'object') {
  if (window.crypto && window.crypto.getRandomValues) {
    // Modern browsers
    Rand.prototype._rand = function _rand(n) {
      var arr = new Uint8Array(n);
      window.crypto.getRandomValues(arr);
      return arr;
    };
  } else if (window.msCrypto && window.msCrypto.getRandomValues) {
    // IE
    Rand.prototype._rand = function _rand(n) {
      var arr = new Uint8Array(n);
      window.msCrypto.getRandomValues(arr);
      return arr;
    };
  } else {
    // Old junk
    Rand.prototype._rand = function() {
      throw new Error('Not implemented yet');
    };
  }
} else {
  // Node.js or Web worker
  try {
    var crypto = require('crypto');

    Rand.prototype._rand = function _rand(n) {
      return crypto.randomBytes(n);
    };
  } catch (e) {
    // Emulate crypto API using randy
    Rand.prototype._rand = function _rand(n) {
      var res = new Uint8Array(n);
      for (var i = 0; i < res.length; i++)
        res[i] = this.rand.getByte();
      return res;
    };
  }
}

},{"crypto":18}],18:[function(require,module,exports){

},{}],19:[function(require,module,exports){
(function (Buffer){
// based on the aes implimentation in triple sec
// https://github.com/keybase/triplesec

// which is in turn based on the one from crypto-js
// https://code.google.com/p/crypto-js/

var uint_max = Math.pow(2, 32)
function fixup_uint32 (x) {
  var ret, x_pos
  ret = x > uint_max || x < 0 ? (x_pos = Math.abs(x) % uint_max, x < 0 ? uint_max - x_pos : x_pos) : x
  return ret
}
function scrub_vec (v) {
  for (var i = 0; i < v.length; v++) {
    v[i] = 0
  }
  return false
}

function Global () {
  this.SBOX = []
  this.INV_SBOX = []
  this.SUB_MIX = [[], [], [], []]
  this.INV_SUB_MIX = [[], [], [], []]
  this.init()
  this.RCON = [0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36]
}

Global.prototype.init = function () {
  var d, i, sx, t, x, x2, x4, x8, xi, _i
  d = (function () {
    var _i, _results
    _results = []
    for (i = _i = 0; _i < 256; i = ++_i) {
      if (i < 128) {
        _results.push(i << 1)
      } else {
        _results.push((i << 1) ^ 0x11b)
      }
    }
    return _results
  })()
  x = 0
  xi = 0
  for (i = _i = 0; _i < 256; i = ++_i) {
    sx = xi ^ (xi << 1) ^ (xi << 2) ^ (xi << 3) ^ (xi << 4)
    sx = (sx >>> 8) ^ (sx & 0xff) ^ 0x63
    this.SBOX[x] = sx
    this.INV_SBOX[sx] = x
    x2 = d[x]
    x4 = d[x2]
    x8 = d[x4]
    t = (d[sx] * 0x101) ^ (sx * 0x1010100)
    this.SUB_MIX[0][x] = (t << 24) | (t >>> 8)
    this.SUB_MIX[1][x] = (t << 16) | (t >>> 16)
    this.SUB_MIX[2][x] = (t << 8) | (t >>> 24)
    this.SUB_MIX[3][x] = t
    t = (x8 * 0x1010101) ^ (x4 * 0x10001) ^ (x2 * 0x101) ^ (x * 0x1010100)
    this.INV_SUB_MIX[0][sx] = (t << 24) | (t >>> 8)
    this.INV_SUB_MIX[1][sx] = (t << 16) | (t >>> 16)
    this.INV_SUB_MIX[2][sx] = (t << 8) | (t >>> 24)
    this.INV_SUB_MIX[3][sx] = t
    if (x === 0) {
      x = xi = 1
    } else {
      x = x2 ^ d[d[d[x8 ^ x2]]]
      xi ^= d[d[xi]]
    }
  }
  return true
}

var G = new Global()

AES.blockSize = 4 * 4

AES.prototype.blockSize = AES.blockSize

AES.keySize = 256 / 8

AES.prototype.keySize = AES.keySize

function bufferToArray (buf) {
  var len = buf.length / 4
  var out = new Array(len)
  var i = -1
  while (++i < len) {
    out[i] = buf.readUInt32BE(i * 4)
  }
  return out
}
function AES (key) {
  this._key = bufferToArray(key)
  this._doReset()
}

AES.prototype._doReset = function () {
  var invKsRow, keySize, keyWords, ksRow, ksRows, t
  keyWords = this._key
  keySize = keyWords.length
  this._nRounds = keySize + 6
  ksRows = (this._nRounds + 1) * 4
  this._keySchedule = []
  for (ksRow = 0; ksRow < ksRows; ksRow++) {
    this._keySchedule[ksRow] = ksRow < keySize ? keyWords[ksRow] : (t = this._keySchedule[ksRow - 1], (ksRow % keySize) === 0 ? (t = (t << 8) | (t >>> 24), t = (G.SBOX[t >>> 24] << 24) | (G.SBOX[(t >>> 16) & 0xff] << 16) | (G.SBOX[(t >>> 8) & 0xff] << 8) | G.SBOX[t & 0xff], t ^= G.RCON[(ksRow / keySize) | 0] << 24) : keySize > 6 && ksRow % keySize === 4 ? t = (G.SBOX[t >>> 24] << 24) | (G.SBOX[(t >>> 16) & 0xff] << 16) | (G.SBOX[(t >>> 8) & 0xff] << 8) | G.SBOX[t & 0xff] : void 0, this._keySchedule[ksRow - keySize] ^ t)
  }
  this._invKeySchedule = []
  for (invKsRow = 0; invKsRow < ksRows; invKsRow++) {
    ksRow = ksRows - invKsRow
    t = this._keySchedule[ksRow - (invKsRow % 4 ? 0 : 4)]
    this._invKeySchedule[invKsRow] = invKsRow < 4 || ksRow <= 4 ? t : G.INV_SUB_MIX[0][G.SBOX[t >>> 24]] ^ G.INV_SUB_MIX[1][G.SBOX[(t >>> 16) & 0xff]] ^ G.INV_SUB_MIX[2][G.SBOX[(t >>> 8) & 0xff]] ^ G.INV_SUB_MIX[3][G.SBOX[t & 0xff]]
  }
  return true
}

AES.prototype.encryptBlock = function (M) {
  M = bufferToArray(new Buffer(M))
  var out = this._doCryptBlock(M, this._keySchedule, G.SUB_MIX, G.SBOX)
  var buf = new Buffer(16)
  buf.writeUInt32BE(out[0], 0)
  buf.writeUInt32BE(out[1], 4)
  buf.writeUInt32BE(out[2], 8)
  buf.writeUInt32BE(out[3], 12)
  return buf
}

AES.prototype.decryptBlock = function (M) {
  M = bufferToArray(new Buffer(M))
  var temp = [M[3], M[1]]
  M[1] = temp[0]
  M[3] = temp[1]
  var out = this._doCryptBlock(M, this._invKeySchedule, G.INV_SUB_MIX, G.INV_SBOX)
  var buf = new Buffer(16)
  buf.writeUInt32BE(out[0], 0)
  buf.writeUInt32BE(out[3], 4)
  buf.writeUInt32BE(out[2], 8)
  buf.writeUInt32BE(out[1], 12)
  return buf
}

AES.prototype.scrub = function () {
  scrub_vec(this._keySchedule)
  scrub_vec(this._invKeySchedule)
  scrub_vec(this._key)
}

AES.prototype._doCryptBlock = function (M, keySchedule, SUB_MIX, SBOX) {
  var ksRow, s0, s1, s2, s3, t0, t1, t2, t3

  s0 = M[0] ^ keySchedule[0]
  s1 = M[1] ^ keySchedule[1]
  s2 = M[2] ^ keySchedule[2]
  s3 = M[3] ^ keySchedule[3]
  ksRow = 4
  for (var round = 1; round < this._nRounds; round++) {
    t0 = SUB_MIX[0][s0 >>> 24] ^ SUB_MIX[1][(s1 >>> 16) & 0xff] ^ SUB_MIX[2][(s2 >>> 8) & 0xff] ^ SUB_MIX[3][s3 & 0xff] ^ keySchedule[ksRow++]
    t1 = SUB_MIX[0][s1 >>> 24] ^ SUB_MIX[1][(s2 >>> 16) & 0xff] ^ SUB_MIX[2][(s3 >>> 8) & 0xff] ^ SUB_MIX[3][s0 & 0xff] ^ keySchedule[ksRow++]
    t2 = SUB_MIX[0][s2 >>> 24] ^ SUB_MIX[1][(s3 >>> 16) & 0xff] ^ SUB_MIX[2][(s0 >>> 8) & 0xff] ^ SUB_MIX[3][s1 & 0xff] ^ keySchedule[ksRow++]
    t3 = SUB_MIX[0][s3 >>> 24] ^ SUB_MIX[1][(s0 >>> 16) & 0xff] ^ SUB_MIX[2][(s1 >>> 8) & 0xff] ^ SUB_MIX[3][s2 & 0xff] ^ keySchedule[ksRow++]
    s0 = t0
    s1 = t1
    s2 = t2
    s3 = t3
  }
  t0 = ((SBOX[s0 >>> 24] << 24) | (SBOX[(s1 >>> 16) & 0xff] << 16) | (SBOX[(s2 >>> 8) & 0xff] << 8) | SBOX[s3 & 0xff]) ^ keySchedule[ksRow++]
  t1 = ((SBOX[s1 >>> 24] << 24) | (SBOX[(s2 >>> 16) & 0xff] << 16) | (SBOX[(s3 >>> 8) & 0xff] << 8) | SBOX[s0 & 0xff]) ^ keySchedule[ksRow++]
  t2 = ((SBOX[s2 >>> 24] << 24) | (SBOX[(s3 >>> 16) & 0xff] << 16) | (SBOX[(s0 >>> 8) & 0xff] << 8) | SBOX[s1 & 0xff]) ^ keySchedule[ksRow++]
  t3 = ((SBOX[s3 >>> 24] << 24) | (SBOX[(s0 >>> 16) & 0xff] << 16) | (SBOX[(s1 >>> 8) & 0xff] << 8) | SBOX[s2 & 0xff]) ^ keySchedule[ksRow++]
  return [
    fixup_uint32(t0),
    fixup_uint32(t1),
    fixup_uint32(t2),
    fixup_uint32(t3)
  ]
}

exports.AES = AES

}).call(this,require("buffer").Buffer)
},{"buffer":45}],20:[function(require,module,exports){
(function (Buffer){
var aes = require('./aes')
var Transform = require('cipher-base')
var inherits = require('inherits')
var GHASH = require('./ghash')
var xor = require('buffer-xor')
inherits(StreamCipher, Transform)
module.exports = StreamCipher

function StreamCipher (mode, key, iv, decrypt) {
  if (!(this instanceof StreamCipher)) {
    return new StreamCipher(mode, key, iv)
  }
  Transform.call(this)
  this._finID = Buffer.concat([iv, new Buffer([0, 0, 0, 1])])
  iv = Buffer.concat([iv, new Buffer([0, 0, 0, 2])])
  this._cipher = new aes.AES(key)
  this._prev = new Buffer(iv.length)
  this._cache = new Buffer('')
  this._secCache = new Buffer('')
  this._decrypt = decrypt
  this._alen = 0
  this._len = 0
  iv.copy(this._prev)
  this._mode = mode
  var h = new Buffer(4)
  h.fill(0)
  this._ghash = new GHASH(this._cipher.encryptBlock(h))
  this._authTag = null
  this._called = false
}
StreamCipher.prototype._update = function (chunk) {
  if (!this._called && this._alen) {
    var rump = 16 - (this._alen % 16)
    if (rump < 16) {
      rump = new Buffer(rump)
      rump.fill(0)
      this._ghash.update(rump)
    }
  }
  this._called = true
  var out = this._mode.encrypt(this, chunk)
  if (this._decrypt) {
    this._ghash.update(chunk)
  } else {
    this._ghash.update(out)
  }
  this._len += chunk.length
  return out
}
StreamCipher.prototype._final = function () {
  if (this._decrypt && !this._authTag) {
    throw new Error('Unsupported state or unable to authenticate data')
  }
  var tag = xor(this._ghash.final(this._alen * 8, this._len * 8), this._cipher.encryptBlock(this._finID))
  if (this._decrypt) {
    if (xorTest(tag, this._authTag)) {
      throw new Error('Unsupported state or unable to authenticate data')
    }
  } else {
    this._authTag = tag
  }
  this._cipher.scrub()
}
StreamCipher.prototype.getAuthTag = function getAuthTag () {
  if (!this._decrypt && Buffer.isBuffer(this._authTag)) {
    return this._authTag
  } else {
    throw new Error('Attempting to get auth tag in unsupported state')
  }
}
StreamCipher.prototype.setAuthTag = function setAuthTag (tag) {
  if (this._decrypt) {
    this._authTag = tag
  } else {
    throw new Error('Attempting to set auth tag in unsupported state')
  }
}
StreamCipher.prototype.setAAD = function setAAD (buf) {
  if (!this._called) {
    this._ghash.update(buf)
    this._alen += buf.length
  } else {
    throw new Error('Attempting to set AAD in unsupported state')
  }
}
function xorTest (a, b) {
  var out = 0
  if (a.length !== b.length) {
    out++
  }
  var len = Math.min(a.length, b.length)
  var i = -1
  while (++i < len) {
    out += (a[i] ^ b[i])
  }
  return out
}

}).call(this,require("buffer").Buffer)
},{"./aes":19,"./ghash":24,"buffer":45,"buffer-xor":33,"cipher-base":48,"inherits":94}],21:[function(require,module,exports){
var ciphers = require('./encrypter')
exports.createCipher = exports.Cipher = ciphers.createCipher
exports.createCipheriv = exports.Cipheriv = ciphers.createCipheriv
var deciphers = require('./decrypter')
exports.createDecipher = exports.Decipher = deciphers.createDecipher
exports.createDecipheriv = exports.Decipheriv = deciphers.createDecipheriv
var modes = require('./modes')
function getCiphers () {
  return Object.keys(modes)
}
exports.listCiphers = exports.getCiphers = getCiphers

},{"./decrypter":22,"./encrypter":23,"./modes":25}],22:[function(require,module,exports){
(function (Buffer){
var aes = require('./aes')
var Transform = require('cipher-base')
var inherits = require('inherits')
var modes = require('./modes')
var StreamCipher = require('./streamCipher')
var AuthCipher = require('./authCipher')
var ebtk = require('evp_bytestokey')

inherits(Decipher, Transform)
function Decipher (mode, key, iv) {
  if (!(this instanceof Decipher)) {
    return new Decipher(mode, key, iv)
  }
  Transform.call(this)
  this._cache = new Splitter()
  this._last = void 0
  this._cipher = new aes.AES(key)
  this._prev = new Buffer(iv.length)
  iv.copy(this._prev)
  this._mode = mode
  this._autopadding = true
}
Decipher.prototype._update = function (data) {
  this._cache.add(data)
  var chunk
  var thing
  var out = []
  while ((chunk = this._cache.get(this._autopadding))) {
    thing = this._mode.decrypt(this, chunk)
    out.push(thing)
  }
  return Buffer.concat(out)
}
Decipher.prototype._final = function () {
  var chunk = this._cache.flush()
  if (this._autopadding) {
    return unpad(this._mode.decrypt(this, chunk))
  } else if (chunk) {
    throw new Error('data not multiple of block length')
  }
}
Decipher.prototype.setAutoPadding = function (setTo) {
  this._autopadding = !!setTo
  return this
}
function Splitter () {
  if (!(this instanceof Splitter)) {
    return new Splitter()
  }
  this.cache = new Buffer('')
}
Splitter.prototype.add = function (data) {
  this.cache = Buffer.concat([this.cache, data])
}

Splitter.prototype.get = function (autoPadding) {
  var out
  if (autoPadding) {
    if (this.cache.length > 16) {
      out = this.cache.slice(0, 16)
      this.cache = this.cache.slice(16)
      return out
    }
  } else {
    if (this.cache.length >= 16) {
      out = this.cache.slice(0, 16)
      this.cache = this.cache.slice(16)
      return out
    }
  }
  return null
}
Splitter.prototype.flush = function () {
  if (this.cache.length) {
    return this.cache
  }
}
function unpad (last) {
  var padded = last[15]
  var i = -1
  while (++i < padded) {
    if (last[(i + (16 - padded))] !== padded) {
      throw new Error('unable to decrypt data')
    }
  }
  if (padded === 16) {
    return
  }
  return last.slice(0, 16 - padded)
}

var modelist = {
  ECB: require('./modes/ecb'),
  CBC: require('./modes/cbc'),
  CFB: require('./modes/cfb'),
  CFB8: require('./modes/cfb8'),
  CFB1: require('./modes/cfb1'),
  OFB: require('./modes/ofb'),
  CTR: require('./modes/ctr'),
  GCM: require('./modes/ctr')
}

function createDecipheriv (suite, password, iv) {
  var config = modes[suite.toLowerCase()]
  if (!config) {
    throw new TypeError('invalid suite type')
  }
  if (typeof iv === 'string') {
    iv = new Buffer(iv)
  }
  if (typeof password === 'string') {
    password = new Buffer(password)
  }
  if (password.length !== config.key / 8) {
    throw new TypeError('invalid key length ' + password.length)
  }
  if (iv.length !== config.iv) {
    throw new TypeError('invalid iv length ' + iv.length)
  }
  if (config.type === 'stream') {
    return new StreamCipher(modelist[config.mode], password, iv, true)
  } else if (config.type === 'auth') {
    return new AuthCipher(modelist[config.mode], password, iv, true)
  }
  return new Decipher(modelist[config.mode], password, iv)
}

function createDecipher (suite, password) {
  var config = modes[suite.toLowerCase()]
  if (!config) {
    throw new TypeError('invalid suite type')
  }
  var keys = ebtk(password, false, config.key, config.iv)
  return createDecipheriv(suite, keys.key, keys.iv)
}
exports.createDecipher = createDecipher
exports.createDecipheriv = createDecipheriv

}).call(this,require("buffer").Buffer)
},{"./aes":19,"./authCipher":20,"./modes":25,"./modes/cbc":26,"./modes/cfb":27,"./modes/cfb1":28,"./modes/cfb8":29,"./modes/ctr":30,"./modes/ecb":31,"./modes/ofb":32,"./streamCipher":34,"buffer":45,"cipher-base":48,"evp_bytestokey":85,"inherits":94}],23:[function(require,module,exports){
(function (Buffer){
var aes = require('./aes')
var Transform = require('cipher-base')
var inherits = require('inherits')
var modes = require('./modes')
var ebtk = require('evp_bytestokey')
var StreamCipher = require('./streamCipher')
var AuthCipher = require('./authCipher')
inherits(Cipher, Transform)
function Cipher (mode, key, iv) {
  if (!(this instanceof Cipher)) {
    return new Cipher(mode, key, iv)
  }
  Transform.call(this)
  this._cache = new Splitter()
  this._cipher = new aes.AES(key)
  this._prev = new Buffer(iv.length)
  iv.copy(this._prev)
  this._mode = mode
  this._autopadding = true
}
Cipher.prototype._update = function (data) {
  this._cache.add(data)
  var chunk
  var thing
  var out = []
  while ((chunk = this._cache.get())) {
    thing = this._mode.encrypt(this, chunk)
    out.push(thing)
  }
  return Buffer.concat(out)
}
Cipher.prototype._final = function () {
  var chunk = this._cache.flush()
  if (this._autopadding) {
    chunk = this._mode.encrypt(this, chunk)
    this._cipher.scrub()
    return chunk
  } else if (chunk.toString('hex') !== '10101010101010101010101010101010') {
    this._cipher.scrub()
    throw new Error('data not multiple of block length')
  }
}
Cipher.prototype.setAutoPadding = function (setTo) {
  this._autopadding = !!setTo
  return this
}

function Splitter () {
  if (!(this instanceof Splitter)) {
    return new Splitter()
  }
  this.cache = new Buffer('')
}
Splitter.prototype.add = function (data) {
  this.cache = Buffer.concat([this.cache, data])
}

Splitter.prototype.get = function () {
  if (this.cache.length > 15) {
    var out = this.cache.slice(0, 16)
    this.cache = this.cache.slice(16)
    return out
  }
  return null
}
Splitter.prototype.flush = function () {
  var len = 16 - this.cache.length
  var padBuff = new Buffer(len)

  var i = -1
  while (++i < len) {
    padBuff.writeUInt8(len, i)
  }
  var out = Buffer.concat([this.cache, padBuff])
  return out
}
var modelist = {
  ECB: require('./modes/ecb'),
  CBC: require('./modes/cbc'),
  CFB: require('./modes/cfb'),
  CFB8: require('./modes/cfb8'),
  CFB1: require('./modes/cfb1'),
  OFB: require('./modes/ofb'),
  CTR: require('./modes/ctr'),
  GCM: require('./modes/ctr')
}

function createCipheriv (suite, password, iv) {
  var config = modes[suite.toLowerCase()]
  if (!config) {
    throw new TypeError('invalid suite type')
  }
  if (typeof iv === 'string') {
    iv = new Buffer(iv)
  }
  if (typeof password === 'string') {
    password = new Buffer(password)
  }
  if (password.length !== config.key / 8) {
    throw new TypeError('invalid key length ' + password.length)
  }
  if (iv.length !== config.iv) {
    throw new TypeError('invalid iv length ' + iv.length)
  }
  if (config.type === 'stream') {
    return new StreamCipher(modelist[config.mode], password, iv)
  } else if (config.type === 'auth') {
    return new AuthCipher(modelist[config.mode], password, iv)
  }
  return new Cipher(modelist[config.mode], password, iv)
}
function createCipher (suite, password) {
  var config = modes[suite.toLowerCase()]
  if (!config) {
    throw new TypeError('invalid suite type')
  }
  var keys = ebtk(password, false, config.key, config.iv)
  return createCipheriv(suite, keys.key, keys.iv)
}

exports.createCipheriv = createCipheriv
exports.createCipher = createCipher

}).call(this,require("buffer").Buffer)
},{"./aes":19,"./authCipher":20,"./modes":25,"./modes/cbc":26,"./modes/cfb":27,"./modes/cfb1":28,"./modes/cfb8":29,"./modes/ctr":30,"./modes/ecb":31,"./modes/ofb":32,"./streamCipher":34,"buffer":45,"cipher-base":48,"evp_bytestokey":85,"inherits":94}],24:[function(require,module,exports){
(function (Buffer){
var zeros = new Buffer(16)
zeros.fill(0)
module.exports = GHASH
function GHASH (key) {
  this.h = key
  this.state = new Buffer(16)
  this.state.fill(0)
  this.cache = new Buffer('')
}
// from http://bitwiseshiftleft.github.io/sjcl/doc/symbols/src/core_gcm.js.html
// by Juho Vähä-Herttua
GHASH.prototype.ghash = function (block) {
  var i = -1
  while (++i < block.length) {
    this.state[i] ^= block[i]
  }
  this._multiply()
}

GHASH.prototype._multiply = function () {
  var Vi = toArray(this.h)
  var Zi = [0, 0, 0, 0]
  var j, xi, lsb_Vi
  var i = -1
  while (++i < 128) {
    xi = (this.state[~~(i / 8)] & (1 << (7 - i % 8))) !== 0
    if (xi) {
      // Z_i+1 = Z_i ^ V_i
      Zi = xor(Zi, Vi)
    }

    // Store the value of LSB(V_i)
    lsb_Vi = (Vi[3] & 1) !== 0

    // V_i+1 = V_i >> 1
    for (j = 3; j > 0; j--) {
      Vi[j] = (Vi[j] >>> 1) | ((Vi[j - 1] & 1) << 31)
    }
    Vi[0] = Vi[0] >>> 1

    // If LSB(V_i) is 1, V_i+1 = (V_i >> 1) ^ R
    if (lsb_Vi) {
      Vi[0] = Vi[0] ^ (0xe1 << 24)
    }
  }
  this.state = fromArray(Zi)
}
GHASH.prototype.update = function (buf) {
  this.cache = Buffer.concat([this.cache, buf])
  var chunk
  while (this.cache.length >= 16) {
    chunk = this.cache.slice(0, 16)
    this.cache = this.cache.slice(16)
    this.ghash(chunk)
  }
}
GHASH.prototype.final = function (abl, bl) {
  if (this.cache.length) {
    this.ghash(Buffer.concat([this.cache, zeros], 16))
  }
  this.ghash(fromArray([
    0, abl,
    0, bl
  ]))
  return this.state
}

function toArray (buf) {
  return [
    buf.readUInt32BE(0),
    buf.readUInt32BE(4),
    buf.readUInt32BE(8),
    buf.readUInt32BE(12)
  ]
}
function fromArray (out) {
  out = out.map(fixup_uint32)
  var buf = new Buffer(16)
  buf.writeUInt32BE(out[0], 0)
  buf.writeUInt32BE(out[1], 4)
  buf.writeUInt32BE(out[2], 8)
  buf.writeUInt32BE(out[3], 12)
  return buf
}
var uint_max = Math.pow(2, 32)
function fixup_uint32 (x) {
  var ret, x_pos
  ret = x > uint_max || x < 0 ? (x_pos = Math.abs(x) % uint_max, x < 0 ? uint_max - x_pos : x_pos) : x
  return ret
}
function xor (a, b) {
  return [
    a[0] ^ b[0],
    a[1] ^ b[1],
    a[2] ^ b[2],
    a[3] ^ b[3]
  ]
}

}).call(this,require("buffer").Buffer)
},{"buffer":45}],25:[function(require,module,exports){
exports['aes-128-ecb'] = {
  cipher: 'AES',
  key: 128,
  iv: 0,
  mode: 'ECB',
  type: 'block'
}
exports['aes-192-ecb'] = {
  cipher: 'AES',
  key: 192,
  iv: 0,
  mode: 'ECB',
  type: 'block'
}
exports['aes-256-ecb'] = {
  cipher: 'AES',
  key: 256,
  iv: 0,
  mode: 'ECB',
  type: 'block'
}
exports['aes-128-cbc'] = {
  cipher: 'AES',
  key: 128,
  iv: 16,
  mode: 'CBC',
  type: 'block'
}
exports['aes-192-cbc'] = {
  cipher: 'AES',
  key: 192,
  iv: 16,
  mode: 'CBC',
  type: 'block'
}
exports['aes-256-cbc'] = {
  cipher: 'AES',
  key: 256,
  iv: 16,
  mode: 'CBC',
  type: 'block'
}
exports['aes128'] = exports['aes-128-cbc']
exports['aes192'] = exports['aes-192-cbc']
exports['aes256'] = exports['aes-256-cbc']
exports['aes-128-cfb'] = {
  cipher: 'AES',
  key: 128,
  iv: 16,
  mode: 'CFB',
  type: 'stream'
}
exports['aes-192-cfb'] = {
  cipher: 'AES',
  key: 192,
  iv: 16,
  mode: 'CFB',
  type: 'stream'
}
exports['aes-256-cfb'] = {
  cipher: 'AES',
  key: 256,
  iv: 16,
  mode: 'CFB',
  type: 'stream'
}
exports['aes-128-cfb8'] = {
  cipher: 'AES',
  key: 128,
  iv: 16,
  mode: 'CFB8',
  type: 'stream'
}
exports['aes-192-cfb8'] = {
  cipher: 'AES',
  key: 192,
  iv: 16,
  mode: 'CFB8',
  type: 'stream'
}
exports['aes-256-cfb8'] = {
  cipher: 'AES',
  key: 256,
  iv: 16,
  mode: 'CFB8',
  type: 'stream'
}
exports['aes-128-cfb1'] = {
  cipher: 'AES',
  key: 128,
  iv: 16,
  mode: 'CFB1',
  type: 'stream'
}
exports['aes-192-cfb1'] = {
  cipher: 'AES',
  key: 192,
  iv: 16,
  mode: 'CFB1',
  type: 'stream'
}
exports['aes-256-cfb1'] = {
  cipher: 'AES',
  key: 256,
  iv: 16,
  mode: 'CFB1',
  type: 'stream'
}
exports['aes-128-ofb'] = {
  cipher: 'AES',
  key: 128,
  iv: 16,
  mode: 'OFB',
  type: 'stream'
}
exports['aes-192-ofb'] = {
  cipher: 'AES',
  key: 192,
  iv: 16,
  mode: 'OFB',
  type: 'stream'
}
exports['aes-256-ofb'] = {
  cipher: 'AES',
  key: 256,
  iv: 16,
  mode: 'OFB',
  type: 'stream'
}
exports['aes-128-ctr'] = {
  cipher: 'AES',
  key: 128,
  iv: 16,
  mode: 'CTR',
  type: 'stream'
}
exports['aes-192-ctr'] = {
  cipher: 'AES',
  key: 192,
  iv: 16,
  mode: 'CTR',
  type: 'stream'
}
exports['aes-256-ctr'] = {
  cipher: 'AES',
  key: 256,
  iv: 16,
  mode: 'CTR',
  type: 'stream'
}
exports['aes-128-gcm'] = {
  cipher: 'AES',
  key: 128,
  iv: 12,
  mode: 'GCM',
  type: 'auth'
}
exports['aes-192-gcm'] = {
  cipher: 'AES',
  key: 192,
  iv: 12,
  mode: 'GCM',
  type: 'auth'
}
exports['aes-256-gcm'] = {
  cipher: 'AES',
  key: 256,
  iv: 12,
  mode: 'GCM',
  type: 'auth'
}

},{}],26:[function(require,module,exports){
var xor = require('buffer-xor')

exports.encrypt = function (self, block) {
  var data = xor(block, self._prev)

  self._prev = self._cipher.encryptBlock(data)
  return self._prev
}

exports.decrypt = function (self, block) {
  var pad = self._prev

  self._prev = block
  var out = self._cipher.decryptBlock(block)

  return xor(out, pad)
}

},{"buffer-xor":33}],27:[function(require,module,exports){
(function (Buffer){
var xor = require('buffer-xor')

exports.encrypt = function (self, data, decrypt) {
  var out = new Buffer('')
  var len

  while (data.length) {
    if (self._cache.length === 0) {
      self._cache = self._cipher.encryptBlock(self._prev)
      self._prev = new Buffer('')
    }

    if (self._cache.length <= data.length) {
      len = self._cache.length
      out = Buffer.concat([out, encryptStart(self, data.slice(0, len), decrypt)])
      data = data.slice(len)
    } else {
      out = Buffer.concat([out, encryptStart(self, data, decrypt)])
      break
    }
  }

  return out
}
function encryptStart (self, data, decrypt) {
  var len = data.length
  var out = xor(data, self._cache)
  self._cache = self._cache.slice(len)
  self._prev = Buffer.concat([self._prev, decrypt ? data : out])
  return out
}

}).call(this,require("buffer").Buffer)
},{"buffer":45,"buffer-xor":33}],28:[function(require,module,exports){
(function (Buffer){
function encryptByte (self, byteParam, decrypt) {
  var pad
  var i = -1
  var len = 8
  var out = 0
  var bit, value
  while (++i < len) {
    pad = self._cipher.encryptBlock(self._prev)
    bit = (byteParam & (1 << (7 - i))) ? 0x80 : 0
    value = pad[0] ^ bit
    out += ((value & 0x80) >> (i % 8))
    self._prev = shiftIn(self._prev, decrypt ? bit : value)
  }
  return out
}
exports.encrypt = function (self, chunk, decrypt) {
  var len = chunk.length
  var out = new Buffer(len)
  var i = -1
  while (++i < len) {
    out[i] = encryptByte(self, chunk[i], decrypt)
  }
  return out
}
function shiftIn (buffer, value) {
  var len = buffer.length
  var i = -1
  var out = new Buffer(buffer.length)
  buffer = Buffer.concat([buffer, new Buffer([value])])
  while (++i < len) {
    out[i] = buffer[i] << 1 | buffer[i + 1] >> (7)
  }
  return out
}

}).call(this,require("buffer").Buffer)
},{"buffer":45}],29:[function(require,module,exports){
(function (Buffer){
function encryptByte (self, byteParam, decrypt) {
  var pad = self._cipher.encryptBlock(self._prev)
  var out = pad[0] ^ byteParam
  self._prev = Buffer.concat([self._prev.slice(1), new Buffer([decrypt ? byteParam : out])])
  return out
}
exports.encrypt = function (self, chunk, decrypt) {
  var len = chunk.length
  var out = new Buffer(len)
  var i = -1
  while (++i < len) {
    out[i] = encryptByte(self, chunk[i], decrypt)
  }
  return out
}

}).call(this,require("buffer").Buffer)
},{"buffer":45}],30:[function(require,module,exports){
(function (Buffer){
var xor = require('buffer-xor')

function incr32 (iv) {
  var len = iv.length
  var item
  while (len--) {
    item = iv.readUInt8(len)
    if (item === 255) {
      iv.writeUInt8(0, len)
    } else {
      item++
      iv.writeUInt8(item, len)
      break
    }
  }
}

function getBlock (self) {
  var out = self._cipher.encryptBlock(self._prev)
  incr32(self._prev)
  return out
}

exports.encrypt = function (self, chunk) {
  while (self._cache.length < chunk.length) {
    self._cache = Buffer.concat([self._cache, getBlock(self)])
  }
  var pad = self._cache.slice(0, chunk.length)
  self._cache = self._cache.slice(chunk.length)
  return xor(chunk, pad)
}

}).call(this,require("buffer").Buffer)
},{"buffer":45,"buffer-xor":33}],31:[function(require,module,exports){
exports.encrypt = function (self, block) {
  return self._cipher.encryptBlock(block)
}
exports.decrypt = function (self, block) {
  return self._cipher.decryptBlock(block)
}

},{}],32:[function(require,module,exports){
(function (Buffer){
var xor = require('buffer-xor')

function getBlock (self) {
  self._prev = self._cipher.encryptBlock(self._prev)
  return self._prev
}

exports.encrypt = function (self, chunk) {
  while (self._cache.length < chunk.length) {
    self._cache = Buffer.concat([self._cache, getBlock(self)])
  }

  var pad = self._cache.slice(0, chunk.length)
  self._cache = self._cache.slice(chunk.length)
  return xor(chunk, pad)
}

}).call(this,require("buffer").Buffer)
},{"buffer":45,"buffer-xor":33}],33:[function(require,module,exports){
(function (Buffer){
module.exports = function xor (a, b) {
  var length = Math.min(a.length, b.length)
  var buffer = new Buffer(length)

  for (var i = 0; i < length; ++i) {
    buffer[i] = a[i] ^ b[i]
  }

  return buffer
}

}).call(this,require("buffer").Buffer)
},{"buffer":45}],34:[function(require,module,exports){
(function (Buffer){
var aes = require('./aes')
var Transform = require('cipher-base')
var inherits = require('inherits')

inherits(StreamCipher, Transform)
module.exports = StreamCipher
function StreamCipher (mode, key, iv, decrypt) {
  if (!(this instanceof StreamCipher)) {
    return new StreamCipher(mode, key, iv)
  }
  Transform.call(this)
  this._cipher = new aes.AES(key)
  this._prev = new Buffer(iv.length)
  this._cache = new Buffer('')
  this._secCache = new Buffer('')
  this._decrypt = decrypt
  iv.copy(this._prev)
  this._mode = mode
}
StreamCipher.prototype._update = function (chunk) {
  return this._mode.encrypt(this, chunk, this._decrypt)
}
StreamCipher.prototype._final = function () {
  this._cipher.scrub()
}

}).call(this,require("buffer").Buffer)
},{"./aes":19,"buffer":45,"cipher-base":48,"inherits":94}],35:[function(require,module,exports){
var ebtk = require('evp_bytestokey')
var aes = require('browserify-aes/browser')
var DES = require('browserify-des')
var desModes = require('browserify-des/modes')
var aesModes = require('browserify-aes/modes')
function createCipher (suite, password) {
  var keyLen, ivLen
  suite = suite.toLowerCase()
  if (aesModes[suite]) {
    keyLen = aesModes[suite].key
    ivLen = aesModes[suite].iv
  } else if (desModes[suite]) {
    keyLen = desModes[suite].key * 8
    ivLen = desModes[suite].iv
  } else {
    throw new TypeError('invalid suite type')
  }
  var keys = ebtk(password, false, keyLen, ivLen)
  return createCipheriv(suite, keys.key, keys.iv)
}
function createDecipher (suite, password) {
  var keyLen, ivLen
  suite = suite.toLowerCase()
  if (aesModes[suite]) {
    keyLen = aesModes[suite].key
    ivLen = aesModes[suite].iv
  } else if (desModes[suite]) {
    keyLen = desModes[suite].key * 8
    ivLen = desModes[suite].iv
  } else {
    throw new TypeError('invalid suite type')
  }
  var keys = ebtk(password, false, keyLen, ivLen)
  return createDecipheriv(suite, keys.key, keys.iv)
}

function createCipheriv (suite, key, iv) {
  suite = suite.toLowerCase()
  if (aesModes[suite]) {
    return aes.createCipheriv(suite, key, iv)
  } else if (desModes[suite]) {
    return new DES({
      key: key,
      iv: iv,
      mode: suite
    })
  } else {
    throw new TypeError('invalid suite type')
  }
}
function createDecipheriv (suite, key, iv) {
  suite = suite.toLowerCase()
  if (aesModes[suite]) {
    return aes.createDecipheriv(suite, key, iv)
  } else if (desModes[suite]) {
    return new DES({
      key: key,
      iv: iv,
      mode: suite,
      decrypt: true
    })
  } else {
    throw new TypeError('invalid suite type')
  }
}
exports.createCipher = exports.Cipher = createCipher
exports.createCipheriv = exports.Cipheriv = createCipheriv
exports.createDecipher = exports.Decipher = createDecipher
exports.createDecipheriv = exports.Decipheriv = createDecipheriv
function getCiphers () {
  return Object.keys(desModes).concat(aes.getCiphers())
}
exports.listCiphers = exports.getCiphers = getCiphers

},{"browserify-aes/browser":21,"browserify-aes/modes":25,"browserify-des":36,"browserify-des/modes":37,"evp_bytestokey":85}],36:[function(require,module,exports){
(function (Buffer){
var CipherBase = require('cipher-base')
var des = require('des.js')
var inherits = require('inherits')

var modes = {
  'des-ede3-cbc': des.CBC.instantiate(des.EDE),
  'des-ede3': des.EDE,
  'des-ede-cbc': des.CBC.instantiate(des.EDE),
  'des-ede': des.EDE,
  'des-cbc': des.CBC.instantiate(des.DES),
  'des-ecb': des.DES
}
modes.des = modes['des-cbc']
modes.des3 = modes['des-ede3-cbc']
module.exports = DES
inherits(DES, CipherBase)
function DES (opts) {
  CipherBase.call(this)
  var modeName = opts.mode.toLowerCase()
  var mode = modes[modeName]
  var type
  if (opts.decrypt) {
    type = 'decrypt'
  } else {
    type = 'encrypt'
  }
  var key = opts.key
  if (modeName === 'des-ede' || modeName === 'des-ede-cbc') {
    key = Buffer.concat([key, key.slice(0, 8)])
  }
  var iv = opts.iv
  this._des = mode.create({
    key: key,
    iv: iv,
    type: type
  })
}
DES.prototype._update = function (data) {
  return new Buffer(this._des.update(data))
}
DES.prototype._final = function () {
  return new Buffer(this._des.final())
}

}).call(this,require("buffer").Buffer)
},{"buffer":45,"cipher-base":48,"des.js":57,"inherits":94}],37:[function(require,module,exports){
exports['des-ecb'] = {
  key: 8,
  iv: 0
}
exports['des-cbc'] = exports.des = {
  key: 8,
  iv: 8
}
exports['des-ede3-cbc'] = exports.des3 = {
  key: 24,
  iv: 8
}
exports['des-ede3'] = {
  key: 24,
  iv: 0
}
exports['des-ede-cbc'] = {
  key: 16,
  iv: 8
}
exports['des-ede'] = {
  key: 16,
  iv: 0
}

},{}],38:[function(require,module,exports){
(function (Buffer){
var bn = require('bn.js');
var randomBytes = require('randombytes');
module.exports = crt;
function blind(priv) {
  var r = getr(priv);
  var blinder = r.toRed(bn.mont(priv.modulus))
  .redPow(new bn(priv.publicExponent)).fromRed();
  return {
    blinder: blinder,
    unblinder:r.invm(priv.modulus)
  };
}
function crt(msg, priv) {
  var blinds = blind(priv);
  var len = priv.modulus.byteLength();
  var mod = bn.mont(priv.modulus);
  var blinded = new bn(msg).mul(blinds.blinder).umod(priv.modulus);
  var c1 = blinded.toRed(bn.mont(priv.prime1));
  var c2 = blinded.toRed(bn.mont(priv.prime2));
  var qinv = priv.coefficient;
  var p = priv.prime1;
  var q = priv.prime2;
  var m1 = c1.redPow(priv.exponent1);
  var m2 = c2.redPow(priv.exponent2);
  m1 = m1.fromRed();
  m2 = m2.fromRed();
  var h = m1.isub(m2).imul(qinv).umod(p);
  h.imul(q);
  m2.iadd(h);
  return new Buffer(m2.imul(blinds.unblinder).umod(priv.modulus).toArray(false, len));
}
crt.getr = getr;
function getr(priv) {
  var len = priv.modulus.byteLength();
  var r = new bn(randomBytes(len));
  while (r.cmp(priv.modulus) >=  0 || !r.umod(priv.prime1) || !r.umod(priv.prime2)) {
    r = new bn(randomBytes(len));
  }
  return r;
}

}).call(this,require("buffer").Buffer)
},{"bn.js":16,"buffer":45,"randombytes":112}],39:[function(require,module,exports){
(function (Buffer){
'use strict'
exports['RSA-SHA224'] = exports.sha224WithRSAEncryption = {
  sign: 'rsa',
  hash: 'sha224',
  id: new Buffer('302d300d06096086480165030402040500041c', 'hex')
}
exports['RSA-SHA256'] = exports.sha256WithRSAEncryption = {
  sign: 'rsa',
  hash: 'sha256',
  id: new Buffer('3031300d060960864801650304020105000420', 'hex')
}
exports['RSA-SHA384'] = exports.sha384WithRSAEncryption = {
  sign: 'rsa',
  hash: 'sha384',
  id: new Buffer('3041300d060960864801650304020205000430', 'hex')
}
exports['RSA-SHA512'] = exports.sha512WithRSAEncryption = {
  sign: 'rsa',
  hash: 'sha512',
  id: new Buffer('3051300d060960864801650304020305000440', 'hex')
}
exports['RSA-SHA1'] = {
  sign: 'rsa',
  hash: 'sha1',
  id: new Buffer('3021300906052b0e03021a05000414', 'hex')
}
exports['ecdsa-with-SHA1'] = {
  sign: 'ecdsa',
  hash: 'sha1',
  id: new Buffer('', 'hex')
}

exports.DSA = exports['DSA-SHA1'] = exports['DSA-SHA'] = {
  sign: 'dsa',
  hash: 'sha1',
  id: new Buffer('', 'hex')
}
exports['DSA-SHA224'] = exports['DSA-WITH-SHA224'] = {
  sign: 'dsa',
  hash: 'sha224',
  id: new Buffer('', 'hex')
}
exports['DSA-SHA256'] = exports['DSA-WITH-SHA256'] = {
  sign: 'dsa',
  hash: 'sha256',
  id: new Buffer('', 'hex')
}
exports['DSA-SHA384'] = exports['DSA-WITH-SHA384'] = {
  sign: 'dsa',
  hash: 'sha384',
  id: new Buffer('', 'hex')
}
exports['DSA-SHA512'] = exports['DSA-WITH-SHA512'] = {
  sign: 'dsa',
  hash: 'sha512',
  id: new Buffer('', 'hex')
}
exports['DSA-RIPEMD160'] = {
  sign: 'dsa',
  hash: 'rmd160',
  id: new Buffer('', 'hex')
}
exports['RSA-RIPEMD160'] = exports.ripemd160WithRSA = {
  sign: 'rsa',
  hash: 'rmd160',
  id: new Buffer('3021300906052b2403020105000414', 'hex')
}
exports['RSA-MD5'] = exports.md5WithRSAEncryption = {
  sign: 'rsa',
  hash: 'md5',
  id: new Buffer('3020300c06082a864886f70d020505000410', 'hex')
}

}).call(this,require("buffer").Buffer)
},{"buffer":45}],40:[function(require,module,exports){
(function (Buffer){
var _algos = require('./algos')
var createHash = require('create-hash')
var inherits = require('inherits')
var sign = require('./sign')
var stream = require('stream')
var verify = require('./verify')

var algos = {}
Object.keys(_algos).forEach(function (key) {
  algos[key] = algos[key.toLowerCase()] = _algos[key]
})

function Sign (algorithm) {
  stream.Writable.call(this)

  var data = algos[algorithm]
  if (!data) {
    throw new Error('Unknown message digest')
  }

  this._hashType = data.hash
  this._hash = createHash(data.hash)
  this._tag = data.id
  this._signType = data.sign
}
inherits(Sign, stream.Writable)

Sign.prototype._write = function _write (data, _, done) {
  this._hash.update(data)
  done()
}

Sign.prototype.update = function update (data, enc) {
  if (typeof data === 'string') {
    data = new Buffer(data, enc)
  }

  this._hash.update(data)
  return this
}

Sign.prototype.sign = function signMethod (key, enc) {
  this.end()
  var hash = this._hash.digest()
  var sig = sign(Buffer.concat([this._tag, hash]), key, this._hashType, this._signType)

  return enc ? sig.toString(enc) : sig
}

function Verify (algorithm) {
  stream.Writable.call(this)

  var data = algos[algorithm]
  if (!data) {
    throw new Error('Unknown message digest')
  }

  this._hash = createHash(data.hash)
  this._tag = data.id
  this._signType = data.sign
}
inherits(Verify, stream.Writable)

Verify.prototype._write = function _write (data, _, done) {
  this._hash.update(data)

  done()
}

Verify.prototype.update = function update (data, enc) {
  if (typeof data === 'string') {
    data = new Buffer(data, enc)
  }

  this._hash.update(data)
  return this
}

Verify.prototype.verify = function verifyMethod (key, sig, enc) {
  if (typeof sig === 'string') {
    sig = new Buffer(sig, enc)
  }

  this.end()
  var hash = this._hash.digest()

  return verify(sig, Buffer.concat([this._tag, hash]), key, this._signType)
}

function createSign (algorithm) {
  return new Sign(algorithm)
}

function createVerify (algorithm) {
  return new Verify(algorithm)
}

module.exports = {
  Sign: createSign,
  Verify: createVerify,
  createSign: createSign,
  createVerify: createVerify
}

}).call(this,require("buffer").Buffer)
},{"./algos":39,"./sign":42,"./verify":43,"buffer":45,"create-hash":51,"inherits":94,"stream":133}],41:[function(require,module,exports){
'use strict'
exports['1.3.132.0.10'] = 'secp256k1'

exports['1.3.132.0.33'] = 'p224'

exports['1.2.840.10045.3.1.1'] = 'p192'

exports['1.2.840.10045.3.1.7'] = 'p256'

exports['1.3.132.0.34'] = 'p384'

exports['1.3.132.0.35'] = 'p521'

},{}],42:[function(require,module,exports){
(function (Buffer){
// much of this based on https://github.com/indutny/self-signed/blob/gh-pages/lib/rsa.js
var createHmac = require('create-hmac')
var crt = require('browserify-rsa')
var curves = require('./curves')
var elliptic = require('elliptic')
var parseKeys = require('parse-asn1')

var BN = require('bn.js')
var EC = elliptic.ec

function sign (hash, key, hashType, signType) {
  var priv = parseKeys(key)
  if (priv.curve) {
    if (signType !== 'ecdsa') throw new Error('wrong private key type')

    return ecSign(hash, priv)
  } else if (priv.type === 'dsa') {
    if (signType !== 'dsa') {
      throw new Error('wrong private key type')
    }
    return dsaSign(hash, priv, hashType)
  } else {
    if (signType !== 'rsa') throw new Error('wrong private key type')
  }

  var len = priv.modulus.byteLength()
  var pad = [ 0, 1 ]
  while (hash.length + pad.length + 1 < len) {
    pad.push(0xff)
  }
  pad.push(0x00)
  var i = -1
  while (++i < hash.length) {
    pad.push(hash[i])
  }

  var out = crt(pad, priv)
  return out
}

function ecSign (hash, priv) {
  var curveId = curves[priv.curve.join('.')]
  if (!curveId) throw new Error('unknown curve ' + priv.curve.join('.'))

  var curve = new EC(curveId)
  var key = curve.genKeyPair()

  key._importPrivate(priv.privateKey)
  var out = key.sign(hash)

  return new Buffer(out.toDER())
}

function dsaSign (hash, priv, algo) {
  var x = priv.params.priv_key
  var p = priv.params.p
  var q = priv.params.q
  var g = priv.params.g
  var r = new BN(0)
  var k
  var H = bits2int(hash, q).mod(q)
  var s = false
  var kv = getKey(x, q, hash, algo)
  while (s === false) {
    k = makeKey(q, kv, algo)
    r = makeR(g, k, p, q)
    s = k.invm(q).imul(H.add(x.mul(r))).mod(q)
    if (!s.cmpn(0)) {
      s = false
      r = new BN(0)
    }
  }
  return toDER(r, s)
}

function toDER (r, s) {
  r = r.toArray()
  s = s.toArray()

  // Pad values
  if (r[0] & 0x80) {
    r = [ 0 ].concat(r)
  }
  // Pad values
  if (s[0] & 0x80) {
    s = [0].concat(s)
  }

  var total = r.length + s.length + 4
  var res = [ 0x30, total, 0x02, r.length ]
  res = res.concat(r, [ 0x02, s.length ], s)
  return new Buffer(res)
}

function getKey (x, q, hash, algo) {
  x = new Buffer(x.toArray())
  if (x.length < q.byteLength()) {
    var zeros = new Buffer(q.byteLength() - x.length)
    zeros.fill(0)
    x = Buffer.concat([zeros, x])
  }
  var hlen = hash.length
  var hbits = bits2octets(hash, q)
  var v = new Buffer(hlen)
  v.fill(1)
  var k = new Buffer(hlen)
  k.fill(0)
  k = createHmac(algo, k)
    .update(v)
    .update(new Buffer([0]))
    .update(x)
    .update(hbits)
    .digest()
  v = createHmac(algo, k)
    .update(v)
    .digest()
  k = createHmac(algo, k)
    .update(v)
    .update(new Buffer([1]))
    .update(x)
    .update(hbits)
    .digest()
  v = createHmac(algo, k)
    .update(v)
    .digest()
  return {
    k: k,
    v: v
  }
}

function bits2int (obits, q) {
  var bits = new BN(obits)
  var shift = (obits.length << 3) - q.bitLength()
  if (shift > 0) {
    bits.ishrn(shift)
  }
  return bits
}

function bits2octets (bits, q) {
  bits = bits2int(bits, q)
  bits = bits.mod(q)
  var out = new Buffer(bits.toArray())
  if (out.length < q.byteLength()) {
    var zeros = new Buffer(q.byteLength() - out.length)
    zeros.fill(0)
    out = Buffer.concat([zeros, out])
  }
  return out
}

function makeKey (q, kv, algo) {
  var t, k

  do {
    t = new Buffer('')

    while (t.length * 8 < q.bitLength()) {
      kv.v = createHmac(algo, kv.k)
        .update(kv.v)
        .digest()
      t = Buffer.concat([t, kv.v])
    }

    k = bits2int(t, q)
    kv.k = createHmac(algo, kv.k)
      .update(kv.v)
      .update(new Buffer([0]))
      .digest()
    kv.v = createHmac(algo, kv.k)
      .update(kv.v)
      .digest()
  } while (k.cmp(q) !== -1)

  return k
}

function makeR (g, k, p, q) {
  return g.toRed(BN.mont(p)).redPow(k).fromRed().mod(q)
}

module.exports = sign
module.exports.getKey = getKey
module.exports.makeKey = makeKey

}).call(this,require("buffer").Buffer)
},{"./curves":41,"bn.js":16,"browserify-rsa":38,"buffer":45,"create-hmac":55,"elliptic":67,"parse-asn1":101}],43:[function(require,module,exports){
(function (Buffer){
// much of this based on https://github.com/indutny/self-signed/blob/gh-pages/lib/rsa.js
var curves = require('./curves')
var elliptic = require('elliptic')
var parseKeys = require('parse-asn1')

var BN = require('bn.js')
var EC = elliptic.ec

function verify (sig, hash, key, signType) {
  var pub = parseKeys(key)
  if (pub.type === 'ec') {
    if (signType !== 'ecdsa') {
      throw new Error('wrong public key type')
    }
    return ecVerify(sig, hash, pub)
  } else if (pub.type === 'dsa') {
    if (signType !== 'dsa') {
      throw new Error('wrong public key type')
    }
    return dsaVerify(sig, hash, pub)
  } else {
    if (signType !== 'rsa') {
      throw new Error('wrong public key type')
    }
  }
  var len = pub.modulus.byteLength()
  var pad = [ 1 ]
  var padNum = 0
  while (hash.length + pad.length + 2 < len) {
    pad.push(0xff)
    padNum++
  }
  pad.push(0x00)
  var i = -1
  while (++i < hash.length) {
    pad.push(hash[i])
  }
  pad = new Buffer(pad)
  var red = BN.mont(pub.modulus)
  sig = new BN(sig).toRed(red)

  sig = sig.redPow(new BN(pub.publicExponent))

  sig = new Buffer(sig.fromRed().toArray())
  var out = 0
  if (padNum < 8) {
    out = 1
  }
  len = Math.min(sig.length, pad.length)
  if (sig.length !== pad.length) {
    out = 1
  }

  i = -1
  while (++i < len) {
    out |= (sig[i] ^ pad[i])
  }
  return out === 0
}

function ecVerify (sig, hash, pub) {
  var curveId = curves[pub.data.algorithm.curve.join('.')]
  if (!curveId) throw new Error('unknown curve ' + pub.data.algorithm.curve.join('.'))

  var curve = new EC(curveId)
  var pubkey = pub.data.subjectPrivateKey.data

  return curve.verify(hash, sig, pubkey)
}

function dsaVerify (sig, hash, pub) {
  var p = pub.data.p
  var q = pub.data.q
  var g = pub.data.g
  var y = pub.data.pub_key
  var unpacked = parseKeys.signature.decode(sig, 'der')
  var s = unpacked.s
  var r = unpacked.r
  checkValue(s, q)
  checkValue(r, q)
  var montp = BN.mont(p)
  var w = s.invm(q)
  var v = g.toRed(montp)
    .redPow(new BN(hash).mul(w).mod(q))
    .fromRed()
    .mul(
      y.toRed(montp)
        .redPow(r.mul(w).mod(q))
        .fromRed()
  ).mod(p).mod(q)
  return !v.cmp(r)
}

function checkValue (b, q) {
  if (b.cmpn(0) <= 0) {
    throw new Error('invalid sig')
  }
  if (b.cmp(q) >= q) {
    throw new Error('invalid sig')
  }
}

module.exports = verify

}).call(this,require("buffer").Buffer)
},{"./curves":41,"bn.js":16,"buffer":45,"elliptic":67,"parse-asn1":101}],44:[function(require,module,exports){
arguments[4][18][0].apply(exports,arguments)
},{"dup":18}],45:[function(require,module,exports){
(function (global){
/*!
 * The buffer module from node.js, for the browser.
 *
 * @author   Feross Aboukhadijeh <http://feross.org>
 * @license  MIT
 */
/* eslint-disable no-proto */

'use strict'

var base64 = require('base64-js')
var ieee754 = require('ieee754')
var isArray = require('isarray')

exports.Buffer = Buffer
exports.SlowBuffer = SlowBuffer
exports.INSPECT_MAX_BYTES = 50

/**
 * If `Buffer.TYPED_ARRAY_SUPPORT`:
 *   === true    Use Uint8Array implementation (fastest)
 *   === false   Use Object implementation (most compatible, even IE6)
 *
 * Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+,
 * Opera 11.6+, iOS 4.2+.
 *
 * Due to various browser bugs, sometimes the Object implementation will be used even
 * when the browser supports typed arrays.
 *
 * Note:
 *
 *   - Firefox 4-29 lacks support for adding new properties to `Uint8Array` instances,
 *     See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438.
 *
 *   - Chrome 9-10 is missing the `TypedArray.prototype.subarray` function.
 *
 *   - IE10 has a broken `TypedArray.prototype.subarray` function which returns arrays of
 *     incorrect length in some situations.

 * We detect these buggy browsers and set `Buffer.TYPED_ARRAY_SUPPORT` to `false` so they
 * get the Object implementation, which is slower but behaves correctly.
 */
Buffer.TYPED_ARRAY_SUPPORT = global.TYPED_ARRAY_SUPPORT !== undefined
  ? global.TYPED_ARRAY_SUPPORT
  : typedArraySupport()

/*
 * Export kMaxLength after typed array support is determined.
 */
exports.kMaxLength = kMaxLength()

function typedArraySupport () {
  try {
    var arr = new Uint8Array(1)
    arr.__proto__ = {__proto__: Uint8Array.prototype, foo: function () { return 42 }}
    return arr.foo() === 42 && // typed array instances can be augmented
        typeof arr.subarray === 'function' && // chrome 9-10 lack `subarray`
        arr.subarray(1, 1).byteLength === 0 // ie10 has broken `subarray`
  } catch (e) {
    return false
  }
}

function kMaxLength () {
  return Buffer.TYPED_ARRAY_SUPPORT
    ? 0x7fffffff
    : 0x3fffffff
}

function createBuffer (that, length) {
  if (kMaxLength() < length) {
    throw new RangeError('Invalid typed array length')
  }
  if (Buffer.TYPED_ARRAY_SUPPORT) {
    // Return an augmented `Uint8Array` instance, for best performance
    that = new Uint8Array(length)
    that.__proto__ = Buffer.prototype
  } else {
    // Fallback: Return an object instance of the Buffer class
    if (that === null) {
      that = new Buffer(length)
    }
    that.length = length
  }

  return that
}

/**
 * The Buffer constructor returns instances of `Uint8Array` that have their
 * prototype changed to `Buffer.prototype`. Furthermore, `Buffer` is a subclass of
 * `Uint8Array`, so the returned instances will have all the node `Buffer` methods
 * and the `Uint8Array` methods. Square bracket notation works as expected -- it
 * returns a single octet.
 *
 * The `Uint8Array` prototype remains unmodified.
 */

function Buffer (arg, encodingOrOffset, length) {
  if (!Buffer.TYPED_ARRAY_SUPPORT && !(this instanceof Buffer)) {
    return new Buffer(arg, encodingOrOffset, length)
  }

  // Common case.
  if (typeof arg === 'number') {
    if (typeof encodingOrOffset === 'string') {
      throw new Error(
        'If encoding is specified then the first argument must be a string'
      )
    }
    return allocUnsafe(this, arg)
  }
  return from(this, arg, encodingOrOffset, length)
}

Buffer.poolSize = 8192 // not used by this implementation

// TODO: Legacy, not needed anymore. Remove in next major version.
Buffer._augment = function (arr) {
  arr.__proto__ = Buffer.prototype
  return arr
}

function from (that, value, encodingOrOffset, length) {
  if (typeof value === 'number') {
    throw new TypeError('"value" argument must not be a number')
  }

  if (typeof ArrayBuffer !== 'undefined' && value instanceof ArrayBuffer) {
    return fromArrayBuffer(that, value, encodingOrOffset, length)
  }

  if (typeof value === 'string') {
    return fromString(that, value, encodingOrOffset)
  }

  return fromObject(that, value)
}

/**
 * Functionally equivalent to Buffer(arg, encoding) but throws a TypeError
 * if value is a number.
 * Buffer.from(str[, encoding])
 * Buffer.from(array)
 * Buffer.from(buffer)
 * Buffer.from(arrayBuffer[, byteOffset[, length]])
 **/
Buffer.from = function (value, encodingOrOffset, length) {
  return from(null, value, encodingOrOffset, length)
}

if (Buffer.TYPED_ARRAY_SUPPORT) {
  Buffer.prototype.__proto__ = Uint8Array.prototype
  Buffer.__proto__ = Uint8Array
  if (typeof Symbol !== 'undefined' && Symbol.species &&
      Buffer[Symbol.species] === Buffer) {
    // Fix subarray() in ES2016. See: https://github.com/feross/buffer/pull/97
    Object.defineProperty(Buffer, Symbol.species, {
      value: null,
      configurable: true
    })
  }
}

function assertSize (size) {
  if (typeof size !== 'number') {
    throw new TypeError('"size" argument must be a number')
  } else if (size < 0) {
    throw new RangeError('"size" argument must not be negative')
  }
}

function alloc (that, size, fill, encoding) {
  assertSize(size)
  if (size <= 0) {
    return createBuffer(that, size)
  }
  if (fill !== undefined) {
    // Only pay attention to encoding if it's a string. This
    // prevents accidentally sending in a number that would
    // be interpretted as a start offset.
    return typeof encoding === 'string'
      ? createBuffer(that, size).fill(fill, encoding)
      : createBuffer(that, size).fill(fill)
  }
  return createBuffer(that, size)
}

/**
 * Creates a new filled Buffer instance.
 * alloc(size[, fill[, encoding]])
 **/
Buffer.alloc = function (size, fill, encoding) {
  return alloc(null, size, fill, encoding)
}

function allocUnsafe (that, size) {
  assertSize(size)
  that = createBuffer(that, size < 0 ? 0 : checked(size) | 0)
  if (!Buffer.TYPED_ARRAY_SUPPORT) {
    for (var i = 0; i < size; ++i) {
      that[i] = 0
    }
  }
  return that
}

/**
 * Equivalent to Buffer(num), by default creates a non-zero-filled Buffer instance.
 * */
Buffer.allocUnsafe = function (size) {
  return allocUnsafe(null, size)
}
/**
 * Equivalent to SlowBuffer(num), by default creates a non-zero-filled Buffer instance.
 */
Buffer.allocUnsafeSlow = function (size) {
  return allocUnsafe(null, size)
}

function fromString (that, string, encoding) {
  if (typeof encoding !== 'string' || encoding === '') {
    encoding = 'utf8'
  }

  if (!Buffer.isEncoding(encoding)) {
    throw new TypeError('"encoding" must be a valid string encoding')
  }

  var length = byteLength(string, encoding) | 0
  that = createBuffer(that, length)

  var actual = that.write(string, encoding)

  if (actual !== length) {
    // Writing a hex string, for example, that contains invalid characters will
    // cause everything after the first invalid character to be ignored. (e.g.
    // 'abxxcd' will be treated as 'ab')
    that = that.slice(0, actual)
  }

  return that
}

function fromArrayLike (that, array) {
  var length = array.length < 0 ? 0 : checked(array.length) | 0
  that = createBuffer(that, length)
  for (var i = 0; i < length; i += 1) {
    that[i] = array[i] & 255
  }
  return that
}

function fromArrayBuffer (that, array, byteOffset, length) {
  array.byteLength // this throws if `array` is not a valid ArrayBuffer

  if (byteOffset < 0 || array.byteLength < byteOffset) {
    throw new RangeError('\'offset\' is out of bounds')
  }

  if (array.byteLength < byteOffset + (length || 0)) {
    throw new RangeError('\'length\' is out of bounds')
  }

  if (byteOffset === undefined && length === undefined) {
    array = new Uint8Array(array)
  } else if (length === undefined) {
    array = new Uint8Array(array, byteOffset)
  } else {
    array = new Uint8Array(array, byteOffset, length)
  }

  if (Buffer.TYPED_ARRAY_SUPPORT) {
    // Return an augmented `Uint8Array` instance, for best performance
    that = array
    that.__proto__ = Buffer.prototype
  } else {
    // Fallback: Return an object instance of the Buffer class
    that = fromArrayLike(that, array)
  }
  return that
}

function fromObject (that, obj) {
  if (Buffer.isBuffer(obj)) {
    var len = checked(obj.length) | 0
    that = createBuffer(that, len)

    if (that.length === 0) {
      return that
    }

    obj.copy(that, 0, 0, len)
    return that
  }

  if (obj) {
    if ((typeof ArrayBuffer !== 'undefined' &&
        obj.buffer instanceof ArrayBuffer) || 'length' in obj) {
      if (typeof obj.length !== 'number' || isnan(obj.length)) {
        return createBuffer(that, 0)
      }
      return fromArrayLike(that, obj)
    }

    if (obj.type === 'Buffer' && isArray(obj.data)) {
      return fromArrayLike(that, obj.data)
    }
  }

  throw new TypeError('First argument must be a string, Buffer, ArrayBuffer, Array, or array-like object.')
}

function checked (length) {
  // Note: cannot use `length < kMaxLength()` here because that fails when
  // length is NaN (which is otherwise coerced to zero.)
  if (length >= kMaxLength()) {
    throw new RangeError('Attempt to allocate Buffer larger than maximum ' +
                         'size: 0x' + kMaxLength().toString(16) + ' bytes')
  }
  return length | 0
}

function SlowBuffer (length) {
  if (+length != length) { // eslint-disable-line eqeqeq
    length = 0
  }
  return Buffer.alloc(+length)
}

Buffer.isBuffer = function isBuffer (b) {
  return !!(b != null && b._isBuffer)
}

Buffer.compare = function compare (a, b) {
  if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) {
    throw new TypeError('Arguments must be Buffers')
  }

  if (a === b) return 0

  var x = a.length
  var y = b.length

  for (var i = 0, len = Math.min(x, y); i < len; ++i) {
    if (a[i] !== b[i]) {
      x = a[i]
      y = b[i]
      break
    }
  }

  if (x < y) return -1
  if (y < x) return 1
  return 0
}

Buffer.isEncoding = function isEncoding (encoding) {
  switch (String(encoding).toLowerCase()) {
    case 'hex':
    case 'utf8':
    case 'utf-8':
    case 'ascii':
    case 'latin1':
    case 'binary':
    case 'base64':
    case 'ucs2':
    case 'ucs-2':
    case 'utf16le':
    case 'utf-16le':
      return true
    default:
      return false
  }
}

Buffer.concat = function concat (list, length) {
  if (!isArray(list)) {
    throw new TypeError('"list" argument must be an Array of Buffers')
  }

  if (list.length === 0) {
    return Buffer.alloc(0)
  }

  var i
  if (length === undefined) {
    length = 0
    for (i = 0; i < list.length; ++i) {
      length += list[i].length
    }
  }

  var buffer = Buffer.allocUnsafe(length)
  var pos = 0
  for (i = 0; i < list.length; ++i) {
    var buf = list[i]
    if (!Buffer.isBuffer(buf)) {
      throw new TypeError('"list" argument must be an Array of Buffers')
    }
    buf.copy(buffer, pos)
    pos += buf.length
  }
  return buffer
}

function byteLength (string, encoding) {
  if (Buffer.isBuffer(string)) {
    return string.length
  }
  if (typeof ArrayBuffer !== 'undefined' && typeof ArrayBuffer.isView === 'function' &&
      (ArrayBuffer.isView(string) || string instanceof ArrayBuffer)) {
    return string.byteLength
  }
  if (typeof string !== 'string') {
    string = '' + string
  }

  var len = string.length
  if (len === 0) return 0

  // Use a for loop to avoid recursion
  var loweredCase = false
  for (;;) {
    switch (encoding) {
      case 'ascii':
      case 'latin1':
      case 'binary':
        return len
      case 'utf8':
      case 'utf-8':
      case undefined:
        return utf8ToBytes(string).length
      case 'ucs2':
      case 'ucs-2':
      case 'utf16le':
      case 'utf-16le':
        return len * 2
      case 'hex':
        return len >>> 1
      case 'base64':
        return base64ToBytes(string).length
      default:
        if (loweredCase) return utf8ToBytes(string).length // assume utf8
        encoding = ('' + encoding).toLowerCase()
        loweredCase = true
    }
  }
}
Buffer.byteLength = byteLength

function slowToString (encoding, start, end) {
  var loweredCase = false

  // No need to verify that "this.length <= MAX_UINT32" since it's a read-only
  // property of a typed array.

  // This behaves neither like String nor Uint8Array in that we set start/end
  // to their upper/lower bounds if the value passed is out of range.
  // undefined is handled specially as per ECMA-262 6th Edition,
  // Section 13.3.3.7 Runtime Semantics: KeyedBindingInitialization.
  if (start === undefined || start < 0) {
    start = 0
  }
  // Return early if start > this.length. Done here to prevent potential uint32
  // coercion fail below.
  if (start > this.length) {
    return ''
  }

  if (end === undefined || end > this.length) {
    end = this.length
  }

  if (end <= 0) {
    return ''
  }

  // Force coersion to uint32. This will also coerce falsey/NaN values to 0.
  end >>>= 0
  start >>>= 0

  if (end <= start) {
    return ''
  }

  if (!encoding) encoding = 'utf8'

  while (true) {
    switch (encoding) {
      case 'hex':
        return hexSlice(this, start, end)

      case 'utf8':
      case 'utf-8':
        return utf8Slice(this, start, end)

      case 'ascii':
        return asciiSlice(this, start, end)

      case 'latin1':
      case 'binary':
        return latin1Slice(this, start, end)

      case 'base64':
        return base64Slice(this, start, end)

      case 'ucs2':
      case 'ucs-2':
      case 'utf16le':
      case 'utf-16le':
        return utf16leSlice(this, start, end)

      default:
        if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding)
        encoding = (encoding + '').toLowerCase()
        loweredCase = true
    }
  }
}

// The property is used by `Buffer.isBuffer` and `is-buffer` (in Safari 5-7) to detect
// Buffer instances.
Buffer.prototype._isBuffer = true

function swap (b, n, m) {
  var i = b[n]
  b[n] = b[m]
  b[m] = i
}

Buffer.prototype.swap16 = function swap16 () {
  var len = this.length
  if (len % 2 !== 0) {
    throw new RangeError('Buffer size must be a multiple of 16-bits')
  }
  for (var i = 0; i < len; i += 2) {
    swap(this, i, i + 1)
  }
  return this
}

Buffer.prototype.swap32 = function swap32 () {
  var len = this.length
  if (len % 4 !== 0) {
    throw new RangeError('Buffer size must be a multiple of 32-bits')
  }
  for (var i = 0; i < len; i += 4) {
    swap(this, i, i + 3)
    swap(this, i + 1, i + 2)
  }
  return this
}

Buffer.prototype.swap64 = function swap64 () {
  var len = this.length
  if (len % 8 !== 0) {
    throw new RangeError('Buffer size must be a multiple of 64-bits')
  }
  for (var i = 0; i < len; i += 8) {
    swap(this, i, i + 7)
    swap(this, i + 1, i + 6)
    swap(this, i + 2, i + 5)
    swap(this, i + 3, i + 4)
  }
  return this
}

Buffer.prototype.toString = function toString () {
  var length = this.length | 0
  if (length === 0) return ''
  if (arguments.length === 0) return utf8Slice(this, 0, length)
  return slowToString.apply(this, arguments)
}

Buffer.prototype.equals = function equals (b) {
  if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer')
  if (this === b) return true
  return Buffer.compare(this, b) === 0
}

Buffer.prototype.inspect = function inspect () {
  var str = ''
  var max = exports.INSPECT_MAX_BYTES
  if (this.length > 0) {
    str = this.toString('hex', 0, max).match(/.{2}/g).join(' ')
    if (this.length > max) str += ' ... '
  }
  return '<Buffer ' + str + '>'
}

Buffer.prototype.compare = function compare (target, start, end, thisStart, thisEnd) {
  if (!Buffer.isBuffer(target)) {
    throw new TypeError('Argument must be a Buffer')
  }

  if (start === undefined) {
    start = 0
  }
  if (end === undefined) {
    end = target ? target.length : 0
  }
  if (thisStart === undefined) {
    thisStart = 0
  }
  if (thisEnd === undefined) {
    thisEnd = this.length
  }

  if (start < 0 || end > target.length || thisStart < 0 || thisEnd > this.length) {
    throw new RangeError('out of range index')
  }

  if (thisStart >= thisEnd && start >= end) {
    return 0
  }
  if (thisStart >= thisEnd) {
    return -1
  }
  if (start >= end) {
    return 1
  }

  start >>>= 0
  end >>>= 0
  thisStart >>>= 0
  thisEnd >>>= 0

  if (this === target) return 0

  var x = thisEnd - thisStart
  var y = end - start
  var len = Math.min(x, y)

  var thisCopy = this.slice(thisStart, thisEnd)
  var targetCopy = target.slice(start, end)

  for (var i = 0; i < len; ++i) {
    if (thisCopy[i] !== targetCopy[i]) {
      x = thisCopy[i]
      y = targetCopy[i]
      break
    }
  }

  if (x < y) return -1
  if (y < x) return 1
  return 0
}

// Finds either the first index of `val` in `buffer` at offset >= `byteOffset`,
// OR the last index of `val` in `buffer` at offset <= `byteOffset`.
//
// Arguments:
// - buffer - a Buffer to search
// - val - a string, Buffer, or number
// - byteOffset - an index into `buffer`; will be clamped to an int32
// - encoding - an optional encoding, relevant is val is a string
// - dir - true for indexOf, false for lastIndexOf
function bidirectionalIndexOf (buffer, val, byteOffset, encoding, dir) {
  // Empty buffer means no match
  if (buffer.length === 0) return -1

  // Normalize byteOffset
  if (typeof byteOffset === 'string') {
    encoding = byteOffset
    byteOffset = 0
  } else if (byteOffset > 0x7fffffff) {
    byteOffset = 0x7fffffff
  } else if (byteOffset < -0x80000000) {
    byteOffset = -0x80000000
  }
  byteOffset = +byteOffset  // Coerce to Number.
  if (isNaN(byteOffset)) {
    // byteOffset: it it's undefined, null, NaN, "foo", etc, search whole buffer
    byteOffset = dir ? 0 : (buffer.length - 1)
  }

  // Normalize byteOffset: negative offsets start from the end of the buffer
  if (byteOffset < 0) byteOffset = buffer.length + byteOffset
  if (byteOffset >= buffer.length) {
    if (dir) return -1
    else byteOffset = buffer.length - 1
  } else if (byteOffset < 0) {
    if (dir) byteOffset = 0
    else return -1
  }

  // Normalize val
  if (typeof val === 'string') {
    val = Buffer.from(val, encoding)
  }

  // Finally, search either indexOf (if dir is true) or lastIndexOf
  if (Buffer.isBuffer(val)) {
    // Special case: looking for empty string/buffer always fails
    if (val.length === 0) {
      return -1
    }
    return arrayIndexOf(buffer, val, byteOffset, encoding, dir)
  } else if (typeof val === 'number') {
    val = val & 0xFF // Search for a byte value [0-255]
    if (Buffer.TYPED_ARRAY_SUPPORT &&
        typeof Uint8Array.prototype.indexOf === 'function') {
      if (dir) {
        return Uint8Array.prototype.indexOf.call(buffer, val, byteOffset)
      } else {
        return Uint8Array.prototype.lastIndexOf.call(buffer, val, byteOffset)
      }
    }
    return arrayIndexOf(buffer, [ val ], byteOffset, encoding, dir)
  }

  throw new TypeError('val must be string, number or Buffer')
}

function arrayIndexOf (arr, val, byteOffset, encoding, dir) {
  var indexSize = 1
  var arrLength = arr.length
  var valLength = val.length

  if (encoding !== undefined) {
    encoding = String(encoding).toLowerCase()
    if (encoding === 'ucs2' || encoding === 'ucs-2' ||
        encoding === 'utf16le' || encoding === 'utf-16le') {
      if (arr.length < 2 || val.length < 2) {
        return -1
      }
      indexSize = 2
      arrLength /= 2
      valLength /= 2
      byteOffset /= 2
    }
  }

  function read (buf, i) {
    if (indexSize === 1) {
      return buf[i]
    } else {
      return buf.readUInt16BE(i * indexSize)
    }
  }

  var i
  if (dir) {
    var foundIndex = -1
    for (i = byteOffset; i < arrLength; i++) {
      if (read(arr, i) === read(val, foundIndex === -1 ? 0 : i - foundIndex)) {
        if (foundIndex === -1) foundIndex = i
        if (i - foundIndex + 1 === valLength) return foundIndex * indexSize
      } else {
        if (foundIndex !== -1) i -= i - foundIndex
        foundIndex = -1
      }
    }
  } else {
    if (byteOffset + valLength > arrLength) byteOffset = arrLength - valLength
    for (i = byteOffset; i >= 0; i--) {
      var found = true
      for (var j = 0; j < valLength; j++) {
        if (read(arr, i + j) !== read(val, j)) {
          found = false
          break
        }
      }
      if (found) return i
    }
  }

  return -1
}

Buffer.prototype.includes = function includes (val, byteOffset, encoding) {
  return this.indexOf(val, byteOffset, encoding) !== -1
}

Buffer.prototype.indexOf = function indexOf (val, byteOffset, encoding) {
  return bidirectionalIndexOf(this, val, byteOffset, encoding, true)
}

Buffer.prototype.lastIndexOf = function lastIndexOf (val, byteOffset, encoding) {
  return bidirectionalIndexOf(this, val, byteOffset, encoding, false)
}

function hexWrite (buf, string, offset, length) {
  offset = Number(offset) || 0
  var remaining = buf.length - offset
  if (!length) {
    length = remaining
  } else {
    length = Number(length)
    if (length > remaining) {
      length = remaining
    }
  }

  // must be an even number of digits
  var strLen = string.length
  if (strLen % 2 !== 0) throw new TypeError('Invalid hex string')

  if (length > strLen / 2) {
    length = strLen / 2
  }
  for (var i = 0; i < length; ++i) {
    var parsed = parseInt(string.substr(i * 2, 2), 16)
    if (isNaN(parsed)) return i
    buf[offset + i] = parsed
  }
  return i
}

function utf8Write (buf, string, offset, length) {
  return blitBuffer(utf8ToBytes(string, buf.length - offset), buf, offset, length)
}

function asciiWrite (buf, string, offset, length) {
  return blitBuffer(asciiToBytes(string), buf, offset, length)
}

function latin1Write (buf, string, offset, length) {
  return asciiWrite(buf, string, offset, length)
}

function base64Write (buf, string, offset, length) {
  return blitBuffer(base64ToBytes(string), buf, offset, length)
}

function ucs2Write (buf, string, offset, length) {
  return blitBuffer(utf16leToBytes(string, buf.length - offset), buf, offset, length)
}

Buffer.prototype.write = function write (string, offset, length, encoding) {
  // Buffer#write(string)
  if (offset === undefined) {
    encoding = 'utf8'
    length = this.length
    offset = 0
  // Buffer#write(string, encoding)
  } else if (length === undefined && typeof offset === 'string') {
    encoding = offset
    length = this.length
    offset = 0
  // Buffer#write(string, offset[, length][, encoding])
  } else if (isFinite(offset)) {
    offset = offset | 0
    if (isFinite(length)) {
      length = length | 0
      if (encoding === undefined) encoding = 'utf8'
    } else {
      encoding = length
      length = undefined
    }
  // legacy write(string, encoding, offset, length) - remove in v0.13
  } else {
    throw new Error(
      'Buffer.write(string, encoding, offset[, length]) is no longer supported'
    )
  }

  var remaining = this.length - offset
  if (length === undefined || length > remaining) length = remaining

  if ((string.length > 0 && (length < 0 || offset < 0)) || offset > this.length) {
    throw new RangeError('Attempt to write outside buffer bounds')
  }

  if (!encoding) encoding = 'utf8'

  var loweredCase = false
  for (;;) {
    switch (encoding) {
      case 'hex':
        return hexWrite(this, string, offset, length)

      case 'utf8':
      case 'utf-8':
        return utf8Write(this, string, offset, length)

      case 'ascii':
        return asciiWrite(this, string, offset, length)

      case 'latin1':
      case 'binary':
        return latin1Write(this, string, offset, length)

      case 'base64':
        // Warning: maxLength not taken into account in base64Write
        return base64Write(this, string, offset, length)

      case 'ucs2':
      case 'ucs-2':
      case 'utf16le':
      case 'utf-16le':
        return ucs2Write(this, string, offset, length)

      default:
        if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding)
        encoding = ('' + encoding).toLowerCase()
        loweredCase = true
    }
  }
}

Buffer.prototype.toJSON = function toJSON () {
  return {
    type: 'Buffer',
    data: Array.prototype.slice.call(this._arr || this, 0)
  }
}

function base64Slice (buf, start, end) {
  if (start === 0 && end === buf.length) {
    return base64.fromByteArray(buf)
  } else {
    return base64.fromByteArray(buf.slice(start, end))
  }
}

function utf8Slice (buf, start, end) {
  end = Math.min(buf.length, end)
  var res = []

  var i = start
  while (i < end) {
    var firstByte = buf[i]
    var codePoint = null
    var bytesPerSequence = (firstByte > 0xEF) ? 4
      : (firstByte > 0xDF) ? 3
      : (firstByte > 0xBF) ? 2
      : 1

    if (i + bytesPerSequence <= end) {
      var secondByte, thirdByte, fourthByte, tempCodePoint

      switch (bytesPerSequence) {
        case 1:
          if (firstByte < 0x80) {
            codePoint = firstByte
          }
          break
        case 2:
          secondByte = buf[i + 1]
          if ((secondByte & 0xC0) === 0x80) {
            tempCodePoint = (firstByte & 0x1F) << 0x6 | (secondByte & 0x3F)
            if (tempCodePoint > 0x7F) {
              codePoint = tempCodePoint
            }
          }
          break
        case 3:
          secondByte = buf[i + 1]
          thirdByte = buf[i + 2]
          if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80) {
            tempCodePoint = (firstByte & 0xF) << 0xC | (secondByte & 0x3F) << 0x6 | (thirdByte & 0x3F)
            if (tempCodePoint > 0x7FF && (tempCodePoint < 0xD800 || tempCodePoint > 0xDFFF)) {
              codePoint = tempCodePoint
            }
          }
          break
        case 4:
          secondByte = buf[i + 1]
          thirdByte = buf[i + 2]
          fourthByte = buf[i + 3]
          if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80 && (fourthByte & 0xC0) === 0x80) {
            tempCodePoint = (firstByte & 0xF) << 0x12 | (secondByte & 0x3F) << 0xC | (thirdByte & 0x3F) << 0x6 | (fourthByte & 0x3F)
            if (tempCodePoint > 0xFFFF && tempCodePoint < 0x110000) {
              codePoint = tempCodePoint
            }
          }
      }
    }

    if (codePoint === null) {
      // we did not generate a valid codePoint so insert a
      // replacement char (U+FFFD) and advance only 1 byte
      codePoint = 0xFFFD
      bytesPerSequence = 1
    } else if (codePoint > 0xFFFF) {
      // encode to utf16 (surrogate pair dance)
      codePoint -= 0x10000
      res.push(codePoint >>> 10 & 0x3FF | 0xD800)
      codePoint = 0xDC00 | codePoint & 0x3FF
    }

    res.push(codePoint)
    i += bytesPerSequence
  }

  return decodeCodePointsArray(res)
}

// Based on http://stackoverflow.com/a/22747272/680742, the browser with
// the lowest limit is Chrome, with 0x10000 args.
// We go 1 magnitude less, for safety
var MAX_ARGUMENTS_LENGTH = 0x1000

function decodeCodePointsArray (codePoints) {
  var len = codePoints.length
  if (len <= MAX_ARGUMENTS_LENGTH) {
    return String.fromCharCode.apply(String, codePoints) // avoid extra slice()
  }

  // Decode in chunks to avoid "call stack size exceeded".
  var res = ''
  var i = 0
  while (i < len) {
    res += String.fromCharCode.apply(
      String,
      codePoints.slice(i, i += MAX_ARGUMENTS_LENGTH)
    )
  }
  return res
}

function asciiSlice (buf, start, end) {
  var ret = ''
  end = Math.min(buf.length, end)

  for (var i = start; i < end; ++i) {
    ret += String.fromCharCode(buf[i] & 0x7F)
  }
  return ret
}

function latin1Slice (buf, start, end) {
  var ret = ''
  end = Math.min(buf.length, end)

  for (var i = start; i < end; ++i) {
    ret += String.fromCharCode(buf[i])
  }
  return ret
}

function hexSlice (buf, start, end) {
  var len = buf.length

  if (!start || start < 0) start = 0
  if (!end || end < 0 || end > len) end = len

  var out = ''
  for (var i = start; i < end; ++i) {
    out += toHex(buf[i])
  }
  return out
}

function utf16leSlice (buf, start, end) {
  var bytes = buf.slice(start, end)
  var res = ''
  for (var i = 0; i < bytes.length; i += 2) {
    res += String.fromCharCode(bytes[i] + bytes[i + 1] * 256)
  }
  return res
}

Buffer.prototype.slice = function slice (start, end) {
  var len = this.length
  start = ~~start
  end = end === undefined ? len : ~~end

  if (start < 0) {
    start += len
    if (start < 0) start = 0
  } else if (start > len) {
    start = len
  }

  if (end < 0) {
    end += len
    if (end < 0) end = 0
  } else if (end > len) {
    end = len
  }

  if (end < start) end = start

  var newBuf
  if (Buffer.TYPED_ARRAY_SUPPORT) {
    newBuf = this.subarray(start, end)
    newBuf.__proto__ = Buffer.prototype
  } else {
    var sliceLen = end - start
    newBuf = new Buffer(sliceLen, undefined)
    for (var i = 0; i < sliceLen; ++i) {
      newBuf[i] = this[i + start]
    }
  }

  return newBuf
}

/*
 * Need to make sure that buffer isn't trying to write out of bounds.
 */
function checkOffset (offset, ext, length) {
  if ((offset % 1) !== 0 || offset < 0) throw new RangeError('offset is not uint')
  if (offset + ext > length) throw new RangeError('Trying to access beyond buffer length')
}

Buffer.prototype.readUIntLE = function readUIntLE (offset, byteLength, noAssert) {
  offset = offset | 0
  byteLength = byteLength | 0
  if (!noAssert) checkOffset(offset, byteLength, this.length)

  var val = this[offset]
  var mul = 1
  var i = 0
  while (++i < byteLength && (mul *= 0x100)) {
    val += this[offset + i] * mul
  }

  return val
}

Buffer.prototype.readUIntBE = function readUIntBE (offset, byteLength, noAssert) {
  offset = offset | 0
  byteLength = byteLength | 0
  if (!noAssert) {
    checkOffset(offset, byteLength, this.length)
  }

  var val = this[offset + --byteLength]
  var mul = 1
  while (byteLength > 0 && (mul *= 0x100)) {
    val += this[offset + --byteLength] * mul
  }

  return val
}

Buffer.prototype.readUInt8 = function readUInt8 (offset, noAssert) {
  if (!noAssert) checkOffset(offset, 1, this.length)
  return this[offset]
}

Buffer.prototype.readUInt16LE = function readUInt16LE (offset, noAssert) {
  if (!noAssert) checkOffset(offset, 2, this.length)
  return this[offset] | (this[offset + 1] << 8)
}

Buffer.prototype.readUInt16BE = function readUInt16BE (offset, noAssert) {
  if (!noAssert) checkOffset(offset, 2, this.length)
  return (this[offset] << 8) | this[offset + 1]
}

Buffer.prototype.readUInt32LE = function readUInt32LE (offset, noAssert) {
  if (!noAssert) checkOffset(offset, 4, this.length)

  return ((this[offset]) |
      (this[offset + 1] << 8) |
      (this[offset + 2] << 16)) +
      (this[offset + 3] * 0x1000000)
}

Buffer.prototype.readUInt32BE = function readUInt32BE (offset, noAssert) {
  if (!noAssert) checkOffset(offset, 4, this.length)

  return (this[offset] * 0x1000000) +
    ((this[offset + 1] << 16) |
    (this[offset + 2] << 8) |
    this[offset + 3])
}

Buffer.prototype.readIntLE = function readIntLE (offset, byteLength, noAssert) {
  offset = offset | 0
  byteLength = byteLength | 0
  if (!noAssert) checkOffset(offset, byteLength, this.length)

  var val = this[offset]
  var mul = 1
  var i = 0
  while (++i < byteLength && (mul *= 0x100)) {
    val += this[offset + i] * mul
  }
  mul *= 0x80

  if (val >= mul) val -= Math.pow(2, 8 * byteLength)

  return val
}

Buffer.prototype.readIntBE = function readIntBE (offset, byteLength, noAssert) {
  offset = offset | 0
  byteLength = byteLength | 0
  if (!noAssert) checkOffset(offset, byteLength, this.length)

  var i = byteLength
  var mul = 1
  var val = this[offset + --i]
  while (i > 0 && (mul *= 0x100)) {
    val += this[offset + --i] * mul
  }
  mul *= 0x80

  if (val >= mul) val -= Math.pow(2, 8 * byteLength)

  return val
}

Buffer.prototype.readInt8 = function readInt8 (offset, noAssert) {
  if (!noAssert) checkOffset(offset, 1, this.length)
  if (!(this[offset] & 0x80)) return (this[offset])
  return ((0xff - this[offset] + 1) * -1)
}

Buffer.prototype.readInt16LE = function readInt16LE (offset, noAssert) {
  if (!noAssert) checkOffset(offset, 2, this.length)
  var val = this[offset] | (this[offset + 1] << 8)
  return (val & 0x8000) ? val | 0xFFFF0000 : val
}

Buffer.prototype.readInt16BE = function readInt16BE (offset, noAssert) {
  if (!noAssert) checkOffset(offset, 2, this.length)
  var val = this[offset + 1] | (this[offset] << 8)
  return (val & 0x8000) ? val | 0xFFFF0000 : val
}

Buffer.prototype.readInt32LE = function readInt32LE (offset, noAssert) {
  if (!noAssert) checkOffset(offset, 4, this.length)

  return (this[offset]) |
    (this[offset + 1] << 8) |
    (this[offset + 2] << 16) |
    (this[offset + 3] << 24)
}

Buffer.prototype.readInt32BE = function readInt32BE (offset, noAssert) {
  if (!noAssert) checkOffset(offset, 4, this.length)

  return (this[offset] << 24) |
    (this[offset + 1] << 16) |
    (this[offset + 2] << 8) |
    (this[offset + 3])
}

Buffer.prototype.readFloatLE = function readFloatLE (offset, noAssert) {
  if (!noAssert) checkOffset(offset, 4, this.length)
  return ieee754.read(this, offset, true, 23, 4)
}

Buffer.prototype.readFloatBE = function readFloatBE (offset, noAssert) {
  if (!noAssert) checkOffset(offset, 4, this.length)
  return ieee754.read(this, offset, false, 23, 4)
}

Buffer.prototype.readDoubleLE = function readDoubleLE (offset, noAssert) {
  if (!noAssert) checkOffset(offset, 8, this.length)
  return ieee754.read(this, offset, true, 52, 8)
}

Buffer.prototype.readDoubleBE = function readDoubleBE (offset, noAssert) {
  if (!noAssert) checkOffset(offset, 8, this.length)
  return ieee754.read(this, offset, false, 52, 8)
}

function checkInt (buf, value, offset, ext, max, min) {
  if (!Buffer.isBuffer(buf)) throw new TypeError('"buffer" argument must be a Buffer instance')
  if (value > max || value < min) throw new RangeError('"value" argument is out of bounds')
  if (offset + ext > buf.length) throw new RangeError('Index out of range')
}

Buffer.prototype.writeUIntLE = function writeUIntLE (value, offset, byteLength, noAssert) {
  value = +value
  offset = offset | 0
  byteLength = byteLength | 0
  if (!noAssert) {
    var maxBytes = Math.pow(2, 8 * byteLength) - 1
    checkInt(this, value, offset, byteLength, maxBytes, 0)
  }

  var mul = 1
  var i = 0
  this[offset] = value & 0xFF
  while (++i < byteLength && (mul *= 0x100)) {
    this[offset + i] = (value / mul) & 0xFF
  }

  return offset + byteLength
}

Buffer.prototype.writeUIntBE = function writeUIntBE (value, offset, byteLength, noAssert) {
  value = +value
  offset = offset | 0
  byteLength = byteLength | 0
  if (!noAssert) {
    var maxBytes = Math.pow(2, 8 * byteLength) - 1
    checkInt(this, value, offset, byteLength, maxBytes, 0)
  }

  var i = byteLength - 1
  var mul = 1
  this[offset + i] = value & 0xFF
  while (--i >= 0 && (mul *= 0x100)) {
    this[offset + i] = (value / mul) & 0xFF
  }

  return offset + byteLength
}

Buffer.prototype.writeUInt8 = function writeUInt8 (value, offset, noAssert) {
  value = +value
  offset = offset | 0
  if (!noAssert) checkInt(this, value, offset, 1, 0xff, 0)
  if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value)
  this[offset] = (value & 0xff)
  return offset + 1
}

function objectWriteUInt16 (buf, value, offset, littleEndian) {
  if (value < 0) value = 0xffff + value + 1
  for (var i = 0, j = Math.min(buf.length - offset, 2); i < j; ++i) {
    buf[offset + i] = (value & (0xff << (8 * (littleEndian ? i : 1 - i)))) >>>
      (littleEndian ? i : 1 - i) * 8
  }
}

Buffer.prototype.writeUInt16LE = function writeUInt16LE (value, offset, noAssert) {
  value = +value
  offset = offset | 0
  if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0)
  if (Buffer.TYPED_ARRAY_SUPPORT) {
    this[offset] = (value & 0xff)
    this[offset + 1] = (value >>> 8)
  } else {
    objectWriteUInt16(this, value, offset, true)
  }
  return offset + 2
}

Buffer.prototype.writeUInt16BE = function writeUInt16BE (value, offset, noAssert) {
  value = +value
  offset = offset | 0
  if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0)
  if (Buffer.TYPED_ARRAY_SUPPORT) {
    this[offset] = (value >>> 8)
    this[offset + 1] = (value & 0xff)
  } else {
    objectWriteUInt16(this, value, offset, false)
  }
  return offset + 2
}

function objectWriteUInt32 (buf, value, offset, littleEndian) {
  if (value < 0) value = 0xffffffff + value + 1
  for (var i = 0, j = Math.min(buf.length - offset, 4); i < j; ++i) {
    buf[offset + i] = (value >>> (littleEndian ? i : 3 - i) * 8) & 0xff
  }
}

Buffer.prototype.writeUInt32LE = function writeUInt32LE (value, offset, noAssert) {
  value = +value
  offset = offset | 0
  if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0)
  if (Buffer.TYPED_ARRAY_SUPPORT) {
    this[offset + 3] = (value >>> 24)
    this[offset + 2] = (value >>> 16)
    this[offset + 1] = (value >>> 8)
    this[offset] = (value & 0xff)
  } else {
    objectWriteUInt32(this, value, offset, true)
  }
  return offset + 4
}

Buffer.prototype.writeUInt32BE = function writeUInt32BE (value, offset, noAssert) {
  value = +value
  offset = offset | 0
  if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0)
  if (Buffer.TYPED_ARRAY_SUPPORT) {
    this[offset] = (value >>> 24)
    this[offset + 1] = (value >>> 16)
    this[offset + 2] = (value >>> 8)
    this[offset + 3] = (value & 0xff)
  } else {
    objectWriteUInt32(this, value, offset, false)
  }
  return offset + 4
}

Buffer.prototype.writeIntLE = function writeIntLE (value, offset, byteLength, noAssert) {
  value = +value
  offset = offset | 0
  if (!noAssert) {
    var limit = Math.pow(2, 8 * byteLength - 1)

    checkInt(this, value, offset, byteLength, limit - 1, -limit)
  }

  var i = 0
  var mul = 1
  var sub = 0
  this[offset] = value & 0xFF
  while (++i < byteLength && (mul *= 0x100)) {
    if (value < 0 && sub === 0 && this[offset + i - 1] !== 0) {
      sub = 1
    }
    this[offset + i] = ((value / mul) >> 0) - sub & 0xFF
  }

  return offset + byteLength
}

Buffer.prototype.writeIntBE = function writeIntBE (value, offset, byteLength, noAssert) {
  value = +value
  offset = offset | 0
  if (!noAssert) {
    var limit = Math.pow(2, 8 * byteLength - 1)

    checkInt(this, value, offset, byteLength, limit - 1, -limit)
  }

  var i = byteLength - 1
  var mul = 1
  var sub = 0
  this[offset + i] = value & 0xFF
  while (--i >= 0 && (mul *= 0x100)) {
    if (value < 0 && sub === 0 && this[offset + i + 1] !== 0) {
      sub = 1
    }
    this[offset + i] = ((value / mul) >> 0) - sub & 0xFF
  }

  return offset + byteLength
}

Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) {
  value = +value
  offset = offset | 0
  if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80)
  if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value)
  if (value < 0) value = 0xff + value + 1
  this[offset] = (value & 0xff)
  return offset + 1
}

Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) {
  value = +value
  offset = offset | 0
  if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000)
  if (Buffer.TYPED_ARRAY_SUPPORT) {
    this[offset] = (value & 0xff)
    this[offset + 1] = (value >>> 8)
  } else {
    objectWriteUInt16(this, value, offset, true)
  }
  return offset + 2
}

Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) {
  value = +value
  offset = offset | 0
  if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000)
  if (Buffer.TYPED_ARRAY_SUPPORT) {
    this[offset] = (value >>> 8)
    this[offset + 1] = (value & 0xff)
  } else {
    objectWriteUInt16(this, value, offset, false)
  }
  return offset + 2
}

Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) {
  value = +value
  offset = offset | 0
  if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000)
  if (Buffer.TYPED_ARRAY_SUPPORT) {
    this[offset] = (value & 0xff)
    this[offset + 1] = (value >>> 8)
    this[offset + 2] = (value >>> 16)
    this[offset + 3] = (value >>> 24)
  } else {
    objectWriteUInt32(this, value, offset, true)
  }
  return offset + 4
}

Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) {
  value = +value
  offset = offset | 0
  if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000)
  if (value < 0) value = 0xffffffff + value + 1
  if (Buffer.TYPED_ARRAY_SUPPORT) {
    this[offset] = (value >>> 24)
    this[offset + 1] = (value >>> 16)
    this[offset + 2] = (value >>> 8)
    this[offset + 3] = (value & 0xff)
  } else {
    objectWriteUInt32(this, value, offset, false)
  }
  return offset + 4
}

function checkIEEE754 (buf, value, offset, ext, max, min) {
  if (offset + ext > buf.length) throw new RangeError('Index out of range')
  if (offset < 0) throw new RangeError('Index out of range')
}

function writeFloat (buf, value, offset, littleEndian, noAssert) {
  if (!noAssert) {
    checkIEEE754(buf, value, offset, 4, 3.4028234663852886e+38, -3.4028234663852886e+38)
  }
  ieee754.write(buf, value, offset, littleEndian, 23, 4)
  return offset + 4
}

Buffer.prototype.writeFloatLE = function writeFloatLE (value, offset, noAssert) {
  return writeFloat(this, value, offset, true, noAssert)
}

Buffer.prototype.writeFloatBE = function writeFloatBE (value, offset, noAssert) {
  return writeFloat(this, value, offset, false, noAssert)
}

function writeDouble (buf, value, offset, littleEndian, noAssert) {
  if (!noAssert) {
    checkIEEE754(buf, value, offset, 8, 1.7976931348623157E+308, -1.7976931348623157E+308)
  }
  ieee754.write(buf, value, offset, littleEndian, 52, 8)
  return offset + 8
}

Buffer.prototype.writeDoubleLE = function writeDoubleLE (value, offset, noAssert) {
  return writeDouble(this, value, offset, true, noAssert)
}

Buffer.prototype.writeDoubleBE = function writeDoubleBE (value, offset, noAssert) {
  return writeDouble(this, value, offset, false, noAssert)
}

// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length)
Buffer.prototype.copy = function copy (target, targetStart, start, end) {
  if (!start) start = 0
  if (!end && end !== 0) end = this.length
  if (targetStart >= target.length) targetStart = target.length
  if (!targetStart) targetStart = 0
  if (end > 0 && end < start) end = start

  // Copy 0 bytes; we're done
  if (end === start) return 0
  if (target.length === 0 || this.length === 0) return 0

  // Fatal error conditions
  if (targetStart < 0) {
    throw new RangeError('targetStart out of bounds')
  }
  if (start < 0 || start >= this.length) throw new RangeError('sourceStart out of bounds')
  if (end < 0) throw new RangeError('sourceEnd out of bounds')

  // Are we oob?
  if (end > this.length) end = this.length
  if (target.length - targetStart < end - start) {
    end = target.length - targetStart + start
  }

  var len = end - start
  var i

  if (this === target && start < targetStart && targetStart < end) {
    // descending copy from end
    for (i = len - 1; i >= 0; --i) {
      target[i + targetStart] = this[i + start]
    }
  } else if (len < 1000 || !Buffer.TYPED_ARRAY_SUPPORT) {
    // ascending copy from start
    for (i = 0; i < len; ++i) {
      target[i + targetStart] = this[i + start]
    }
  } else {
    Uint8Array.prototype.set.call(
      target,
      this.subarray(start, start + len),
      targetStart
    )
  }

  return len
}

// Usage:
//    buffer.fill(number[, offset[, end]])
//    buffer.fill(buffer[, offset[, end]])
//    buffer.fill(string[, offset[, end]][, encoding])
Buffer.prototype.fill = function fill (val, start, end, encoding) {
  // Handle string cases:
  if (typeof val === 'string') {
    if (typeof start === 'string') {
      encoding = start
      start = 0
      end = this.length
    } else if (typeof end === 'string') {
      encoding = end
      end = this.length
    }
    if (val.length === 1) {
      var code = val.charCodeAt(0)
      if (code < 256) {
        val = code
      }
    }
    if (encoding !== undefined && typeof encoding !== 'string') {
      throw new TypeError('encoding must be a string')
    }
    if (typeof encoding === 'string' && !Buffer.isEncoding(encoding)) {
      throw new TypeError('Unknown encoding: ' + encoding)
    }
  } else if (typeof val === 'number') {
    val = val & 255
  }

  // Invalid ranges are not set to a default, so can range check early.
  if (start < 0 || this.length < start || this.length < end) {
    throw new RangeError('Out of range index')
  }

  if (end <= start) {
    return this
  }

  start = start >>> 0
  end = end === undefined ? this.length : end >>> 0

  if (!val) val = 0

  var i
  if (typeof val === 'number') {
    for (i = start; i < end; ++i) {
      this[i] = val
    }
  } else {
    var bytes = Buffer.isBuffer(val)
      ? val
      : utf8ToBytes(new Buffer(val, encoding).toString())
    var len = bytes.length
    for (i = 0; i < end - start; ++i) {
      this[i + start] = bytes[i % len]
    }
  }

  return this
}

// HELPER FUNCTIONS
// ================

var INVALID_BASE64_RE = /[^+\/0-9A-Za-z-_]/g

function base64clean (str) {
  // Node strips out invalid characters like \n and \t from the string, base64-js does not
  str = stringtrim(str).replace(INVALID_BASE64_RE, '')
  // Node converts strings with length < 2 to ''
  if (str.length < 2) return ''
  // Node allows for non-padded base64 strings (missing trailing ===), base64-js does not
  while (str.length % 4 !== 0) {
    str = str + '='
  }
  return str
}

function stringtrim (str) {
  if (str.trim) return str.trim()
  return str.replace(/^\s+|\s+$/g, '')
}

function toHex (n) {
  if (n < 16) return '0' + n.toString(16)
  return n.toString(16)
}

function utf8ToBytes (string, units) {
  units = units || Infinity
  var codePoint
  var length = string.length
  var leadSurrogate = null
  var bytes = []

  for (var i = 0; i < length; ++i) {
    codePoint = string.charCodeAt(i)

    // is surrogate component
    if (codePoint > 0xD7FF && codePoint < 0xE000) {
      // last char was a lead
      if (!leadSurrogate) {
        // no lead yet
        if (codePoint > 0xDBFF) {
          // unexpected trail
          if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
          continue
        } else if (i + 1 === length) {
          // unpaired lead
          if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
          continue
        }

        // valid lead
        leadSurrogate = codePoint

        continue
      }

      // 2 leads in a row
      if (codePoint < 0xDC00) {
        if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
        leadSurrogate = codePoint
        continue
      }

      // valid surrogate pair
      codePoint = (leadSurrogate - 0xD800 << 10 | codePoint - 0xDC00) + 0x10000
    } else if (leadSurrogate) {
      // valid bmp char, but last char was a lead
      if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
    }

    leadSurrogate = null

    // encode utf8
    if (codePoint < 0x80) {
      if ((units -= 1) < 0) break
      bytes.push(codePoint)
    } else if (codePoint < 0x800) {
      if ((units -= 2) < 0) break
      bytes.push(
        codePoint >> 0x6 | 0xC0,
        codePoint & 0x3F | 0x80
      )
    } else if (codePoint < 0x10000) {
      if ((units -= 3) < 0) break
      bytes.push(
        codePoint >> 0xC | 0xE0,
        codePoint >> 0x6 & 0x3F | 0x80,
        codePoint & 0x3F | 0x80
      )
    } else if (codePoint < 0x110000) {
      if ((units -= 4) < 0) break
      bytes.push(
        codePoint >> 0x12 | 0xF0,
        codePoint >> 0xC & 0x3F | 0x80,
        codePoint >> 0x6 & 0x3F | 0x80,
        codePoint & 0x3F | 0x80
      )
    } else {
      throw new Error('Invalid code point')
    }
  }

  return bytes
}

function asciiToBytes (str) {
  var byteArray = []
  for (var i = 0; i < str.length; ++i) {
    // Node's code seems to be doing this and not & 0x7F..
    byteArray.push(str.charCodeAt(i) & 0xFF)
  }
  return byteArray
}

function utf16leToBytes (str, units) {
  var c, hi, lo
  var byteArray = []
  for (var i = 0; i < str.length; ++i) {
    if ((units -= 2) < 0) break

    c = str.charCodeAt(i)
    hi = c >> 8
    lo = c % 256
    byteArray.push(lo)
    byteArray.push(hi)
  }

  return byteArray
}

function base64ToBytes (str) {
  return base64.toByteArray(base64clean(str))
}

function blitBuffer (src, dst, offset, length) {
  for (var i = 0; i < length; ++i) {
    if ((i + offset >= dst.length) || (i >= src.length)) break
    dst[i + offset] = src[i]
  }
  return i
}

function isnan (val) {
  return val !== val // eslint-disable-line no-self-compare
}

}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{"base64-js":15,"ieee754":92,"isarray":46}],46:[function(require,module,exports){
var toString = {}.toString;

module.exports = Array.isArray || function (arr) {
  return toString.call(arr) == '[object Array]';
};

},{}],47:[function(require,module,exports){
(function (global){
'use strict';

var buffer = require('buffer');
var Buffer = buffer.Buffer;
var SlowBuffer = buffer.SlowBuffer;
var MAX_LEN = buffer.kMaxLength || 2147483647;
exports.alloc = function alloc(size, fill, encoding) {
  if (typeof Buffer.alloc === 'function') {
    return Buffer.alloc(size, fill, encoding);
  }
  if (typeof encoding === 'number') {
    throw new TypeError('encoding must not be number');
  }
  if (typeof size !== 'number') {
    throw new TypeError('size must be a number');
  }
  if (size > MAX_LEN) {
    throw new RangeError('size is too large');
  }
  var enc = encoding;
  var _fill = fill;
  if (_fill === undefined) {
    enc = undefined;
    _fill = 0;
  }
  var buf = new Buffer(size);
  if (typeof _fill === 'string') {
    var fillBuf = new Buffer(_fill, enc);
    var flen = fillBuf.length;
    var i = -1;
    while (++i < size) {
      buf[i] = fillBuf[i % flen];
    }
  } else {
    buf.fill(_fill);
  }
  return buf;
}
exports.allocUnsafe = function allocUnsafe(size) {
  if (typeof Buffer.allocUnsafe === 'function') {
    return Buffer.allocUnsafe(size);
  }
  if (typeof size !== 'number') {
    throw new TypeError('size must be a number');
  }
  if (size > MAX_LEN) {
    throw new RangeError('size is too large');
  }
  return new Buffer(size);
}
exports.from = function from(value, encodingOrOffset, length) {
  if (typeof Buffer.from === 'function' && (!global.Uint8Array || Uint8Array.from !== Buffer.from)) {
    return Buffer.from(value, encodingOrOffset, length);
  }
  if (typeof value === 'number') {
    throw new TypeError('"value" argument must not be a number');
  }
  if (typeof value === 'string') {
    return new Buffer(value, encodingOrOffset);
  }
  if (typeof ArrayBuffer !== 'undefined' && value instanceof ArrayBuffer) {
    var offset = encodingOrOffset;
    if (arguments.length === 1) {
      return new Buffer(value);
    }
    if (typeof offset === 'undefined') {
      offset = 0;
    }
    var len = length;
    if (typeof len === 'undefined') {
      len = value.byteLength - offset;
    }
    if (offset >= value.byteLength) {
      throw new RangeError('\'offset\' is out of bounds');
    }
    if (len > value.byteLength - offset) {
      throw new RangeError('\'length\' is out of bounds');
    }
    return new Buffer(value.slice(offset, offset + len));
  }
  if (Buffer.isBuffer(value)) {
    var out = new Buffer(value.length);
    value.copy(out, 0, 0, value.length);
    return out;
  }
  if (value) {
    if (Array.isArray(value) || (typeof ArrayBuffer !== 'undefined' && value.buffer instanceof ArrayBuffer) || 'length' in value) {
      return new Buffer(value);
    }
    if (value.type === 'Buffer' && Array.isArray(value.data)) {
      return new Buffer(value.data);
    }
  }

  throw new TypeError('First argument must be a string, Buffer, ' + 'ArrayBuffer, Array, or array-like object.');
}
exports.allocUnsafeSlow = function allocUnsafeSlow(size) {
  if (typeof Buffer.allocUnsafeSlow === 'function') {
    return Buffer.allocUnsafeSlow(size);
  }
  if (typeof size !== 'number') {
    throw new TypeError('size must be a number');
  }
  if (size >= MAX_LEN) {
    throw new RangeError('size is too large');
  }
  return new SlowBuffer(size);
}

}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{"buffer":45}],48:[function(require,module,exports){
(function (Buffer){
var Transform = require('stream').Transform
var inherits = require('inherits')
var StringDecoder = require('string_decoder').StringDecoder
module.exports = CipherBase
inherits(CipherBase, Transform)
function CipherBase (hashMode) {
  Transform.call(this)
  this.hashMode = typeof hashMode === 'string'
  if (this.hashMode) {
    this[hashMode] = this._finalOrDigest
  } else {
    this.final = this._finalOrDigest
  }
  this._decoder = null
  this._encoding = null
}
CipherBase.prototype.update = function (data, inputEnc, outputEnc) {
  if (typeof data === 'string') {
    data = new Buffer(data, inputEnc)
  }
  var outData = this._update(data)
  if (this.hashMode) {
    return this
  }
  if (outputEnc) {
    outData = this._toString(outData, outputEnc)
  }
  return outData
}

CipherBase.prototype.setAutoPadding = function () {}

CipherBase.prototype.getAuthTag = function () {
  throw new Error('trying to get auth tag in unsupported state')
}

CipherBase.prototype.setAuthTag = function () {
  throw new Error('trying to set auth tag in unsupported state')
}

CipherBase.prototype.setAAD = function () {
  throw new Error('trying to set aad in unsupported state')
}

CipherBase.prototype._transform = function (data, _, next) {
  var err
  try {
    if (this.hashMode) {
      this._update(data)
    } else {
      this.push(this._update(data))
    }
  } catch (e) {
    err = e
  } finally {
    next(err)
  }
}
CipherBase.prototype._flush = function (done) {
  var err
  try {
    this.push(this._final())
  } catch (e) {
    err = e
  } finally {
    done(err)
  }
}
CipherBase.prototype._finalOrDigest = function (outputEnc) {
  var outData = this._final() || new Buffer('')
  if (outputEnc) {
    outData = this._toString(outData, outputEnc, true)
  }
  return outData
}

CipherBase.prototype._toString = function (value, enc, fin) {
  if (!this._decoder) {
    this._decoder = new StringDecoder(enc)
    this._encoding = enc
  }
  if (this._encoding !== enc) {
    throw new Error('can\'t switch encodings')
  }
  var out = this._decoder.write(value)
  if (fin) {
    out += this._decoder.end()
  }
  return out
}

}).call(this,require("buffer").Buffer)
},{"buffer":45,"inherits":94,"stream":133,"string_decoder":134}],49:[function(require,module,exports){
(function (Buffer){
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.

// NOTE: These type checking functions intentionally don't use `instanceof`
// because it is fragile and can be easily faked with `Object.create()`.

function isArray(arg) {
  if (Array.isArray) {
    return Array.isArray(arg);
  }
  return objectToString(arg) === '[object Array]';
}
exports.isArray = isArray;

function isBoolean(arg) {
  return typeof arg === 'boolean';
}
exports.isBoolean = isBoolean;

function isNull(arg) {
  return arg === null;
}
exports.isNull = isNull;

function isNullOrUndefined(arg) {
  return arg == null;
}
exports.isNullOrUndefined = isNullOrUndefined;

function isNumber(arg) {
  return typeof arg === 'number';
}
exports.isNumber = isNumber;

function isString(arg) {
  return typeof arg === 'string';
}
exports.isString = isString;

function isSymbol(arg) {
  return typeof arg === 'symbol';
}
exports.isSymbol = isSymbol;

function isUndefined(arg) {
  return arg === void 0;
}
exports.isUndefined = isUndefined;

function isRegExp(re) {
  return objectToString(re) === '[object RegExp]';
}
exports.isRegExp = isRegExp;

function isObject(arg) {
  return typeof arg === 'object' && arg !== null;
}
exports.isObject = isObject;

function isDate(d) {
  return objectToString(d) === '[object Date]';
}
exports.isDate = isDate;

function isError(e) {
  return (objectToString(e) === '[object Error]' || e instanceof Error);
}
exports.isError = isError;

function isFunction(arg) {
  return typeof arg === 'function';
}
exports.isFunction = isFunction;

function isPrimitive(arg) {
  return arg === null ||
         typeof arg === 'boolean' ||
         typeof arg === 'number' ||
         typeof arg === 'string' ||
         typeof arg === 'symbol' ||  // ES6 symbol
         typeof arg === 'undefined';
}
exports.isPrimitive = isPrimitive;

exports.isBuffer = Buffer.isBuffer;

function objectToString(o) {
  return Object.prototype.toString.call(o);
}

}).call(this,{"isBuffer":require("../../is-buffer/index.js")})
},{"../../is-buffer/index.js":95}],50:[function(require,module,exports){
(function (Buffer){
var elliptic = require('elliptic');
var BN = require('bn.js');

module.exports = function createECDH(curve) {
	return new ECDH(curve);
};

var aliases = {
	secp256k1: {
		name: 'secp256k1',
		byteLength: 32
	},
	secp224r1: {
		name: 'p224',
		byteLength: 28
	},
	prime256v1: {
		name: 'p256',
		byteLength: 32
	},
	prime192v1: {
		name: 'p192',
		byteLength: 24
	},
	ed25519: {
		name: 'ed25519',
		byteLength: 32
	},
	secp384r1: {
		name: 'p384',
		byteLength: 48
	},
	secp521r1: {
		name: 'p521',
		byteLength: 66
	}
};

aliases.p224 = aliases.secp224r1;
aliases.p256 = aliases.secp256r1 = aliases.prime256v1;
aliases.p192 = aliases.secp192r1 = aliases.prime192v1;
aliases.p384 = aliases.secp384r1;
aliases.p521 = aliases.secp521r1;

function ECDH(curve) {
	this.curveType = aliases[curve];
	if (!this.curveType ) {
		this.curveType = {
			name: curve
		};
	}
	this.curve = new elliptic.ec(this.curveType.name);
	this.keys = void 0;
}

ECDH.prototype.generateKeys = function (enc, format) {
	this.keys = this.curve.genKeyPair();
	return this.getPublicKey(enc, format);
};

ECDH.prototype.computeSecret = function (other, inenc, enc) {
	inenc = inenc || 'utf8';
	if (!Buffer.isBuffer(other)) {
		other = new Buffer(other, inenc);
	}
	var otherPub = this.curve.keyFromPublic(other).getPublic();
	var out = otherPub.mul(this.keys.getPrivate()).getX();
	return formatReturnValue(out, enc, this.curveType.byteLength);
};

ECDH.prototype.getPublicKey = function (enc, format) {
	var key = this.keys.getPublic(format === 'compressed', true);
	if (format === 'hybrid') {
		if (key[key.length - 1] % 2) {
			key[0] = 7;
		} else {
			key [0] = 6;
		}
	}
	return formatReturnValue(key, enc);
};

ECDH.prototype.getPrivateKey = function (enc) {
	return formatReturnValue(this.keys.getPrivate(), enc);
};

ECDH.prototype.setPublicKey = function (pub, enc) {
	enc = enc || 'utf8';
	if (!Buffer.isBuffer(pub)) {
		pub = new Buffer(pub, enc);
	}
	this.keys._importPublic(pub);
	return this;
};

ECDH.prototype.setPrivateKey = function (priv, enc) {
	enc = enc || 'utf8';
	if (!Buffer.isBuffer(priv)) {
		priv = new Buffer(priv, enc);
	}
	var _priv = new BN(priv);
	_priv = _priv.toString(16);
	this.keys._importPrivate(_priv);
	return this;
};

function formatReturnValue(bn, enc, len) {
	if (!Array.isArray(bn)) {
		bn = bn.toArray();
	}
	var buf = new Buffer(bn);
	if (len && buf.length < len) {
		var zeros = new Buffer(len - buf.length);
		zeros.fill(0);
		buf = Buffer.concat([zeros, buf]);
	}
	if (!enc) {
		return buf;
	} else {
		return buf.toString(enc);
	}
}

}).call(this,require("buffer").Buffer)
},{"bn.js":16,"buffer":45,"elliptic":67}],51:[function(require,module,exports){
(function (Buffer){
'use strict';
var inherits = require('inherits')
var md5 = require('./md5')
var rmd160 = require('ripemd160')
var sha = require('sha.js')

var Base = require('cipher-base')

function HashNoConstructor(hash) {
  Base.call(this, 'digest')

  this._hash = hash
  this.buffers = []
}

inherits(HashNoConstructor, Base)

HashNoConstructor.prototype._update = function (data) {
  this.buffers.push(data)
}

HashNoConstructor.prototype._final = function () {
  var buf = Buffer.concat(this.buffers)
  var r = this._hash(buf)
  this.buffers = null

  return r
}

function Hash(hash) {
  Base.call(this, 'digest')

  this._hash = hash
}

inherits(Hash, Base)

Hash.prototype._update = function (data) {
  this._hash.update(data)
}

Hash.prototype._final = function () {
  return this._hash.digest()
}

module.exports = function createHash (alg) {
  alg = alg.toLowerCase()
  if ('md5' === alg) return new HashNoConstructor(md5)
  if ('rmd160' === alg || 'ripemd160' === alg) return new HashNoConstructor(rmd160)

  return new Hash(sha(alg))
}

}).call(this,require("buffer").Buffer)
},{"./md5":53,"buffer":45,"cipher-base":48,"inherits":94,"ripemd160":54,"sha.js":126}],52:[function(require,module,exports){
(function (Buffer){
'use strict';
var intSize = 4;
var zeroBuffer = new Buffer(intSize); zeroBuffer.fill(0);
var chrsz = 8;

function toArray(buf, bigEndian) {
  if ((buf.length % intSize) !== 0) {
    var len = buf.length + (intSize - (buf.length % intSize));
    buf = Buffer.concat([buf, zeroBuffer], len);
  }

  var arr = [];
  var fn = bigEndian ? buf.readInt32BE : buf.readInt32LE;
  for (var i = 0; i < buf.length; i += intSize) {
    arr.push(fn.call(buf, i));
  }
  return arr;
}

function toBuffer(arr, size, bigEndian) {
  var buf = new Buffer(size);
  var fn = bigEndian ? buf.writeInt32BE : buf.writeInt32LE;
  for (var i = 0; i < arr.length; i++) {
    fn.call(buf, arr[i], i * 4, true);
  }
  return buf;
}

function hash(buf, fn, hashSize, bigEndian) {
  if (!Buffer.isBuffer(buf)) buf = new Buffer(buf);
  var arr = fn(toArray(buf, bigEndian), buf.length * chrsz);
  return toBuffer(arr, hashSize, bigEndian);
}
exports.hash = hash;
}).call(this,require("buffer").Buffer)
},{"buffer":45}],53:[function(require,module,exports){
'use strict';
/*
 * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
 * Digest Algorithm, as defined in RFC 1321.
 * Version 2.1 Copyright (C) Paul Johnston 1999 - 2002.
 * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
 * Distributed under the BSD License
 * See http://pajhome.org.uk/crypt/md5 for more info.
 */

var helpers = require('./helpers');

/*
 * Calculate the MD5 of an array of little-endian words, and a bit length
 */
function core_md5(x, len)
{
  /* append padding */
  x[len >> 5] |= 0x80 << ((len) % 32);
  x[(((len + 64) >>> 9) << 4) + 14] = len;

  var a =  1732584193;
  var b = -271733879;
  var c = -1732584194;
  var d =  271733878;

  for(var i = 0; i < x.length; i += 16)
  {
    var olda = a;
    var oldb = b;
    var oldc = c;
    var oldd = d;

    a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936);
    d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586);
    c = md5_ff(c, d, a, b, x[i+ 2], 17,  606105819);
    b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330);
    a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897);
    d = md5_ff(d, a, b, c, x[i+ 5], 12,  1200080426);
    c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341);
    b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983);
    a = md5_ff(a, b, c, d, x[i+ 8], 7 ,  1770035416);
    d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417);
    c = md5_ff(c, d, a, b, x[i+10], 17, -42063);
    b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162);
    a = md5_ff(a, b, c, d, x[i+12], 7 ,  1804603682);
    d = md5_ff(d, a, b, c, x[i+13], 12, -40341101);
    c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290);
    b = md5_ff(b, c, d, a, x[i+15], 22,  1236535329);

    a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510);
    d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632);
    c = md5_gg(c, d, a, b, x[i+11], 14,  643717713);
    b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302);
    a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691);
    d = md5_gg(d, a, b, c, x[i+10], 9 ,  38016083);
    c = md5_gg(c, d, a, b, x[i+15], 14, -660478335);
    b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848);
    a = md5_gg(a, b, c, d, x[i+ 9], 5 ,  568446438);
    d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690);
    c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961);
    b = md5_gg(b, c, d, a, x[i+ 8], 20,  1163531501);
    a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467);
    d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784);
    c = md5_gg(c, d, a, b, x[i+ 7], 14,  1735328473);
    b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734);

    a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558);
    d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463);
    c = md5_hh(c, d, a, b, x[i+11], 16,  1839030562);
    b = md5_hh(b, c, d, a, x[i+14], 23, -35309556);
    a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060);
    d = md5_hh(d, a, b, c, x[i+ 4], 11,  1272893353);
    c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632);
    b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640);
    a = md5_hh(a, b, c, d, x[i+13], 4 ,  681279174);
    d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222);
    c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979);
    b = md5_hh(b, c, d, a, x[i+ 6], 23,  76029189);
    a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487);
    d = md5_hh(d, a, b, c, x[i+12], 11, -421815835);
    c = md5_hh(c, d, a, b, x[i+15], 16,  530742520);
    b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651);

    a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844);
    d = md5_ii(d, a, b, c, x[i+ 7], 10,  1126891415);
    c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905);
    b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055);
    a = md5_ii(a, b, c, d, x[i+12], 6 ,  1700485571);
    d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606);
    c = md5_ii(c, d, a, b, x[i+10], 15, -1051523);
    b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799);
    a = md5_ii(a, b, c, d, x[i+ 8], 6 ,  1873313359);
    d = md5_ii(d, a, b, c, x[i+15], 10, -30611744);
    c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380);
    b = md5_ii(b, c, d, a, x[i+13], 21,  1309151649);
    a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070);
    d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379);
    c = md5_ii(c, d, a, b, x[i+ 2], 15,  718787259);
    b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551);

    a = safe_add(a, olda);
    b = safe_add(b, oldb);
    c = safe_add(c, oldc);
    d = safe_add(d, oldd);
  }
  return Array(a, b, c, d);

}

/*
 * These functions implement the four basic operations the algorithm uses.
 */
function md5_cmn(q, a, b, x, s, t)
{
  return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b);
}
function md5_ff(a, b, c, d, x, s, t)
{
  return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
}
function md5_gg(a, b, c, d, x, s, t)
{
  return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
}
function md5_hh(a, b, c, d, x, s, t)
{
  return md5_cmn(b ^ c ^ d, a, b, x, s, t);
}
function md5_ii(a, b, c, d, x, s, t)
{
  return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
}

/*
 * Add integers, wrapping at 2^32. This uses 16-bit operations internally
 * to work around bugs in some JS interpreters.
 */
function safe_add(x, y)
{
  var lsw = (x & 0xFFFF) + (y & 0xFFFF);
  var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
  return (msw << 16) | (lsw & 0xFFFF);
}

/*
 * Bitwise rotate a 32-bit number to the left.
 */
function bit_rol(num, cnt)
{
  return (num << cnt) | (num >>> (32 - cnt));
}

module.exports = function md5(buf) {
  return helpers.hash(buf, core_md5, 16);
};
},{"./helpers":52}],54:[function(require,module,exports){
(function (Buffer){
/*
CryptoJS v3.1.2
code.google.com/p/crypto-js
(c) 2009-2013 by Jeff Mott. All rights reserved.
code.google.com/p/crypto-js/wiki/License
*/
/** @preserve
(c) 2012 by Cédric Mesnil. All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

    - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
    - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

// constants table
var zl = [
  0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
  7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8,
  3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12,
  1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2,
  4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13
]

var zr = [
  5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12,
  6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2,
  15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13,
  8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14,
  12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11
]

var sl = [
  11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8,
  7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12,
  11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5,
  11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12,
  9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6
]

var sr = [
  8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6,
  9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11,
  9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5,
  15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8,
  8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11
]

var hl = [0x00000000, 0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xA953FD4E]
var hr = [0x50A28BE6, 0x5C4DD124, 0x6D703EF3, 0x7A6D76E9, 0x00000000]

function bytesToWords (bytes) {
  var words = []
  for (var i = 0, b = 0; i < bytes.length; i++, b += 8) {
    words[b >>> 5] |= bytes[i] << (24 - b % 32)
  }
  return words
}

function wordsToBytes (words) {
  var bytes = []
  for (var b = 0; b < words.length * 32; b += 8) {
    bytes.push((words[b >>> 5] >>> (24 - b % 32)) & 0xFF)
  }
  return bytes
}

function processBlock (H, M, offset) {
  // swap endian
  for (var i = 0; i < 16; i++) {
    var offset_i = offset + i
    var M_offset_i = M[offset_i]

    // Swap
    M[offset_i] = (
      (((M_offset_i << 8) | (M_offset_i >>> 24)) & 0x00ff00ff) |
      (((M_offset_i << 24) | (M_offset_i >>> 8)) & 0xff00ff00)
    )
  }

  // Working variables
  var al, bl, cl, dl, el
  var ar, br, cr, dr, er

  ar = al = H[0]
  br = bl = H[1]
  cr = cl = H[2]
  dr = dl = H[3]
  er = el = H[4]

  // computation
  var t
  for (i = 0; i < 80; i += 1) {
    t = (al + M[offset + zl[i]]) | 0
    if (i < 16) {
      t += f1(bl, cl, dl) + hl[0]
    } else if (i < 32) {
      t += f2(bl, cl, dl) + hl[1]
    } else if (i < 48) {
      t += f3(bl, cl, dl) + hl[2]
    } else if (i < 64) {
      t += f4(bl, cl, dl) + hl[3]
    } else {// if (i<80) {
      t += f5(bl, cl, dl) + hl[4]
    }
    t = t | 0
    t = rotl(t, sl[i])
    t = (t + el) | 0
    al = el
    el = dl
    dl = rotl(cl, 10)
    cl = bl
    bl = t

    t = (ar + M[offset + zr[i]]) | 0
    if (i < 16) {
      t += f5(br, cr, dr) + hr[0]
    } else if (i < 32) {
      t += f4(br, cr, dr) + hr[1]
    } else if (i < 48) {
      t += f3(br, cr, dr) + hr[2]
    } else if (i < 64) {
      t += f2(br, cr, dr) + hr[3]
    } else {// if (i<80) {
      t += f1(br, cr, dr) + hr[4]
    }

    t = t | 0
    t = rotl(t, sr[i])
    t = (t + er) | 0
    ar = er
    er = dr
    dr = rotl(cr, 10)
    cr = br
    br = t
  }

  // intermediate hash value
  t = (H[1] + cl + dr) | 0
  H[1] = (H[2] + dl + er) | 0
  H[2] = (H[3] + el + ar) | 0
  H[3] = (H[4] + al + br) | 0
  H[4] = (H[0] + bl + cr) | 0
  H[0] = t
}

function f1 (x, y, z) {
  return ((x) ^ (y) ^ (z))
}

function f2 (x, y, z) {
  return (((x) & (y)) | ((~x) & (z)))
}

function f3 (x, y, z) {
  return (((x) | (~(y))) ^ (z))
}

function f4 (x, y, z) {
  return (((x) & (z)) | ((y) & (~(z))))
}

function f5 (x, y, z) {
  return ((x) ^ ((y) | (~(z))))
}

function rotl (x, n) {
  return (x << n) | (x >>> (32 - n))
}

function ripemd160 (message) {
  var H = [0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0]

  if (typeof message === 'string') {
    message = new Buffer(message, 'utf8')
  }

  var m = bytesToWords(message)

  var nBitsLeft = message.length * 8
  var nBitsTotal = message.length * 8

  // Add padding
  m[nBitsLeft >>> 5] |= 0x80 << (24 - nBitsLeft % 32)
  m[(((nBitsLeft + 64) >>> 9) << 4) + 14] = (
    (((nBitsTotal << 8) | (nBitsTotal >>> 24)) & 0x00ff00ff) |
    (((nBitsTotal << 24) | (nBitsTotal >>> 8)) & 0xff00ff00)
  )

  for (var i = 0; i < m.length; i += 16) {
    processBlock(H, m, i)
  }

  // swap endian
  for (i = 0; i < 5; i++) {
    // shortcut
    var H_i = H[i]

    // Swap
    H[i] = (((H_i << 8) | (H_i >>> 24)) & 0x00ff00ff) |
      (((H_i << 24) | (H_i >>> 8)) & 0xff00ff00)
  }

  var digestbytes = wordsToBytes(H)
  return new Buffer(digestbytes)
}

module.exports = ripemd160

}).call(this,require("buffer").Buffer)
},{"buffer":45}],55:[function(require,module,exports){
(function (Buffer){
'use strict';
var createHash = require('create-hash/browser');
var inherits = require('inherits')

var Transform = require('stream').Transform

var ZEROS = new Buffer(128)
ZEROS.fill(0)

function Hmac(alg, key) {
  Transform.call(this)
  alg = alg.toLowerCase()
  if (typeof key === 'string') {
    key = new Buffer(key)
  }

  var blocksize = (alg === 'sha512' || alg === 'sha384') ? 128 : 64

  this._alg = alg
  this._key = key

  if (key.length > blocksize) {
    key = createHash(alg).update(key).digest()

  } else if (key.length < blocksize) {
    key = Buffer.concat([key, ZEROS], blocksize)
  }

  var ipad = this._ipad = new Buffer(blocksize)
  var opad = this._opad = new Buffer(blocksize)

  for (var i = 0; i < blocksize; i++) {
    ipad[i] = key[i] ^ 0x36
    opad[i] = key[i] ^ 0x5C
  }

  this._hash = createHash(alg).update(ipad)
}

inherits(Hmac, Transform)

Hmac.prototype.update = function (data, enc) {
  this._hash.update(data, enc)

  return this
}

Hmac.prototype._transform = function (data, _, next) {
  this._hash.update(data)

  next()
}

Hmac.prototype._flush = function (next) {
  this.push(this.digest())

  next()
}

Hmac.prototype.digest = function (enc) {
  var h = this._hash.digest()

  return createHash(this._alg).update(this._opad).update(h).digest(enc)
}

module.exports = function createHmac(alg, key) {
  return new Hmac(alg, key)
}

}).call(this,require("buffer").Buffer)
},{"buffer":45,"create-hash/browser":51,"inherits":94,"stream":133}],56:[function(require,module,exports){
'use strict'

exports.randomBytes = exports.rng = exports.pseudoRandomBytes = exports.prng = require('randombytes')
exports.createHash = exports.Hash = require('create-hash')
exports.createHmac = exports.Hmac = require('create-hmac')

var hashes = ['sha1', 'sha224', 'sha256', 'sha384', 'sha512', 'md5', 'rmd160'].concat(Object.keys(require('browserify-sign/algos')))
exports.getHashes = function () {
  return hashes
}

var p = require('pbkdf2')
exports.pbkdf2 = p.pbkdf2
exports.pbkdf2Sync = p.pbkdf2Sync

var aes = require('browserify-cipher')
;[
  'Cipher',
  'createCipher',
  'Cipheriv',
  'createCipheriv',
  'Decipher',
  'createDecipher',
  'Decipheriv',
  'createDecipheriv',
  'getCiphers',
  'listCiphers'
].forEach(function (key) {
  exports[key] = aes[key]
})

var dh = require('diffie-hellman')
;[
  'DiffieHellmanGroup',
  'createDiffieHellmanGroup',
  'getDiffieHellman',
  'createDiffieHellman',
  'DiffieHellman'
].forEach(function (key) {
  exports[key] = dh[key]
})

var sign = require('browserify-sign')
;[
  'createSign',
  'Sign',
  'createVerify',
  'Verify'
].forEach(function (key) {
  exports[key] = sign[key]
})

exports.createECDH = require('create-ecdh')

var publicEncrypt = require('public-encrypt')

;[
  'publicEncrypt',
  'privateEncrypt',
  'publicDecrypt',
  'privateDecrypt'
].forEach(function (key) {
  exports[key] = publicEncrypt[key]
})

// the least I can do is make error messages for the rest of the node.js/crypto api.
;[
  'createCredentials'
].forEach(function (name) {
  exports[name] = function () {
    throw new Error([
      'sorry, ' + name + ' is not implemented yet',
      'we accept pull requests',
      'https://github.com/crypto-browserify/crypto-browserify'
    ].join('\n'))
  }
})

},{"browserify-cipher":35,"browserify-sign":40,"browserify-sign/algos":39,"create-ecdh":50,"create-hash":51,"create-hmac":55,"diffie-hellman":63,"pbkdf2":102,"public-encrypt":106,"randombytes":112}],57:[function(require,module,exports){
'use strict';

exports.utils = require('./des/utils');
exports.Cipher = require('./des/cipher');
exports.DES = require('./des/des');
exports.CBC = require('./des/cbc');
exports.EDE = require('./des/ede');

},{"./des/cbc":58,"./des/cipher":59,"./des/des":60,"./des/ede":61,"./des/utils":62}],58:[function(require,module,exports){
'use strict';

var assert = require('minimalistic-assert');
var inherits = require('inherits');

var proto = {};

function CBCState(iv) {
  assert.equal(iv.length, 8, 'Invalid IV length');

  this.iv = new Array(8);
  for (var i = 0; i < this.iv.length; i++)
    this.iv[i] = iv[i];
}

function instantiate(Base) {
  function CBC(options) {
    Base.call(this, options);
    this._cbcInit();
  }
  inherits(CBC, Base);

  var keys = Object.keys(proto);
  for (var i = 0; i < keys.length; i++) {
    var key = keys[i];
    CBC.prototype[key] = proto[key];
  }

  CBC.create = function create(options) {
    return new CBC(options);
  };

  return CBC;
}

exports.instantiate = instantiate;

proto._cbcInit = function _cbcInit() {
  var state = new CBCState(this.options.iv);
  this._cbcState = state;
};

proto._update = function _update(inp, inOff, out, outOff) {
  var state = this._cbcState;
  var superProto = this.constructor.super_.prototype;

  var iv = state.iv;
  if (this.type === 'encrypt') {
    for (var i = 0; i < this.blockSize; i++)
      iv[i] ^= inp[inOff + i];

    superProto._update.call(this, iv, 0, out, outOff);

    for (var i = 0; i < this.blockSize; i++)
      iv[i] = out[outOff + i];
  } else {
    superProto._update.call(this, inp, inOff, out, outOff);

    for (var i = 0; i < this.blockSize; i++)
      out[outOff + i] ^= iv[i];

    for (var i = 0; i < this.blockSize; i++)
      iv[i] = inp[inOff + i];
  }
};

},{"inherits":94,"minimalistic-assert":97}],59:[function(require,module,exports){
'use strict';

var assert = require('minimalistic-assert');

function Cipher(options) {
  this.options = options;

  this.type = this.options.type;
  this.blockSize = 8;
  this._init();

  this.buffer = new Array(this.blockSize);
  this.bufferOff = 0;
}
module.exports = Cipher;

Cipher.prototype._init = function _init() {
  // Might be overrided
};

Cipher.prototype.update = function update(data) {
  if (data.length === 0)
    return [];

  if (this.type === 'decrypt')
    return this._updateDecrypt(data);
  else
    return this._updateEncrypt(data);
};

Cipher.prototype._buffer = function _buffer(data, off) {
  // Append data to buffer
  var min = Math.min(this.buffer.length - this.bufferOff, data.length - off);
  for (var i = 0; i < min; i++)
    this.buffer[this.bufferOff + i] = data[off + i];
  this.bufferOff += min;

  // Shift next
  return min;
};

Cipher.prototype._flushBuffer = function _flushBuffer(out, off) {
  this._update(this.buffer, 0, out, off);
  this.bufferOff = 0;
  return this.blockSize;
};

Cipher.prototype._updateEncrypt = function _updateEncrypt(data) {
  var inputOff = 0;
  var outputOff = 0;

  var count = ((this.bufferOff + data.length) / this.blockSize) | 0;
  var out = new Array(count * this.blockSize);

  if (this.bufferOff !== 0) {
    inputOff += this._buffer(data, inputOff);

    if (this.bufferOff === this.buffer.length)
      outputOff += this._flushBuffer(out, outputOff);
  }

  // Write blocks
  var max = data.length - ((data.length - inputOff) % this.blockSize);
  for (; inputOff < max; inputOff += this.blockSize) {
    this._update(data, inputOff, out, outputOff);
    outputOff += this.blockSize;
  }

  // Queue rest
  for (; inputOff < data.length; inputOff++, this.bufferOff++)
    this.buffer[this.bufferOff] = data[inputOff];

  return out;
};

Cipher.prototype._updateDecrypt = function _updateDecrypt(data) {
  var inputOff = 0;
  var outputOff = 0;

  var count = Math.ceil((this.bufferOff + data.length) / this.blockSize) - 1;
  var out = new Array(count * this.blockSize);

  // TODO(indutny): optimize it, this is far from optimal
  for (; count > 0; count--) {
    inputOff += this._buffer(data, inputOff);
    outputOff += this._flushBuffer(out, outputOff);
  }

  // Buffer rest of the input
  inputOff += this._buffer(data, inputOff);

  return out;
};

Cipher.prototype.final = function final(buffer) {
  var first;
  if (buffer)
    first = this.update(buffer);

  var last;
  if (this.type === 'encrypt')
    last = this._finalEncrypt();
  else
    last = this._finalDecrypt();

  if (first)
    return first.concat(last);
  else
    return last;
};

Cipher.prototype._pad = function _pad(buffer, off) {
  if (off === 0)
    return false;

  while (off < buffer.length)
    buffer[off++] = 0;

  return true;
};

Cipher.prototype._finalEncrypt = function _finalEncrypt() {
  if (!this._pad(this.buffer, this.bufferOff))
    return [];

  var out = new Array(this.blockSize);
  this._update(this.buffer, 0, out, 0);
  return out;
};

Cipher.prototype._unpad = function _unpad(buffer) {
  return buffer;
};

Cipher.prototype._finalDecrypt = function _finalDecrypt() {
  assert.equal(this.bufferOff, this.blockSize, 'Not enough data to decrypt');
  var out = new Array(this.blockSize);
  this._flushBuffer(out, 0);

  return this._unpad(out);
};

},{"minimalistic-assert":97}],60:[function(require,module,exports){
'use strict';

var assert = require('minimalistic-assert');
var inherits = require('inherits');

var des = require('../des');
var utils = des.utils;
var Cipher = des.Cipher;

function DESState() {
  this.tmp = new Array(2);
  this.keys = null;
}

function DES(options) {
  Cipher.call(this, options);

  var state = new DESState();
  this._desState = state;

  this.deriveKeys(state, options.key);
}
inherits(DES, Cipher);
module.exports = DES;

DES.create = function create(options) {
  return new DES(options);
};

var shiftTable = [
  1, 1, 2, 2, 2, 2, 2, 2,
  1, 2, 2, 2, 2, 2, 2, 1
];

DES.prototype.deriveKeys = function deriveKeys(state, key) {
  state.keys = new Array(16 * 2);

  assert.equal(key.length, this.blockSize, 'Invalid key length');

  var kL = utils.readUInt32BE(key, 0);
  var kR = utils.readUInt32BE(key, 4);

  utils.pc1(kL, kR, state.tmp, 0);
  kL = state.tmp[0];
  kR = state.tmp[1];
  for (var i = 0; i < state.keys.length; i += 2) {
    var shift = shiftTable[i >>> 1];
    kL = utils.r28shl(kL, shift);
    kR = utils.r28shl(kR, shift);
    utils.pc2(kL, kR, state.keys, i);
  }
};

DES.prototype._update = function _update(inp, inOff, out, outOff) {
  var state = this._desState;

  var l = utils.readUInt32BE(inp, inOff);
  var r = utils.readUInt32BE(inp, inOff + 4);

  // Initial Permutation
  utils.ip(l, r, state.tmp, 0);
  l = state.tmp[0];
  r = state.tmp[1];

  if (this.type === 'encrypt')
    this._encrypt(state, l, r, state.tmp, 0);
  else
    this._decrypt(state, l, r, state.tmp, 0);

  l = state.tmp[0];
  r = state.tmp[1];

  utils.writeUInt32BE(out, l, outOff);
  utils.writeUInt32BE(out, r, outOff + 4);
};

DES.prototype._pad = function _pad(buffer, off) {
  var value = buffer.length - off;
  for (var i = off; i < buffer.length; i++)
    buffer[i] = value;

  return true;
};

DES.prototype._unpad = function _unpad(buffer) {
  var pad = buffer[buffer.length - 1];
  for (var i = buffer.length - pad; i < buffer.length; i++)
    assert.equal(buffer[i], pad);

  return buffer.slice(0, buffer.length - pad);
};

DES.prototype._encrypt = function _encrypt(state, lStart, rStart, out, off) {
  var l = lStart;
  var r = rStart;

  // Apply f() x16 times
  for (var i = 0; i < state.keys.length; i += 2) {
    var keyL = state.keys[i];
    var keyR = state.keys[i + 1];

    // f(r, k)
    utils.expand(r, state.tmp, 0);

    keyL ^= state.tmp[0];
    keyR ^= state.tmp[1];
    var s = utils.substitute(keyL, keyR);
    var f = utils.permute(s);

    var t = r;
    r = (l ^ f) >>> 0;
    l = t;
  }

  // Reverse Initial Permutation
  utils.rip(r, l, out, off);
};

DES.prototype._decrypt = function _decrypt(state, lStart, rStart, out, off) {
  var l = rStart;
  var r = lStart;

  // Apply f() x16 times
  for (var i = state.keys.length - 2; i >= 0; i -= 2) {
    var keyL = state.keys[i];
    var keyR = state.keys[i + 1];

    // f(r, k)
    utils.expand(l, state.tmp, 0);

    keyL ^= state.tmp[0];
    keyR ^= state.tmp[1];
    var s = utils.substitute(keyL, keyR);
    var f = utils.permute(s);

    var t = l;
    l = (r ^ f) >>> 0;
    r = t;
  }

  // Reverse Initial Permutation
  utils.rip(l, r, out, off);
};

},{"../des":57,"inherits":94,"minimalistic-assert":97}],61:[function(require,module,exports){
'use strict';

var assert = require('minimalistic-assert');
var inherits = require('inherits');

var des = require('../des');
var Cipher = des.Cipher;
var DES = des.DES;

function EDEState(type, key) {
  assert.equal(key.length, 24, 'Invalid key length');

  var k1 = key.slice(0, 8);
  var k2 = key.slice(8, 16);
  var k3 = key.slice(16, 24);

  if (type === 'encrypt') {
    this.ciphers = [
      DES.create({ type: 'encrypt', key: k1 }),
      DES.create({ type: 'decrypt', key: k2 }),
      DES.create({ type: 'encrypt', key: k3 })
    ];
  } else {
    this.ciphers = [
      DES.create({ type: 'decrypt', key: k3 }),
      DES.create({ type: 'encrypt', key: k2 }),
      DES.create({ type: 'decrypt', key: k1 })
    ];
  }
}

function EDE(options) {
  Cipher.call(this, options);

  var state = new EDEState(this.type, this.options.key);
  this._edeState = state;
}
inherits(EDE, Cipher);

module.exports = EDE;

EDE.create = function create(options) {
  return new EDE(options);
};

EDE.prototype._update = function _update(inp, inOff, out, outOff) {
  var state = this._edeState;

  state.ciphers[0]._update(inp, inOff, out, outOff);
  state.ciphers[1]._update(out, outOff, out, outOff);
  state.ciphers[2]._update(out, outOff, out, outOff);
};

EDE.prototype._pad = DES.prototype._pad;
EDE.prototype._unpad = DES.prototype._unpad;

},{"../des":57,"inherits":94,"minimalistic-assert":97}],62:[function(require,module,exports){
'use strict';

exports.readUInt32BE = function readUInt32BE(bytes, off) {
  var res =  (bytes[0 + off] << 24) |
             (bytes[1 + off] << 16) |
             (bytes[2 + off] << 8) |
             bytes[3 + off];
  return res >>> 0;
};

exports.writeUInt32BE = function writeUInt32BE(bytes, value, off) {
  bytes[0 + off] = value >>> 24;
  bytes[1 + off] = (value >>> 16) & 0xff;
  bytes[2 + off] = (value >>> 8) & 0xff;
  bytes[3 + off] = value & 0xff;
};

exports.ip = function ip(inL, inR, out, off) {
  var outL = 0;
  var outR = 0;

  for (var i = 6; i >= 0; i -= 2) {
    for (var j = 0; j <= 24; j += 8) {
      outL <<= 1;
      outL |= (inR >>> (j + i)) & 1;
    }
    for (var j = 0; j <= 24; j += 8) {
      outL <<= 1;
      outL |= (inL >>> (j + i)) & 1;
    }
  }

  for (var i = 6; i >= 0; i -= 2) {
    for (var j = 1; j <= 25; j += 8) {
      outR <<= 1;
      outR |= (inR >>> (j + i)) & 1;
    }
    for (var j = 1; j <= 25; j += 8) {
      outR <<= 1;
      outR |= (inL >>> (j + i)) & 1;
    }
  }

  out[off + 0] = outL >>> 0;
  out[off + 1] = outR >>> 0;
};

exports.rip = function rip(inL, inR, out, off) {
  var outL = 0;
  var outR = 0;

  for (var i = 0; i < 4; i++) {
    for (var j = 24; j >= 0; j -= 8) {
      outL <<= 1;
      outL |= (inR >>> (j + i)) & 1;
      outL <<= 1;
      outL |= (inL >>> (j + i)) & 1;
    }
  }
  for (var i = 4; i < 8; i++) {
    for (var j = 24; j >= 0; j -= 8) {
      outR <<= 1;
      outR |= (inR >>> (j + i)) & 1;
      outR <<= 1;
      outR |= (inL >>> (j + i)) & 1;
    }
  }

  out[off + 0] = outL >>> 0;
  out[off + 1] = outR >>> 0;
};

exports.pc1 = function pc1(inL, inR, out, off) {
  var outL = 0;
  var outR = 0;

  // 7, 15, 23, 31, 39, 47, 55, 63
  // 6, 14, 22, 30, 39, 47, 55, 63
  // 5, 13, 21, 29, 39, 47, 55, 63
  // 4, 12, 20, 28
  for (var i = 7; i >= 5; i--) {
    for (var j = 0; j <= 24; j += 8) {
      outL <<= 1;
      outL |= (inR >> (j + i)) & 1;
    }
    for (var j = 0; j <= 24; j += 8) {
      outL <<= 1;
      outL |= (inL >> (j + i)) & 1;
    }
  }
  for (var j = 0; j <= 24; j += 8) {
    outL <<= 1;
    outL |= (inR >> (j + i)) & 1;
  }

  // 1, 9, 17, 25, 33, 41, 49, 57
  // 2, 10, 18, 26, 34, 42, 50, 58
  // 3, 11, 19, 27, 35, 43, 51, 59
  // 36, 44, 52, 60
  for (var i = 1; i <= 3; i++) {
    for (var j = 0; j <= 24; j += 8) {
      outR <<= 1;
      outR |= (inR >> (j + i)) & 1;
    }
    for (var j = 0; j <= 24; j += 8) {
      outR <<= 1;
      outR |= (inL >> (j + i)) & 1;
    }
  }
  for (var j = 0; j <= 24; j += 8) {
    outR <<= 1;
    outR |= (inL >> (j + i)) & 1;
  }

  out[off + 0] = outL >>> 0;
  out[off + 1] = outR >>> 0;
};

exports.r28shl = function r28shl(num, shift) {
  return ((num << shift) & 0xfffffff) | (num >>> (28 - shift));
};

var pc2table = [
  // inL => outL
  14, 11, 17, 4, 27, 23, 25, 0,
  13, 22, 7, 18, 5, 9, 16, 24,
  2, 20, 12, 21, 1, 8, 15, 26,

  // inR => outR
  15, 4, 25, 19, 9, 1, 26, 16,
  5, 11, 23, 8, 12, 7, 17, 0,
  22, 3, 10, 14, 6, 20, 27, 24
];

exports.pc2 = function pc2(inL, inR, out, off) {
  var outL = 0;
  var outR = 0;

  var len = pc2table.length >>> 1;
  for (var i = 0; i < len; i++) {
    outL <<= 1;
    outL |= (inL >>> pc2table[i]) & 0x1;
  }
  for (var i = len; i < pc2table.length; i++) {
    outR <<= 1;
    outR |= (inR >>> pc2table[i]) & 0x1;
  }

  out[off + 0] = outL >>> 0;
  out[off + 1] = outR >>> 0;
};

exports.expand = function expand(r, out, off) {
  var outL = 0;
  var outR = 0;

  outL = ((r & 1) << 5) | (r >>> 27);
  for (var i = 23; i >= 15; i -= 4) {
    outL <<= 6;
    outL |= (r >>> i) & 0x3f;
  }
  for (var i = 11; i >= 3; i -= 4) {
    outR |= (r >>> i) & 0x3f;
    outR <<= 6;
  }
  outR |= ((r & 0x1f) << 1) | (r >>> 31);

  out[off + 0] = outL >>> 0;
  out[off + 1] = outR >>> 0;
};

var sTable = [
  14, 0, 4, 15, 13, 7, 1, 4, 2, 14, 15, 2, 11, 13, 8, 1,
  3, 10, 10, 6, 6, 12, 12, 11, 5, 9, 9, 5, 0, 3, 7, 8,
  4, 15, 1, 12, 14, 8, 8, 2, 13, 4, 6, 9, 2, 1, 11, 7,
  15, 5, 12, 11, 9, 3, 7, 14, 3, 10, 10, 0, 5, 6, 0, 13,

  15, 3, 1, 13, 8, 4, 14, 7, 6, 15, 11, 2, 3, 8, 4, 14,
  9, 12, 7, 0, 2, 1, 13, 10, 12, 6, 0, 9, 5, 11, 10, 5,
  0, 13, 14, 8, 7, 10, 11, 1, 10, 3, 4, 15, 13, 4, 1, 2,
  5, 11, 8, 6, 12, 7, 6, 12, 9, 0, 3, 5, 2, 14, 15, 9,

  10, 13, 0, 7, 9, 0, 14, 9, 6, 3, 3, 4, 15, 6, 5, 10,
  1, 2, 13, 8, 12, 5, 7, 14, 11, 12, 4, 11, 2, 15, 8, 1,
  13, 1, 6, 10, 4, 13, 9, 0, 8, 6, 15, 9, 3, 8, 0, 7,
  11, 4, 1, 15, 2, 14, 12, 3, 5, 11, 10, 5, 14, 2, 7, 12,

  7, 13, 13, 8, 14, 11, 3, 5, 0, 6, 6, 15, 9, 0, 10, 3,
  1, 4, 2, 7, 8, 2, 5, 12, 11, 1, 12, 10, 4, 14, 15, 9,
  10, 3, 6, 15, 9, 0, 0, 6, 12, 10, 11, 1, 7, 13, 13, 8,
  15, 9, 1, 4, 3, 5, 14, 11, 5, 12, 2, 7, 8, 2, 4, 14,

  2, 14, 12, 11, 4, 2, 1, 12, 7, 4, 10, 7, 11, 13, 6, 1,
  8, 5, 5, 0, 3, 15, 15, 10, 13, 3, 0, 9, 14, 8, 9, 6,
  4, 11, 2, 8, 1, 12, 11, 7, 10, 1, 13, 14, 7, 2, 8, 13,
  15, 6, 9, 15, 12, 0, 5, 9, 6, 10, 3, 4, 0, 5, 14, 3,

  12, 10, 1, 15, 10, 4, 15, 2, 9, 7, 2, 12, 6, 9, 8, 5,
  0, 6, 13, 1, 3, 13, 4, 14, 14, 0, 7, 11, 5, 3, 11, 8,
  9, 4, 14, 3, 15, 2, 5, 12, 2, 9, 8, 5, 12, 15, 3, 10,
  7, 11, 0, 14, 4, 1, 10, 7, 1, 6, 13, 0, 11, 8, 6, 13,

  4, 13, 11, 0, 2, 11, 14, 7, 15, 4, 0, 9, 8, 1, 13, 10,
  3, 14, 12, 3, 9, 5, 7, 12, 5, 2, 10, 15, 6, 8, 1, 6,
  1, 6, 4, 11, 11, 13, 13, 8, 12, 1, 3, 4, 7, 10, 14, 7,
  10, 9, 15, 5, 6, 0, 8, 15, 0, 14, 5, 2, 9, 3, 2, 12,

  13, 1, 2, 15, 8, 13, 4, 8, 6, 10, 15, 3, 11, 7, 1, 4,
  10, 12, 9, 5, 3, 6, 14, 11, 5, 0, 0, 14, 12, 9, 7, 2,
  7, 2, 11, 1, 4, 14, 1, 7, 9, 4, 12, 10, 14, 8, 2, 13,
  0, 15, 6, 12, 10, 9, 13, 0, 15, 3, 3, 5, 5, 6, 8, 11
];

exports.substitute = function substitute(inL, inR) {
  var out = 0;
  for (var i = 0; i < 4; i++) {
    var b = (inL >>> (18 - i * 6)) & 0x3f;
    var sb = sTable[i * 0x40 + b];

    out <<= 4;
    out |= sb;
  }
  for (var i = 0; i < 4; i++) {
    var b = (inR >>> (18 - i * 6)) & 0x3f;
    var sb = sTable[4 * 0x40 + i * 0x40 + b];

    out <<= 4;
    out |= sb;
  }
  return out >>> 0;
};

var permuteTable = [
  16, 25, 12, 11, 3, 20, 4, 15, 31, 17, 9, 6, 27, 14, 1, 22,
  30, 24, 8, 18, 0, 5, 29, 23, 13, 19, 2, 26, 10, 21, 28, 7
];

exports.permute = function permute(num) {
  var out = 0;
  for (var i = 0; i < permuteTable.length; i++) {
    out <<= 1;
    out |= (num >>> permuteTable[i]) & 0x1;
  }
  return out >>> 0;
};

exports.padSplit = function padSplit(num, size, group) {
  var str = num.toString(2);
  while (str.length < size)
    str = '0' + str;

  var out = [];
  for (var i = 0; i < size; i += group)
    out.push(str.slice(i, i + group));
  return out.join(' ');
};

},{}],63:[function(require,module,exports){
(function (Buffer){
var generatePrime = require('./lib/generatePrime')
var primes = require('./lib/primes.json')

var DH = require('./lib/dh')

function getDiffieHellman (mod) {
  var prime = new Buffer(primes[mod].prime, 'hex')
  var gen = new Buffer(primes[mod].gen, 'hex')

  return new DH(prime, gen)
}

var ENCODINGS = {
  'binary': true, 'hex': true, 'base64': true
}

function createDiffieHellman (prime, enc, generator, genc) {
  if (Buffer.isBuffer(enc) || ENCODINGS[enc] === undefined) {
    return createDiffieHellman(prime, 'binary', enc, generator)
  }

  enc = enc || 'binary'
  genc = genc || 'binary'
  generator = generator || new Buffer([2])

  if (!Buffer.isBuffer(generator)) {
    generator = new Buffer(generator, genc)
  }

  if (typeof prime === 'number') {
    return new DH(generatePrime(prime, generator), generator, true)
  }

  if (!Buffer.isBuffer(prime)) {
    prime = new Buffer(prime, enc)
  }

  return new DH(prime, generator, true)
}

exports.DiffieHellmanGroup = exports.createDiffieHellmanGroup = exports.getDiffieHellman = getDiffieHellman
exports.createDiffieHellman = exports.DiffieHellman = createDiffieHellman

}).call(this,require("buffer").Buffer)
},{"./lib/dh":64,"./lib/generatePrime":65,"./lib/primes.json":66,"buffer":45}],64:[function(require,module,exports){
(function (Buffer){
var BN = require('bn.js');
var MillerRabin = require('miller-rabin');
var millerRabin = new MillerRabin();
var TWENTYFOUR = new BN(24);
var ELEVEN = new BN(11);
var TEN = new BN(10);
var THREE = new BN(3);
var SEVEN = new BN(7);
var primes = require('./generatePrime');
var randomBytes = require('randombytes');
module.exports = DH;

function setPublicKey(pub, enc) {
  enc = enc || 'utf8';
  if (!Buffer.isBuffer(pub)) {
    pub = new Buffer(pub, enc);
  }
  this._pub = new BN(pub);
  return this;
}

function setPrivateKey(priv, enc) {
  enc = enc || 'utf8';
  if (!Buffer.isBuffer(priv)) {
    priv = new Buffer(priv, enc);
  }
  this._priv = new BN(priv);
  return this;
}

var primeCache = {};
function checkPrime(prime, generator) {
  var gen = generator.toString('hex');
  var hex = [gen, prime.toString(16)].join('_');
  if (hex in primeCache) {
    return primeCache[hex];
  }
  var error = 0;

  if (prime.isEven() ||
    !primes.simpleSieve ||
    !primes.fermatTest(prime) ||
    !millerRabin.test(prime)) {
    //not a prime so +1
    error += 1;

    if (gen === '02' || gen === '05') {
      // we'd be able to check the generator
      // it would fail so +8
      error += 8;
    } else {
      //we wouldn't be able to test the generator
      // so +4
      error += 4;
    }
    primeCache[hex] = error;
    return error;
  }
  if (!millerRabin.test(prime.shrn(1))) {
    //not a safe prime
    error += 2;
  }
  var rem;
  switch (gen) {
    case '02':
      if (prime.mod(TWENTYFOUR).cmp(ELEVEN)) {
        // unsuidable generator
        error += 8;
      }
      break;
    case '05':
      rem = prime.mod(TEN);
      if (rem.cmp(THREE) && rem.cmp(SEVEN)) {
        // prime mod 10 needs to equal 3 or 7
        error += 8;
      }
      break;
    default:
      error += 4;
  }
  primeCache[hex] = error;
  return error;
}

function DH(prime, generator, malleable) {
  this.setGenerator(generator);
  this.__prime = new BN(prime);
  this._prime = BN.mont(this.__prime);
  this._primeLen = prime.length;
  this._pub = undefined;
  this._priv = undefined;
  this._primeCode = undefined;
  if (malleable) {
    this.setPublicKey = setPublicKey;
    this.setPrivateKey = setPrivateKey;
  } else {
    this._primeCode = 8;
  }
}
Object.defineProperty(DH.prototype, 'verifyError', {
  enumerable: true,
  get: function () {
    if (typeof this._primeCode !== 'number') {
      this._primeCode = checkPrime(this.__prime, this.__gen);
    }
    return this._primeCode;
  }
});
DH.prototype.generateKeys = function () {
  if (!this._priv) {
    this._priv = new BN(randomBytes(this._primeLen));
  }
  this._pub = this._gen.toRed(this._prime).redPow(this._priv).fromRed();
  return this.getPublicKey();
};

DH.prototype.computeSecret = function (other) {
  other = new BN(other);
  other = other.toRed(this._prime);
  var secret = other.redPow(this._priv).fromRed();
  var out = new Buffer(secret.toArray());
  var prime = this.getPrime();
  if (out.length < prime.length) {
    var front = new Buffer(prime.length - out.length);
    front.fill(0);
    out = Buffer.concat([front, out]);
  }
  return out;
};

DH.prototype.getPublicKey = function getPublicKey(enc) {
  return formatReturnValue(this._pub, enc);
};

DH.prototype.getPrivateKey = function getPrivateKey(enc) {
  return formatReturnValue(this._priv, enc);
};

DH.prototype.getPrime = function (enc) {
  return formatReturnValue(this.__prime, enc);
};

DH.prototype.getGenerator = function (enc) {
  return formatReturnValue(this._gen, enc);
};

DH.prototype.setGenerator = function (gen, enc) {
  enc = enc || 'utf8';
  if (!Buffer.isBuffer(gen)) {
    gen = new Buffer(gen, enc);
  }
  this.__gen = gen;
  this._gen = new BN(gen);
  return this;
};

function formatReturnValue(bn, enc) {
  var buf = new Buffer(bn.toArray());
  if (!enc) {
    return buf;
  } else {
    return buf.toString(enc);
  }
}

}).call(this,require("buffer").Buffer)
},{"./generatePrime":65,"bn.js":16,"buffer":45,"miller-rabin":96,"randombytes":112}],65:[function(require,module,exports){
var randomBytes = require('randombytes');
module.exports = findPrime;
findPrime.simpleSieve = simpleSieve;
findPrime.fermatTest = fermatTest;
var BN = require('bn.js');
var TWENTYFOUR = new BN(24);
var MillerRabin = require('miller-rabin');
var millerRabin = new MillerRabin();
var ONE = new BN(1);
var TWO = new BN(2);
var FIVE = new BN(5);
var SIXTEEN = new BN(16);
var EIGHT = new BN(8);
var TEN = new BN(10);
var THREE = new BN(3);
var SEVEN = new BN(7);
var ELEVEN = new BN(11);
var FOUR = new BN(4);
var TWELVE = new BN(12);
var primes = null;

function _getPrimes() {
  if (primes !== null)
    return primes;

  var limit = 0x100000;
  var res = [];
  res[0] = 2;
  for (var i = 1, k = 3; k < limit; k += 2) {
    var sqrt = Math.ceil(Math.sqrt(k));
    for (var j = 0; j < i && res[j] <= sqrt; j++)
      if (k % res[j] === 0)
        break;

    if (i !== j && res[j] <= sqrt)
      continue;

    res[i++] = k;
  }
  primes = res;
  return res;
}

function simpleSieve(p) {
  var primes = _getPrimes();

  for (var i = 0; i < primes.length; i++)
    if (p.modn(primes[i]) === 0) {
      if (p.cmpn(primes[i]) === 0) {
        return true;
      } else {
        return false;
      }
    }

  return true;
}

function fermatTest(p) {
  var red = BN.mont(p);
  return TWO.toRed(red).redPow(p.subn(1)).fromRed().cmpn(1) === 0;
}

function findPrime(bits, gen) {
  if (bits < 16) {
    // this is what openssl does
    if (gen === 2 || gen === 5) {
      return new BN([0x8c, 0x7b]);
    } else {
      return new BN([0x8c, 0x27]);
    }
  }
  gen = new BN(gen);

  var num, n2;

  while (true) {
    num = new BN(randomBytes(Math.ceil(bits / 8)));
    while (num.bitLength() > bits) {
      num.ishrn(1);
    }
    if (num.isEven()) {
      num.iadd(ONE);
    }
    if (!num.testn(1)) {
      num.iadd(TWO);
    }
    if (!gen.cmp(TWO)) {
      while (num.mod(TWENTYFOUR).cmp(ELEVEN)) {
        num.iadd(FOUR);
      }
    } else if (!gen.cmp(FIVE)) {
      while (num.mod(TEN).cmp(THREE)) {
        num.iadd(FOUR);
      }
    }
    n2 = num.shrn(1);
    if (simpleSieve(n2) && simpleSieve(num) &&
      fermatTest(n2) && fermatTest(num) &&
      millerRabin.test(n2) && millerRabin.test(num)) {
      return num;
    }
  }

}

},{"bn.js":16,"miller-rabin":96,"randombytes":112}],66:[function(require,module,exports){
module.exports={
    "modp1": {
        "gen": "02",
        "prime": "ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a63a3620ffffffffffffffff"
    },
    "modp2": {
        "gen": "02",
        "prime": "ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece65381ffffffffffffffff"
    },
    "modp5": {
        "gen": "02",
        "prime": "ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca237327ffffffffffffffff"
    },
    "modp14": {
        "gen": "02",
        "prime": "ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf6955817183995497cea956ae515d2261898fa051015728e5a8aacaa68ffffffffffffffff"
    },
    "modp15": {
        "gen": "02",
        "prime": "ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf6955817183995497cea956ae515d2261898fa051015728e5a8aaac42dad33170d04507a33a85521abdf1cba64ecfb850458dbef0a8aea71575d060c7db3970f85a6e1e4c7abf5ae8cdb0933d71e8c94e04a25619dcee3d2261ad2ee6bf12ffa06d98a0864d87602733ec86a64521f2b18177b200cbbe117577a615d6c770988c0bad946e208e24fa074e5ab3143db5bfce0fd108e4b82d120a93ad2caffffffffffffffff"
    },
    "modp16": {
        "gen": "02",
        "prime": "ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf6955817183995497cea956ae515d2261898fa051015728e5a8aaac42dad33170d04507a33a85521abdf1cba64ecfb850458dbef0a8aea71575d060c7db3970f85a6e1e4c7abf5ae8cdb0933d71e8c94e04a25619dcee3d2261ad2ee6bf12ffa06d98a0864d87602733ec86a64521f2b18177b200cbbe117577a615d6c770988c0bad946e208e24fa074e5ab3143db5bfce0fd108e4b82d120a92108011a723c12a787e6d788719a10bdba5b2699c327186af4e23c1a946834b6150bda2583e9ca2ad44ce8dbbbc2db04de8ef92e8efc141fbecaa6287c59474e6bc05d99b2964fa090c3a2233ba186515be7ed1f612970cee2d7afb81bdd762170481cd0069127d5b05aa993b4ea988d8fddc186ffb7dc90a6c08f4df435c934063199ffffffffffffffff"
    },
    "modp17": {
        "gen": "02",
        "prime": "ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf6955817183995497cea956ae515d2261898fa051015728e5a8aaac42dad33170d04507a33a85521abdf1cba64ecfb850458dbef0a8aea71575d060c7db3970f85a6e1e4c7abf5ae8cdb0933d71e8c94e04a25619dcee3d2261ad2ee6bf12ffa06d98a0864d87602733ec86a64521f2b18177b200cbbe117577a615d6c770988c0bad946e208e24fa074e5ab3143db5bfce0fd108e4b82d120a92108011a723c12a787e6d788719a10bdba5b2699c327186af4e23c1a946834b6150bda2583e9ca2ad44ce8dbbbc2db04de8ef92e8efc141fbecaa6287c59474e6bc05d99b2964fa090c3a2233ba186515be7ed1f612970cee2d7afb81bdd762170481cd0069127d5b05aa993b4ea988d8fddc186ffb7dc90a6c08f4df435c93402849236c3fab4d27c7026c1d4dcb2602646dec9751e763dba37bdf8ff9406ad9e530ee5db382f413001aeb06a53ed9027d831179727b0865a8918da3edbebcf9b14ed44ce6cbaced4bb1bdb7f1447e6cc254b332051512bd7af426fb8f401378cd2bf5983ca01c64b92ecf032ea15d1721d03f482d7ce6e74fef6d55e702f46980c82b5a84031900b1c9e59e7c97fbec7e8f323a97a7e36cc88be0f1d45b7ff585ac54bd407b22b4154aacc8f6d7ebf48e1d814cc5ed20f8037e0a79715eef29be32806a1d58bb7c5da76f550aa3d8a1fbff0eb19ccb1a313d55cda56c9ec2ef29632387fe8d76e3c0468043e8f663f4860ee12bf2d5b0b7474d6e694f91e6dcc4024ffffffffffffffff"
    },
    "modp18": {
        "gen": "02",
        "prime": "ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf6955817183995497cea956ae515d2261898fa051015728e5a8aaac42dad33170d04507a33a85521abdf1cba64ecfb850458dbef0a8aea71575d060c7db3970f85a6e1e4c7abf5ae8cdb0933d71e8c94e04a25619dcee3d2261ad2ee6bf12ffa06d98a0864d87602733ec86a64521f2b18177b200cbbe117577a615d6c770988c0bad946e208e24fa074e5ab3143db5bfce0fd108e4b82d120a92108011a723c12a787e6d788719a10bdba5b2699c327186af4e23c1a946834b6150bda2583e9ca2ad44ce8dbbbc2db04de8ef92e8efc141fbecaa6287c59474e6bc05d99b2964fa090c3a2233ba186515be7ed1f612970cee2d7afb81bdd762170481cd0069127d5b05aa993b4ea988d8fddc186ffb7dc90a6c08f4df435c93402849236c3fab4d27c7026c1d4dcb2602646dec9751e763dba37bdf8ff9406ad9e530ee5db382f413001aeb06a53ed9027d831179727b0865a8918da3edbebcf9b14ed44ce6cbaced4bb1bdb7f1447e6cc254b332051512bd7af426fb8f401378cd2bf5983ca01c64b92ecf032ea15d1721d03f482d7ce6e74fef6d55e702f46980c82b5a84031900b1c9e59e7c97fbec7e8f323a97a7e36cc88be0f1d45b7ff585ac54bd407b22b4154aacc8f6d7ebf48e1d814cc5ed20f8037e0a79715eef29be32806a1d58bb7c5da76f550aa3d8a1fbff0eb19ccb1a313d55cda56c9ec2ef29632387fe8d76e3c0468043e8f663f4860ee12bf2d5b0b7474d6e694f91e6dbe115974a3926f12fee5e438777cb6a932df8cd8bec4d073b931ba3bc832b68d9dd300741fa7bf8afc47ed2576f6936ba424663aab639c5ae4f5683423b4742bf1c978238f16cbe39d652de3fdb8befc848ad922222e04a4037c0713eb57a81a23f0c73473fc646cea306b4bcbc8862f8385ddfa9d4b7fa2c087e879683303ed5bdd3a062b3cf5b3a278a66d2a13f83f44f82ddf310ee074ab6a364597e899a0255dc164f31cc50846851df9ab48195ded7ea1b1d510bd7ee74d73faf36bc31ecfa268359046f4eb879f924009438b481c6cd7889a002ed5ee382bc9190da6fc026e479558e4475677e9aa9e3050e2765694dfc81f56e880b96e7160c980dd98edd3dfffffffffffffffff"
    }
}
},{}],67:[function(require,module,exports){
'use strict';

var elliptic = exports;

elliptic.version = require('../package.json').version;
elliptic.utils = require('./elliptic/utils');
elliptic.rand = require('brorand');
elliptic.hmacDRBG = require('./elliptic/hmac-drbg');
elliptic.curve = require('./elliptic/curve');
elliptic.curves = require('./elliptic/curves');

// Protocols
elliptic.ec = require('./elliptic/ec');
elliptic.eddsa = require('./elliptic/eddsa');

},{"../package.json":83,"./elliptic/curve":70,"./elliptic/curves":73,"./elliptic/ec":74,"./elliptic/eddsa":77,"./elliptic/hmac-drbg":80,"./elliptic/utils":82,"brorand":17}],68:[function(require,module,exports){
'use strict';

var BN = require('bn.js');
var elliptic = require('../../elliptic');
var utils = elliptic.utils;
var getNAF = utils.getNAF;
var getJSF = utils.getJSF;
var assert = utils.assert;

function BaseCurve(type, conf) {
  this.type = type;
  this.p = new BN(conf.p, 16);

  // Use Montgomery, when there is no fast reduction for the prime
  this.red = conf.prime ? BN.red(conf.prime) : BN.mont(this.p);

  // Useful for many curves
  this.zero = new BN(0).toRed(this.red);
  this.one = new BN(1).toRed(this.red);
  this.two = new BN(2).toRed(this.red);

  // Curve configuration, optional
  this.n = conf.n && new BN(conf.n, 16);
  this.g = conf.g && this.pointFromJSON(conf.g, conf.gRed);

  // Temporary arrays
  this._wnafT1 = new Array(4);
  this._wnafT2 = new Array(4);
  this._wnafT3 = new Array(4);
  this._wnafT4 = new Array(4);

  // Generalized Greg Maxwell's trick
  var adjustCount = this.n && this.p.div(this.n);
  if (!adjustCount || adjustCount.cmpn(100) > 0) {
    this.redN = null;
  } else {
    this._maxwellTrick = true;
    this.redN = this.n.toRed(this.red);
  }
}
module.exports = BaseCurve;

BaseCurve.prototype.point = function point() {
  throw new Error('Not implemented');
};

BaseCurve.prototype.validate = function validate() {
  throw new Error('Not implemented');
};

BaseCurve.prototype._fixedNafMul = function _fixedNafMul(p, k) {
  assert(p.precomputed);
  var doubles = p._getDoubles();

  var naf = getNAF(k, 1);
  var I = (1 << (doubles.step + 1)) - (doubles.step % 2 === 0 ? 2 : 1);
  I /= 3;

  // Translate into more windowed form
  var repr = [];
  for (var j = 0; j < naf.length; j += doubles.step) {
    var nafW = 0;
    for (var k = j + doubles.step - 1; k >= j; k--)
      nafW = (nafW << 1) + naf[k];
    repr.push(nafW);
  }

  var a = this.jpoint(null, null, null);
  var b = this.jpoint(null, null, null);
  for (var i = I; i > 0; i--) {
    for (var j = 0; j < repr.length; j++) {
      var nafW = repr[j];
      if (nafW === i)
        b = b.mixedAdd(doubles.points[j]);
      else if (nafW === -i)
        b = b.mixedAdd(doubles.points[j].neg());
    }
    a = a.add(b);
  }
  return a.toP();
};

BaseCurve.prototype._wnafMul = function _wnafMul(p, k) {
  var w = 4;

  // Precompute window
  var nafPoints = p._getNAFPoints(w);
  w = nafPoints.wnd;
  var wnd = nafPoints.points;

  // Get NAF form
  var naf = getNAF(k, w);

  // Add `this`*(N+1) for every w-NAF index
  var acc = this.jpoint(null, null, null);
  for (var i = naf.length - 1; i >= 0; i--) {
    // Count zeroes
    for (var k = 0; i >= 0 && naf[i] === 0; i--)
      k++;
    if (i >= 0)
      k++;
    acc = acc.dblp(k);

    if (i < 0)
      break;
    var z = naf[i];
    assert(z !== 0);
    if (p.type === 'affine') {
      // J +- P
      if (z > 0)
        acc = acc.mixedAdd(wnd[(z - 1) >> 1]);
      else
        acc = acc.mixedAdd(wnd[(-z - 1) >> 1].neg());
    } else {
      // J +- J
      if (z > 0)
        acc = acc.add(wnd[(z - 1) >> 1]);
      else
        acc = acc.add(wnd[(-z - 1) >> 1].neg());
    }
  }
  return p.type === 'affine' ? acc.toP() : acc;
};

BaseCurve.prototype._wnafMulAdd = function _wnafMulAdd(defW,
                                                       points,
                                                       coeffs,
                                                       len,
                                                       jacobianResult) {
  var wndWidth = this._wnafT1;
  var wnd = this._wnafT2;
  var naf = this._wnafT3;

  // Fill all arrays
  var max = 0;
  for (var i = 0; i < len; i++) {
    var p = points[i];
    var nafPoints = p._getNAFPoints(defW);
    wndWidth[i] = nafPoints.wnd;
    wnd[i] = nafPoints.points;
  }

  // Comb small window NAFs
  for (var i = len - 1; i >= 1; i -= 2) {
    var a = i - 1;
    var b = i;
    if (wndWidth[a] !== 1 || wndWidth[b] !== 1) {
      naf[a] = getNAF(coeffs[a], wndWidth[a]);
      naf[b] = getNAF(coeffs[b], wndWidth[b]);
      max = Math.max(naf[a].length, max);
      max = Math.max(naf[b].length, max);
      continue;
    }

    var comb = [
      points[a], /* 1 */
      null, /* 3 */
      null, /* 5 */
      points[b] /* 7 */
    ];

    // Try to avoid Projective points, if possible
    if (points[a].y.cmp(points[b].y) === 0) {
      comb[1] = points[a].add(points[b]);
      comb[2] = points[a].toJ().mixedAdd(points[b].neg());
    } else if (points[a].y.cmp(points[b].y.redNeg()) === 0) {
      comb[1] = points[a].toJ().mixedAdd(points[b]);
      comb[2] = points[a].add(points[b].neg());
    } else {
      comb[1] = points[a].toJ().mixedAdd(points[b]);
      comb[2] = points[a].toJ().mixedAdd(points[b].neg());
    }

    var index = [
      -3, /* -1 -1 */
      -1, /* -1 0 */
      -5, /* -1 1 */
      -7, /* 0 -1 */
      0, /* 0 0 */
      7, /* 0 1 */
      5, /* 1 -1 */
      1, /* 1 0 */
      3  /* 1 1 */
    ];

    var jsf = getJSF(coeffs[a], coeffs[b]);
    max = Math.max(jsf[0].length, max);
    naf[a] = new Array(max);
    naf[b] = new Array(max);
    for (var j = 0; j < max; j++) {
      var ja = jsf[0][j] | 0;
      var jb = jsf[1][j] | 0;

      naf[a][j] = index[(ja + 1) * 3 + (jb + 1)];
      naf[b][j] = 0;
      wnd[a] = comb;
    }
  }

  var acc = this.jpoint(null, null, null);
  var tmp = this._wnafT4;
  for (var i = max; i >= 0; i--) {
    var k = 0;

    while (i >= 0) {
      var zero = true;
      for (var j = 0; j < len; j++) {
        tmp[j] = naf[j][i] | 0;
        if (tmp[j] !== 0)
          zero = false;
      }
      if (!zero)
        break;
      k++;
      i--;
    }
    if (i >= 0)
      k++;
    acc = acc.dblp(k);
    if (i < 0)
      break;

    for (var j = 0; j < len; j++) {
      var z = tmp[j];
      var p;
      if (z === 0)
        continue;
      else if (z > 0)
        p = wnd[j][(z - 1) >> 1];
      else if (z < 0)
        p = wnd[j][(-z - 1) >> 1].neg();

      if (p.type === 'affine')
        acc = acc.mixedAdd(p);
      else
        acc = acc.add(p);
    }
  }
  // Zeroify references
  for (var i = 0; i < len; i++)
    wnd[i] = null;

  if (jacobianResult)
    return acc;
  else
    return acc.toP();
};

function BasePoint(curve, type) {
  this.curve = curve;
  this.type = type;
  this.precomputed = null;
}
BaseCurve.BasePoint = BasePoint;

BasePoint.prototype.eq = function eq(/*other*/) {
  throw new Error('Not implemented');
};

BasePoint.prototype.validate = function validate() {
  return this.curve.validate(this);
};

BaseCurve.prototype.decodePoint = function decodePoint(bytes, enc) {
  bytes = utils.toArray(bytes, enc);

  var len = this.p.byteLength();

  // uncompressed, hybrid-odd, hybrid-even
  if ((bytes[0] === 0x04 || bytes[0] === 0x06 || bytes[0] === 0x07) &&
      bytes.length - 1 === 2 * len) {
    if (bytes[0] === 0x06)
      assert(bytes[bytes.length - 1] % 2 === 0);
    else if (bytes[0] === 0x07)
      assert(bytes[bytes.length - 1] % 2 === 1);

    var res =  this.point(bytes.slice(1, 1 + len),
                          bytes.slice(1 + len, 1 + 2 * len));

    return res;
  } else if ((bytes[0] === 0x02 || bytes[0] === 0x03) &&
              bytes.length - 1 === len) {
    return this.pointFromX(bytes.slice(1, 1 + len), bytes[0] === 0x03);
  }
  throw new Error('Unknown point format');
};

BasePoint.prototype.encodeCompressed = function encodeCompressed(enc) {
  return this.encode(enc, true);
};

BasePoint.prototype._encode = function _encode(compact) {
  var len = this.curve.p.byteLength();
  var x = this.getX().toArray('be', len);

  if (compact)
    return [ this.getY().isEven() ? 0x02 : 0x03 ].concat(x);

  return [ 0x04 ].concat(x, this.getY().toArray('be', len)) ;
};

BasePoint.prototype.encode = function encode(enc, compact) {
  return utils.encode(this._encode(compact), enc);
};

BasePoint.prototype.precompute = function precompute(power) {
  if (this.precomputed)
    return this;

  var precomputed = {
    doubles: null,
    naf: null,
    beta: null
  };
  precomputed.naf = this._getNAFPoints(8);
  precomputed.doubles = this._getDoubles(4, power);
  precomputed.beta = this._getBeta();
  this.precomputed = precomputed;

  return this;
};

BasePoint.prototype._hasDoubles = function _hasDoubles(k) {
  if (!this.precomputed)
    return false;

  var doubles = this.precomputed.doubles;
  if (!doubles)
    return false;

  return doubles.points.length >= Math.ceil((k.bitLength() + 1) / doubles.step);
};

BasePoint.prototype._getDoubles = function _getDoubles(step, power) {
  if (this.precomputed && this.precomputed.doubles)
    return this.precomputed.doubles;

  var doubles = [ this ];
  var acc = this;
  for (var i = 0; i < power; i += step) {
    for (var j = 0; j < step; j++)
      acc = acc.dbl();
    doubles.push(acc);
  }
  return {
    step: step,
    points: doubles
  };
};

BasePoint.prototype._getNAFPoints = function _getNAFPoints(wnd) {
  if (this.precomputed && this.precomputed.naf)
    return this.precomputed.naf;

  var res = [ this ];
  var max = (1 << wnd) - 1;
  var dbl = max === 1 ? null : this.dbl();
  for (var i = 1; i < max; i++)
    res[i] = res[i - 1].add(dbl);
  return {
    wnd: wnd,
    points: res
  };
};

BasePoint.prototype._getBeta = function _getBeta() {
  return null;
};

BasePoint.prototype.dblp = function dblp(k) {
  var r = this;
  for (var i = 0; i < k; i++)
    r = r.dbl();
  return r;
};

},{"../../elliptic":67,"bn.js":16}],69:[function(require,module,exports){
'use strict';

var curve = require('../curve');
var elliptic = require('../../elliptic');
var BN = require('bn.js');
var inherits = require('inherits');
var Base = curve.base;

var assert = elliptic.utils.assert;

function EdwardsCurve(conf) {
  // NOTE: Important as we are creating point in Base.call()
  this.twisted = (conf.a | 0) !== 1;
  this.mOneA = this.twisted && (conf.a | 0) === -1;
  this.extended = this.mOneA;

  Base.call(this, 'edwards', conf);

  this.a = new BN(conf.a, 16).umod(this.red.m);
  this.a = this.a.toRed(this.red);
  this.c = new BN(conf.c, 16).toRed(this.red);
  this.c2 = this.c.redSqr();
  this.d = new BN(conf.d, 16).toRed(this.red);
  this.dd = this.d.redAdd(this.d);

  assert(!this.twisted || this.c.fromRed().cmpn(1) === 0);
  this.oneC = (conf.c | 0) === 1;
}
inherits(EdwardsCurve, Base);
module.exports = EdwardsCurve;

EdwardsCurve.prototype._mulA = function _mulA(num) {
  if (this.mOneA)
    return num.redNeg();
  else
    return this.a.redMul(num);
};

EdwardsCurve.prototype._mulC = function _mulC(num) {
  if (this.oneC)
    return num;
  else
    return this.c.redMul(num);
};

// Just for compatibility with Short curve
EdwardsCurve.prototype.jpoint = function jpoint(x, y, z, t) {
  return this.point(x, y, z, t);
};

EdwardsCurve.prototype.pointFromX = function pointFromX(x, odd) {
  x = new BN(x, 16);
  if (!x.red)
    x = x.toRed(this.red);

  var x2 = x.redSqr();
  var rhs = this.c2.redSub(this.a.redMul(x2));
  var lhs = this.one.redSub(this.c2.redMul(this.d).redMul(x2));

  var y2 = rhs.redMul(lhs.redInvm());
  var y = y2.redSqrt();
  if (y.redSqr().redSub(y2).cmp(this.zero) !== 0)
    throw new Error('invalid point');

  var isOdd = y.fromRed().isOdd();
  if (odd && !isOdd || !odd && isOdd)
    y = y.redNeg();

  return this.point(x, y);
};

EdwardsCurve.prototype.pointFromY = function pointFromY(y, odd) {
  y = new BN(y, 16);
  if (!y.red)
    y = y.toRed(this.red);

  // x^2 = (y^2 - 1) / (d y^2 + 1)
  var y2 = y.redSqr();
  var lhs = y2.redSub(this.one);
  var rhs = y2.redMul(this.d).redAdd(this.one);
  var x2 = lhs.redMul(rhs.redInvm());

  if (x2.cmp(this.zero) === 0) {
    if (odd)
      throw new Error('invalid point');
    else
      return this.point(this.zero, y);
  }

  var x = x2.redSqrt();
  if (x.redSqr().redSub(x2).cmp(this.zero) !== 0)
    throw new Error('invalid point');

  if (x.isOdd() !== odd)
    x = x.redNeg();

  return this.point(x, y);
};

EdwardsCurve.prototype.validate = function validate(point) {
  if (point.isInfinity())
    return true;

  // Curve: A * X^2 + Y^2 = C^2 * (1 + D * X^2 * Y^2)
  point.normalize();

  var x2 = point.x.redSqr();
  var y2 = point.y.redSqr();
  var lhs = x2.redMul(this.a).redAdd(y2);
  var rhs = this.c2.redMul(this.one.redAdd(this.d.redMul(x2).redMul(y2)));

  return lhs.cmp(rhs) === 0;
};

function Point(curve, x, y, z, t) {
  Base.BasePoint.call(this, curve, 'projective');
  if (x === null && y === null && z === null) {
    this.x = this.curve.zero;
    this.y = this.curve.one;
    this.z = this.curve.one;
    this.t = this.curve.zero;
    this.zOne = true;
  } else {
    this.x = new BN(x, 16);
    this.y = new BN(y, 16);
    this.z = z ? new BN(z, 16) : this.curve.one;
    this.t = t && new BN(t, 16);
    if (!this.x.red)
      this.x = this.x.toRed(this.curve.red);
    if (!this.y.red)
      this.y = this.y.toRed(this.curve.red);
    if (!this.z.red)
      this.z = this.z.toRed(this.curve.red);
    if (this.t && !this.t.red)
      this.t = this.t.toRed(this.curve.red);
    this.zOne = this.z === this.curve.one;

    // Use extended coordinates
    if (this.curve.extended && !this.t) {
      this.t = this.x.redMul(this.y);
      if (!this.zOne)
        this.t = this.t.redMul(this.z.redInvm());
    }
  }
}
inherits(Point, Base.BasePoint);

EdwardsCurve.prototype.pointFromJSON = function pointFromJSON(obj) {
  return Point.fromJSON(this, obj);
};

EdwardsCurve.prototype.point = function point(x, y, z, t) {
  return new Point(this, x, y, z, t);
};

Point.fromJSON = function fromJSON(curve, obj) {
  return new Point(curve, obj[0], obj[1], obj[2]);
};

Point.prototype.inspect = function inspect() {
  if (this.isInfinity())
    return '<EC Point Infinity>';
  return '<EC Point x: ' + this.x.fromRed().toString(16, 2) +
      ' y: ' + this.y.fromRed().toString(16, 2) +
      ' z: ' + this.z.fromRed().toString(16, 2) + '>';
};

Point.prototype.isInfinity = function isInfinity() {
  // XXX This code assumes that zero is always zero in red
  return this.x.cmpn(0) === 0 &&
         this.y.cmp(this.z) === 0;
};

Point.prototype._extDbl = function _extDbl() {
  // hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html
  //     #doubling-dbl-2008-hwcd
  // 4M + 4S

  // A = X1^2
  var a = this.x.redSqr();
  // B = Y1^2
  var b = this.y.redSqr();
  // C = 2 * Z1^2
  var c = this.z.redSqr();
  c = c.redIAdd(c);
  // D = a * A
  var d = this.curve._mulA(a);
  // E = (X1 + Y1)^2 - A - B
  var e = this.x.redAdd(this.y).redSqr().redISub(a).redISub(b);
  // G = D + B
  var g = d.redAdd(b);
  // F = G - C
  var f = g.redSub(c);
  // H = D - B
  var h = d.redSub(b);
  // X3 = E * F
  var nx = e.redMul(f);
  // Y3 = G * H
  var ny = g.redMul(h);
  // T3 = E * H
  var nt = e.redMul(h);
  // Z3 = F * G
  var nz = f.redMul(g);
  return this.curve.point(nx, ny, nz, nt);
};

Point.prototype._projDbl = function _projDbl() {
  // hyperelliptic.org/EFD/g1p/auto-twisted-projective.html
  //     #doubling-dbl-2008-bbjlp
  //     #doubling-dbl-2007-bl
  // and others
  // Generally 3M + 4S or 2M + 4S

  // B = (X1 + Y1)^2
  var b = this.x.redAdd(this.y).redSqr();
  // C = X1^2
  var c = this.x.redSqr();
  // D = Y1^2
  var d = this.y.redSqr();

  var nx;
  var ny;
  var nz;
  if (this.curve.twisted) {
    // E = a * C
    var e = this.curve._mulA(c);
    // F = E + D
    var f = e.redAdd(d);
    if (this.zOne) {
      // X3 = (B - C - D) * (F - 2)
      nx = b.redSub(c).redSub(d).redMul(f.redSub(this.curve.two));
      // Y3 = F * (E - D)
      ny = f.redMul(e.redSub(d));
      // Z3 = F^2 - 2 * F
      nz = f.redSqr().redSub(f).redSub(f);
    } else {
      // H = Z1^2
      var h = this.z.redSqr();
      // J = F - 2 * H
      var j = f.redSub(h).redISub(h);
      // X3 = (B-C-D)*J
      nx = b.redSub(c).redISub(d).redMul(j);
      // Y3 = F * (E - D)
      ny = f.redMul(e.redSub(d));
      // Z3 = F * J
      nz = f.redMul(j);
    }
  } else {
    // E = C + D
    var e = c.redAdd(d);
    // H = (c * Z1)^2
    var h = this.curve._mulC(this.c.redMul(this.z)).redSqr();
    // J = E - 2 * H
    var j = e.redSub(h).redSub(h);
    // X3 = c * (B - E) * J
    nx = this.curve._mulC(b.redISub(e)).redMul(j);
    // Y3 = c * E * (C - D)
    ny = this.curve._mulC(e).redMul(c.redISub(d));
    // Z3 = E * J
    nz = e.redMul(j);
  }
  return this.curve.point(nx, ny, nz);
};

Point.prototype.dbl = function dbl() {
  if (this.isInfinity())
    return this;

  // Double in extended coordinates
  if (this.curve.extended)
    return this._extDbl();
  else
    return this._projDbl();
};

Point.prototype._extAdd = function _extAdd(p) {
  // hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html
  //     #addition-add-2008-hwcd-3
  // 8M

  // A = (Y1 - X1) * (Y2 - X2)
  var a = this.y.redSub(this.x).redMul(p.y.redSub(p.x));
  // B = (Y1 + X1) * (Y2 + X2)
  var b = this.y.redAdd(this.x).redMul(p.y.redAdd(p.x));
  // C = T1 * k * T2
  var c = this.t.redMul(this.curve.dd).redMul(p.t);
  // D = Z1 * 2 * Z2
  var d = this.z.redMul(p.z.redAdd(p.z));
  // E = B - A
  var e = b.redSub(a);
  // F = D - C
  var f = d.redSub(c);
  // G = D + C
  var g = d.redAdd(c);
  // H = B + A
  var h = b.redAdd(a);
  // X3 = E * F
  var nx = e.redMul(f);
  // Y3 = G * H
  var ny = g.redMul(h);
  // T3 = E * H
  var nt = e.redMul(h);
  // Z3 = F * G
  var nz = f.redMul(g);
  return this.curve.point(nx, ny, nz, nt);
};

Point.prototype._projAdd = function _projAdd(p) {
  // hyperelliptic.org/EFD/g1p/auto-twisted-projective.html
  //     #addition-add-2008-bbjlp
  //     #addition-add-2007-bl
  // 10M + 1S

  // A = Z1 * Z2
  var a = this.z.redMul(p.z);
  // B = A^2
  var b = a.redSqr();
  // C = X1 * X2
  var c = this.x.redMul(p.x);
  // D = Y1 * Y2
  var d = this.y.redMul(p.y);
  // E = d * C * D
  var e = this.curve.d.redMul(c).redMul(d);
  // F = B - E
  var f = b.redSub(e);
  // G = B + E
  var g = b.redAdd(e);
  // X3 = A * F * ((X1 + Y1) * (X2 + Y2) - C - D)
  var tmp = this.x.redAdd(this.y).redMul(p.x.redAdd(p.y)).redISub(c).redISub(d);
  var nx = a.redMul(f).redMul(tmp);
  var ny;
  var nz;
  if (this.curve.twisted) {
    // Y3 = A * G * (D - a * C)
    ny = a.redMul(g).redMul(d.redSub(this.curve._mulA(c)));
    // Z3 = F * G
    nz = f.redMul(g);
  } else {
    // Y3 = A * G * (D - C)
    ny = a.redMul(g).redMul(d.redSub(c));
    // Z3 = c * F * G
    nz = this.curve._mulC(f).redMul(g);
  }
  return this.curve.point(nx, ny, nz);
};

Point.prototype.add = function add(p) {
  if (this.isInfinity())
    return p;
  if (p.isInfinity())
    return this;

  if (this.curve.extended)
    return this._extAdd(p);
  else
    return this._projAdd(p);
};

Point.prototype.mul = function mul(k) {
  if (this._hasDoubles(k))
    return this.curve._fixedNafMul(this, k);
  else
    return this.curve._wnafMul(this, k);
};

Point.prototype.mulAdd = function mulAdd(k1, p, k2) {
  return this.curve._wnafMulAdd(1, [ this, p ], [ k1, k2 ], 2, false);
};

Point.prototype.jmulAdd = function jmulAdd(k1, p, k2) {
  return this.curve._wnafMulAdd(1, [ this, p ], [ k1, k2 ], 2, true);
};

Point.prototype.normalize = function normalize() {
  if (this.zOne)
    return this;

  // Normalize coordinates
  var zi = this.z.redInvm();
  this.x = this.x.redMul(zi);
  this.y = this.y.redMul(zi);
  if (this.t)
    this.t = this.t.redMul(zi);
  this.z = this.curve.one;
  this.zOne = true;
  return this;
};

Point.prototype.neg = function neg() {
  return this.curve.point(this.x.redNeg(),
                          this.y,
                          this.z,
                          this.t && this.t.redNeg());
};

Point.prototype.getX = function getX() {
  this.normalize();
  return this.x.fromRed();
};

Point.prototype.getY = function getY() {
  this.normalize();
  return this.y.fromRed();
};

Point.prototype.eq = function eq(other) {
  return this === other ||
         this.getX().cmp(other.getX()) === 0 &&
         this.getY().cmp(other.getY()) === 0;
};

Point.prototype.eqXToP = function eqXToP(x) {
  var rx = x.toRed(this.curve.red).redMul(this.z);
  if (this.x.cmp(rx) === 0)
    return true;

  var xc = x.clone();
  var t = this.curve.redN.redMul(this.z);
  for (;;) {
    xc.iadd(this.curve.n);
    if (xc.cmp(this.curve.p) >= 0)
      return false;

    rx.redIAdd(t);
    if (this.x.cmp(rx) === 0)
      return true;
  }
  return false;
};

// Compatibility with BaseCurve
Point.prototype.toP = Point.prototype.normalize;
Point.prototype.mixedAdd = Point.prototype.add;

},{"../../elliptic":67,"../curve":70,"bn.js":16,"inherits":94}],70:[function(require,module,exports){
'use strict';

var curve = exports;

curve.base = require('./base');
curve.short = require('./short');
curve.mont = require('./mont');
curve.edwards = require('./edwards');

},{"./base":68,"./edwards":69,"./mont":71,"./short":72}],71:[function(require,module,exports){
'use strict';

var curve = require('../curve');
var BN = require('bn.js');
var inherits = require('inherits');
var Base = curve.base;

var elliptic = require('../../elliptic');
var utils = elliptic.utils;

function MontCurve(conf) {
  Base.call(this, 'mont', conf);

  this.a = new BN(conf.a, 16).toRed(this.red);
  this.b = new BN(conf.b, 16).toRed(this.red);
  this.i4 = new BN(4).toRed(this.red).redInvm();
  this.two = new BN(2).toRed(this.red);
  this.a24 = this.i4.redMul(this.a.redAdd(this.two));
}
inherits(MontCurve, Base);
module.exports = MontCurve;

MontCurve.prototype.validate = function validate(point) {
  var x = point.normalize().x;
  var x2 = x.redSqr();
  var rhs = x2.redMul(x).redAdd(x2.redMul(this.a)).redAdd(x);
  var y = rhs.redSqrt();

  return y.redSqr().cmp(rhs) === 0;
};

function Point(curve, x, z) {
  Base.BasePoint.call(this, curve, 'projective');
  if (x === null && z === null) {
    this.x = this.curve.one;
    this.z = this.curve.zero;
  } else {
    this.x = new BN(x, 16);
    this.z = new BN(z, 16);
    if (!this.x.red)
      this.x = this.x.toRed(this.curve.red);
    if (!this.z.red)
      this.z = this.z.toRed(this.curve.red);
  }
}
inherits(Point, Base.BasePoint);

MontCurve.prototype.decodePoint = function decodePoint(bytes, enc) {
  return this.point(utils.toArray(bytes, enc), 1);
};

MontCurve.prototype.point = function point(x, z) {
  return new Point(this, x, z);
};

MontCurve.prototype.pointFromJSON = function pointFromJSON(obj) {
  return Point.fromJSON(this, obj);
};

Point.prototype.precompute = function precompute() {
  // No-op
};

Point.prototype._encode = function _encode() {
  return this.getX().toArray('be', this.curve.p.byteLength());
};

Point.fromJSON = function fromJSON(curve, obj) {
  return new Point(curve, obj[0], obj[1] || curve.one);
};

Point.prototype.inspect = function inspect() {
  if (this.isInfinity())
    return '<EC Point Infinity>';
  return '<EC Point x: ' + this.x.fromRed().toString(16, 2) +
      ' z: ' + this.z.fromRed().toString(16, 2) + '>';
};

Point.prototype.isInfinity = function isInfinity() {
  // XXX This code assumes that zero is always zero in red
  return this.z.cmpn(0) === 0;
};

Point.prototype.dbl = function dbl() {
  // http://hyperelliptic.org/EFD/g1p/auto-montgom-xz.html#doubling-dbl-1987-m-3
  // 2M + 2S + 4A

  // A = X1 + Z1
  var a = this.x.redAdd(this.z);
  // AA = A^2
  var aa = a.redSqr();
  // B = X1 - Z1
  var b = this.x.redSub(this.z);
  // BB = B^2
  var bb = b.redSqr();
  // C = AA - BB
  var c = aa.redSub(bb);
  // X3 = AA * BB
  var nx = aa.redMul(bb);
  // Z3 = C * (BB + A24 * C)
  var nz = c.redMul(bb.redAdd(this.curve.a24.redMul(c)));
  return this.curve.point(nx, nz);
};

Point.prototype.add = function add() {
  throw new Error('Not supported on Montgomery curve');
};

Point.prototype.diffAdd = function diffAdd(p, diff) {
  // http://hyperelliptic.org/EFD/g1p/auto-montgom-xz.html#diffadd-dadd-1987-m-3
  // 4M + 2S + 6A

  // A = X2 + Z2
  var a = this.x.redAdd(this.z);
  // B = X2 - Z2
  var b = this.x.redSub(this.z);
  // C = X3 + Z3
  var c = p.x.redAdd(p.z);
  // D = X3 - Z3
  var d = p.x.redSub(p.z);
  // DA = D * A
  var da = d.redMul(a);
  // CB = C * B
  var cb = c.redMul(b);
  // X5 = Z1 * (DA + CB)^2
  var nx = diff.z.redMul(da.redAdd(cb).redSqr());
  // Z5 = X1 * (DA - CB)^2
  var nz = diff.x.redMul(da.redISub(cb).redSqr());
  return this.curve.point(nx, nz);
};

Point.prototype.mul = function mul(k) {
  var t = k.clone();
  var a = this; // (N / 2) * Q + Q
  var b = this.curve.point(null, null); // (N / 2) * Q
  var c = this; // Q

  for (var bits = []; t.cmpn(0) !== 0; t.iushrn(1))
    bits.push(t.andln(1));

  for (var i = bits.length - 1; i >= 0; i--) {
    if (bits[i] === 0) {
      // N * Q + Q = ((N / 2) * Q + Q)) + (N / 2) * Q
      a = a.diffAdd(b, c);
      // N * Q = 2 * ((N / 2) * Q + Q))
      b = b.dbl();
    } else {
      // N * Q = ((N / 2) * Q + Q) + ((N / 2) * Q)
      b = a.diffAdd(b, c);
      // N * Q + Q = 2 * ((N / 2) * Q + Q)
      a = a.dbl();
    }
  }
  return b;
};

Point.prototype.mulAdd = function mulAdd() {
  throw new Error('Not supported on Montgomery curve');
};

Point.prototype.jumlAdd = function jumlAdd() {
  throw new Error('Not supported on Montgomery curve');
};

Point.prototype.eq = function eq(other) {
  return this.getX().cmp(other.getX()) === 0;
};

Point.prototype.normalize = function normalize() {
  this.x = this.x.redMul(this.z.redInvm());
  this.z = this.curve.one;
  return this;
};

Point.prototype.getX = function getX() {
  // Normalize coordinates
  this.normalize();

  return this.x.fromRed();
};

},{"../../elliptic":67,"../curve":70,"bn.js":16,"inherits":94}],72:[function(require,module,exports){
'use strict';

var curve = require('../curve');
var elliptic = require('../../elliptic');
var BN = require('bn.js');
var inherits = require('inherits');
var Base = curve.base;

var assert = elliptic.utils.assert;

function ShortCurve(conf) {
  Base.call(this, 'short', conf);

  this.a = new BN(conf.a, 16).toRed(this.red);
  this.b = new BN(conf.b, 16).toRed(this.red);
  this.tinv = this.two.redInvm();

  this.zeroA = this.a.fromRed().cmpn(0) === 0;
  this.threeA = this.a.fromRed().sub(this.p).cmpn(-3) === 0;

  // If the curve is endomorphic, precalculate beta and lambda
  this.endo = this._getEndomorphism(conf);
  this._endoWnafT1 = new Array(4);
  this._endoWnafT2 = new Array(4);
}
inherits(ShortCurve, Base);
module.exports = ShortCurve;

ShortCurve.prototype._getEndomorphism = function _getEndomorphism(conf) {
  // No efficient endomorphism
  if (!this.zeroA || !this.g || !this.n || this.p.modn(3) !== 1)
    return;

  // Compute beta and lambda, that lambda * P = (beta * Px; Py)
  var beta;
  var lambda;
  if (conf.beta) {
    beta = new BN(conf.beta, 16).toRed(this.red);
  } else {
    var betas = this._getEndoRoots(this.p);
    // Choose the smallest beta
    beta = betas[0].cmp(betas[1]) < 0 ? betas[0] : betas[1];
    beta = beta.toRed(this.red);
  }
  if (conf.lambda) {
    lambda = new BN(conf.lambda, 16);
  } else {
    // Choose the lambda that is matching selected beta
    var lambdas = this._getEndoRoots(this.n);
    if (this.g.mul(lambdas[0]).x.cmp(this.g.x.redMul(beta)) === 0) {
      lambda = lambdas[0];
    } else {
      lambda = lambdas[1];
      assert(this.g.mul(lambda).x.cmp(this.g.x.redMul(beta)) === 0);
    }
  }

  // Get basis vectors, used for balanced length-two representation
  var basis;
  if (conf.basis) {
    basis = conf.basis.map(function(vec) {
      return {
        a: new BN(vec.a, 16),
        b: new BN(vec.b, 16)
      };
    });
  } else {
    basis = this._getEndoBasis(lambda);
  }

  return {
    beta: beta,
    lambda: lambda,
    basis: basis
  };
};

ShortCurve.prototype._getEndoRoots = function _getEndoRoots(num) {
  // Find roots of for x^2 + x + 1 in F
  // Root = (-1 +- Sqrt(-3)) / 2
  //
  var red = num === this.p ? this.red : BN.mont(num);
  var tinv = new BN(2).toRed(red).redInvm();
  var ntinv = tinv.redNeg();

  var s = new BN(3).toRed(red).redNeg().redSqrt().redMul(tinv);

  var l1 = ntinv.redAdd(s).fromRed();
  var l2 = ntinv.redSub(s).fromRed();
  return [ l1, l2 ];
};

ShortCurve.prototype._getEndoBasis = function _getEndoBasis(lambda) {
  // aprxSqrt >= sqrt(this.n)
  var aprxSqrt = this.n.ushrn(Math.floor(this.n.bitLength() / 2));

  // 3.74
  // Run EGCD, until r(L + 1) < aprxSqrt
  var u = lambda;
  var v = this.n.clone();
  var x1 = new BN(1);
  var y1 = new BN(0);
  var x2 = new BN(0);
  var y2 = new BN(1);

  // NOTE: all vectors are roots of: a + b * lambda = 0 (mod n)
  var a0;
  var b0;
  // First vector
  var a1;
  var b1;
  // Second vector
  var a2;
  var b2;

  var prevR;
  var i = 0;
  var r;
  var x;
  while (u.cmpn(0) !== 0) {
    var q = v.div(u);
    r = v.sub(q.mul(u));
    x = x2.sub(q.mul(x1));
    var y = y2.sub(q.mul(y1));

    if (!a1 && r.cmp(aprxSqrt) < 0) {
      a0 = prevR.neg();
      b0 = x1;
      a1 = r.neg();
      b1 = x;
    } else if (a1 && ++i === 2) {
      break;
    }
    prevR = r;

    v = u;
    u = r;
    x2 = x1;
    x1 = x;
    y2 = y1;
    y1 = y;
  }
  a2 = r.neg();
  b2 = x;

  var len1 = a1.sqr().add(b1.sqr());
  var len2 = a2.sqr().add(b2.sqr());
  if (len2.cmp(len1) >= 0) {
    a2 = a0;
    b2 = b0;
  }

  // Normalize signs
  if (a1.negative) {
    a1 = a1.neg();
    b1 = b1.neg();
  }
  if (a2.negative) {
    a2 = a2.neg();
    b2 = b2.neg();
  }

  return [
    { a: a1, b: b1 },
    { a: a2, b: b2 }
  ];
};

ShortCurve.prototype._endoSplit = function _endoSplit(k) {
  var basis = this.endo.basis;
  var v1 = basis[0];
  var v2 = basis[1];

  var c1 = v2.b.mul(k).divRound(this.n);
  var c2 = v1.b.neg().mul(k).divRound(this.n);

  var p1 = c1.mul(v1.a);
  var p2 = c2.mul(v2.a);
  var q1 = c1.mul(v1.b);
  var q2 = c2.mul(v2.b);

  // Calculate answer
  var k1 = k.sub(p1).sub(p2);
  var k2 = q1.add(q2).neg();
  return { k1: k1, k2: k2 };
};

ShortCurve.prototype.pointFromX = function pointFromX(x, odd) {
  x = new BN(x, 16);
  if (!x.red)
    x = x.toRed(this.red);

  var y2 = x.redSqr().redMul(x).redIAdd(x.redMul(this.a)).redIAdd(this.b);
  var y = y2.redSqrt();
  if (y.redSqr().redSub(y2).cmp(this.zero) !== 0)
    throw new Error('invalid point');

  // XXX Is there any way to tell if the number is odd without converting it
  // to non-red form?
  var isOdd = y.fromRed().isOdd();
  if (odd && !isOdd || !odd && isOdd)
    y = y.redNeg();

  return this.point(x, y);
};

ShortCurve.prototype.validate = function validate(point) {
  if (point.inf)
    return true;

  var x = point.x;
  var y = point.y;

  var ax = this.a.redMul(x);
  var rhs = x.redSqr().redMul(x).redIAdd(ax).redIAdd(this.b);
  return y.redSqr().redISub(rhs).cmpn(0) === 0;
};

ShortCurve.prototype._endoWnafMulAdd =
    function _endoWnafMulAdd(points, coeffs, jacobianResult) {
  var npoints = this._endoWnafT1;
  var ncoeffs = this._endoWnafT2;
  for (var i = 0; i < points.length; i++) {
    var split = this._endoSplit(coeffs[i]);
    var p = points[i];
    var beta = p._getBeta();

    if (split.k1.negative) {
      split.k1.ineg();
      p = p.neg(true);
    }
    if (split.k2.negative) {
      split.k2.ineg();
      beta = beta.neg(true);
    }

    npoints[i * 2] = p;
    npoints[i * 2 + 1] = beta;
    ncoeffs[i * 2] = split.k1;
    ncoeffs[i * 2 + 1] = split.k2;
  }
  var res = this._wnafMulAdd(1, npoints, ncoeffs, i * 2, jacobianResult);

  // Clean-up references to points and coefficients
  for (var j = 0; j < i * 2; j++) {
    npoints[j] = null;
    ncoeffs[j] = null;
  }
  return res;
};

function Point(curve, x, y, isRed) {
  Base.BasePoint.call(this, curve, 'affine');
  if (x === null && y === null) {
    this.x = null;
    this.y = null;
    this.inf = true;
  } else {
    this.x = new BN(x, 16);
    this.y = new BN(y, 16);
    // Force redgomery representation when loading from JSON
    if (isRed) {
      this.x.forceRed(this.curve.red);
      this.y.forceRed(this.curve.red);
    }
    if (!this.x.red)
      this.x = this.x.toRed(this.curve.red);
    if (!this.y.red)
      this.y = this.y.toRed(this.curve.red);
    this.inf = false;
  }
}
inherits(Point, Base.BasePoint);

ShortCurve.prototype.point = function point(x, y, isRed) {
  return new Point(this, x, y, isRed);
};

ShortCurve.prototype.pointFromJSON = function pointFromJSON(obj, red) {
  return Point.fromJSON(this, obj, red);
};

Point.prototype._getBeta = function _getBeta() {
  if (!this.curve.endo)
    return;

  var pre = this.precomputed;
  if (pre && pre.beta)
    return pre.beta;

  var beta = this.curve.point(this.x.redMul(this.curve.endo.beta), this.y);
  if (pre) {
    var curve = this.curve;
    var endoMul = function(p) {
      return curve.point(p.x.redMul(curve.endo.beta), p.y);
    };
    pre.beta = beta;
    beta.precomputed = {
      beta: null,
      naf: pre.naf && {
        wnd: pre.naf.wnd,
        points: pre.naf.points.map(endoMul)
      },
      doubles: pre.doubles && {
        step: pre.doubles.step,
        points: pre.doubles.points.map(endoMul)
      }
    };
  }
  return beta;
};

Point.prototype.toJSON = function toJSON() {
  if (!this.precomputed)
    return [ this.x, this.y ];

  return [ this.x, this.y, this.precomputed && {
    doubles: this.precomputed.doubles && {
      step: this.precomputed.doubles.step,
      points: this.precomputed.doubles.points.slice(1)
    },
    naf: this.precomputed.naf && {
      wnd: this.precomputed.naf.wnd,
      points: this.precomputed.naf.points.slice(1)
    }
  } ];
};

Point.fromJSON = function fromJSON(curve, obj, red) {
  if (typeof obj === 'string')
    obj = JSON.parse(obj);
  var res = curve.point(obj[0], obj[1], red);
  if (!obj[2])
    return res;

  function obj2point(obj) {
    return curve.point(obj[0], obj[1], red);
  }

  var pre = obj[2];
  res.precomputed = {
    beta: null,
    doubles: pre.doubles && {
      step: pre.doubles.step,
      points: [ res ].concat(pre.doubles.points.map(obj2point))
    },
    naf: pre.naf && {
      wnd: pre.naf.wnd,
      points: [ res ].concat(pre.naf.points.map(obj2point))
    }
  };
  return res;
};

Point.prototype.inspect = function inspect() {
  if (this.isInfinity())
    return '<EC Point Infinity>';
  return '<EC Point x: ' + this.x.fromRed().toString(16, 2) +
      ' y: ' + this.y.fromRed().toString(16, 2) + '>';
};

Point.prototype.isInfinity = function isInfinity() {
  return this.inf;
};

Point.prototype.add = function add(p) {
  // O + P = P
  if (this.inf)
    return p;

  // P + O = P
  if (p.inf)
    return this;

  // P + P = 2P
  if (this.eq(p))
    return this.dbl();

  // P + (-P) = O
  if (this.neg().eq(p))
    return this.curve.point(null, null);

  // P + Q = O
  if (this.x.cmp(p.x) === 0)
    return this.curve.point(null, null);

  var c = this.y.redSub(p.y);
  if (c.cmpn(0) !== 0)
    c = c.redMul(this.x.redSub(p.x).redInvm());
  var nx = c.redSqr().redISub(this.x).redISub(p.x);
  var ny = c.redMul(this.x.redSub(nx)).redISub(this.y);
  return this.curve.point(nx, ny);
};

Point.prototype.dbl = function dbl() {
  if (this.inf)
    return this;

  // 2P = O
  var ys1 = this.y.redAdd(this.y);
  if (ys1.cmpn(0) === 0)
    return this.curve.point(null, null);

  var a = this.curve.a;

  var x2 = this.x.redSqr();
  var dyinv = ys1.redInvm();
  var c = x2.redAdd(x2).redIAdd(x2).redIAdd(a).redMul(dyinv);

  var nx = c.redSqr().redISub(this.x.redAdd(this.x));
  var ny = c.redMul(this.x.redSub(nx)).redISub(this.y);
  return this.curve.point(nx, ny);
};

Point.prototype.getX = function getX() {
  return this.x.fromRed();
};

Point.prototype.getY = function getY() {
  return this.y.fromRed();
};

Point.prototype.mul = function mul(k) {
  k = new BN(k, 16);

  if (this._hasDoubles(k))
    return this.curve._fixedNafMul(this, k);
  else if (this.curve.endo)
    return this.curve._endoWnafMulAdd([ this ], [ k ]);
  else
    return this.curve._wnafMul(this, k);
};

Point.prototype.mulAdd = function mulAdd(k1, p2, k2) {
  var points = [ this, p2 ];
  var coeffs = [ k1, k2 ];
  if (this.curve.endo)
    return this.curve._endoWnafMulAdd(points, coeffs);
  else
    return this.curve._wnafMulAdd(1, points, coeffs, 2);
};

Point.prototype.jmulAdd = function jmulAdd(k1, p2, k2) {
  var points = [ this, p2 ];
  var coeffs = [ k1, k2 ];
  if (this.curve.endo)
    return this.curve._endoWnafMulAdd(points, coeffs, true);
  else
    return this.curve._wnafMulAdd(1, points, coeffs, 2, true);
};

Point.prototype.eq = function eq(p) {
  return this === p ||
         this.inf === p.inf &&
             (this.inf || this.x.cmp(p.x) === 0 && this.y.cmp(p.y) === 0);
};

Point.prototype.neg = function neg(_precompute) {
  if (this.inf)
    return this;

  var res = this.curve.point(this.x, this.y.redNeg());
  if (_precompute && this.precomputed) {
    var pre = this.precomputed;
    var negate = function(p) {
      return p.neg();
    };
    res.precomputed = {
      naf: pre.naf && {
        wnd: pre.naf.wnd,
        points: pre.naf.points.map(negate)
      },
      doubles: pre.doubles && {
        step: pre.doubles.step,
        points: pre.doubles.points.map(negate)
      }
    };
  }
  return res;
};

Point.prototype.toJ = function toJ() {
  if (this.inf)
    return this.curve.jpoint(null, null, null);

  var res = this.curve.jpoint(this.x, this.y, this.curve.one);
  return res;
};

function JPoint(curve, x, y, z) {
  Base.BasePoint.call(this, curve, 'jacobian');
  if (x === null && y === null && z === null) {
    this.x = this.curve.one;
    this.y = this.curve.one;
    this.z = new BN(0);
  } else {
    this.x = new BN(x, 16);
    this.y = new BN(y, 16);
    this.z = new BN(z, 16);
  }
  if (!this.x.red)
    this.x = this.x.toRed(this.curve.red);
  if (!this.y.red)
    this.y = this.y.toRed(this.curve.red);
  if (!this.z.red)
    this.z = this.z.toRed(this.curve.red);

  this.zOne = this.z === this.curve.one;
}
inherits(JPoint, Base.BasePoint);

ShortCurve.prototype.jpoint = function jpoint(x, y, z) {
  return new JPoint(this, x, y, z);
};

JPoint.prototype.toP = function toP() {
  if (this.isInfinity())
    return this.curve.point(null, null);

  var zinv = this.z.redInvm();
  var zinv2 = zinv.redSqr();
  var ax = this.x.redMul(zinv2);
  var ay = this.y.redMul(zinv2).redMul(zinv);

  return this.curve.point(ax, ay);
};

JPoint.prototype.neg = function neg() {
  return this.curve.jpoint(this.x, this.y.redNeg(), this.z);
};

JPoint.prototype.add = function add(p) {
  // O + P = P
  if (this.isInfinity())
    return p;

  // P + O = P
  if (p.isInfinity())
    return this;

  // 12M + 4S + 7A
  var pz2 = p.z.redSqr();
  var z2 = this.z.redSqr();
  var u1 = this.x.redMul(pz2);
  var u2 = p.x.redMul(z2);
  var s1 = this.y.redMul(pz2.redMul(p.z));
  var s2 = p.y.redMul(z2.redMul(this.z));

  var h = u1.redSub(u2);
  var r = s1.redSub(s2);
  if (h.cmpn(0) === 0) {
    if (r.cmpn(0) !== 0)
      return this.curve.jpoint(null, null, null);
    else
      return this.dbl();
  }

  var h2 = h.redSqr();
  var h3 = h2.redMul(h);
  var v = u1.redMul(h2);

  var nx = r.redSqr().redIAdd(h3).redISub(v).redISub(v);
  var ny = r.redMul(v.redISub(nx)).redISub(s1.redMul(h3));
  var nz = this.z.redMul(p.z).redMul(h);

  return this.curve.jpoint(nx, ny, nz);
};

JPoint.prototype.mixedAdd = function mixedAdd(p) {
  // O + P = P
  if (this.isInfinity())
    return p.toJ();

  // P + O = P
  if (p.isInfinity())
    return this;

  // 8M + 3S + 7A
  var z2 = this.z.redSqr();
  var u1 = this.x;
  var u2 = p.x.redMul(z2);
  var s1 = this.y;
  var s2 = p.y.redMul(z2).redMul(this.z);

  var h = u1.redSub(u2);
  var r = s1.redSub(s2);
  if (h.cmpn(0) === 0) {
    if (r.cmpn(0) !== 0)
      return this.curve.jpoint(null, null, null);
    else
      return this.dbl();
  }

  var h2 = h.redSqr();
  var h3 = h2.redMul(h);
  var v = u1.redMul(h2);

  var nx = r.redSqr().redIAdd(h3).redISub(v).redISub(v);
  var ny = r.redMul(v.redISub(nx)).redISub(s1.redMul(h3));
  var nz = this.z.redMul(h);

  return this.curve.jpoint(nx, ny, nz);
};

JPoint.prototype.dblp = function dblp(pow) {
  if (pow === 0)
    return this;
  if (this.isInfinity())
    return this;
  if (!pow)
    return this.dbl();

  if (this.curve.zeroA || this.curve.threeA) {
    var r = this;
    for (var i = 0; i < pow; i++)
      r = r.dbl();
    return r;
  }

  // 1M + 2S + 1A + N * (4S + 5M + 8A)
  // N = 1 => 6M + 6S + 9A
  var a = this.curve.a;
  var tinv = this.curve.tinv;

  var jx = this.x;
  var jy = this.y;
  var jz = this.z;
  var jz4 = jz.redSqr().redSqr();

  // Reuse results
  var jyd = jy.redAdd(jy);
  for (var i = 0; i < pow; i++) {
    var jx2 = jx.redSqr();
    var jyd2 = jyd.redSqr();
    var jyd4 = jyd2.redSqr();
    var c = jx2.redAdd(jx2).redIAdd(jx2).redIAdd(a.redMul(jz4));

    var t1 = jx.redMul(jyd2);
    var nx = c.redSqr().redISub(t1.redAdd(t1));
    var t2 = t1.redISub(nx);
    var dny = c.redMul(t2);
    dny = dny.redIAdd(dny).redISub(jyd4);
    var nz = jyd.redMul(jz);
    if (i + 1 < pow)
      jz4 = jz4.redMul(jyd4);

    jx = nx;
    jz = nz;
    jyd = dny;
  }

  return this.curve.jpoint(jx, jyd.redMul(tinv), jz);
};

JPoint.prototype.dbl = function dbl() {
  if (this.isInfinity())
    return this;

  if (this.curve.zeroA)
    return this._zeroDbl();
  else if (this.curve.threeA)
    return this._threeDbl();
  else
    return this._dbl();
};

JPoint.prototype._zeroDbl = function _zeroDbl() {
  var nx;
  var ny;
  var nz;
  // Z = 1
  if (this.zOne) {
    // hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html
    //     #doubling-mdbl-2007-bl
    // 1M + 5S + 14A

    // XX = X1^2
    var xx = this.x.redSqr();
    // YY = Y1^2
    var yy = this.y.redSqr();
    // YYYY = YY^2
    var yyyy = yy.redSqr();
    // S = 2 * ((X1 + YY)^2 - XX - YYYY)
    var s = this.x.redAdd(yy).redSqr().redISub(xx).redISub(yyyy);
    s = s.redIAdd(s);
    // M = 3 * XX + a; a = 0
    var m = xx.redAdd(xx).redIAdd(xx);
    // T = M ^ 2 - 2*S
    var t = m.redSqr().redISub(s).redISub(s);

    // 8 * YYYY
    var yyyy8 = yyyy.redIAdd(yyyy);
    yyyy8 = yyyy8.redIAdd(yyyy8);
    yyyy8 = yyyy8.redIAdd(yyyy8);

    // X3 = T
    nx = t;
    // Y3 = M * (S - T) - 8 * YYYY
    ny = m.redMul(s.redISub(t)).redISub(yyyy8);
    // Z3 = 2*Y1
    nz = this.y.redAdd(this.y);
  } else {
    // hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html
    //     #doubling-dbl-2009-l
    // 2M + 5S + 13A

    // A = X1^2
    var a = this.x.redSqr();
    // B = Y1^2
    var b = this.y.redSqr();
    // C = B^2
    var c = b.redSqr();
    // D = 2 * ((X1 + B)^2 - A - C)
    var d = this.x.redAdd(b).redSqr().redISub(a).redISub(c);
    d = d.redIAdd(d);
    // E = 3 * A
    var e = a.redAdd(a).redIAdd(a);
    // F = E^2
    var f = e.redSqr();

    // 8 * C
    var c8 = c.redIAdd(c);
    c8 = c8.redIAdd(c8);
    c8 = c8.redIAdd(c8);

    // X3 = F - 2 * D
    nx = f.redISub(d).redISub(d);
    // Y3 = E * (D - X3) - 8 * C
    ny = e.redMul(d.redISub(nx)).redISub(c8);
    // Z3 = 2 * Y1 * Z1
    nz = this.y.redMul(this.z);
    nz = nz.redIAdd(nz);
  }

  return this.curve.jpoint(nx, ny, nz);
};

JPoint.prototype._threeDbl = function _threeDbl() {
  var nx;
  var ny;
  var nz;
  // Z = 1
  if (this.zOne) {
    // hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html
    //     #doubling-mdbl-2007-bl
    // 1M + 5S + 15A

    // XX = X1^2
    var xx = this.x.redSqr();
    // YY = Y1^2
    var yy = this.y.redSqr();
    // YYYY = YY^2
    var yyyy = yy.redSqr();
    // S = 2 * ((X1 + YY)^2 - XX - YYYY)
    var s = this.x.redAdd(yy).redSqr().redISub(xx).redISub(yyyy);
    s = s.redIAdd(s);
    // M = 3 * XX + a
    var m = xx.redAdd(xx).redIAdd(xx).redIAdd(this.curve.a);
    // T = M^2 - 2 * S
    var t = m.redSqr().redISub(s).redISub(s);
    // X3 = T
    nx = t;
    // Y3 = M * (S - T) - 8 * YYYY
    var yyyy8 = yyyy.redIAdd(yyyy);
    yyyy8 = yyyy8.redIAdd(yyyy8);
    yyyy8 = yyyy8.redIAdd(yyyy8);
    ny = m.redMul(s.redISub(t)).redISub(yyyy8);
    // Z3 = 2 * Y1
    nz = this.y.redAdd(this.y);
  } else {
    // hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2001-b
    // 3M + 5S

    // delta = Z1^2
    var delta = this.z.redSqr();
    // gamma = Y1^2
    var gamma = this.y.redSqr();
    // beta = X1 * gamma
    var beta = this.x.redMul(gamma);
    // alpha = 3 * (X1 - delta) * (X1 + delta)
    var alpha = this.x.redSub(delta).redMul(this.x.redAdd(delta));
    alpha = alpha.redAdd(alpha).redIAdd(alpha);
    // X3 = alpha^2 - 8 * beta
    var beta4 = beta.redIAdd(beta);
    beta4 = beta4.redIAdd(beta4);
    var beta8 = beta4.redAdd(beta4);
    nx = alpha.redSqr().redISub(beta8);
    // Z3 = (Y1 + Z1)^2 - gamma - delta
    nz = this.y.redAdd(this.z).redSqr().redISub(gamma).redISub(delta);
    // Y3 = alpha * (4 * beta - X3) - 8 * gamma^2
    var ggamma8 = gamma.redSqr();
    ggamma8 = ggamma8.redIAdd(ggamma8);
    ggamma8 = ggamma8.redIAdd(ggamma8);
    ggamma8 = ggamma8.redIAdd(ggamma8);
    ny = alpha.redMul(beta4.redISub(nx)).redISub(ggamma8);
  }

  return this.curve.jpoint(nx, ny, nz);
};

JPoint.prototype._dbl = function _dbl() {
  var a = this.curve.a;

  // 4M + 6S + 10A
  var jx = this.x;
  var jy = this.y;
  var jz = this.z;
  var jz4 = jz.redSqr().redSqr();

  var jx2 = jx.redSqr();
  var jy2 = jy.redSqr();

  var c = jx2.redAdd(jx2).redIAdd(jx2).redIAdd(a.redMul(jz4));

  var jxd4 = jx.redAdd(jx);
  jxd4 = jxd4.redIAdd(jxd4);
  var t1 = jxd4.redMul(jy2);
  var nx = c.redSqr().redISub(t1.redAdd(t1));
  var t2 = t1.redISub(nx);

  var jyd8 = jy2.redSqr();
  jyd8 = jyd8.redIAdd(jyd8);
  jyd8 = jyd8.redIAdd(jyd8);
  jyd8 = jyd8.redIAdd(jyd8);
  var ny = c.redMul(t2).redISub(jyd8);
  var nz = jy.redAdd(jy).redMul(jz);

  return this.curve.jpoint(nx, ny, nz);
};

JPoint.prototype.trpl = function trpl() {
  if (!this.curve.zeroA)
    return this.dbl().add(this);

  // hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#tripling-tpl-2007-bl
  // 5M + 10S + ...

  // XX = X1^2
  var xx = this.x.redSqr();
  // YY = Y1^2
  var yy = this.y.redSqr();
  // ZZ = Z1^2
  var zz = this.z.redSqr();
  // YYYY = YY^2
  var yyyy = yy.redSqr();
  // M = 3 * XX + a * ZZ2; a = 0
  var m = xx.redAdd(xx).redIAdd(xx);
  // MM = M^2
  var mm = m.redSqr();
  // E = 6 * ((X1 + YY)^2 - XX - YYYY) - MM
  var e = this.x.redAdd(yy).redSqr().redISub(xx).redISub(yyyy);
  e = e.redIAdd(e);
  e = e.redAdd(e).redIAdd(e);
  e = e.redISub(mm);
  // EE = E^2
  var ee = e.redSqr();
  // T = 16*YYYY
  var t = yyyy.redIAdd(yyyy);
  t = t.redIAdd(t);
  t = t.redIAdd(t);
  t = t.redIAdd(t);
  // U = (M + E)^2 - MM - EE - T
  var u = m.redIAdd(e).redSqr().redISub(mm).redISub(ee).redISub(t);
  // X3 = 4 * (X1 * EE - 4 * YY * U)
  var yyu4 = yy.redMul(u);
  yyu4 = yyu4.redIAdd(yyu4);
  yyu4 = yyu4.redIAdd(yyu4);
  var nx = this.x.redMul(ee).redISub(yyu4);
  nx = nx.redIAdd(nx);
  nx = nx.redIAdd(nx);
  // Y3 = 8 * Y1 * (U * (T - U) - E * EE)
  var ny = this.y.redMul(u.redMul(t.redISub(u)).redISub(e.redMul(ee)));
  ny = ny.redIAdd(ny);
  ny = ny.redIAdd(ny);
  ny = ny.redIAdd(ny);
  // Z3 = (Z1 + E)^2 - ZZ - EE
  var nz = this.z.redAdd(e).redSqr().redISub(zz).redISub(ee);

  return this.curve.jpoint(nx, ny, nz);
};

JPoint.prototype.mul = function mul(k, kbase) {
  k = new BN(k, kbase);

  return this.curve._wnafMul(this, k);
};

JPoint.prototype.eq = function eq(p) {
  if (p.type === 'affine')
    return this.eq(p.toJ());

  if (this === p)
    return true;

  // x1 * z2^2 == x2 * z1^2
  var z2 = this.z.redSqr();
  var pz2 = p.z.redSqr();
  if (this.x.redMul(pz2).redISub(p.x.redMul(z2)).cmpn(0) !== 0)
    return false;

  // y1 * z2^3 == y2 * z1^3
  var z3 = z2.redMul(this.z);
  var pz3 = pz2.redMul(p.z);
  return this.y.redMul(pz3).redISub(p.y.redMul(z3)).cmpn(0) === 0;
};

JPoint.prototype.eqXToP = function eqXToP(x) {
  var zs = this.z.redSqr();
  var rx = x.toRed(this.curve.red).redMul(zs);
  if (this.x.cmp(rx) === 0)
    return true;

  var xc = x.clone();
  var t = this.curve.redN.redMul(zs);
  for (;;) {
    xc.iadd(this.curve.n);
    if (xc.cmp(this.curve.p) >= 0)
      return false;

    rx.redIAdd(t);
    if (this.x.cmp(rx) === 0)
      return true;
  }
  return false;
};

JPoint.prototype.inspect = function inspect() {
  if (this.isInfinity())
    return '<EC JPoint Infinity>';
  return '<EC JPoint x: ' + this.x.toString(16, 2) +
      ' y: ' + this.y.toString(16, 2) +
      ' z: ' + this.z.toString(16, 2) + '>';
};

JPoint.prototype.isInfinity = function isInfinity() {
  // XXX This code assumes that zero is always zero in red
  return this.z.cmpn(0) === 0;
};

},{"../../elliptic":67,"../curve":70,"bn.js":16,"inherits":94}],73:[function(require,module,exports){
'use strict';

var curves = exports;

var hash = require('hash.js');
var elliptic = require('../elliptic');

var assert = elliptic.utils.assert;

function PresetCurve(options) {
  if (options.type === 'short')
    this.curve = new elliptic.curve.short(options);
  else if (options.type === 'edwards')
    this.curve = new elliptic.curve.edwards(options);
  else
    this.curve = new elliptic.curve.mont(options);
  this.g = this.curve.g;
  this.n = this.curve.n;
  this.hash = options.hash;

  assert(this.g.validate(), 'Invalid curve');
  assert(this.g.mul(this.n).isInfinity(), 'Invalid curve, G*N != O');
}
curves.PresetCurve = PresetCurve;

function defineCurve(name, options) {
  Object.defineProperty(curves, name, {
    configurable: true,
    enumerable: true,
    get: function() {
      var curve = new PresetCurve(options);
      Object.defineProperty(curves, name, {
        configurable: true,
        enumerable: true,
        value: curve
      });
      return curve;
    }
  });
}

defineCurve('p192', {
  type: 'short',
  prime: 'p192',
  p: 'ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff',
  a: 'ffffffff ffffffff ffffffff fffffffe ffffffff fffffffc',
  b: '64210519 e59c80e7 0fa7e9ab 72243049 feb8deec c146b9b1',
  n: 'ffffffff ffffffff ffffffff 99def836 146bc9b1 b4d22831',
  hash: hash.sha256,
  gRed: false,
  g: [
    '188da80e b03090f6 7cbf20eb 43a18800 f4ff0afd 82ff1012',
    '07192b95 ffc8da78 631011ed 6b24cdd5 73f977a1 1e794811'
  ]
});

defineCurve('p224', {
  type: 'short',
  prime: 'p224',
  p: 'ffffffff ffffffff ffffffff ffffffff 00000000 00000000 00000001',
  a: 'ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff fffffffe',
  b: 'b4050a85 0c04b3ab f5413256 5044b0b7 d7bfd8ba 270b3943 2355ffb4',
  n: 'ffffffff ffffffff ffffffff ffff16a2 e0b8f03e 13dd2945 5c5c2a3d',
  hash: hash.sha256,
  gRed: false,
  g: [
    'b70e0cbd 6bb4bf7f 321390b9 4a03c1d3 56c21122 343280d6 115c1d21',
    'bd376388 b5f723fb 4c22dfe6 cd4375a0 5a074764 44d58199 85007e34'
  ]
});

defineCurve('p256', {
  type: 'short',
  prime: null,
  p: 'ffffffff 00000001 00000000 00000000 00000000 ffffffff ffffffff ffffffff',
  a: 'ffffffff 00000001 00000000 00000000 00000000 ffffffff ffffffff fffffffc',
  b: '5ac635d8 aa3a93e7 b3ebbd55 769886bc 651d06b0 cc53b0f6 3bce3c3e 27d2604b',
  n: 'ffffffff 00000000 ffffffff ffffffff bce6faad a7179e84 f3b9cac2 fc632551',
  hash: hash.sha256,
  gRed: false,
  g: [
    '6b17d1f2 e12c4247 f8bce6e5 63a440f2 77037d81 2deb33a0 f4a13945 d898c296',
    '4fe342e2 fe1a7f9b 8ee7eb4a 7c0f9e16 2bce3357 6b315ece cbb64068 37bf51f5'
  ]
});

defineCurve('p384', {
  type: 'short',
  prime: null,
  p: 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ' +
     'fffffffe ffffffff 00000000 00000000 ffffffff',
  a: 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ' +
     'fffffffe ffffffff 00000000 00000000 fffffffc',
  b: 'b3312fa7 e23ee7e4 988e056b e3f82d19 181d9c6e fe814112 0314088f ' +
     '5013875a c656398d 8a2ed19d 2a85c8ed d3ec2aef',
  n: 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff c7634d81 ' +
     'f4372ddf 581a0db2 48b0a77a ecec196a ccc52973',
  hash: hash.sha384,
  gRed: false,
  g: [
    'aa87ca22 be8b0537 8eb1c71e f320ad74 6e1d3b62 8ba79b98 59f741e0 82542a38 ' +
    '5502f25d bf55296c 3a545e38 72760ab7',
    '3617de4a 96262c6f 5d9e98bf 9292dc29 f8f41dbd 289a147c e9da3113 b5f0b8c0 ' +
    '0a60b1ce 1d7e819d 7a431d7c 90ea0e5f'
  ]
});

defineCurve('p521', {
  type: 'short',
  prime: null,
  p: '000001ff ffffffff ffffffff ffffffff ffffffff ffffffff ' +
     'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ' +
     'ffffffff ffffffff ffffffff ffffffff ffffffff',
  a: '000001ff ffffffff ffffffff ffffffff ffffffff ffffffff ' +
     'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ' +
     'ffffffff ffffffff ffffffff ffffffff fffffffc',
  b: '00000051 953eb961 8e1c9a1f 929a21a0 b68540ee a2da725b ' +
     '99b315f3 b8b48991 8ef109e1 56193951 ec7e937b 1652c0bd ' +
     '3bb1bf07 3573df88 3d2c34f1 ef451fd4 6b503f00',
  n: '000001ff ffffffff ffffffff ffffffff ffffffff ffffffff ' +
     'ffffffff ffffffff fffffffa 51868783 bf2f966b 7fcc0148 ' +
     'f709a5d0 3bb5c9b8 899c47ae bb6fb71e 91386409',
  hash: hash.sha512,
  gRed: false,
  g: [
    '000000c6 858e06b7 0404e9cd 9e3ecb66 2395b442 9c648139 ' +
    '053fb521 f828af60 6b4d3dba a14b5e77 efe75928 fe1dc127 ' +
    'a2ffa8de 3348b3c1 856a429b f97e7e31 c2e5bd66',
    '00000118 39296a78 9a3bc004 5c8a5fb4 2c7d1bd9 98f54449 ' +
    '579b4468 17afbd17 273e662c 97ee7299 5ef42640 c550b901 ' +
    '3fad0761 353c7086 a272c240 88be9476 9fd16650'
  ]
});

defineCurve('curve25519', {
  type: 'mont',
  prime: 'p25519',
  p: '7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed',
  a: '76d06',
  b: '0',
  n: '1000000000000000 0000000000000000 14def9dea2f79cd6 5812631a5cf5d3ed',
  hash: hash.sha256,
  gRed: false,
  g: [
    '9'
  ]
});

defineCurve('ed25519', {
  type: 'edwards',
  prime: 'p25519',
  p: '7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed',
  a: '-1',
  c: '1',
  // -121665 * (121666^(-1)) (mod P)
  d: '52036cee2b6ffe73 8cc740797779e898 00700a4d4141d8ab 75eb4dca135978a3',
  n: '1000000000000000 0000000000000000 14def9dea2f79cd6 5812631a5cf5d3ed',
  hash: hash.sha256,
  gRed: false,
  g: [
    '216936d3cd6e53fec0a4e231fdd6dc5c692cc7609525a7b2c9562d608f25d51a',

    // 4/5
    '6666666666666666666666666666666666666666666666666666666666666658'
  ]
});

var pre;
try {
  pre = require('./precomputed/secp256k1');
} catch (e) {
  pre = undefined;
}

defineCurve('secp256k1', {
  type: 'short',
  prime: 'k256',
  p: 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffc2f',
  a: '0',
  b: '7',
  n: 'ffffffff ffffffff ffffffff fffffffe baaedce6 af48a03b bfd25e8c d0364141',
  h: '1',
  hash: hash.sha256,

  // Precomputed endomorphism
  beta: '7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee',
  lambda: '5363ad4cc05c30e0a5261c028812645a122e22ea20816678df02967c1b23bd72',
  basis: [
    {
      a: '3086d221a7d46bcde86c90e49284eb15',
      b: '-e4437ed6010e88286f547fa90abfe4c3'
    },
    {
      a: '114ca50f7a8e2f3f657c1108d9d44cfd8',
      b: '3086d221a7d46bcde86c90e49284eb15'
    }
  ],

  gRed: false,
  g: [
    '79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798',
    '483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8',
    pre
  ]
});

},{"../elliptic":67,"./precomputed/secp256k1":81,"hash.js":86}],74:[function(require,module,exports){
'use strict';

var BN = require('bn.js');
var elliptic = require('../../elliptic');
var utils = elliptic.utils;
var assert = utils.assert;

var KeyPair = require('./key');
var Signature = require('./signature');

function EC(options) {
  if (!(this instanceof EC))
    return new EC(options);

  // Shortcut `elliptic.ec(curve-name)`
  if (typeof options === 'string') {
    assert(elliptic.curves.hasOwnProperty(options), 'Unknown curve ' + options);

    options = elliptic.curves[options];
  }

  // Shortcut for `elliptic.ec(elliptic.curves.curveName)`
  if (options instanceof elliptic.curves.PresetCurve)
    options = { curve: options };

  this.curve = options.curve.curve;
  this.n = this.curve.n;
  this.nh = this.n.ushrn(1);
  this.g = this.curve.g;

  // Point on curve
  this.g = options.curve.g;
  this.g.precompute(options.curve.n.bitLength() + 1);

  // Hash for function for DRBG
  this.hash = options.hash || options.curve.hash;
}
module.exports = EC;

EC.prototype.keyPair = function keyPair(options) {
  return new KeyPair(this, options);
};

EC.prototype.keyFromPrivate = function keyFromPrivate(priv, enc) {
  return KeyPair.fromPrivate(this, priv, enc);
};

EC.prototype.keyFromPublic = function keyFromPublic(pub, enc) {
  return KeyPair.fromPublic(this, pub, enc);
};

EC.prototype.genKeyPair = function genKeyPair(options) {
  if (!options)
    options = {};

  // Instantiate Hmac_DRBG
  var drbg = new elliptic.hmacDRBG({
    hash: this.hash,
    pers: options.pers,
    entropy: options.entropy || elliptic.rand(this.hash.hmacStrength),
    nonce: this.n.toArray()
  });

  var bytes = this.n.byteLength();
  var ns2 = this.n.sub(new BN(2));
  do {
    var priv = new BN(drbg.generate(bytes));
    if (priv.cmp(ns2) > 0)
      continue;

    priv.iaddn(1);
    return this.keyFromPrivate(priv);
  } while (true);
};

EC.prototype._truncateToN = function truncateToN(msg, truncOnly) {
  var delta = msg.byteLength() * 8 - this.n.bitLength();
  if (delta > 0)
    msg = msg.ushrn(delta);
  if (!truncOnly && msg.cmp(this.n) >= 0)
    return msg.sub(this.n);
  else
    return msg;
};

EC.prototype.sign = function sign(msg, key, enc, options) {
  if (typeof enc === 'object') {
    options = enc;
    enc = null;
  }
  if (!options)
    options = {};

  key = this.keyFromPrivate(key, enc);
  msg = this._truncateToN(new BN(msg, 16));

  // Zero-extend key to provide enough entropy
  var bytes = this.n.byteLength();
  var bkey = key.getPrivate().toArray('be', bytes);

  // Zero-extend nonce to have the same byte size as N
  var nonce = msg.toArray('be', bytes);

  // Instantiate Hmac_DRBG
  var drbg = new elliptic.hmacDRBG({
    hash: this.hash,
    entropy: bkey,
    nonce: nonce,
    pers: options.pers,
    persEnc: options.persEnc
  });

  // Number of bytes to generate
  var ns1 = this.n.sub(new BN(1));

  for (var iter = 0; true; iter++) {
    var k = options.k ?
        options.k(iter) :
        new BN(drbg.generate(this.n.byteLength()));
    k = this._truncateToN(k, true);
    if (k.cmpn(1) <= 0 || k.cmp(ns1) >= 0)
      continue;

    var kp = this.g.mul(k);
    if (kp.isInfinity())
      continue;

    var kpX = kp.getX();
    var r = kpX.umod(this.n);
    if (r.cmpn(0) === 0)
      continue;

    var s = k.invm(this.n).mul(r.mul(key.getPrivate()).iadd(msg));
    s = s.umod(this.n);
    if (s.cmpn(0) === 0)
      continue;

    var recoveryParam = (kp.getY().isOdd() ? 1 : 0) |
                        (kpX.cmp(r) !== 0 ? 2 : 0);

    // Use complement of `s`, if it is > `n / 2`
    if (options.canonical && s.cmp(this.nh) > 0) {
      s = this.n.sub(s);
      recoveryParam ^= 1;
    }

    return new Signature({ r: r, s: s, recoveryParam: recoveryParam });
  }
};

EC.prototype.verify = function verify(msg, signature, key, enc) {
  msg = this._truncateToN(new BN(msg, 16));
  key = this.keyFromPublic(key, enc);
  signature = new Signature(signature, 'hex');

  // Perform primitive values validation
  var r = signature.r;
  var s = signature.s;
  if (r.cmpn(1) < 0 || r.cmp(this.n) >= 0)
    return false;
  if (s.cmpn(1) < 0 || s.cmp(this.n) >= 0)
    return false;

  // Validate signature
  var sinv = s.invm(this.n);
  var u1 = sinv.mul(msg).umod(this.n);
  var u2 = sinv.mul(r).umod(this.n);

  if (!this.curve._maxwellTrick) {
    var p = this.g.mulAdd(u1, key.getPublic(), u2);
    if (p.isInfinity())
      return false;

    return p.getX().umod(this.n).cmp(r) === 0;
  }

  // NOTE: Greg Maxwell's trick, inspired by:
  // https://git.io/vad3K

  var p = this.g.jmulAdd(u1, key.getPublic(), u2);
  if (p.isInfinity())
    return false;

  // Compare `p.x` of Jacobian point with `r`,
  // this will do `p.x == r * p.z^2` instead of multiplying `p.x` by the
  // inverse of `p.z^2`
  return p.eqXToP(r);
};

EC.prototype.recoverPubKey = function(msg, signature, j, enc) {
  assert((3 & j) === j, 'The recovery param is more than two bits');
  signature = new Signature(signature, enc);

  var n = this.n;
  var e = new BN(msg);
  var r = signature.r;
  var s = signature.s;

  // A set LSB signifies that the y-coordinate is odd
  var isYOdd = j & 1;
  var isSecondKey = j >> 1;
  if (r.cmp(this.curve.p.umod(this.curve.n)) >= 0 && isSecondKey)
    throw new Error('Unable to find sencond key candinate');

  // 1.1. Let x = r + jn.
  if (isSecondKey)
    r = this.curve.pointFromX(r.add(this.curve.n), isYOdd);
  else
    r = this.curve.pointFromX(r, isYOdd);

  var rInv = signature.r.invm(n);
  var s1 = n.sub(e).mul(rInv).umod(n);
  var s2 = s.mul(rInv).umod(n);

  // 1.6.1 Compute Q = r^-1 (sR -  eG)
  //               Q = r^-1 (sR + -eG)
  return this.g.mulAdd(s1, r, s2);
};

EC.prototype.getKeyRecoveryParam = function(e, signature, Q, enc) {
  signature = new Signature(signature, enc);
  if (signature.recoveryParam !== null)
    return signature.recoveryParam;

  for (var i = 0; i < 4; i++) {
    var Qprime;
    try {
      Qprime = this.recoverPubKey(e, signature, i);
    } catch (e) {
      continue;
    }

    if (Qprime.eq(Q))
      return i;
  }
  throw new Error('Unable to find valid recovery factor');
};

},{"../../elliptic":67,"./key":75,"./signature":76,"bn.js":16}],75:[function(require,module,exports){
'use strict';

var BN = require('bn.js');

function KeyPair(ec, options) {
  this.ec = ec;
  this.priv = null;
  this.pub = null;

  // KeyPair(ec, { priv: ..., pub: ... })
  if (options.priv)
    this._importPrivate(options.priv, options.privEnc);
  if (options.pub)
    this._importPublic(options.pub, options.pubEnc);
}
module.exports = KeyPair;

KeyPair.fromPublic = function fromPublic(ec, pub, enc) {
  if (pub instanceof KeyPair)
    return pub;

  return new KeyPair(ec, {
    pub: pub,
    pubEnc: enc
  });
};

KeyPair.fromPrivate = function fromPrivate(ec, priv, enc) {
  if (priv instanceof KeyPair)
    return priv;

  return new KeyPair(ec, {
    priv: priv,
    privEnc: enc
  });
};

KeyPair.prototype.validate = function validate() {
  var pub = this.getPublic();

  if (pub.isInfinity())
    return { result: false, reason: 'Invalid public key' };
  if (!pub.validate())
    return { result: false, reason: 'Public key is not a point' };
  if (!pub.mul(this.ec.curve.n).isInfinity())
    return { result: false, reason: 'Public key * N != O' };

  return { result: true, reason: null };
};

KeyPair.prototype.getPublic = function getPublic(compact, enc) {
  // compact is optional argument
  if (typeof compact === 'string') {
    enc = compact;
    compact = null;
  }

  if (!this.pub)
    this.pub = this.ec.g.mul(this.priv);

  if (!enc)
    return this.pub;

  return this.pub.encode(enc, compact);
};

KeyPair.prototype.getPrivate = function getPrivate(enc) {
  if (enc === 'hex')
    return this.priv.toString(16, 2);
  else
    return this.priv;
};

KeyPair.prototype._importPrivate = function _importPrivate(key, enc) {
  this.priv = new BN(key, enc || 16);

  // Ensure that the priv won't be bigger than n, otherwise we may fail
  // in fixed multiplication method
  this.priv = this.priv.umod(this.ec.curve.n);
};

KeyPair.prototype._importPublic = function _importPublic(key, enc) {
  if (key.x || key.y) {
    this.pub = this.ec.curve.point(key.x, key.y);
    return;
  }
  this.pub = this.ec.curve.decodePoint(key, enc);
};

// ECDH
KeyPair.prototype.derive = function derive(pub) {
  return pub.mul(this.priv).getX();
};

// ECDSA
KeyPair.prototype.sign = function sign(msg, enc, options) {
  return this.ec.sign(msg, this, enc, options);
};

KeyPair.prototype.verify = function verify(msg, signature) {
  return this.ec.verify(msg, signature, this);
};

KeyPair.prototype.inspect = function inspect() {
  return '<Key priv: ' + (this.priv && this.priv.toString(16, 2)) +
         ' pub: ' + (this.pub && this.pub.inspect()) + ' >';
};

},{"bn.js":16}],76:[function(require,module,exports){
'use strict';

var BN = require('bn.js');

var elliptic = require('../../elliptic');
var utils = elliptic.utils;
var assert = utils.assert;

function Signature(options, enc) {
  if (options instanceof Signature)
    return options;

  if (this._importDER(options, enc))
    return;

  assert(options.r && options.s, 'Signature without r or s');
  this.r = new BN(options.r, 16);
  this.s = new BN(options.s, 16);
  if (options.recoveryParam === undefined)
    this.recoveryParam = null;
  else
    this.recoveryParam = options.recoveryParam;
}
module.exports = Signature;

function Position() {
  this.place = 0;
}

function getLength(buf, p) {
  var initial = buf[p.place++];
  if (!(initial & 0x80)) {
    return initial;
  }
  var octetLen = initial & 0xf;
  var val = 0;
  for (var i = 0, off = p.place; i < octetLen; i++, off++) {
    val <<= 8;
    val |= buf[off];
  }
  p.place = off;
  return val;
}

function rmPadding(buf) {
  var i = 0;
  var len = buf.length - 1;
  while (!buf[i] && !(buf[i + 1] & 0x80) && i < len) {
    i++;
  }
  if (i === 0) {
    return buf;
  }
  return buf.slice(i);
}

Signature.prototype._importDER = function _importDER(data, enc) {
  data = utils.toArray(data, enc);
  var p = new Position();
  if (data[p.place++] !== 0x30) {
    return false;
  }
  var len = getLength(data, p);
  if ((len + p.place) !== data.length) {
    return false;
  }
  if (data[p.place++] !== 0x02) {
    return false;
  }
  var rlen = getLength(data, p);
  var r = data.slice(p.place, rlen + p.place);
  p.place += rlen;
  if (data[p.place++] !== 0x02) {
    return false;
  }
  var slen = getLength(data, p);
  if (data.length !== slen + p.place) {
    return false;
  }
  var s = data.slice(p.place, slen + p.place);
  if (r[0] === 0 && (r[1] & 0x80)) {
    r = r.slice(1);
  }
  if (s[0] === 0 && (s[1] & 0x80)) {
    s = s.slice(1);
  }

  this.r = new BN(r);
  this.s = new BN(s);
  this.recoveryParam = null;

  return true;
};

function constructLength(arr, len) {
  if (len < 0x80) {
    arr.push(len);
    return;
  }
  var octets = 1 + (Math.log(len) / Math.LN2 >>> 3);
  arr.push(octets | 0x80);
  while (--octets) {
    arr.push((len >>> (octets << 3)) & 0xff);
  }
  arr.push(len);
}

Signature.prototype.toDER = function toDER(enc) {
  var r = this.r.toArray();
  var s = this.s.toArray();

  // Pad values
  if (r[0] & 0x80)
    r = [ 0 ].concat(r);
  // Pad values
  if (s[0] & 0x80)
    s = [ 0 ].concat(s);

  r = rmPadding(r);
  s = rmPadding(s);

  while (!s[0] && !(s[1] & 0x80)) {
    s = s.slice(1);
  }
  var arr = [ 0x02 ];
  constructLength(arr, r.length);
  arr = arr.concat(r);
  arr.push(0x02);
  constructLength(arr, s.length);
  var backHalf = arr.concat(s);
  var res = [ 0x30 ];
  constructLength(res, backHalf.length);
  res = res.concat(backHalf);
  return utils.encode(res, enc);
};

},{"../../elliptic":67,"bn.js":16}],77:[function(require,module,exports){
'use strict';

var hash = require('hash.js');
var elliptic = require('../../elliptic');
var utils = elliptic.utils;
var assert = utils.assert;
var parseBytes = utils.parseBytes;
var KeyPair = require('./key');
var Signature = require('./signature');

function EDDSA(curve) {
  assert(curve === 'ed25519', 'only tested with ed25519 so far');

  if (!(this instanceof EDDSA))
    return new EDDSA(curve);

  var curve = elliptic.curves[curve].curve;
  this.curve = curve;
  this.g = curve.g;
  this.g.precompute(curve.n.bitLength() + 1);

  this.pointClass = curve.point().constructor;
  this.encodingLength = Math.ceil(curve.n.bitLength() / 8);
  this.hash = hash.sha512;
}

module.exports = EDDSA;

/**
* @param {Array|String} message - message bytes
* @param {Array|String|KeyPair} secret - secret bytes or a keypair
* @returns {Signature} - signature
*/
EDDSA.prototype.sign = function sign(message, secret) {
  message = parseBytes(message);
  var key = this.keyFromSecret(secret);
  var r = this.hashInt(key.messagePrefix(), message);
  var R = this.g.mul(r);
  var Rencoded = this.encodePoint(R);
  var s_ = this.hashInt(Rencoded, key.pubBytes(), message)
               .mul(key.priv());
  var S = r.add(s_).umod(this.curve.n);
  return this.makeSignature({ R: R, S: S, Rencoded: Rencoded });
};

/**
* @param {Array} message - message bytes
* @param {Array|String|Signature} sig - sig bytes
* @param {Array|String|Point|KeyPair} pub - public key
* @returns {Boolean} - true if public key matches sig of message
*/
EDDSA.prototype.verify = function verify(message, sig, pub) {
  message = parseBytes(message);
  sig = this.makeSignature(sig);
  var key = this.keyFromPublic(pub);
  var h = this.hashInt(sig.Rencoded(), key.pubBytes(), message);
  var SG = this.g.mul(sig.S());
  var RplusAh = sig.R().add(key.pub().mul(h));
  return RplusAh.eq(SG);
};

EDDSA.prototype.hashInt = function hashInt() {
  var hash = this.hash();
  for (var i = 0; i < arguments.length; i++)
    hash.update(arguments[i]);
  return utils.intFromLE(hash.digest()).umod(this.curve.n);
};

EDDSA.prototype.keyFromPublic = function keyFromPublic(pub) {
  return KeyPair.fromPublic(this, pub);
};

EDDSA.prototype.keyFromSecret = function keyFromSecret(secret) {
  return KeyPair.fromSecret(this, secret);
};

EDDSA.prototype.makeSignature = function makeSignature(sig) {
  if (sig instanceof Signature)
    return sig;
  return new Signature(this, sig);
};

/**
* * https://tools.ietf.org/html/draft-josefsson-eddsa-ed25519-03#section-5.2
*
* EDDSA defines methods for encoding and decoding points and integers. These are
* helper convenience methods, that pass along to utility functions implied
* parameters.
*
*/
EDDSA.prototype.encodePoint = function encodePoint(point) {
  var enc = point.getY().toArray('le', this.encodingLength);
  enc[this.encodingLength - 1] |= point.getX().isOdd() ? 0x80 : 0;
  return enc;
};

EDDSA.prototype.decodePoint = function decodePoint(bytes) {
  bytes = utils.parseBytes(bytes);

  var lastIx = bytes.length - 1;
  var normed = bytes.slice(0, lastIx).concat(bytes[lastIx] & ~0x80);
  var xIsOdd = (bytes[lastIx] & 0x80) !== 0;

  var y = utils.intFromLE(normed);
  return this.curve.pointFromY(y, xIsOdd);
};

EDDSA.prototype.encodeInt = function encodeInt(num) {
  return num.toArray('le', this.encodingLength);
};

EDDSA.prototype.decodeInt = function decodeInt(bytes) {
  return utils.intFromLE(bytes);
};

EDDSA.prototype.isPoint = function isPoint(val) {
  return val instanceof this.pointClass;
};

},{"../../elliptic":67,"./key":78,"./signature":79,"hash.js":86}],78:[function(require,module,exports){
'use strict';

var elliptic = require('../../elliptic');
var utils = elliptic.utils;
var assert = utils.assert;
var parseBytes = utils.parseBytes;
var cachedProperty = utils.cachedProperty;

/**
* @param {EDDSA} eddsa - instance
* @param {Object} params - public/private key parameters
*
* @param {Array<Byte>} [params.secret] - secret seed bytes
* @param {Point} [params.pub] - public key point (aka `A` in eddsa terms)
* @param {Array<Byte>} [params.pub] - public key point encoded as bytes
*
*/
function KeyPair(eddsa, params) {
  this.eddsa = eddsa;
  this._secret = parseBytes(params.secret);
  if (eddsa.isPoint(params.pub))
    this._pub = params.pub;
  else
    this._pubBytes = parseBytes(params.pub);
}

KeyPair.fromPublic = function fromPublic(eddsa, pub) {
  if (pub instanceof KeyPair)
    return pub;
  return new KeyPair(eddsa, { pub: pub });
};

KeyPair.fromSecret = function fromSecret(eddsa, secret) {
  if (secret instanceof KeyPair)
    return secret;
  return new KeyPair(eddsa, { secret: secret });
};

KeyPair.prototype.secret = function secret() {
  return this._secret;
};

cachedProperty(KeyPair, 'pubBytes', function pubBytes() {
  return this.eddsa.encodePoint(this.pub());
});

cachedProperty(KeyPair, 'pub', function pub() {
  if (this._pubBytes)
    return this.eddsa.decodePoint(this._pubBytes);
  return this.eddsa.g.mul(this.priv());
});

cachedProperty(KeyPair, 'privBytes', function privBytes() {
  var eddsa = this.eddsa;
  var hash = this.hash();
  var lastIx = eddsa.encodingLength - 1;

  var a = hash.slice(0, eddsa.encodingLength);
  a[0] &= 248;
  a[lastIx] &= 127;
  a[lastIx] |= 64;

  return a;
});

cachedProperty(KeyPair, 'priv', function priv() {
  return this.eddsa.decodeInt(this.privBytes());
});

cachedProperty(KeyPair, 'hash', function hash() {
  return this.eddsa.hash().update(this.secret()).digest();
});

cachedProperty(KeyPair, 'messagePrefix', function messagePrefix() {
  return this.hash().slice(this.eddsa.encodingLength);
});

KeyPair.prototype.sign = function sign(message) {
  assert(this._secret, 'KeyPair can only verify');
  return this.eddsa.sign(message, this);
};

KeyPair.prototype.verify = function verify(message, sig) {
  return this.eddsa.verify(message, sig, this);
};

KeyPair.prototype.getSecret = function getSecret(enc) {
  assert(this._secret, 'KeyPair is public only');
  return utils.encode(this.secret(), enc);
};

KeyPair.prototype.getPublic = function getPublic(enc) {
  return utils.encode(this.pubBytes(), enc);
};

module.exports = KeyPair;

},{"../../elliptic":67}],79:[function(require,module,exports){
'use strict';

var BN = require('bn.js');
var elliptic = require('../../elliptic');
var utils = elliptic.utils;
var assert = utils.assert;
var cachedProperty = utils.cachedProperty;
var parseBytes = utils.parseBytes;

/**
* @param {EDDSA} eddsa - eddsa instance
* @param {Array<Bytes>|Object} sig -
* @param {Array<Bytes>|Point} [sig.R] - R point as Point or bytes
* @param {Array<Bytes>|bn} [sig.S] - S scalar as bn or bytes
* @param {Array<Bytes>} [sig.Rencoded] - R point encoded
* @param {Array<Bytes>} [sig.Sencoded] - S scalar encoded
*/
function Signature(eddsa, sig) {
  this.eddsa = eddsa;

  if (typeof sig !== 'object')
    sig = parseBytes(sig);

  if (Array.isArray(sig)) {
    sig = {
      R: sig.slice(0, eddsa.encodingLength),
      S: sig.slice(eddsa.encodingLength)
    };
  }

  assert(sig.R && sig.S, 'Signature without R or S');

  if (eddsa.isPoint(sig.R))
    this._R = sig.R;
  if (sig.S instanceof BN)
    this._S = sig.S;

  this._Rencoded = Array.isArray(sig.R) ? sig.R : sig.Rencoded;
  this._Sencoded = Array.isArray(sig.S) ? sig.S : sig.Sencoded;
}

cachedProperty(Signature, 'S', function S() {
  return this.eddsa.decodeInt(this.Sencoded());
});

cachedProperty(Signature, 'R', function R() {
  return this.eddsa.decodePoint(this.Rencoded());
});

cachedProperty(Signature, 'Rencoded', function Rencoded() {
  return this.eddsa.encodePoint(this.R());
});

cachedProperty(Signature, 'Sencoded', function Sencoded() {
  return this.eddsa.encodeInt(this.S());
});

Signature.prototype.toBytes = function toBytes() {
  return this.Rencoded().concat(this.Sencoded());
};

Signature.prototype.toHex = function toHex() {
  return utils.encode(this.toBytes(), 'hex').toUpperCase();
};

module.exports = Signature;

},{"../../elliptic":67,"bn.js":16}],80:[function(require,module,exports){
'use strict';

var hash = require('hash.js');
var elliptic = require('../elliptic');
var utils = elliptic.utils;
var assert = utils.assert;

function HmacDRBG(options) {
  if (!(this instanceof HmacDRBG))
    return new HmacDRBG(options);
  this.hash = options.hash;
  this.predResist = !!options.predResist;

  this.outLen = this.hash.outSize;
  this.minEntropy = options.minEntropy || this.hash.hmacStrength;

  this.reseed = null;
  this.reseedInterval = null;
  this.K = null;
  this.V = null;

  var entropy = utils.toArray(options.entropy, options.entropyEnc);
  var nonce = utils.toArray(options.nonce, options.nonceEnc);
  var pers = utils.toArray(options.pers, options.persEnc);
  assert(entropy.length >= (this.minEntropy / 8),
         'Not enough entropy. Minimum is: ' + this.minEntropy + ' bits');
  this._init(entropy, nonce, pers);
}
module.exports = HmacDRBG;

HmacDRBG.prototype._init = function init(entropy, nonce, pers) {
  var seed = entropy.concat(nonce).concat(pers);

  this.K = new Array(this.outLen / 8);
  this.V = new Array(this.outLen / 8);
  for (var i = 0; i < this.V.length; i++) {
    this.K[i] = 0x00;
    this.V[i] = 0x01;
  }

  this._update(seed);
  this.reseed = 1;
  this.reseedInterval = 0x1000000000000;  // 2^48
};

HmacDRBG.prototype._hmac = function hmac() {
  return new hash.hmac(this.hash, this.K);
};

HmacDRBG.prototype._update = function update(seed) {
  var kmac = this._hmac()
                 .update(this.V)
                 .update([ 0x00 ]);
  if (seed)
    kmac = kmac.update(seed);
  this.K = kmac.digest();
  this.V = this._hmac().update(this.V).digest();
  if (!seed)
    return;

  this.K = this._hmac()
               .update(this.V)
               .update([ 0x01 ])
               .update(seed)
               .digest();
  this.V = this._hmac().update(this.V).digest();
};

HmacDRBG.prototype.reseed = function reseed(entropy, entropyEnc, add, addEnc) {
  // Optional entropy enc
  if (typeof entropyEnc !== 'string') {
    addEnc = add;
    add = entropyEnc;
    entropyEnc = null;
  }

  entropy = utils.toBuffer(entropy, entropyEnc);
  add = utils.toBuffer(add, addEnc);

  assert(entropy.length >= (this.minEntropy / 8),
         'Not enough entropy. Minimum is: ' + this.minEntropy + ' bits');

  this._update(entropy.concat(add || []));
  this.reseed = 1;
};

HmacDRBG.prototype.generate = function generate(len, enc, add, addEnc) {
  if (this.reseed > this.reseedInterval)
    throw new Error('Reseed is required');

  // Optional encoding
  if (typeof enc !== 'string') {
    addEnc = add;
    add = enc;
    enc = null;
  }

  // Optional additional data
  if (add) {
    add = utils.toArray(add, addEnc);
    this._update(add);
  }

  var temp = [];
  while (temp.length < len) {
    this.V = this._hmac().update(this.V).digest();
    temp = temp.concat(this.V);
  }

  var res = temp.slice(0, len);
  this._update(add);
  this.reseed++;
  return utils.encode(res, enc);
};

},{"../elliptic":67,"hash.js":86}],81:[function(require,module,exports){
module.exports = {
  doubles: {
    step: 4,
    points: [
      [
        'e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a',
        'f7e3507399e595929db99f34f57937101296891e44d23f0be1f32cce69616821'
      ],
      [
        '8282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508',
        '11f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf'
      ],
      [
        '175e159f728b865a72f99cc6c6fc846de0b93833fd2222ed73fce5b551e5b739',
        'd3506e0d9e3c79eba4ef97a51ff71f5eacb5955add24345c6efa6ffee9fed695'
      ],
      [
        '363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640',
        '4e273adfc732221953b445397f3363145b9a89008199ecb62003c7f3bee9de9'
      ],
      [
        '8b4b5f165df3c2be8c6244b5b745638843e4a781a15bcd1b69f79a55dffdf80c',
        '4aad0a6f68d308b4b3fbd7813ab0da04f9e336546162ee56b3eff0c65fd4fd36'
      ],
      [
        '723cbaa6e5db996d6bf771c00bd548c7b700dbffa6c0e77bcb6115925232fcda',
        '96e867b5595cc498a921137488824d6e2660a0653779494801dc069d9eb39f5f'
      ],
      [
        'eebfa4d493bebf98ba5feec812c2d3b50947961237a919839a533eca0e7dd7fa',
        '5d9a8ca3970ef0f269ee7edaf178089d9ae4cdc3a711f712ddfd4fdae1de8999'
      ],
      [
        '100f44da696e71672791d0a09b7bde459f1215a29b3c03bfefd7835b39a48db0',
        'cdd9e13192a00b772ec8f3300c090666b7ff4a18ff5195ac0fbd5cd62bc65a09'
      ],
      [
        'e1031be262c7ed1b1dc9227a4a04c017a77f8d4464f3b3852c8acde6e534fd2d',
        '9d7061928940405e6bb6a4176597535af292dd419e1ced79a44f18f29456a00d'
      ],
      [
        'feea6cae46d55b530ac2839f143bd7ec5cf8b266a41d6af52d5e688d9094696d',
        'e57c6b6c97dce1bab06e4e12bf3ecd5c981c8957cc41442d3155debf18090088'
      ],
      [
        'da67a91d91049cdcb367be4be6ffca3cfeed657d808583de33fa978bc1ec6cb1',
        '9bacaa35481642bc41f463f7ec9780e5dec7adc508f740a17e9ea8e27a68be1d'
      ],
      [
        '53904faa0b334cdda6e000935ef22151ec08d0f7bb11069f57545ccc1a37b7c0',
        '5bc087d0bc80106d88c9eccac20d3c1c13999981e14434699dcb096b022771c8'
      ],
      [
        '8e7bcd0bd35983a7719cca7764ca906779b53a043a9b8bcaeff959f43ad86047',
        '10b7770b2a3da4b3940310420ca9514579e88e2e47fd68b3ea10047e8460372a'
      ],
      [
        '385eed34c1cdff21e6d0818689b81bde71a7f4f18397e6690a841e1599c43862',
        '283bebc3e8ea23f56701de19e9ebf4576b304eec2086dc8cc0458fe5542e5453'
      ],
      [
        '6f9d9b803ecf191637c73a4413dfa180fddf84a5947fbc9c606ed86c3fac3a7',
        '7c80c68e603059ba69b8e2a30e45c4d47ea4dd2f5c281002d86890603a842160'
      ],
      [
        '3322d401243c4e2582a2147c104d6ecbf774d163db0f5e5313b7e0e742d0e6bd',
        '56e70797e9664ef5bfb019bc4ddaf9b72805f63ea2873af624f3a2e96c28b2a0'
      ],
      [
        '85672c7d2de0b7da2bd1770d89665868741b3f9af7643397721d74d28134ab83',
        '7c481b9b5b43b2eb6374049bfa62c2e5e77f17fcc5298f44c8e3094f790313a6'
      ],
      [
        '948bf809b1988a46b06c9f1919413b10f9226c60f668832ffd959af60c82a0a',
        '53a562856dcb6646dc6b74c5d1c3418c6d4dff08c97cd2bed4cb7f88d8c8e589'
      ],
      [
        '6260ce7f461801c34f067ce0f02873a8f1b0e44dfc69752accecd819f38fd8e8',
        'bc2da82b6fa5b571a7f09049776a1ef7ecd292238051c198c1a84e95b2b4ae17'
      ],
      [
        'e5037de0afc1d8d43d8348414bbf4103043ec8f575bfdc432953cc8d2037fa2d',
        '4571534baa94d3b5f9f98d09fb990bddbd5f5b03ec481f10e0e5dc841d755bda'
      ],
      [
        'e06372b0f4a207adf5ea905e8f1771b4e7e8dbd1c6a6c5b725866a0ae4fce725',
        '7a908974bce18cfe12a27bb2ad5a488cd7484a7787104870b27034f94eee31dd'
      ],
      [
        '213c7a715cd5d45358d0bbf9dc0ce02204b10bdde2a3f58540ad6908d0559754',
        '4b6dad0b5ae462507013ad06245ba190bb4850f5f36a7eeddff2c27534b458f2'
      ],
      [
        '4e7c272a7af4b34e8dbb9352a5419a87e2838c70adc62cddf0cc3a3b08fbd53c',
        '17749c766c9d0b18e16fd09f6def681b530b9614bff7dd33e0b3941817dcaae6'
      ],
      [
        'fea74e3dbe778b1b10f238ad61686aa5c76e3db2be43057632427e2840fb27b6',
        '6e0568db9b0b13297cf674deccb6af93126b596b973f7b77701d3db7f23cb96f'
      ],
      [
        '76e64113f677cf0e10a2570d599968d31544e179b760432952c02a4417bdde39',
        'c90ddf8dee4e95cf577066d70681f0d35e2a33d2b56d2032b4b1752d1901ac01'
      ],
      [
        'c738c56b03b2abe1e8281baa743f8f9a8f7cc643df26cbee3ab150242bcbb891',
        '893fb578951ad2537f718f2eacbfbbbb82314eef7880cfe917e735d9699a84c3'
      ],
      [
        'd895626548b65b81e264c7637c972877d1d72e5f3a925014372e9f6588f6c14b',
        'febfaa38f2bc7eae728ec60818c340eb03428d632bb067e179363ed75d7d991f'
      ],
      [
        'b8da94032a957518eb0f6433571e8761ceffc73693e84edd49150a564f676e03',
        '2804dfa44805a1e4d7c99cc9762808b092cc584d95ff3b511488e4e74efdf6e7'
      ],
      [
        'e80fea14441fb33a7d8adab9475d7fab2019effb5156a792f1a11778e3c0df5d',
        'eed1de7f638e00771e89768ca3ca94472d155e80af322ea9fcb4291b6ac9ec78'
      ],
      [
        'a301697bdfcd704313ba48e51d567543f2a182031efd6915ddc07bbcc4e16070',
        '7370f91cfb67e4f5081809fa25d40f9b1735dbf7c0a11a130c0d1a041e177ea1'
      ],
      [
        '90ad85b389d6b936463f9d0512678de208cc330b11307fffab7ac63e3fb04ed4',
        'e507a3620a38261affdcbd9427222b839aefabe1582894d991d4d48cb6ef150'
      ],
      [
        '8f68b9d2f63b5f339239c1ad981f162ee88c5678723ea3351b7b444c9ec4c0da',
        '662a9f2dba063986de1d90c2b6be215dbbea2cfe95510bfdf23cbf79501fff82'
      ],
      [
        'e4f3fb0176af85d65ff99ff9198c36091f48e86503681e3e6686fd5053231e11',
        '1e63633ad0ef4f1c1661a6d0ea02b7286cc7e74ec951d1c9822c38576feb73bc'
      ],
      [
        '8c00fa9b18ebf331eb961537a45a4266c7034f2f0d4e1d0716fb6eae20eae29e',
        'efa47267fea521a1a9dc343a3736c974c2fadafa81e36c54e7d2a4c66702414b'
      ],
      [
        'e7a26ce69dd4829f3e10cec0a9e98ed3143d084f308b92c0997fddfc60cb3e41',
        '2a758e300fa7984b471b006a1aafbb18d0a6b2c0420e83e20e8a9421cf2cfd51'
      ],
      [
        'b6459e0ee3662ec8d23540c223bcbdc571cbcb967d79424f3cf29eb3de6b80ef',
        '67c876d06f3e06de1dadf16e5661db3c4b3ae6d48e35b2ff30bf0b61a71ba45'
      ],
      [
        'd68a80c8280bb840793234aa118f06231d6f1fc67e73c5a5deda0f5b496943e8',
        'db8ba9fff4b586d00c4b1f9177b0e28b5b0e7b8f7845295a294c84266b133120'
      ],
      [
        '324aed7df65c804252dc0270907a30b09612aeb973449cea4095980fc28d3d5d',
        '648a365774b61f2ff130c0c35aec1f4f19213b0c7e332843967224af96ab7c84'
      ],
      [
        '4df9c14919cde61f6d51dfdbe5fee5dceec4143ba8d1ca888e8bd373fd054c96',
        '35ec51092d8728050974c23a1d85d4b5d506cdc288490192ebac06cad10d5d'
      ],
      [
        '9c3919a84a474870faed8a9c1cc66021523489054d7f0308cbfc99c8ac1f98cd',
        'ddb84f0f4a4ddd57584f044bf260e641905326f76c64c8e6be7e5e03d4fc599d'
      ],
      [
        '6057170b1dd12fdf8de05f281d8e06bb91e1493a8b91d4cc5a21382120a959e5',
        '9a1af0b26a6a4807add9a2daf71df262465152bc3ee24c65e899be932385a2a8'
      ],
      [
        'a576df8e23a08411421439a4518da31880cef0fba7d4df12b1a6973eecb94266',
        '40a6bf20e76640b2c92b97afe58cd82c432e10a7f514d9f3ee8be11ae1b28ec8'
      ],
      [
        '7778a78c28dec3e30a05fe9629de8c38bb30d1f5cf9a3a208f763889be58ad71',
        '34626d9ab5a5b22ff7098e12f2ff580087b38411ff24ac563b513fc1fd9f43ac'
      ],
      [
        '928955ee637a84463729fd30e7afd2ed5f96274e5ad7e5cb09eda9c06d903ac',
        'c25621003d3f42a827b78a13093a95eeac3d26efa8a8d83fc5180e935bcd091f'
      ],
      [
        '85d0fef3ec6db109399064f3a0e3b2855645b4a907ad354527aae75163d82751',
        '1f03648413a38c0be29d496e582cf5663e8751e96877331582c237a24eb1f962'
      ],
      [
        'ff2b0dce97eece97c1c9b6041798b85dfdfb6d8882da20308f5404824526087e',
        '493d13fef524ba188af4c4dc54d07936c7b7ed6fb90e2ceb2c951e01f0c29907'
      ],
      [
        '827fbbe4b1e880ea9ed2b2e6301b212b57f1ee148cd6dd28780e5e2cf856e241',
        'c60f9c923c727b0b71bef2c67d1d12687ff7a63186903166d605b68baec293ec'
      ],
      [
        'eaa649f21f51bdbae7be4ae34ce6e5217a58fdce7f47f9aa7f3b58fa2120e2b3',
        'be3279ed5bbbb03ac69a80f89879aa5a01a6b965f13f7e59d47a5305ba5ad93d'
      ],
      [
        'e4a42d43c5cf169d9391df6decf42ee541b6d8f0c9a137401e23632dda34d24f',
        '4d9f92e716d1c73526fc99ccfb8ad34ce886eedfa8d8e4f13a7f7131deba9414'
      ],
      [
        '1ec80fef360cbdd954160fadab352b6b92b53576a88fea4947173b9d4300bf19',
        'aeefe93756b5340d2f3a4958a7abbf5e0146e77f6295a07b671cdc1cc107cefd'
      ],
      [
        '146a778c04670c2f91b00af4680dfa8bce3490717d58ba889ddb5928366642be',
        'b318e0ec3354028add669827f9d4b2870aaa971d2f7e5ed1d0b297483d83efd0'
      ],
      [
        'fa50c0f61d22e5f07e3acebb1aa07b128d0012209a28b9776d76a8793180eef9',
        '6b84c6922397eba9b72cd2872281a68a5e683293a57a213b38cd8d7d3f4f2811'
      ],
      [
        'da1d61d0ca721a11b1a5bf6b7d88e8421a288ab5d5bba5220e53d32b5f067ec2',
        '8157f55a7c99306c79c0766161c91e2966a73899d279b48a655fba0f1ad836f1'
      ],
      [
        'a8e282ff0c9706907215ff98e8fd416615311de0446f1e062a73b0610d064e13',
        '7f97355b8db81c09abfb7f3c5b2515888b679a3e50dd6bd6cef7c73111f4cc0c'
      ],
      [
        '174a53b9c9a285872d39e56e6913cab15d59b1fa512508c022f382de8319497c',
        'ccc9dc37abfc9c1657b4155f2c47f9e6646b3a1d8cb9854383da13ac079afa73'
      ],
      [
        '959396981943785c3d3e57edf5018cdbe039e730e4918b3d884fdff09475b7ba',
        '2e7e552888c331dd8ba0386a4b9cd6849c653f64c8709385e9b8abf87524f2fd'
      ],
      [
        'd2a63a50ae401e56d645a1153b109a8fcca0a43d561fba2dbb51340c9d82b151',
        'e82d86fb6443fcb7565aee58b2948220a70f750af484ca52d4142174dcf89405'
      ],
      [
        '64587e2335471eb890ee7896d7cfdc866bacbdbd3839317b3436f9b45617e073',
        'd99fcdd5bf6902e2ae96dd6447c299a185b90a39133aeab358299e5e9faf6589'
      ],
      [
        '8481bde0e4e4d885b3a546d3e549de042f0aa6cea250e7fd358d6c86dd45e458',
        '38ee7b8cba5404dd84a25bf39cecb2ca900a79c42b262e556d64b1b59779057e'
      ],
      [
        '13464a57a78102aa62b6979ae817f4637ffcfed3c4b1ce30bcd6303f6caf666b',
        '69be159004614580ef7e433453ccb0ca48f300a81d0942e13f495a907f6ecc27'
      ],
      [
        'bc4a9df5b713fe2e9aef430bcc1dc97a0cd9ccede2f28588cada3a0d2d83f366',
        'd3a81ca6e785c06383937adf4b798caa6e8a9fbfa547b16d758d666581f33c1'
      ],
      [
        '8c28a97bf8298bc0d23d8c749452a32e694b65e30a9472a3954ab30fe5324caa',
        '40a30463a3305193378fedf31f7cc0eb7ae784f0451cb9459e71dc73cbef9482'
      ],
      [
        '8ea9666139527a8c1dd94ce4f071fd23c8b350c5a4bb33748c4ba111faccae0',
        '620efabbc8ee2782e24e7c0cfb95c5d735b783be9cf0f8e955af34a30e62b945'
      ],
      [
        'dd3625faef5ba06074669716bbd3788d89bdde815959968092f76cc4eb9a9787',
        '7a188fa3520e30d461da2501045731ca941461982883395937f68d00c644a573'
      ],
      [
        'f710d79d9eb962297e4f6232b40e8f7feb2bc63814614d692c12de752408221e',
        'ea98e67232d3b3295d3b535532115ccac8612c721851617526ae47a9c77bfc82'
      ]
    ]
  },
  naf: {
    wnd: 7,
    points: [
      [
        'f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9',
        '388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672'
      ],
      [
        '2f8bde4d1a07209355b4a7250a5c5128e88b84bddc619ab7cba8d569b240efe4',
        'd8ac222636e5e3d6d4dba9dda6c9c426f788271bab0d6840dca87d3aa6ac62d6'
      ],
      [
        '5cbdf0646e5db4eaa398f365f2ea7a0e3d419b7e0330e39ce92bddedcac4f9bc',
        '6aebca40ba255960a3178d6d861a54dba813d0b813fde7b5a5082628087264da'
      ],
      [
        'acd484e2f0c7f65309ad178a9f559abde09796974c57e714c35f110dfc27ccbe',
        'cc338921b0a7d9fd64380971763b61e9add888a4375f8e0f05cc262ac64f9c37'
      ],
      [
        '774ae7f858a9411e5ef4246b70c65aac5649980be5c17891bbec17895da008cb',
        'd984a032eb6b5e190243dd56d7b7b365372db1e2dff9d6a8301d74c9c953c61b'
      ],
      [
        'f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8',
        'ab0902e8d880a89758212eb65cdaf473a1a06da521fa91f29b5cb52db03ed81'
      ],
      [
        'd7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e',
        '581e2872a86c72a683842ec228cc6defea40af2bd896d3a5c504dc9ff6a26b58'
      ],
      [
        'defdea4cdb677750a420fee807eacf21eb9898ae79b9768766e4faa04a2d4a34',
        '4211ab0694635168e997b0ead2a93daeced1f4a04a95c0f6cfb199f69e56eb77'
      ],
      [
        '2b4ea0a797a443d293ef5cff444f4979f06acfebd7e86d277475656138385b6c',
        '85e89bc037945d93b343083b5a1c86131a01f60c50269763b570c854e5c09b7a'
      ],
      [
        '352bbf4a4cdd12564f93fa332ce333301d9ad40271f8107181340aef25be59d5',
        '321eb4075348f534d59c18259dda3e1f4a1b3b2e71b1039c67bd3d8bcf81998c'
      ],
      [
        '2fa2104d6b38d11b0230010559879124e42ab8dfeff5ff29dc9cdadd4ecacc3f',
        '2de1068295dd865b64569335bd5dd80181d70ecfc882648423ba76b532b7d67'
      ],
      [
        '9248279b09b4d68dab21a9b066edda83263c3d84e09572e269ca0cd7f5453714',
        '73016f7bf234aade5d1aa71bdea2b1ff3fc0de2a887912ffe54a32ce97cb3402'
      ],
      [
        'daed4f2be3a8bf278e70132fb0beb7522f570e144bf615c07e996d443dee8729',
        'a69dce4a7d6c98e8d4a1aca87ef8d7003f83c230f3afa726ab40e52290be1c55'
      ],
      [
        'c44d12c7065d812e8acf28d7cbb19f9011ecd9e9fdf281b0e6a3b5e87d22e7db',
        '2119a460ce326cdc76c45926c982fdac0e106e861edf61c5a039063f0e0e6482'
      ],
      [
        '6a245bf6dc698504c89a20cfded60853152b695336c28063b61c65cbd269e6b4',
        'e022cf42c2bd4a708b3f5126f16a24ad8b33ba48d0423b6efd5e6348100d8a82'
      ],
      [
        '1697ffa6fd9de627c077e3d2fe541084ce13300b0bec1146f95ae57f0d0bd6a5',
        'b9c398f186806f5d27561506e4557433a2cf15009e498ae7adee9d63d01b2396'
      ],
      [
        '605bdb019981718b986d0f07e834cb0d9deb8360ffb7f61df982345ef27a7479',
        '2972d2de4f8d20681a78d93ec96fe23c26bfae84fb14db43b01e1e9056b8c49'
      ],
      [
        '62d14dab4150bf497402fdc45a215e10dcb01c354959b10cfe31c7e9d87ff33d',
        '80fc06bd8cc5b01098088a1950eed0db01aa132967ab472235f5642483b25eaf'
      ],
      [
        '80c60ad0040f27dade5b4b06c408e56b2c50e9f56b9b8b425e555c2f86308b6f',
        '1c38303f1cc5c30f26e66bad7fe72f70a65eed4cbe7024eb1aa01f56430bd57a'
      ],
      [
        '7a9375ad6167ad54aa74c6348cc54d344cc5dc9487d847049d5eabb0fa03c8fb',
        'd0e3fa9eca8726909559e0d79269046bdc59ea10c70ce2b02d499ec224dc7f7'
      ],
      [
        'd528ecd9b696b54c907a9ed045447a79bb408ec39b68df504bb51f459bc3ffc9',
        'eecf41253136e5f99966f21881fd656ebc4345405c520dbc063465b521409933'
      ],
      [
        '49370a4b5f43412ea25f514e8ecdad05266115e4a7ecb1387231808f8b45963',
        '758f3f41afd6ed428b3081b0512fd62a54c3f3afbb5b6764b653052a12949c9a'
      ],
      [
        '77f230936ee88cbbd73df930d64702ef881d811e0e1498e2f1c13eb1fc345d74',
        '958ef42a7886b6400a08266e9ba1b37896c95330d97077cbbe8eb3c7671c60d6'
      ],
      [
        'f2dac991cc4ce4b9ea44887e5c7c0bce58c80074ab9d4dbaeb28531b7739f530',
        'e0dedc9b3b2f8dad4da1f32dec2531df9eb5fbeb0598e4fd1a117dba703a3c37'
      ],
      [
        '463b3d9f662621fb1b4be8fbbe2520125a216cdfc9dae3debcba4850c690d45b',
        '5ed430d78c296c3543114306dd8622d7c622e27c970a1de31cb377b01af7307e'
      ],
      [
        'f16f804244e46e2a09232d4aff3b59976b98fac14328a2d1a32496b49998f247',
        'cedabd9b82203f7e13d206fcdf4e33d92a6c53c26e5cce26d6579962c4e31df6'
      ],
      [
        'caf754272dc84563b0352b7a14311af55d245315ace27c65369e15f7151d41d1',
        'cb474660ef35f5f2a41b643fa5e460575f4fa9b7962232a5c32f908318a04476'
      ],
      [
        '2600ca4b282cb986f85d0f1709979d8b44a09c07cb86d7c124497bc86f082120',
        '4119b88753c15bd6a693b03fcddbb45d5ac6be74ab5f0ef44b0be9475a7e4b40'
      ],
      [
        '7635ca72d7e8432c338ec53cd12220bc01c48685e24f7dc8c602a7746998e435',
        '91b649609489d613d1d5e590f78e6d74ecfc061d57048bad9e76f302c5b9c61'
      ],
      [
        '754e3239f325570cdbbf4a87deee8a66b7f2b33479d468fbc1a50743bf56cc18',
        '673fb86e5bda30fb3cd0ed304ea49a023ee33d0197a695d0c5d98093c536683'
      ],
      [
        'e3e6bd1071a1e96aff57859c82d570f0330800661d1c952f9fe2694691d9b9e8',
        '59c9e0bba394e76f40c0aa58379a3cb6a5a2283993e90c4167002af4920e37f5'
      ],
      [
        '186b483d056a033826ae73d88f732985c4ccb1f32ba35f4b4cc47fdcf04aa6eb',
        '3b952d32c67cf77e2e17446e204180ab21fb8090895138b4a4a797f86e80888b'
      ],
      [
        'df9d70a6b9876ce544c98561f4be4f725442e6d2b737d9c91a8321724ce0963f',
        '55eb2dafd84d6ccd5f862b785dc39d4ab157222720ef9da217b8c45cf2ba2417'
      ],
      [
        '5edd5cc23c51e87a497ca815d5dce0f8ab52554f849ed8995de64c5f34ce7143',
        'efae9c8dbc14130661e8cec030c89ad0c13c66c0d17a2905cdc706ab7399a868'
      ],
      [
        '290798c2b6476830da12fe02287e9e777aa3fba1c355b17a722d362f84614fba',
        'e38da76dcd440621988d00bcf79af25d5b29c094db2a23146d003afd41943e7a'
      ],
      [
        'af3c423a95d9f5b3054754efa150ac39cd29552fe360257362dfdecef4053b45',
        'f98a3fd831eb2b749a93b0e6f35cfb40c8cd5aa667a15581bc2feded498fd9c6'
      ],
      [
        '766dbb24d134e745cccaa28c99bf274906bb66b26dcf98df8d2fed50d884249a',
        '744b1152eacbe5e38dcc887980da38b897584a65fa06cedd2c924f97cbac5996'
      ],
      [
        '59dbf46f8c94759ba21277c33784f41645f7b44f6c596a58ce92e666191abe3e',
        'c534ad44175fbc300f4ea6ce648309a042ce739a7919798cd85e216c4a307f6e'
      ],
      [
        'f13ada95103c4537305e691e74e9a4a8dd647e711a95e73cb62dc6018cfd87b8',
        'e13817b44ee14de663bf4bc808341f326949e21a6a75c2570778419bdaf5733d'
      ],
      [
        '7754b4fa0e8aced06d4167a2c59cca4cda1869c06ebadfb6488550015a88522c',
        '30e93e864e669d82224b967c3020b8fa8d1e4e350b6cbcc537a48b57841163a2'
      ],
      [
        '948dcadf5990e048aa3874d46abef9d701858f95de8041d2a6828c99e2262519',
        'e491a42537f6e597d5d28a3224b1bc25df9154efbd2ef1d2cbba2cae5347d57e'
      ],
      [
        '7962414450c76c1689c7b48f8202ec37fb224cf5ac0bfa1570328a8a3d7c77ab',
        '100b610ec4ffb4760d5c1fc133ef6f6b12507a051f04ac5760afa5b29db83437'
      ],
      [
        '3514087834964b54b15b160644d915485a16977225b8847bb0dd085137ec47ca',
        'ef0afbb2056205448e1652c48e8127fc6039e77c15c2378b7e7d15a0de293311'
      ],
      [
        'd3cc30ad6b483e4bc79ce2c9dd8bc54993e947eb8df787b442943d3f7b527eaf',
        '8b378a22d827278d89c5e9be8f9508ae3c2ad46290358630afb34db04eede0a4'
      ],
      [
        '1624d84780732860ce1c78fcbfefe08b2b29823db913f6493975ba0ff4847610',
        '68651cf9b6da903e0914448c6cd9d4ca896878f5282be4c8cc06e2a404078575'
      ],
      [
        '733ce80da955a8a26902c95633e62a985192474b5af207da6df7b4fd5fc61cd4',
        'f5435a2bd2badf7d485a4d8b8db9fcce3e1ef8e0201e4578c54673bc1dc5ea1d'
      ],
      [
        '15d9441254945064cf1a1c33bbd3b49f8966c5092171e699ef258dfab81c045c',
        'd56eb30b69463e7234f5137b73b84177434800bacebfc685fc37bbe9efe4070d'
      ],
      [
        'a1d0fcf2ec9de675b612136e5ce70d271c21417c9d2b8aaaac138599d0717940',
        'edd77f50bcb5a3cab2e90737309667f2641462a54070f3d519212d39c197a629'
      ],
      [
        'e22fbe15c0af8ccc5780c0735f84dbe9a790badee8245c06c7ca37331cb36980',
        'a855babad5cd60c88b430a69f53a1a7a38289154964799be43d06d77d31da06'
      ],
      [
        '311091dd9860e8e20ee13473c1155f5f69635e394704eaa74009452246cfa9b3',
        '66db656f87d1f04fffd1f04788c06830871ec5a64feee685bd80f0b1286d8374'
      ],
      [
        '34c1fd04d301be89b31c0442d3e6ac24883928b45a9340781867d4232ec2dbdf',
        '9414685e97b1b5954bd46f730174136d57f1ceeb487443dc5321857ba73abee'
      ],
      [
        'f219ea5d6b54701c1c14de5b557eb42a8d13f3abbcd08affcc2a5e6b049b8d63',
        '4cb95957e83d40b0f73af4544cccf6b1f4b08d3c07b27fb8d8c2962a400766d1'
      ],
      [
        'd7b8740f74a8fbaab1f683db8f45de26543a5490bca627087236912469a0b448',
        'fa77968128d9c92ee1010f337ad4717eff15db5ed3c049b3411e0315eaa4593b'
      ],
      [
        '32d31c222f8f6f0ef86f7c98d3a3335ead5bcd32abdd94289fe4d3091aa824bf',
        '5f3032f5892156e39ccd3d7915b9e1da2e6dac9e6f26e961118d14b8462e1661'
      ],
      [
        '7461f371914ab32671045a155d9831ea8793d77cd59592c4340f86cbc18347b5',
        '8ec0ba238b96bec0cbdddcae0aa442542eee1ff50c986ea6b39847b3cc092ff6'
      ],
      [
        'ee079adb1df1860074356a25aa38206a6d716b2c3e67453d287698bad7b2b2d6',
        '8dc2412aafe3be5c4c5f37e0ecc5f9f6a446989af04c4e25ebaac479ec1c8c1e'
      ],
      [
        '16ec93e447ec83f0467b18302ee620f7e65de331874c9dc72bfd8616ba9da6b5',
        '5e4631150e62fb40d0e8c2a7ca5804a39d58186a50e497139626778e25b0674d'
      ],
      [
        'eaa5f980c245f6f038978290afa70b6bd8855897f98b6aa485b96065d537bd99',
        'f65f5d3e292c2e0819a528391c994624d784869d7e6ea67fb18041024edc07dc'
      ],
      [
        '78c9407544ac132692ee1910a02439958ae04877151342ea96c4b6b35a49f51',
        'f3e0319169eb9b85d5404795539a5e68fa1fbd583c064d2462b675f194a3ddb4'
      ],
      [
        '494f4be219a1a77016dcd838431aea0001cdc8ae7a6fc688726578d9702857a5',
        '42242a969283a5f339ba7f075e36ba2af925ce30d767ed6e55f4b031880d562c'
      ],
      [
        'a598a8030da6d86c6bc7f2f5144ea549d28211ea58faa70ebf4c1e665c1fe9b5',
        '204b5d6f84822c307e4b4a7140737aec23fc63b65b35f86a10026dbd2d864e6b'
      ],
      [
        'c41916365abb2b5d09192f5f2dbeafec208f020f12570a184dbadc3e58595997',
        '4f14351d0087efa49d245b328984989d5caf9450f34bfc0ed16e96b58fa9913'
      ],
      [
        '841d6063a586fa475a724604da03bc5b92a2e0d2e0a36acfe4c73a5514742881',
        '73867f59c0659e81904f9a1c7543698e62562d6744c169ce7a36de01a8d6154'
      ],
      [
        '5e95bb399a6971d376026947f89bde2f282b33810928be4ded112ac4d70e20d5',
        '39f23f366809085beebfc71181313775a99c9aed7d8ba38b161384c746012865'
      ],
      [
        '36e4641a53948fd476c39f8a99fd974e5ec07564b5315d8bf99471bca0ef2f66',
        'd2424b1b1abe4eb8164227b085c9aa9456ea13493fd563e06fd51cf5694c78fc'
      ],
      [
        '336581ea7bfbbb290c191a2f507a41cf5643842170e914faeab27c2c579f726',
        'ead12168595fe1be99252129b6e56b3391f7ab1410cd1e0ef3dcdcabd2fda224'
      ],
      [
        '8ab89816dadfd6b6a1f2634fcf00ec8403781025ed6890c4849742706bd43ede',
        '6fdcef09f2f6d0a044e654aef624136f503d459c3e89845858a47a9129cdd24e'
      ],
      [
        '1e33f1a746c9c5778133344d9299fcaa20b0938e8acff2544bb40284b8c5fb94',
        '60660257dd11b3aa9c8ed618d24edff2306d320f1d03010e33a7d2057f3b3b6'
      ],
      [
        '85b7c1dcb3cec1b7ee7f30ded79dd20a0ed1f4cc18cbcfcfa410361fd8f08f31',
        '3d98a9cdd026dd43f39048f25a8847f4fcafad1895d7a633c6fed3c35e999511'
      ],
      [
        '29df9fbd8d9e46509275f4b125d6d45d7fbe9a3b878a7af872a2800661ac5f51',
        'b4c4fe99c775a606e2d8862179139ffda61dc861c019e55cd2876eb2a27d84b'
      ],
      [
        'a0b1cae06b0a847a3fea6e671aaf8adfdfe58ca2f768105c8082b2e449fce252',
        'ae434102edde0958ec4b19d917a6a28e6b72da1834aff0e650f049503a296cf2'
      ],
      [
        '4e8ceafb9b3e9a136dc7ff67e840295b499dfb3b2133e4ba113f2e4c0e121e5',
        'cf2174118c8b6d7a4b48f6d534ce5c79422c086a63460502b827ce62a326683c'
      ],
      [
        'd24a44e047e19b6f5afb81c7ca2f69080a5076689a010919f42725c2b789a33b',
        '6fb8d5591b466f8fc63db50f1c0f1c69013f996887b8244d2cdec417afea8fa3'
      ],
      [
        'ea01606a7a6c9cdd249fdfcfacb99584001edd28abbab77b5104e98e8e3b35d4',
        '322af4908c7312b0cfbfe369f7a7b3cdb7d4494bc2823700cfd652188a3ea98d'
      ],
      [
        'af8addbf2b661c8a6c6328655eb96651252007d8c5ea31be4ad196de8ce2131f',
        '6749e67c029b85f52a034eafd096836b2520818680e26ac8f3dfbcdb71749700'
      ],
      [
        'e3ae1974566ca06cc516d47e0fb165a674a3dabcfca15e722f0e3450f45889',
        '2aeabe7e4531510116217f07bf4d07300de97e4874f81f533420a72eeb0bd6a4'
      ],
      [
        '591ee355313d99721cf6993ffed1e3e301993ff3ed258802075ea8ced397e246',
        'b0ea558a113c30bea60fc4775460c7901ff0b053d25ca2bdeee98f1a4be5d196'
      ],
      [
        '11396d55fda54c49f19aa97318d8da61fa8584e47b084945077cf03255b52984',
        '998c74a8cd45ac01289d5833a7beb4744ff536b01b257be4c5767bea93ea57a4'
      ],
      [
        '3c5d2a1ba39c5a1790000738c9e0c40b8dcdfd5468754b6405540157e017aa7a',
        'b2284279995a34e2f9d4de7396fc18b80f9b8b9fdd270f6661f79ca4c81bd257'
      ],
      [
        'cc8704b8a60a0defa3a99a7299f2e9c3fbc395afb04ac078425ef8a1793cc030',
        'bdd46039feed17881d1e0862db347f8cf395b74fc4bcdc4e940b74e3ac1f1b13'
      ],
      [
        'c533e4f7ea8555aacd9777ac5cad29b97dd4defccc53ee7ea204119b2889b197',
        '6f0a256bc5efdf429a2fb6242f1a43a2d9b925bb4a4b3a26bb8e0f45eb596096'
      ],
      [
        'c14f8f2ccb27d6f109f6d08d03cc96a69ba8c34eec07bbcf566d48e33da6593',
        'c359d6923bb398f7fd4473e16fe1c28475b740dd098075e6c0e8649113dc3a38'
      ],
      [
        'a6cbc3046bc6a450bac24789fa17115a4c9739ed75f8f21ce441f72e0b90e6ef',
        '21ae7f4680e889bb130619e2c0f95a360ceb573c70603139862afd617fa9b9f'
      ],
      [
        '347d6d9a02c48927ebfb86c1359b1caf130a3c0267d11ce6344b39f99d43cc38',
        '60ea7f61a353524d1c987f6ecec92f086d565ab687870cb12689ff1e31c74448'
      ],
      [
        'da6545d2181db8d983f7dcb375ef5866d47c67b1bf31c8cf855ef7437b72656a',
        '49b96715ab6878a79e78f07ce5680c5d6673051b4935bd897fea824b77dc208a'
      ],
      [
        'c40747cc9d012cb1a13b8148309c6de7ec25d6945d657146b9d5994b8feb1111',
        '5ca560753be2a12fc6de6caf2cb489565db936156b9514e1bb5e83037e0fa2d4'
      ],
      [
        '4e42c8ec82c99798ccf3a610be870e78338c7f713348bd34c8203ef4037f3502',
        '7571d74ee5e0fb92a7a8b33a07783341a5492144cc54bcc40a94473693606437'
      ],
      [
        '3775ab7089bc6af823aba2e1af70b236d251cadb0c86743287522a1b3b0dedea',
        'be52d107bcfa09d8bcb9736a828cfa7fac8db17bf7a76a2c42ad961409018cf7'
      ],
      [
        'cee31cbf7e34ec379d94fb814d3d775ad954595d1314ba8846959e3e82f74e26',
        '8fd64a14c06b589c26b947ae2bcf6bfa0149ef0be14ed4d80f448a01c43b1c6d'
      ],
      [
        'b4f9eaea09b6917619f6ea6a4eb5464efddb58fd45b1ebefcdc1a01d08b47986',
        '39e5c9925b5a54b07433a4f18c61726f8bb131c012ca542eb24a8ac07200682a'
      ],
      [
        'd4263dfc3d2df923a0179a48966d30ce84e2515afc3dccc1b77907792ebcc60e',
        '62dfaf07a0f78feb30e30d6295853ce189e127760ad6cf7fae164e122a208d54'
      ],
      [
        '48457524820fa65a4f8d35eb6930857c0032acc0a4a2de422233eeda897612c4',
        '25a748ab367979d98733c38a1fa1c2e7dc6cc07db2d60a9ae7a76aaa49bd0f77'
      ],
      [
        'dfeeef1881101f2cb11644f3a2afdfc2045e19919152923f367a1767c11cceda',
        'ecfb7056cf1de042f9420bab396793c0c390bde74b4bbdff16a83ae09a9a7517'
      ],
      [
        '6d7ef6b17543f8373c573f44e1f389835d89bcbc6062ced36c82df83b8fae859',
        'cd450ec335438986dfefa10c57fea9bcc521a0959b2d80bbf74b190dca712d10'
      ],
      [
        'e75605d59102a5a2684500d3b991f2e3f3c88b93225547035af25af66e04541f',
        'f5c54754a8f71ee540b9b48728473e314f729ac5308b06938360990e2bfad125'
      ],
      [
        'eb98660f4c4dfaa06a2be453d5020bc99a0c2e60abe388457dd43fefb1ed620c',
        '6cb9a8876d9cb8520609af3add26cd20a0a7cd8a9411131ce85f44100099223e'
      ],
      [
        '13e87b027d8514d35939f2e6892b19922154596941888336dc3563e3b8dba942',
        'fef5a3c68059a6dec5d624114bf1e91aac2b9da568d6abeb2570d55646b8adf1'
      ],
      [
        'ee163026e9fd6fe017c38f06a5be6fc125424b371ce2708e7bf4491691e5764a',
        '1acb250f255dd61c43d94ccc670d0f58f49ae3fa15b96623e5430da0ad6c62b2'
      ],
      [
        'b268f5ef9ad51e4d78de3a750c2dc89b1e626d43505867999932e5db33af3d80',
        '5f310d4b3c99b9ebb19f77d41c1dee018cf0d34fd4191614003e945a1216e423'
      ],
      [
        'ff07f3118a9df035e9fad85eb6c7bfe42b02f01ca99ceea3bf7ffdba93c4750d',
        '438136d603e858a3a5c440c38eccbaddc1d2942114e2eddd4740d098ced1f0d8'
      ],
      [
        '8d8b9855c7c052a34146fd20ffb658bea4b9f69e0d825ebec16e8c3ce2b526a1',
        'cdb559eedc2d79f926baf44fb84ea4d44bcf50fee51d7ceb30e2e7f463036758'
      ],
      [
        '52db0b5384dfbf05bfa9d472d7ae26dfe4b851ceca91b1eba54263180da32b63',
        'c3b997d050ee5d423ebaf66a6db9f57b3180c902875679de924b69d84a7b375'
      ],
      [
        'e62f9490d3d51da6395efd24e80919cc7d0f29c3f3fa48c6fff543becbd43352',
        '6d89ad7ba4876b0b22c2ca280c682862f342c8591f1daf5170e07bfd9ccafa7d'
      ],
      [
        '7f30ea2476b399b4957509c88f77d0191afa2ff5cb7b14fd6d8e7d65aaab1193',
        'ca5ef7d4b231c94c3b15389a5f6311e9daff7bb67b103e9880ef4bff637acaec'
      ],
      [
        '5098ff1e1d9f14fb46a210fada6c903fef0fb7b4a1dd1d9ac60a0361800b7a00',
        '9731141d81fc8f8084d37c6e7542006b3ee1b40d60dfe5362a5b132fd17ddc0'
      ],
      [
        '32b78c7de9ee512a72895be6b9cbefa6e2f3c4ccce445c96b9f2c81e2778ad58',
        'ee1849f513df71e32efc3896ee28260c73bb80547ae2275ba497237794c8753c'
      ],
      [
        'e2cb74fddc8e9fbcd076eef2a7c72b0ce37d50f08269dfc074b581550547a4f7',
        'd3aa2ed71c9dd2247a62df062736eb0baddea9e36122d2be8641abcb005cc4a4'
      ],
      [
        '8438447566d4d7bedadc299496ab357426009a35f235cb141be0d99cd10ae3a8',
        'c4e1020916980a4da5d01ac5e6ad330734ef0d7906631c4f2390426b2edd791f'
      ],
      [
        '4162d488b89402039b584c6fc6c308870587d9c46f660b878ab65c82c711d67e',
        '67163e903236289f776f22c25fb8a3afc1732f2b84b4e95dbda47ae5a0852649'
      ],
      [
        '3fad3fa84caf0f34f0f89bfd2dcf54fc175d767aec3e50684f3ba4a4bf5f683d',
        'cd1bc7cb6cc407bb2f0ca647c718a730cf71872e7d0d2a53fa20efcdfe61826'
      ],
      [
        '674f2600a3007a00568c1a7ce05d0816c1fb84bf1370798f1c69532faeb1a86b',
        '299d21f9413f33b3edf43b257004580b70db57da0b182259e09eecc69e0d38a5'
      ],
      [
        'd32f4da54ade74abb81b815ad1fb3b263d82d6c692714bcff87d29bd5ee9f08f',
        'f9429e738b8e53b968e99016c059707782e14f4535359d582fc416910b3eea87'
      ],
      [
        '30e4e670435385556e593657135845d36fbb6931f72b08cb1ed954f1e3ce3ff6',
        '462f9bce619898638499350113bbc9b10a878d35da70740dc695a559eb88db7b'
      ],
      [
        'be2062003c51cc3004682904330e4dee7f3dcd10b01e580bf1971b04d4cad297',
        '62188bc49d61e5428573d48a74e1c655b1c61090905682a0d5558ed72dccb9bc'
      ],
      [
        '93144423ace3451ed29e0fb9ac2af211cb6e84a601df5993c419859fff5df04a',
        '7c10dfb164c3425f5c71a3f9d7992038f1065224f72bb9d1d902a6d13037b47c'
      ],
      [
        'b015f8044f5fcbdcf21ca26d6c34fb8197829205c7b7d2a7cb66418c157b112c',
        'ab8c1e086d04e813744a655b2df8d5f83b3cdc6faa3088c1d3aea1454e3a1d5f'
      ],
      [
        'd5e9e1da649d97d89e4868117a465a3a4f8a18de57a140d36b3f2af341a21b52',
        '4cb04437f391ed73111a13cc1d4dd0db1693465c2240480d8955e8592f27447a'
      ],
      [
        'd3ae41047dd7ca065dbf8ed77b992439983005cd72e16d6f996a5316d36966bb',
        'bd1aeb21ad22ebb22a10f0303417c6d964f8cdd7df0aca614b10dc14d125ac46'
      ],
      [
        '463e2763d885f958fc66cdd22800f0a487197d0a82e377b49f80af87c897b065',
        'bfefacdb0e5d0fd7df3a311a94de062b26b80c61fbc97508b79992671ef7ca7f'
      ],
      [
        '7985fdfd127c0567c6f53ec1bb63ec3158e597c40bfe747c83cddfc910641917',
        '603c12daf3d9862ef2b25fe1de289aed24ed291e0ec6708703a5bd567f32ed03'
      ],
      [
        '74a1ad6b5f76e39db2dd249410eac7f99e74c59cb83d2d0ed5ff1543da7703e9',
        'cc6157ef18c9c63cd6193d83631bbea0093e0968942e8c33d5737fd790e0db08'
      ],
      [
        '30682a50703375f602d416664ba19b7fc9bab42c72747463a71d0896b22f6da3',
        '553e04f6b018b4fa6c8f39e7f311d3176290d0e0f19ca73f17714d9977a22ff8'
      ],
      [
        '9e2158f0d7c0d5f26c3791efefa79597654e7a2b2464f52b1ee6c1347769ef57',
        '712fcdd1b9053f09003a3481fa7762e9ffd7c8ef35a38509e2fbf2629008373'
      ],
      [
        '176e26989a43c9cfeba4029c202538c28172e566e3c4fce7322857f3be327d66',
        'ed8cc9d04b29eb877d270b4878dc43c19aefd31f4eee09ee7b47834c1fa4b1c3'
      ],
      [
        '75d46efea3771e6e68abb89a13ad747ecf1892393dfc4f1b7004788c50374da8',
        '9852390a99507679fd0b86fd2b39a868d7efc22151346e1a3ca4726586a6bed8'
      ],
      [
        '809a20c67d64900ffb698c4c825f6d5f2310fb0451c869345b7319f645605721',
        '9e994980d9917e22b76b061927fa04143d096ccc54963e6a5ebfa5f3f8e286c1'
      ],
      [
        '1b38903a43f7f114ed4500b4eac7083fdefece1cf29c63528d563446f972c180',
        '4036edc931a60ae889353f77fd53de4a2708b26b6f5da72ad3394119daf408f9'
      ]
    ]
  }
};

},{}],82:[function(require,module,exports){
'use strict';

var utils = exports;
var BN = require('bn.js');

utils.assert = function assert(val, msg) {
  if (!val)
    throw new Error(msg || 'Assertion failed');
};

function toArray(msg, enc) {
  if (Array.isArray(msg))
    return msg.slice();
  if (!msg)
    return [];
  var res = [];
  if (typeof msg !== 'string') {
    for (var i = 0; i < msg.length; i++)
      res[i] = msg[i] | 0;
    return res;
  }
  if (!enc) {
    for (var i = 0; i < msg.length; i++) {
      var c = msg.charCodeAt(i);
      var hi = c >> 8;
      var lo = c & 0xff;
      if (hi)
        res.push(hi, lo);
      else
        res.push(lo);
    }
  } else if (enc === 'hex') {
    msg = msg.replace(/[^a-z0-9]+/ig, '');
    if (msg.length % 2 !== 0)
      msg = '0' + msg;
    for (var i = 0; i < msg.length; i += 2)
      res.push(parseInt(msg[i] + msg[i + 1], 16));
  }
  return res;
}
utils.toArray = toArray;

function zero2(word) {
  if (word.length === 1)
    return '0' + word;
  else
    return word;
}
utils.zero2 = zero2;

function toHex(msg) {
  var res = '';
  for (var i = 0; i < msg.length; i++)
    res += zero2(msg[i].toString(16));
  return res;
}
utils.toHex = toHex;

utils.encode = function encode(arr, enc) {
  if (enc === 'hex')
    return toHex(arr);
  else
    return arr;
};

// Represent num in a w-NAF form
function getNAF(num, w) {
  var naf = [];
  var ws = 1 << (w + 1);
  var k = num.clone();
  while (k.cmpn(1) >= 0) {
    var z;
    if (k.isOdd()) {
      var mod = k.andln(ws - 1);
      if (mod > (ws >> 1) - 1)
        z = (ws >> 1) - mod;
      else
        z = mod;
      k.isubn(z);
    } else {
      z = 0;
    }
    naf.push(z);

    // Optimization, shift by word if possible
    var shift = (k.cmpn(0) !== 0 && k.andln(ws - 1) === 0) ? (w + 1) : 1;
    for (var i = 1; i < shift; i++)
      naf.push(0);
    k.iushrn(shift);
  }

  return naf;
}
utils.getNAF = getNAF;

// Represent k1, k2 in a Joint Sparse Form
function getJSF(k1, k2) {
  var jsf = [
    [],
    []
  ];

  k1 = k1.clone();
  k2 = k2.clone();
  var d1 = 0;
  var d2 = 0;
  while (k1.cmpn(-d1) > 0 || k2.cmpn(-d2) > 0) {

    // First phase
    var m14 = (k1.andln(3) + d1) & 3;
    var m24 = (k2.andln(3) + d2) & 3;
    if (m14 === 3)
      m14 = -1;
    if (m24 === 3)
      m24 = -1;
    var u1;
    if ((m14 & 1) === 0) {
      u1 = 0;
    } else {
      var m8 = (k1.andln(7) + d1) & 7;
      if ((m8 === 3 || m8 === 5) && m24 === 2)
        u1 = -m14;
      else
        u1 = m14;
    }
    jsf[0].push(u1);

    var u2;
    if ((m24 & 1) === 0) {
      u2 = 0;
    } else {
      var m8 = (k2.andln(7) + d2) & 7;
      if ((m8 === 3 || m8 === 5) && m14 === 2)
        u2 = -m24;
      else
        u2 = m24;
    }
    jsf[1].push(u2);

    // Second phase
    if (2 * d1 === u1 + 1)
      d1 = 1 - d1;
    if (2 * d2 === u2 + 1)
      d2 = 1 - d2;
    k1.iushrn(1);
    k2.iushrn(1);
  }

  return jsf;
}
utils.getJSF = getJSF;

function cachedProperty(obj, name, computer) {
  var key = '_' + name;
  obj.prototype[name] = function cachedProperty() {
    return this[key] !== undefined ? this[key] :
           this[key] = computer.call(this);
  };
}
utils.cachedProperty = cachedProperty;

function parseBytes(bytes) {
  return typeof bytes === 'string' ? utils.toArray(bytes, 'hex') :
                                     bytes;
}
utils.parseBytes = parseBytes;

function intFromLE(bytes) {
  return new BN(bytes, 'hex', 'le');
}
utils.intFromLE = intFromLE;


},{"bn.js":16}],83:[function(require,module,exports){
module.exports={
  "_from": "elliptic@6.3.2",
  "_id": "elliptic@6.3.2",
  "_inBundle": false,
  "_integrity": "sha1-5MgeCCnPCmWrcOmYuCMnI7XBvEg=",
  "_location": "/elliptic",
  "_phantomChildren": {},
  "_requested": {
    "type": "version",
    "registry": true,
    "raw": "elliptic@6.3.2",
    "name": "elliptic",
    "escapedName": "elliptic",
    "rawSpec": "6.3.2",
    "saveSpec": null,
    "fetchSpec": "6.3.2"
  },
  "_requiredBy": [
    "/browserify-sign",
    "/create-ecdh"
  ],
  "_resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.3.2.tgz",
  "_shasum": "e4c81e0829cf0a65ab70e998b8232723b5c1bc48",
  "_spec": "elliptic@6.3.2",
  "_where": "/home/matthias/tf/dev/generators/javascript/browserify",
  "author": {
    "name": "Fedor Indutny",
    "email": "fedor@indutny.com"
  },
  "bugs": {
    "url": "https://github.com/indutny/elliptic/issues"
  },
  "bundleDependencies": false,
  "dependencies": {
    "bn.js": "^4.4.0",
    "brorand": "^1.0.1",
    "hash.js": "^1.0.0",
    "inherits": "^2.0.1"
  },
  "deprecated": false,
  "description": "EC cryptography",
  "devDependencies": {
    "brfs": "^1.4.3",
    "coveralls": "^2.11.3",
    "grunt": "^0.4.5",
    "grunt-browserify": "^5.0.0",
    "grunt-contrib-connect": "^1.0.0",
    "grunt-contrib-copy": "^1.0.0",
    "grunt-contrib-uglify": "^1.0.1",
    "grunt-mocha-istanbul": "^3.0.1",
    "grunt-saucelabs": "^8.6.2",
    "istanbul": "^0.4.2",
    "jscs": "^2.9.0",
    "jshint": "^2.6.0",
    "mocha": "^2.1.0"
  },
  "files": [
    "lib"
  ],
  "homepage": "https://github.com/indutny/elliptic",
  "keywords": [
    "EC",
    "Elliptic",
    "curve",
    "Cryptography"
  ],
  "license": "MIT",
  "main": "lib/elliptic.js",
  "name": "elliptic",
  "repository": {
    "type": "git",
    "url": "git+ssh://git@github.com/indutny/elliptic.git"
  },
  "scripts": {
    "jscs": "jscs benchmarks/*.js lib/*.js lib/**/*.js lib/**/**/*.js test/index.js",
    "jshint": "jscs benchmarks/*.js lib/*.js lib/**/*.js lib/**/**/*.js test/index.js",
    "lint": "npm run jscs && npm run jshint",
    "test": "npm run lint && npm run unit",
    "unit": "istanbul test _mocha --reporter=spec test/index.js",
    "version": "grunt dist && git add dist/"
  },
  "version": "6.3.2"
}

},{}],84:[function(require,module,exports){
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.

function EventEmitter() {
  this._events = this._events || {};
  this._maxListeners = this._maxListeners || undefined;
}
module.exports = EventEmitter;

// Backwards-compat with node 0.10.x
EventEmitter.EventEmitter = EventEmitter;

EventEmitter.prototype._events = undefined;
EventEmitter.prototype._maxListeners = undefined;

// By default EventEmitters will print a warning if more than 10 listeners are
// added to it. This is a useful default which helps finding memory leaks.
EventEmitter.defaultMaxListeners = 10;

// Obviously not all Emitters should be limited to 10. This function allows
// that to be increased. Set to zero for unlimited.
EventEmitter.prototype.setMaxListeners = function(n) {
  if (!isNumber(n) || n < 0 || isNaN(n))
    throw TypeError('n must be a positive number');
  this._maxListeners = n;
  return this;
};

EventEmitter.prototype.emit = function(type) {
  var er, handler, len, args, i, listeners;

  if (!this._events)
    this._events = {};

  // If there is no 'error' event listener then throw.
  if (type === 'error') {
    if (!this._events.error ||
        (isObject(this._events.error) && !this._events.error.length)) {
      er = arguments[1];
      if (er instanceof Error) {
        throw er; // Unhandled 'error' event
      } else {
        // At least give some kind of context to the user
        var err = new Error('Uncaught, unspecified "error" event. (' + er + ')');
        err.context = er;
        throw err;
      }
    }
  }

  handler = this._events[type];

  if (isUndefined(handler))
    return false;

  if (isFunction(handler)) {
    switch (arguments.length) {
      // fast cases
      case 1:
        handler.call(this);
        break;
      case 2:
        handler.call(this, arguments[1]);
        break;
      case 3:
        handler.call(this, arguments[1], arguments[2]);
        break;
      // slower
      default:
        args = Array.prototype.slice.call(arguments, 1);
        handler.apply(this, args);
    }
  } else if (isObject(handler)) {
    args = Array.prototype.slice.call(arguments, 1);
    listeners = handler.slice();
    len = listeners.length;
    for (i = 0; i < len; i++)
      listeners[i].apply(this, args);
  }

  return true;
};

EventEmitter.prototype.addListener = function(type, listener) {
  var m;

  if (!isFunction(listener))
    throw TypeError('listener must be a function');

  if (!this._events)
    this._events = {};

  // To avoid recursion in the case that type === "newListener"! Before
  // adding it to the listeners, first emit "newListener".
  if (this._events.newListener)
    this.emit('newListener', type,
              isFunction(listener.listener) ?
              listener.listener : listener);

  if (!this._events[type])
    // Optimize the case of one listener. Don't need the extra array object.
    this._events[type] = listener;
  else if (isObject(this._events[type]))
    // If we've already got an array, just append.
    this._events[type].push(listener);
  else
    // Adding the second element, need to change to array.
    this._events[type] = [this._events[type], listener];

  // Check for listener leak
  if (isObject(this._events[type]) && !this._events[type].warned) {
    if (!isUndefined(this._maxListeners)) {
      m = this._maxListeners;
    } else {
      m = EventEmitter.defaultMaxListeners;
    }

    if (m && m > 0 && this._events[type].length > m) {
      this._events[type].warned = true;
      console.error('(node) warning: possible EventEmitter memory ' +
                    'leak detected. %d listeners added. ' +
                    'Use emitter.setMaxListeners() to increase limit.',
                    this._events[type].length);
      if (typeof console.trace === 'function') {
        // not supported in IE 10
        console.trace();
      }
    }
  }

  return this;
};

EventEmitter.prototype.on = EventEmitter.prototype.addListener;

EventEmitter.prototype.once = function(type, listener) {
  if (!isFunction(listener))
    throw TypeError('listener must be a function');

  var fired = false;

  function g() {
    this.removeListener(type, g);

    if (!fired) {
      fired = true;
      listener.apply(this, arguments);
    }
  }

  g.listener = listener;
  this.on(type, g);

  return this;
};

// emits a 'removeListener' event iff the listener was removed
EventEmitter.prototype.removeListener = function(type, listener) {
  var list, position, length, i;

  if (!isFunction(listener))
    throw TypeError('listener must be a function');

  if (!this._events || !this._events[type])
    return this;

  list = this._events[type];
  length = list.length;
  position = -1;

  if (list === listener ||
      (isFunction(list.listener) && list.listener === listener)) {
    delete this._events[type];
    if (this._events.removeListener)
      this.emit('removeListener', type, listener);

  } else if (isObject(list)) {
    for (i = length; i-- > 0;) {
      if (list[i] === listener ||
          (list[i].listener && list[i].listener === listener)) {
        position = i;
        break;
      }
    }

    if (position < 0)
      return this;

    if (list.length === 1) {
      list.length = 0;
      delete this._events[type];
    } else {
      list.splice(position, 1);
    }

    if (this._events.removeListener)
      this.emit('removeListener', type, listener);
  }

  return this;
};

EventEmitter.prototype.removeAllListeners = function(type) {
  var key, listeners;

  if (!this._events)
    return this;

  // not listening for removeListener, no need to emit
  if (!this._events.removeListener) {
    if (arguments.length === 0)
      this._events = {};
    else if (this._events[type])
      delete this._events[type];
    return this;
  }

  // emit removeListener for all listeners on all events
  if (arguments.length === 0) {
    for (key in this._events) {
      if (key === 'removeListener') continue;
      this.removeAllListeners(key);
    }
    this.removeAllListeners('removeListener');
    this._events = {};
    return this;
  }

  listeners = this._events[type];

  if (isFunction(listeners)) {
    this.removeListener(type, listeners);
  } else if (listeners) {
    // LIFO order
    while (listeners.length)
      this.removeListener(type, listeners[listeners.length - 1]);
  }
  delete this._events[type];

  return this;
};

EventEmitter.prototype.listeners = function(type) {
  var ret;
  if (!this._events || !this._events[type])
    ret = [];
  else if (isFunction(this._events[type]))
    ret = [this._events[type]];
  else
    ret = this._events[type].slice();
  return ret;
};

EventEmitter.prototype.listenerCount = function(type) {
  if (this._events) {
    var evlistener = this._events[type];

    if (isFunction(evlistener))
      return 1;
    else if (evlistener)
      return evlistener.length;
  }
  return 0;
};

EventEmitter.listenerCount = function(emitter, type) {
  return emitter.listenerCount(type);
};

function isFunction(arg) {
  return typeof arg === 'function';
}

function isNumber(arg) {
  return typeof arg === 'number';
}

function isObject(arg) {
  return typeof arg === 'object' && arg !== null;
}

function isUndefined(arg) {
  return arg === void 0;
}

},{}],85:[function(require,module,exports){
(function (Buffer){
var md5 = require('create-hash/md5')
module.exports = EVP_BytesToKey
function EVP_BytesToKey (password, salt, keyLen, ivLen) {
  if (!Buffer.isBuffer(password)) {
    password = new Buffer(password, 'binary')
  }
  if (salt && !Buffer.isBuffer(salt)) {
    salt = new Buffer(salt, 'binary')
  }
  keyLen = keyLen / 8
  ivLen = ivLen || 0
  var ki = 0
  var ii = 0
  var key = new Buffer(keyLen)
  var iv = new Buffer(ivLen)
  var addmd = 0
  var md_buf
  var i
  var bufs = []
  while (true) {
    if (addmd++ > 0) {
      bufs.push(md_buf)
    }
    bufs.push(password)
    if (salt) {
      bufs.push(salt)
    }
    md_buf = md5(Buffer.concat(bufs))
    bufs = []
    i = 0
    if (keyLen > 0) {
      while (true) {
        if (keyLen === 0) {
          break
        }
        if (i === md_buf.length) {
          break
        }
        key[ki++] = md_buf[i]
        keyLen--
        i++
      }
    }
    if (ivLen > 0 && i !== md_buf.length) {
      while (true) {
        if (ivLen === 0) {
          break
        }
        if (i === md_buf.length) {
          break
        }
        iv[ii++] = md_buf[i]
        ivLen--
        i++
      }
    }
    if (keyLen === 0 && ivLen === 0) {
      break
    }
  }
  for (i = 0; i < md_buf.length; i++) {
    md_buf[i] = 0
  }
  return {
    key: key,
    iv: iv
  }
}

}).call(this,require("buffer").Buffer)
},{"buffer":45,"create-hash/md5":53}],86:[function(require,module,exports){
var hash = exports;

hash.utils = require('./hash/utils');
hash.common = require('./hash/common');
hash.sha = require('./hash/sha');
hash.ripemd = require('./hash/ripemd');
hash.hmac = require('./hash/hmac');

// Proxy hash functions to the main object
hash.sha1 = hash.sha.sha1;
hash.sha256 = hash.sha.sha256;
hash.sha224 = hash.sha.sha224;
hash.sha384 = hash.sha.sha384;
hash.sha512 = hash.sha.sha512;
hash.ripemd160 = hash.ripemd.ripemd160;

},{"./hash/common":87,"./hash/hmac":88,"./hash/ripemd":89,"./hash/sha":90,"./hash/utils":91}],87:[function(require,module,exports){
var hash = require('../hash');
var utils = hash.utils;
var assert = utils.assert;

function BlockHash() {
  this.pending = null;
  this.pendingTotal = 0;
  this.blockSize = this.constructor.blockSize;
  this.outSize = this.constructor.outSize;
  this.hmacStrength = this.constructor.hmacStrength;
  this.padLength = this.constructor.padLength / 8;
  this.endian = 'big';

  this._delta8 = this.blockSize / 8;
  this._delta32 = this.blockSize / 32;
}
exports.BlockHash = BlockHash;

BlockHash.prototype.update = function update(msg, enc) {
  // Convert message to array, pad it, and join into 32bit blocks
  msg = utils.toArray(msg, enc);
  if (!this.pending)
    this.pending = msg;
  else
    this.pending = this.pending.concat(msg);
  this.pendingTotal += msg.length;

  // Enough data, try updating
  if (this.pending.length >= this._delta8) {
    msg = this.pending;

    // Process pending data in blocks
    var r = msg.length % this._delta8;
    this.pending = msg.slice(msg.length - r, msg.length);
    if (this.pending.length === 0)
      this.pending = null;

    msg = utils.join32(msg, 0, msg.length - r, this.endian);
    for (var i = 0; i < msg.length; i += this._delta32)
      this._update(msg, i, i + this._delta32);
  }

  return this;
};

BlockHash.prototype.digest = function digest(enc) {
  this.update(this._pad());
  assert(this.pending === null);

  return this._digest(enc);
};

BlockHash.prototype._pad = function pad() {
  var len = this.pendingTotal;
  var bytes = this._delta8;
  var k = bytes - ((len + this.padLength) % bytes);
  var res = new Array(k + this.padLength);
  res[0] = 0x80;
  for (var i = 1; i < k; i++)
    res[i] = 0;

  // Append length
  len <<= 3;
  if (this.endian === 'big') {
    for (var t = 8; t < this.padLength; t++)
      res[i++] = 0;

    res[i++] = 0;
    res[i++] = 0;
    res[i++] = 0;
    res[i++] = 0;
    res[i++] = (len >>> 24) & 0xff;
    res[i++] = (len >>> 16) & 0xff;
    res[i++] = (len >>> 8) & 0xff;
    res[i++] = len & 0xff;
  } else {
    res[i++] = len & 0xff;
    res[i++] = (len >>> 8) & 0xff;
    res[i++] = (len >>> 16) & 0xff;
    res[i++] = (len >>> 24) & 0xff;
    res[i++] = 0;
    res[i++] = 0;
    res[i++] = 0;
    res[i++] = 0;

    for (var t = 8; t < this.padLength; t++)
      res[i++] = 0;
  }

  return res;
};

},{"../hash":86}],88:[function(require,module,exports){
var hmac = exports;

var hash = require('../hash');
var utils = hash.utils;
var assert = utils.assert;

function Hmac(hash, key, enc) {
  if (!(this instanceof Hmac))
    return new Hmac(hash, key, enc);
  this.Hash = hash;
  this.blockSize = hash.blockSize / 8;
  this.outSize = hash.outSize / 8;
  this.inner = null;
  this.outer = null;

  this._init(utils.toArray(key, enc));
}
module.exports = Hmac;

Hmac.prototype._init = function init(key) {
  // Shorten key, if needed
  if (key.length > this.blockSize)
    key = new this.Hash().update(key).digest();
  assert(key.length <= this.blockSize);

  // Add padding to key
  for (var i = key.length; i < this.blockSize; i++)
    key.push(0);

  for (var i = 0; i < key.length; i++)
    key[i] ^= 0x36;
  this.inner = new this.Hash().update(key);

  // 0x36 ^ 0x5c = 0x6a
  for (var i = 0; i < key.length; i++)
    key[i] ^= 0x6a;
  this.outer = new this.Hash().update(key);
};

Hmac.prototype.update = function update(msg, enc) {
  this.inner.update(msg, enc);
  return this;
};

Hmac.prototype.digest = function digest(enc) {
  this.outer.update(this.inner.digest());
  return this.outer.digest(enc);
};

},{"../hash":86}],89:[function(require,module,exports){
var hash = require('../hash');
var utils = hash.utils;

var rotl32 = utils.rotl32;
var sum32 = utils.sum32;
var sum32_3 = utils.sum32_3;
var sum32_4 = utils.sum32_4;
var BlockHash = hash.common.BlockHash;

function RIPEMD160() {
  if (!(this instanceof RIPEMD160))
    return new RIPEMD160();

  BlockHash.call(this);

  this.h = [ 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0 ];
  this.endian = 'little';
}
utils.inherits(RIPEMD160, BlockHash);
exports.ripemd160 = RIPEMD160;

RIPEMD160.blockSize = 512;
RIPEMD160.outSize = 160;
RIPEMD160.hmacStrength = 192;
RIPEMD160.padLength = 64;

RIPEMD160.prototype._update = function update(msg, start) {
  var A = this.h[0];
  var B = this.h[1];
  var C = this.h[2];
  var D = this.h[3];
  var E = this.h[4];
  var Ah = A;
  var Bh = B;
  var Ch = C;
  var Dh = D;
  var Eh = E;
  for (var j = 0; j < 80; j++) {
    var T = sum32(
      rotl32(
        sum32_4(A, f(j, B, C, D), msg[r[j] + start], K(j)),
        s[j]),
      E);
    A = E;
    E = D;
    D = rotl32(C, 10);
    C = B;
    B = T;
    T = sum32(
      rotl32(
        sum32_4(Ah, f(79 - j, Bh, Ch, Dh), msg[rh[j] + start], Kh(j)),
        sh[j]),
      Eh);
    Ah = Eh;
    Eh = Dh;
    Dh = rotl32(Ch, 10);
    Ch = Bh;
    Bh = T;
  }
  T = sum32_3(this.h[1], C, Dh);
  this.h[1] = sum32_3(this.h[2], D, Eh);
  this.h[2] = sum32_3(this.h[3], E, Ah);
  this.h[3] = sum32_3(this.h[4], A, Bh);
  this.h[4] = sum32_3(this.h[0], B, Ch);
  this.h[0] = T;
};

RIPEMD160.prototype._digest = function digest(enc) {
  if (enc === 'hex')
    return utils.toHex32(this.h, 'little');
  else
    return utils.split32(this.h, 'little');
};

function f(j, x, y, z) {
  if (j <= 15)
    return x ^ y ^ z;
  else if (j <= 31)
    return (x & y) | ((~x) & z);
  else if (j <= 47)
    return (x | (~y)) ^ z;
  else if (j <= 63)
    return (x & z) | (y & (~z));
  else
    return x ^ (y | (~z));
}

function K(j) {
  if (j <= 15)
    return 0x00000000;
  else if (j <= 31)
    return 0x5a827999;
  else if (j <= 47)
    return 0x6ed9eba1;
  else if (j <= 63)
    return 0x8f1bbcdc;
  else
    return 0xa953fd4e;
}

function Kh(j) {
  if (j <= 15)
    return 0x50a28be6;
  else if (j <= 31)
    return 0x5c4dd124;
  else if (j <= 47)
    return 0x6d703ef3;
  else if (j <= 63)
    return 0x7a6d76e9;
  else
    return 0x00000000;
}

var r = [
  0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
  7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8,
  3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12,
  1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2,
  4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13
];

var rh = [
  5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12,
  6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2,
  15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13,
  8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14,
  12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11
];

var s = [
  11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8,
  7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12,
  11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5,
  11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12,
  9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6
];

var sh = [
  8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6,
  9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11,
  9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5,
  15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8,
  8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11
];

},{"../hash":86}],90:[function(require,module,exports){
var hash = require('../hash');
var utils = hash.utils;
var assert = utils.assert;

var rotr32 = utils.rotr32;
var rotl32 = utils.rotl32;
var sum32 = utils.sum32;
var sum32_4 = utils.sum32_4;
var sum32_5 = utils.sum32_5;
var rotr64_hi = utils.rotr64_hi;
var rotr64_lo = utils.rotr64_lo;
var shr64_hi = utils.shr64_hi;
var shr64_lo = utils.shr64_lo;
var sum64 = utils.sum64;
var sum64_hi = utils.sum64_hi;
var sum64_lo = utils.sum64_lo;
var sum64_4_hi = utils.sum64_4_hi;
var sum64_4_lo = utils.sum64_4_lo;
var sum64_5_hi = utils.sum64_5_hi;
var sum64_5_lo = utils.sum64_5_lo;
var BlockHash = hash.common.BlockHash;

var sha256_K = [
  0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
  0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
  0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
  0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
  0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
  0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
  0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
  0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
  0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
  0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
  0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
  0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
  0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
  0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
  0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
  0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
];

var sha512_K = [
  0x428a2f98, 0xd728ae22, 0x71374491, 0x23ef65cd,
  0xb5c0fbcf, 0xec4d3b2f, 0xe9b5dba5, 0x8189dbbc,
  0x3956c25b, 0xf348b538, 0x59f111f1, 0xb605d019,
  0x923f82a4, 0xaf194f9b, 0xab1c5ed5, 0xda6d8118,
  0xd807aa98, 0xa3030242, 0x12835b01, 0x45706fbe,
  0x243185be, 0x4ee4b28c, 0x550c7dc3, 0xd5ffb4e2,
  0x72be5d74, 0xf27b896f, 0x80deb1fe, 0x3b1696b1,
  0x9bdc06a7, 0x25c71235, 0xc19bf174, 0xcf692694,
  0xe49b69c1, 0x9ef14ad2, 0xefbe4786, 0x384f25e3,
  0x0fc19dc6, 0x8b8cd5b5, 0x240ca1cc, 0x77ac9c65,
  0x2de92c6f, 0x592b0275, 0x4a7484aa, 0x6ea6e483,
  0x5cb0a9dc, 0xbd41fbd4, 0x76f988da, 0x831153b5,
  0x983e5152, 0xee66dfab, 0xa831c66d, 0x2db43210,
  0xb00327c8, 0x98fb213f, 0xbf597fc7, 0xbeef0ee4,
  0xc6e00bf3, 0x3da88fc2, 0xd5a79147, 0x930aa725,
  0x06ca6351, 0xe003826f, 0x14292967, 0x0a0e6e70,
  0x27b70a85, 0x46d22ffc, 0x2e1b2138, 0x5c26c926,
  0x4d2c6dfc, 0x5ac42aed, 0x53380d13, 0x9d95b3df,
  0x650a7354, 0x8baf63de, 0x766a0abb, 0x3c77b2a8,
  0x81c2c92e, 0x47edaee6, 0x92722c85, 0x1482353b,
  0xa2bfe8a1, 0x4cf10364, 0xa81a664b, 0xbc423001,
  0xc24b8b70, 0xd0f89791, 0xc76c51a3, 0x0654be30,
  0xd192e819, 0xd6ef5218, 0xd6990624, 0x5565a910,
  0xf40e3585, 0x5771202a, 0x106aa070, 0x32bbd1b8,
  0x19a4c116, 0xb8d2d0c8, 0x1e376c08, 0x5141ab53,
  0x2748774c, 0xdf8eeb99, 0x34b0bcb5, 0xe19b48a8,
  0x391c0cb3, 0xc5c95a63, 0x4ed8aa4a, 0xe3418acb,
  0x5b9cca4f, 0x7763e373, 0x682e6ff3, 0xd6b2b8a3,
  0x748f82ee, 0x5defb2fc, 0x78a5636f, 0x43172f60,
  0x84c87814, 0xa1f0ab72, 0x8cc70208, 0x1a6439ec,
  0x90befffa, 0x23631e28, 0xa4506ceb, 0xde82bde9,
  0xbef9a3f7, 0xb2c67915, 0xc67178f2, 0xe372532b,
  0xca273ece, 0xea26619c, 0xd186b8c7, 0x21c0c207,
  0xeada7dd6, 0xcde0eb1e, 0xf57d4f7f, 0xee6ed178,
  0x06f067aa, 0x72176fba, 0x0a637dc5, 0xa2c898a6,
  0x113f9804, 0xbef90dae, 0x1b710b35, 0x131c471b,
  0x28db77f5, 0x23047d84, 0x32caab7b, 0x40c72493,
  0x3c9ebe0a, 0x15c9bebc, 0x431d67c4, 0x9c100d4c,
  0x4cc5d4be, 0xcb3e42b6, 0x597f299c, 0xfc657e2a,
  0x5fcb6fab, 0x3ad6faec, 0x6c44198c, 0x4a475817
];

var sha1_K = [
  0x5A827999, 0x6ED9EBA1,
  0x8F1BBCDC, 0xCA62C1D6
];

function SHA256() {
  if (!(this instanceof SHA256))
    return new SHA256();

  BlockHash.call(this);
  this.h = [ 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
             0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 ];
  this.k = sha256_K;
  this.W = new Array(64);
}
utils.inherits(SHA256, BlockHash);
exports.sha256 = SHA256;

SHA256.blockSize = 512;
SHA256.outSize = 256;
SHA256.hmacStrength = 192;
SHA256.padLength = 64;

SHA256.prototype._update = function _update(msg, start) {
  var W = this.W;

  for (var i = 0; i < 16; i++)
    W[i] = msg[start + i];
  for (; i < W.length; i++)
    W[i] = sum32_4(g1_256(W[i - 2]), W[i - 7], g0_256(W[i - 15]), W[i - 16]);

  var a = this.h[0];
  var b = this.h[1];
  var c = this.h[2];
  var d = this.h[3];
  var e = this.h[4];
  var f = this.h[5];
  var g = this.h[6];
  var h = this.h[7];

  assert(this.k.length === W.length);
  for (var i = 0; i < W.length; i++) {
    var T1 = sum32_5(h, s1_256(e), ch32(e, f, g), this.k[i], W[i]);
    var T2 = sum32(s0_256(a), maj32(a, b, c));
    h = g;
    g = f;
    f = e;
    e = sum32(d, T1);
    d = c;
    c = b;
    b = a;
    a = sum32(T1, T2);
  }

  this.h[0] = sum32(this.h[0], a);
  this.h[1] = sum32(this.h[1], b);
  this.h[2] = sum32(this.h[2], c);
  this.h[3] = sum32(this.h[3], d);
  this.h[4] = sum32(this.h[4], e);
  this.h[5] = sum32(this.h[5], f);
  this.h[6] = sum32(this.h[6], g);
  this.h[7] = sum32(this.h[7], h);
};

SHA256.prototype._digest = function digest(enc) {
  if (enc === 'hex')
    return utils.toHex32(this.h, 'big');
  else
    return utils.split32(this.h, 'big');
};

function SHA224() {
  if (!(this instanceof SHA224))
    return new SHA224();

  SHA256.call(this);
  this.h = [ 0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939,
             0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4 ];
}
utils.inherits(SHA224, SHA256);
exports.sha224 = SHA224;

SHA224.blockSize = 512;
SHA224.outSize = 224;
SHA224.hmacStrength = 192;
SHA224.padLength = 64;

SHA224.prototype._digest = function digest(enc) {
  // Just truncate output
  if (enc === 'hex')
    return utils.toHex32(this.h.slice(0, 7), 'big');
  else
    return utils.split32(this.h.slice(0, 7), 'big');
};

function SHA512() {
  if (!(this instanceof SHA512))
    return new SHA512();

  BlockHash.call(this);
  this.h = [ 0x6a09e667, 0xf3bcc908,
             0xbb67ae85, 0x84caa73b,
             0x3c6ef372, 0xfe94f82b,
             0xa54ff53a, 0x5f1d36f1,
             0x510e527f, 0xade682d1,
             0x9b05688c, 0x2b3e6c1f,
             0x1f83d9ab, 0xfb41bd6b,
             0x5be0cd19, 0x137e2179 ];
  this.k = sha512_K;
  this.W = new Array(160);
}
utils.inherits(SHA512, BlockHash);
exports.sha512 = SHA512;

SHA512.blockSize = 1024;
SHA512.outSize = 512;
SHA512.hmacStrength = 192;
SHA512.padLength = 128;

SHA512.prototype._prepareBlock = function _prepareBlock(msg, start) {
  var W = this.W;

  // 32 x 32bit words
  for (var i = 0; i < 32; i++)
    W[i] = msg[start + i];
  for (; i < W.length; i += 2) {
    var c0_hi = g1_512_hi(W[i - 4], W[i - 3]);  // i - 2
    var c0_lo = g1_512_lo(W[i - 4], W[i - 3]);
    var c1_hi = W[i - 14];  // i - 7
    var c1_lo = W[i - 13];
    var c2_hi = g0_512_hi(W[i - 30], W[i - 29]);  // i - 15
    var c2_lo = g0_512_lo(W[i - 30], W[i - 29]);
    var c3_hi = W[i - 32];  // i - 16
    var c3_lo = W[i - 31];

    W[i] = sum64_4_hi(c0_hi, c0_lo,
                      c1_hi, c1_lo,
                      c2_hi, c2_lo,
                      c3_hi, c3_lo);
    W[i + 1] = sum64_4_lo(c0_hi, c0_lo,
                          c1_hi, c1_lo,
                          c2_hi, c2_lo,
                          c3_hi, c3_lo);
  }
};

SHA512.prototype._update = function _update(msg, start) {
  this._prepareBlock(msg, start);

  var W = this.W;

  var ah = this.h[0];
  var al = this.h[1];
  var bh = this.h[2];
  var bl = this.h[3];
  var ch = this.h[4];
  var cl = this.h[5];
  var dh = this.h[6];
  var dl = this.h[7];
  var eh = this.h[8];
  var el = this.h[9];
  var fh = this.h[10];
  var fl = this.h[11];
  var gh = this.h[12];
  var gl = this.h[13];
  var hh = this.h[14];
  var hl = this.h[15];

  assert(this.k.length === W.length);
  for (var i = 0; i < W.length; i += 2) {
    var c0_hi = hh;
    var c0_lo = hl;
    var c1_hi = s1_512_hi(eh, el);
    var c1_lo = s1_512_lo(eh, el);
    var c2_hi = ch64_hi(eh, el, fh, fl, gh, gl);
    var c2_lo = ch64_lo(eh, el, fh, fl, gh, gl);
    var c3_hi = this.k[i];
    var c3_lo = this.k[i + 1];
    var c4_hi = W[i];
    var c4_lo = W[i + 1];

    var T1_hi = sum64_5_hi(c0_hi, c0_lo,
                           c1_hi, c1_lo,
                           c2_hi, c2_lo,
                           c3_hi, c3_lo,
                           c4_hi, c4_lo);
    var T1_lo = sum64_5_lo(c0_hi, c0_lo,
                           c1_hi, c1_lo,
                           c2_hi, c2_lo,
                           c3_hi, c3_lo,
                           c4_hi, c4_lo);

    var c0_hi = s0_512_hi(ah, al);
    var c0_lo = s0_512_lo(ah, al);
    var c1_hi = maj64_hi(ah, al, bh, bl, ch, cl);
    var c1_lo = maj64_lo(ah, al, bh, bl, ch, cl);

    var T2_hi = sum64_hi(c0_hi, c0_lo, c1_hi, c1_lo);
    var T2_lo = sum64_lo(c0_hi, c0_lo, c1_hi, c1_lo);

    hh = gh;
    hl = gl;

    gh = fh;
    gl = fl;

    fh = eh;
    fl = el;

    eh = sum64_hi(dh, dl, T1_hi, T1_lo);
    el = sum64_lo(dl, dl, T1_hi, T1_lo);

    dh = ch;
    dl = cl;

    ch = bh;
    cl = bl;

    bh = ah;
    bl = al;

    ah = sum64_hi(T1_hi, T1_lo, T2_hi, T2_lo);
    al = sum64_lo(T1_hi, T1_lo, T2_hi, T2_lo);
  }

  sum64(this.h, 0, ah, al);
  sum64(this.h, 2, bh, bl);
  sum64(this.h, 4, ch, cl);
  sum64(this.h, 6, dh, dl);
  sum64(this.h, 8, eh, el);
  sum64(this.h, 10, fh, fl);
  sum64(this.h, 12, gh, gl);
  sum64(this.h, 14, hh, hl);
};

SHA512.prototype._digest = function digest(enc) {
  if (enc === 'hex')
    return utils.toHex32(this.h, 'big');
  else
    return utils.split32(this.h, 'big');
};

function SHA384() {
  if (!(this instanceof SHA384))
    return new SHA384();

  SHA512.call(this);
  this.h = [ 0xcbbb9d5d, 0xc1059ed8,
             0x629a292a, 0x367cd507,
             0x9159015a, 0x3070dd17,
             0x152fecd8, 0xf70e5939,
             0x67332667, 0xffc00b31,
             0x8eb44a87, 0x68581511,
             0xdb0c2e0d, 0x64f98fa7,
             0x47b5481d, 0xbefa4fa4 ];
}
utils.inherits(SHA384, SHA512);
exports.sha384 = SHA384;

SHA384.blockSize = 1024;
SHA384.outSize = 384;
SHA384.hmacStrength = 192;
SHA384.padLength = 128;

SHA384.prototype._digest = function digest(enc) {
  if (enc === 'hex')
    return utils.toHex32(this.h.slice(0, 12), 'big');
  else
    return utils.split32(this.h.slice(0, 12), 'big');
};

function SHA1() {
  if (!(this instanceof SHA1))
    return new SHA1();

  BlockHash.call(this);
  this.h = [ 0x67452301, 0xefcdab89, 0x98badcfe,
             0x10325476, 0xc3d2e1f0 ];
  this.W = new Array(80);
}

utils.inherits(SHA1, BlockHash);
exports.sha1 = SHA1;

SHA1.blockSize = 512;
SHA1.outSize = 160;
SHA1.hmacStrength = 80;
SHA1.padLength = 64;

SHA1.prototype._update = function _update(msg, start) {
  var W = this.W;

  for (var i = 0; i < 16; i++)
    W[i] = msg[start + i];

  for(; i < W.length; i++)
    W[i] = rotl32(W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16], 1);

  var a = this.h[0];
  var b = this.h[1];
  var c = this.h[2];
  var d = this.h[3];
  var e = this.h[4];

  for (var i = 0; i < W.length; i++) {
    var s = ~~(i / 20);
    var t = sum32_5(rotl32(a, 5), ft_1(s, b, c, d), e, W[i], sha1_K[s]);
    e = d;
    d = c;
    c = rotl32(b, 30);
    b = a;
    a = t;
  }

  this.h[0] = sum32(this.h[0], a);
  this.h[1] = sum32(this.h[1], b);
  this.h[2] = sum32(this.h[2], c);
  this.h[3] = sum32(this.h[3], d);
  this.h[4] = sum32(this.h[4], e);
};

SHA1.prototype._digest = function digest(enc) {
  if (enc === 'hex')
    return utils.toHex32(this.h, 'big');
  else
    return utils.split32(this.h, 'big');
};

function ch32(x, y, z) {
  return (x & y) ^ ((~x) & z);
}

function maj32(x, y, z) {
  return (x & y) ^ (x & z) ^ (y & z);
}

function p32(x, y, z) {
  return x ^ y ^ z;
}

function s0_256(x) {
  return rotr32(x, 2) ^ rotr32(x, 13) ^ rotr32(x, 22);
}

function s1_256(x) {
  return rotr32(x, 6) ^ rotr32(x, 11) ^ rotr32(x, 25);
}

function g0_256(x) {
  return rotr32(x, 7) ^ rotr32(x, 18) ^ (x >>> 3);
}

function g1_256(x) {
  return rotr32(x, 17) ^ rotr32(x, 19) ^ (x >>> 10);
}

function ft_1(s, x, y, z) {
  if (s === 0)
    return ch32(x, y, z);
  if (s === 1 || s === 3)
    return p32(x, y, z);
  if (s === 2)
    return maj32(x, y, z);
}

function ch64_hi(xh, xl, yh, yl, zh, zl) {
  var r = (xh & yh) ^ ((~xh) & zh);
  if (r < 0)
    r += 0x100000000;
  return r;
}

function ch64_lo(xh, xl, yh, yl, zh, zl) {
  var r = (xl & yl) ^ ((~xl) & zl);
  if (r < 0)
    r += 0x100000000;
  return r;
}

function maj64_hi(xh, xl, yh, yl, zh, zl) {
  var r = (xh & yh) ^ (xh & zh) ^ (yh & zh);
  if (r < 0)
    r += 0x100000000;
  return r;
}

function maj64_lo(xh, xl, yh, yl, zh, zl) {
  var r = (xl & yl) ^ (xl & zl) ^ (yl & zl);
  if (r < 0)
    r += 0x100000000;
  return r;
}

function s0_512_hi(xh, xl) {
  var c0_hi = rotr64_hi(xh, xl, 28);
  var c1_hi = rotr64_hi(xl, xh, 2);  // 34
  var c2_hi = rotr64_hi(xl, xh, 7);  // 39

  var r = c0_hi ^ c1_hi ^ c2_hi;
  if (r < 0)
    r += 0x100000000;
  return r;
}

function s0_512_lo(xh, xl) {
  var c0_lo = rotr64_lo(xh, xl, 28);
  var c1_lo = rotr64_lo(xl, xh, 2);  // 34
  var c2_lo = rotr64_lo(xl, xh, 7);  // 39

  var r = c0_lo ^ c1_lo ^ c2_lo;
  if (r < 0)
    r += 0x100000000;
  return r;
}

function s1_512_hi(xh, xl) {
  var c0_hi = rotr64_hi(xh, xl, 14);
  var c1_hi = rotr64_hi(xh, xl, 18);
  var c2_hi = rotr64_hi(xl, xh, 9);  // 41

  var r = c0_hi ^ c1_hi ^ c2_hi;
  if (r < 0)
    r += 0x100000000;
  return r;
}

function s1_512_lo(xh, xl) {
  var c0_lo = rotr64_lo(xh, xl, 14);
  var c1_lo = rotr64_lo(xh, xl, 18);
  var c2_lo = rotr64_lo(xl, xh, 9);  // 41

  var r = c0_lo ^ c1_lo ^ c2_lo;
  if (r < 0)
    r += 0x100000000;
  return r;
}

function g0_512_hi(xh, xl) {
  var c0_hi = rotr64_hi(xh, xl, 1);
  var c1_hi = rotr64_hi(xh, xl, 8);
  var c2_hi = shr64_hi(xh, xl, 7);

  var r = c0_hi ^ c1_hi ^ c2_hi;
  if (r < 0)
    r += 0x100000000;
  return r;
}

function g0_512_lo(xh, xl) {
  var c0_lo = rotr64_lo(xh, xl, 1);
  var c1_lo = rotr64_lo(xh, xl, 8);
  var c2_lo = shr64_lo(xh, xl, 7);

  var r = c0_lo ^ c1_lo ^ c2_lo;
  if (r < 0)
    r += 0x100000000;
  return r;
}

function g1_512_hi(xh, xl) {
  var c0_hi = rotr64_hi(xh, xl, 19);
  var c1_hi = rotr64_hi(xl, xh, 29);  // 61
  var c2_hi = shr64_hi(xh, xl, 6);

  var r = c0_hi ^ c1_hi ^ c2_hi;
  if (r < 0)
    r += 0x100000000;
  return r;
}

function g1_512_lo(xh, xl) {
  var c0_lo = rotr64_lo(xh, xl, 19);
  var c1_lo = rotr64_lo(xl, xh, 29);  // 61
  var c2_lo = shr64_lo(xh, xl, 6);

  var r = c0_lo ^ c1_lo ^ c2_lo;
  if (r < 0)
    r += 0x100000000;
  return r;
}

},{"../hash":86}],91:[function(require,module,exports){
var utils = exports;
var inherits = require('inherits');

function toArray(msg, enc) {
  if (Array.isArray(msg))
    return msg.slice();
  if (!msg)
    return [];
  var res = [];
  if (typeof msg === 'string') {
    if (!enc) {
      for (var i = 0; i < msg.length; i++) {
        var c = msg.charCodeAt(i);
        var hi = c >> 8;
        var lo = c & 0xff;
        if (hi)
          res.push(hi, lo);
        else
          res.push(lo);
      }
    } else if (enc === 'hex') {
      msg = msg.replace(/[^a-z0-9]+/ig, '');
      if (msg.length % 2 !== 0)
        msg = '0' + msg;
      for (var i = 0; i < msg.length; i += 2)
        res.push(parseInt(msg[i] + msg[i + 1], 16));
    }
  } else {
    for (var i = 0; i < msg.length; i++)
      res[i] = msg[i] | 0;
  }
  return res;
}
utils.toArray = toArray;

function toHex(msg) {
  var res = '';
  for (var i = 0; i < msg.length; i++)
    res += zero2(msg[i].toString(16));
  return res;
}
utils.toHex = toHex;

function htonl(w) {
  var res = (w >>> 24) |
            ((w >>> 8) & 0xff00) |
            ((w << 8) & 0xff0000) |
            ((w & 0xff) << 24);
  return res >>> 0;
}
utils.htonl = htonl;

function toHex32(msg, endian) {
  var res = '';
  for (var i = 0; i < msg.length; i++) {
    var w = msg[i];
    if (endian === 'little')
      w = htonl(w);
    res += zero8(w.toString(16));
  }
  return res;
}
utils.toHex32 = toHex32;

function zero2(word) {
  if (word.length === 1)
    return '0' + word;
  else
    return word;
}
utils.zero2 = zero2;

function zero8(word) {
  if (word.length === 7)
    return '0' + word;
  else if (word.length === 6)
    return '00' + word;
  else if (word.length === 5)
    return '000' + word;
  else if (word.length === 4)
    return '0000' + word;
  else if (word.length === 3)
    return '00000' + word;
  else if (word.length === 2)
    return '000000' + word;
  else if (word.length === 1)
    return '0000000' + word;
  else
    return word;
}
utils.zero8 = zero8;

function join32(msg, start, end, endian) {
  var len = end - start;
  assert(len % 4 === 0);
  var res = new Array(len / 4);
  for (var i = 0, k = start; i < res.length; i++, k += 4) {
    var w;
    if (endian === 'big')
      w = (msg[k] << 24) | (msg[k + 1] << 16) | (msg[k + 2] << 8) | msg[k + 3];
    else
      w = (msg[k + 3] << 24) | (msg[k + 2] << 16) | (msg[k + 1] << 8) | msg[k];
    res[i] = w >>> 0;
  }
  return res;
}
utils.join32 = join32;

function split32(msg, endian) {
  var res = new Array(msg.length * 4);
  for (var i = 0, k = 0; i < msg.length; i++, k += 4) {
    var m = msg[i];
    if (endian === 'big') {
      res[k] = m >>> 24;
      res[k + 1] = (m >>> 16) & 0xff;
      res[k + 2] = (m >>> 8) & 0xff;
      res[k + 3] = m & 0xff;
    } else {
      res[k + 3] = m >>> 24;
      res[k + 2] = (m >>> 16) & 0xff;
      res[k + 1] = (m >>> 8) & 0xff;
      res[k] = m & 0xff;
    }
  }
  return res;
}
utils.split32 = split32;

function rotr32(w, b) {
  return (w >>> b) | (w << (32 - b));
}
utils.rotr32 = rotr32;

function rotl32(w, b) {
  return (w << b) | (w >>> (32 - b));
}
utils.rotl32 = rotl32;

function sum32(a, b) {
  return (a + b) >>> 0;
}
utils.sum32 = sum32;

function sum32_3(a, b, c) {
  return (a + b + c) >>> 0;
}
utils.sum32_3 = sum32_3;

function sum32_4(a, b, c, d) {
  return (a + b + c + d) >>> 0;
}
utils.sum32_4 = sum32_4;

function sum32_5(a, b, c, d, e) {
  return (a + b + c + d + e) >>> 0;
}
utils.sum32_5 = sum32_5;

function assert(cond, msg) {
  if (!cond)
    throw new Error(msg || 'Assertion failed');
}
utils.assert = assert;

utils.inherits = inherits;

function sum64(buf, pos, ah, al) {
  var bh = buf[pos];
  var bl = buf[pos + 1];

  var lo = (al + bl) >>> 0;
  var hi = (lo < al ? 1 : 0) + ah + bh;
  buf[pos] = hi >>> 0;
  buf[pos + 1] = lo;
}
exports.sum64 = sum64;

function sum64_hi(ah, al, bh, bl) {
  var lo = (al + bl) >>> 0;
  var hi = (lo < al ? 1 : 0) + ah + bh;
  return hi >>> 0;
};
exports.sum64_hi = sum64_hi;

function sum64_lo(ah, al, bh, bl) {
  var lo = al + bl;
  return lo >>> 0;
};
exports.sum64_lo = sum64_lo;

function sum64_4_hi(ah, al, bh, bl, ch, cl, dh, dl) {
  var carry = 0;
  var lo = al;
  lo = (lo + bl) >>> 0;
  carry += lo < al ? 1 : 0;
  lo = (lo + cl) >>> 0;
  carry += lo < cl ? 1 : 0;
  lo = (lo + dl) >>> 0;
  carry += lo < dl ? 1 : 0;

  var hi = ah + bh + ch + dh + carry;
  return hi >>> 0;
};
exports.sum64_4_hi = sum64_4_hi;

function sum64_4_lo(ah, al, bh, bl, ch, cl, dh, dl) {
  var lo = al + bl + cl + dl;
  return lo >>> 0;
};
exports.sum64_4_lo = sum64_4_lo;

function sum64_5_hi(ah, al, bh, bl, ch, cl, dh, dl, eh, el) {
  var carry = 0;
  var lo = al;
  lo = (lo + bl) >>> 0;
  carry += lo < al ? 1 : 0;
  lo = (lo + cl) >>> 0;
  carry += lo < cl ? 1 : 0;
  lo = (lo + dl) >>> 0;
  carry += lo < dl ? 1 : 0;
  lo = (lo + el) >>> 0;
  carry += lo < el ? 1 : 0;

  var hi = ah + bh + ch + dh + eh + carry;
  return hi >>> 0;
};
exports.sum64_5_hi = sum64_5_hi;

function sum64_5_lo(ah, al, bh, bl, ch, cl, dh, dl, eh, el) {
  var lo = al + bl + cl + dl + el;

  return lo >>> 0;
};
exports.sum64_5_lo = sum64_5_lo;

function rotr64_hi(ah, al, num) {
  var r = (al << (32 - num)) | (ah >>> num);
  return r >>> 0;
};
exports.rotr64_hi = rotr64_hi;

function rotr64_lo(ah, al, num) {
  var r = (ah << (32 - num)) | (al >>> num);
  return r >>> 0;
};
exports.rotr64_lo = rotr64_lo;

function shr64_hi(ah, al, num) {
  return ah >>> num;
};
exports.shr64_hi = shr64_hi;

function shr64_lo(ah, al, num) {
  var r = (ah << (32 - num)) | (al >>> num);
  return r >>> 0;
};
exports.shr64_lo = shr64_lo;

},{"inherits":94}],92:[function(require,module,exports){
exports.read = function (buffer, offset, isLE, mLen, nBytes) {
  var e, m
  var eLen = nBytes * 8 - mLen - 1
  var eMax = (1 << eLen) - 1
  var eBias = eMax >> 1
  var nBits = -7
  var i = isLE ? (nBytes - 1) : 0
  var d = isLE ? -1 : 1
  var s = buffer[offset + i]

  i += d

  e = s & ((1 << (-nBits)) - 1)
  s >>= (-nBits)
  nBits += eLen
  for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8) {}

  m = e & ((1 << (-nBits)) - 1)
  e >>= (-nBits)
  nBits += mLen
  for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8) {}

  if (e === 0) {
    e = 1 - eBias
  } else if (e === eMax) {
    return m ? NaN : ((s ? -1 : 1) * Infinity)
  } else {
    m = m + Math.pow(2, mLen)
    e = e - eBias
  }
  return (s ? -1 : 1) * m * Math.pow(2, e - mLen)
}

exports.write = function (buffer, value, offset, isLE, mLen, nBytes) {
  var e, m, c
  var eLen = nBytes * 8 - mLen - 1
  var eMax = (1 << eLen) - 1
  var eBias = eMax >> 1
  var rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0)
  var i = isLE ? 0 : (nBytes - 1)
  var d = isLE ? 1 : -1
  var s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0

  value = Math.abs(value)

  if (isNaN(value) || value === Infinity) {
    m = isNaN(value) ? 1 : 0
    e = eMax
  } else {
    e = Math.floor(Math.log(value) / Math.LN2)
    if (value * (c = Math.pow(2, -e)) < 1) {
      e--
      c *= 2
    }
    if (e + eBias >= 1) {
      value += rt / c
    } else {
      value += rt * Math.pow(2, 1 - eBias)
    }
    if (value * c >= 2) {
      e++
      c /= 2
    }

    if (e + eBias >= eMax) {
      m = 0
      e = eMax
    } else if (e + eBias >= 1) {
      m = (value * c - 1) * Math.pow(2, mLen)
      e = e + eBias
    } else {
      m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen)
      e = 0
    }
  }

  for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8) {}

  e = (e << mLen) | m
  eLen += mLen
  for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8) {}

  buffer[offset + i - d] |= s * 128
}

},{}],93:[function(require,module,exports){

var indexOf = [].indexOf;

module.exports = function(arr, obj){
  if (indexOf) return arr.indexOf(obj);
  for (var i = 0; i < arr.length; ++i) {
    if (arr[i] === obj) return i;
  }
  return -1;
};
},{}],94:[function(require,module,exports){
if (typeof Object.create === 'function') {
  // implementation from standard node.js 'util' module
  module.exports = function inherits(ctor, superCtor) {
    ctor.super_ = superCtor
    ctor.prototype = Object.create(superCtor.prototype, {
      constructor: {
        value: ctor,
        enumerable: false,
        writable: true,
        configurable: true
      }
    });
  };
} else {
  // old school shim for old browsers
  module.exports = function inherits(ctor, superCtor) {
    ctor.super_ = superCtor
    var TempCtor = function () {}
    TempCtor.prototype = superCtor.prototype
    ctor.prototype = new TempCtor()
    ctor.prototype.constructor = ctor
  }
}

},{}],95:[function(require,module,exports){
/*!
 * Determine if an object is a Buffer
 *
 * @author   Feross Aboukhadijeh <feross@feross.org> <http://feross.org>
 * @license  MIT
 */

// The _isBuffer check is for Safari 5-7 support, because it's missing
// Object.prototype.constructor. Remove this eventually
module.exports = function (obj) {
  return obj != null && (isBuffer(obj) || isSlowBuffer(obj) || !!obj._isBuffer)
}

function isBuffer (obj) {
  return !!obj.constructor && typeof obj.constructor.isBuffer === 'function' && obj.constructor.isBuffer(obj)
}

// For Node v0.10 support. Remove this eventually.
function isSlowBuffer (obj) {
  return typeof obj.readFloatLE === 'function' && typeof obj.slice === 'function' && isBuffer(obj.slice(0, 0))
}

},{}],96:[function(require,module,exports){
var bn = require('bn.js');
var brorand = require('brorand');

function MillerRabin(rand) {
  this.rand = rand || new brorand.Rand();
}
module.exports = MillerRabin;

MillerRabin.create = function create(rand) {
  return new MillerRabin(rand);
};

MillerRabin.prototype._rand = function _rand(n) {
  var len = n.bitLength();
  var buf = this.rand.generate(Math.ceil(len / 8));

  // Set low bits
  buf[0] |= 3;

  // Mask high bits
  var mask = len & 0x7;
  if (mask !== 0)
    buf[buf.length - 1] >>= 7 - mask;

  return new bn(buf);
}

MillerRabin.prototype.test = function test(n, k, cb) {
  var len = n.bitLength();
  var red = bn.mont(n);
  var rone = new bn(1).toRed(red);

  if (!k)
    k = Math.max(1, (len / 48) | 0);

  // Find d and s, (n - 1) = (2 ^ s) * d;
  var n1 = n.subn(1);
  var n2 = n1.subn(1);
  for (var s = 0; !n1.testn(s); s++) {}
  var d = n.shrn(s);

  var rn1 = n1.toRed(red);

  var prime = true;
  for (; k > 0; k--) {
    var a = this._rand(n2);
    if (cb)
      cb(a);

    var x = a.toRed(red).redPow(d);
    if (x.cmp(rone) === 0 || x.cmp(rn1) === 0)
      continue;

    for (var i = 1; i < s; i++) {
      x = x.redSqr();

      if (x.cmp(rone) === 0)
        return false;
      if (x.cmp(rn1) === 0)
        break;
    }

    if (i === s)
      return false;
  }

  return prime;
};

MillerRabin.prototype.getDivisor = function getDivisor(n, k) {
  var len = n.bitLength();
  var red = bn.mont(n);
  var rone = new bn(1).toRed(red);

  if (!k)
    k = Math.max(1, (len / 48) | 0);

  // Find d and s, (n - 1) = (2 ^ s) * d;
  var n1 = n.subn(1);
  var n2 = n1.subn(1);
  for (var s = 0; !n1.testn(s); s++) {}
  var d = n.shrn(s);

  var rn1 = n1.toRed(red);

  for (; k > 0; k--) {
    var a = this._rand(n2);

    var g = n.gcd(a);
    if (g.cmpn(1) !== 0)
      return g;

    var x = a.toRed(red).redPow(d);
    if (x.cmp(rone) === 0 || x.cmp(rn1) === 0)
      continue;

    for (var i = 1; i < s; i++) {
      x = x.redSqr();

      if (x.cmp(rone) === 0)
        return x.fromRed().subn(1).gcd(n);
      if (x.cmp(rn1) === 0)
        break;
    }

    if (i === s) {
      x = x.redSqr();
      return x.fromRed().subn(1).gcd(n);
    }
  }

  return false;
};

},{"bn.js":16,"brorand":17}],97:[function(require,module,exports){
module.exports = assert;

function assert(val, msg) {
  if (!val)
    throw new Error(msg || 'Assertion failed');
}

assert.equal = function assertEqual(l, r, msg) {
  if (l != r)
    throw new Error(msg || ('Assertion failed: ' + l + ' != ' + r));
};

},{}],98:[function(require,module,exports){
module.exports={"2.16.840.1.101.3.4.1.1": "aes-128-ecb",
"2.16.840.1.101.3.4.1.2": "aes-128-cbc",
"2.16.840.1.101.3.4.1.3": "aes-128-ofb",
"2.16.840.1.101.3.4.1.4": "aes-128-cfb",
"2.16.840.1.101.3.4.1.21": "aes-192-ecb",
"2.16.840.1.101.3.4.1.22": "aes-192-cbc",
"2.16.840.1.101.3.4.1.23": "aes-192-ofb",
"2.16.840.1.101.3.4.1.24": "aes-192-cfb",
"2.16.840.1.101.3.4.1.41": "aes-256-ecb",
"2.16.840.1.101.3.4.1.42": "aes-256-cbc",
"2.16.840.1.101.3.4.1.43": "aes-256-ofb",
"2.16.840.1.101.3.4.1.44": "aes-256-cfb"
}
},{}],99:[function(require,module,exports){
// from https://github.com/indutny/self-signed/blob/gh-pages/lib/asn1.js
// Fedor, you are amazing.

var asn1 = require('asn1.js')

var RSAPrivateKey = asn1.define('RSAPrivateKey', function () {
  this.seq().obj(
    this.key('version').int(),
    this.key('modulus').int(),
    this.key('publicExponent').int(),
    this.key('privateExponent').int(),
    this.key('prime1').int(),
    this.key('prime2').int(),
    this.key('exponent1').int(),
    this.key('exponent2').int(),
    this.key('coefficient').int()
  )
})
exports.RSAPrivateKey = RSAPrivateKey

var RSAPublicKey = asn1.define('RSAPublicKey', function () {
  this.seq().obj(
    this.key('modulus').int(),
    this.key('publicExponent').int()
  )
})
exports.RSAPublicKey = RSAPublicKey

var PublicKey = asn1.define('SubjectPublicKeyInfo', function () {
  this.seq().obj(
    this.key('algorithm').use(AlgorithmIdentifier),
    this.key('subjectPublicKey').bitstr()
  )
})
exports.PublicKey = PublicKey

var AlgorithmIdentifier = asn1.define('AlgorithmIdentifier', function () {
  this.seq().obj(
    this.key('algorithm').objid(),
    this.key('none').null_().optional(),
    this.key('curve').objid().optional(),
    this.key('params').seq().obj(
      this.key('p').int(),
      this.key('q').int(),
      this.key('g').int()
    ).optional()
  )
})

var PrivateKeyInfo = asn1.define('PrivateKeyInfo', function () {
  this.seq().obj(
    this.key('version').int(),
    this.key('algorithm').use(AlgorithmIdentifier),
    this.key('subjectPrivateKey').octstr()
  )
})
exports.PrivateKey = PrivateKeyInfo
var EncryptedPrivateKeyInfo = asn1.define('EncryptedPrivateKeyInfo', function () {
  this.seq().obj(
    this.key('algorithm').seq().obj(
      this.key('id').objid(),
      this.key('decrypt').seq().obj(
        this.key('kde').seq().obj(
          this.key('id').objid(),
          this.key('kdeparams').seq().obj(
            this.key('salt').octstr(),
            this.key('iters').int()
          )
        ),
        this.key('cipher').seq().obj(
          this.key('algo').objid(),
          this.key('iv').octstr()
        )
      )
    ),
    this.key('subjectPrivateKey').octstr()
  )
})

exports.EncryptedPrivateKey = EncryptedPrivateKeyInfo

var DSAPrivateKey = asn1.define('DSAPrivateKey', function () {
  this.seq().obj(
    this.key('version').int(),
    this.key('p').int(),
    this.key('q').int(),
    this.key('g').int(),
    this.key('pub_key').int(),
    this.key('priv_key').int()
  )
})
exports.DSAPrivateKey = DSAPrivateKey

exports.DSAparam = asn1.define('DSAparam', function () {
  this.int()
})
var ECPrivateKey = asn1.define('ECPrivateKey', function () {
  this.seq().obj(
    this.key('version').int(),
    this.key('privateKey').octstr(),
    this.key('parameters').optional().explicit(0).use(ECParameters),
    this.key('publicKey').optional().explicit(1).bitstr()
  )
})
exports.ECPrivateKey = ECPrivateKey
var ECParameters = asn1.define('ECParameters', function () {
  this.choice({
    namedCurve: this.objid()
  })
})

exports.signature = asn1.define('signature', function () {
  this.seq().obj(
    this.key('r').int(),
    this.key('s').int()
  )
})

},{"asn1.js":1}],100:[function(require,module,exports){
(function (Buffer){
// adapted from https://github.com/apatil/pemstrip
var findProc = /Proc-Type: 4,ENCRYPTED\r?\nDEK-Info: AES-((?:128)|(?:192)|(?:256))-CBC,([0-9A-H]+)\r?\n\r?\n([0-9A-z\n\r\+\/\=]+)\r?\n/m
var startRegex = /^-----BEGIN (.*) KEY-----\r?\n/m
var fullRegex = /^-----BEGIN (.*) KEY-----\r?\n([0-9A-z\n\r\+\/\=]+)\r?\n-----END \1 KEY-----$/m
var evp = require('evp_bytestokey')
var ciphers = require('browserify-aes')
module.exports = function (okey, password) {
  var key = okey.toString()
  var match = key.match(findProc)
  var decrypted
  if (!match) {
    var match2 = key.match(fullRegex)
    decrypted = new Buffer(match2[2].replace(/\r?\n/g, ''), 'base64')
  } else {
    var suite = 'aes' + match[1]
    var iv = new Buffer(match[2], 'hex')
    var cipherText = new Buffer(match[3].replace(/\r?\n/g, ''), 'base64')
    var cipherKey = evp(password, iv.slice(0, 8), parseInt(match[1], 10)).key
    var out = []
    var cipher = ciphers.createDecipheriv(suite, cipherKey, iv)
    out.push(cipher.update(cipherText))
    out.push(cipher.final())
    decrypted = Buffer.concat(out)
  }
  var tag = key.match(startRegex)[1] + ' KEY'
  return {
    tag: tag,
    data: decrypted
  }
}

}).call(this,require("buffer").Buffer)
},{"browserify-aes":21,"buffer":45,"evp_bytestokey":85}],101:[function(require,module,exports){
(function (Buffer){
var asn1 = require('./asn1')
var aesid = require('./aesid.json')
var fixProc = require('./fixProc')
var ciphers = require('browserify-aes')
var compat = require('pbkdf2')
module.exports = parseKeys

function parseKeys (buffer) {
  var password
  if (typeof buffer === 'object' && !Buffer.isBuffer(buffer)) {
    password = buffer.passphrase
    buffer = buffer.key
  }
  if (typeof buffer === 'string') {
    buffer = new Buffer(buffer)
  }

  var stripped = fixProc(buffer, password)

  var type = stripped.tag
  var data = stripped.data
  var subtype, ndata
  switch (type) {
    case 'PUBLIC KEY':
      ndata = asn1.PublicKey.decode(data, 'der')
      subtype = ndata.algorithm.algorithm.join('.')
      switch (subtype) {
        case '1.2.840.113549.1.1.1':
          return asn1.RSAPublicKey.decode(ndata.subjectPublicKey.data, 'der')
        case '1.2.840.10045.2.1':
          ndata.subjectPrivateKey = ndata.subjectPublicKey
          return {
            type: 'ec',
            data: ndata
          }
        case '1.2.840.10040.4.1':
          ndata.algorithm.params.pub_key = asn1.DSAparam.decode(ndata.subjectPublicKey.data, 'der')
          return {
            type: 'dsa',
            data: ndata.algorithm.params
          }
        default: throw new Error('unknown key id ' + subtype)
      }
      throw new Error('unknown key type ' + type)
    case 'ENCRYPTED PRIVATE KEY':
      data = asn1.EncryptedPrivateKey.decode(data, 'der')
      data = decrypt(data, password)
      // falls through
    case 'PRIVATE KEY':
      ndata = asn1.PrivateKey.decode(data, 'der')
      subtype = ndata.algorithm.algorithm.join('.')
      switch (subtype) {
        case '1.2.840.113549.1.1.1':
          return asn1.RSAPrivateKey.decode(ndata.subjectPrivateKey, 'der')
        case '1.2.840.10045.2.1':
          return {
            curve: ndata.algorithm.curve,
            privateKey: asn1.ECPrivateKey.decode(ndata.subjectPrivateKey, 'der').privateKey
          }
        case '1.2.840.10040.4.1':
          ndata.algorithm.params.priv_key = asn1.DSAparam.decode(ndata.subjectPrivateKey, 'der')
          return {
            type: 'dsa',
            params: ndata.algorithm.params
          }
        default: throw new Error('unknown key id ' + subtype)
      }
      throw new Error('unknown key type ' + type)
    case 'RSA PUBLIC KEY':
      return asn1.RSAPublicKey.decode(data, 'der')
    case 'RSA PRIVATE KEY':
      return asn1.RSAPrivateKey.decode(data, 'der')
    case 'DSA PRIVATE KEY':
      return {
        type: 'dsa',
        params: asn1.DSAPrivateKey.decode(data, 'der')
      }
    case 'EC PRIVATE KEY':
      data = asn1.ECPrivateKey.decode(data, 'der')
      return {
        curve: data.parameters.value,
        privateKey: data.privateKey
      }
    default: throw new Error('unknown key type ' + type)
  }
}
parseKeys.signature = asn1.signature
function decrypt (data, password) {
  var salt = data.algorithm.decrypt.kde.kdeparams.salt
  var iters = parseInt(data.algorithm.decrypt.kde.kdeparams.iters.toString(), 10)
  var algo = aesid[data.algorithm.decrypt.cipher.algo.join('.')]
  var iv = data.algorithm.decrypt.cipher.iv
  var cipherText = data.subjectPrivateKey
  var keylen = parseInt(algo.split('-')[1], 10) / 8
  var key = compat.pbkdf2Sync(password, salt, iters, keylen)
  var cipher = ciphers.createDecipheriv(algo, key, iv)
  var out = []
  out.push(cipher.update(cipherText))
  out.push(cipher.final())
  return Buffer.concat(out)
}

}).call(this,require("buffer").Buffer)
},{"./aesid.json":98,"./asn1":99,"./fixProc":100,"browserify-aes":21,"buffer":45,"pbkdf2":102}],102:[function(require,module,exports){
(function (process,Buffer){
var createHmac = require('create-hmac')
var checkParameters = require('./precondition')

exports.pbkdf2 = function (password, salt, iterations, keylen, digest, callback) {
  if (typeof digest === 'function') {
    callback = digest
    digest = undefined
  }

  checkParameters(iterations, keylen)
  if (typeof callback !== 'function') throw new Error('No callback provided to pbkdf2')

  setTimeout(function () {
    callback(null, exports.pbkdf2Sync(password, salt, iterations, keylen, digest))
  })
}

var defaultEncoding
if (process.browser) {
  defaultEncoding = 'utf-8'
} else {
  var pVersionMajor = parseInt(process.version.split('.')[0].slice(1), 10)

  defaultEncoding = pVersionMajor >= 6 ? 'utf-8' : 'binary'
}

exports.pbkdf2Sync = function (password, salt, iterations, keylen, digest) {
  if (!Buffer.isBuffer(password)) password = new Buffer(password, defaultEncoding)
  if (!Buffer.isBuffer(salt)) salt = new Buffer(salt, defaultEncoding)

  checkParameters(iterations, keylen)

  digest = digest || 'sha1'

  var hLen
  var l = 1
  var DK = new Buffer(keylen)
  var block1 = new Buffer(salt.length + 4)
  salt.copy(block1, 0, 0, salt.length)

  var r
  var T

  for (var i = 1; i <= l; i++) {
    block1.writeUInt32BE(i, salt.length)
    var U = createHmac(digest, password).update(block1).digest()

    if (!hLen) {
      hLen = U.length
      T = new Buffer(hLen)
      l = Math.ceil(keylen / hLen)
      r = keylen - (l - 1) * hLen
    }

    U.copy(T, 0, 0, hLen)

    for (var j = 1; j < iterations; j++) {
      U = createHmac(digest, password).update(U).digest()
      for (var k = 0; k < hLen; k++) T[k] ^= U[k]
    }

    var destPos = (i - 1) * hLen
    var len = (i === l ? r : hLen)
    T.copy(DK, destPos, 0, len)
  }

  return DK
}

}).call(this,require('_process'),require("buffer").Buffer)
},{"./precondition":103,"_process":105,"buffer":45,"create-hmac":55}],103:[function(require,module,exports){
var MAX_ALLOC = Math.pow(2, 30) - 1 // default in iojs
module.exports = function (iterations, keylen) {
  if (typeof iterations !== 'number') {
    throw new TypeError('Iterations not a number')
  }

  if (iterations < 0) {
    throw new TypeError('Bad iterations')
  }

  if (typeof keylen !== 'number') {
    throw new TypeError('Key length not a number')
  }

  if (keylen < 0 || keylen > MAX_ALLOC || keylen !== keylen) { /* eslint no-self-compare: 0 */
    throw new TypeError('Bad key length')
  }
}

},{}],104:[function(require,module,exports){
(function (process){
'use strict';

if (!process.version ||
    process.version.indexOf('v0.') === 0 ||
    process.version.indexOf('v1.') === 0 && process.version.indexOf('v1.8.') !== 0) {
  module.exports = nextTick;
} else {
  module.exports = process.nextTick;
}

function nextTick(fn, arg1, arg2, arg3) {
  if (typeof fn !== 'function') {
    throw new TypeError('"callback" argument must be a function');
  }
  var len = arguments.length;
  var args, i;
  switch (len) {
  case 0:
  case 1:
    return process.nextTick(fn);
  case 2:
    return process.nextTick(function afterTickOne() {
      fn.call(null, arg1);
    });
  case 3:
    return process.nextTick(function afterTickTwo() {
      fn.call(null, arg1, arg2);
    });
  case 4:
    return process.nextTick(function afterTickThree() {
      fn.call(null, arg1, arg2, arg3);
    });
  default:
    args = new Array(len - 1);
    i = 0;
    while (i < args.length) {
      args[i++] = arguments[i];
    }
    return process.nextTick(function afterTick() {
      fn.apply(null, args);
    });
  }
}

}).call(this,require('_process'))
},{"_process":105}],105:[function(require,module,exports){
// shim for using process in browser
var process = module.exports = {};

// cached from whatever global is present so that test runners that stub it
// don't break things.  But we need to wrap it in a try catch in case it is
// wrapped in strict mode code which doesn't define any globals.  It's inside a
// function because try/catches deoptimize in certain engines.

var cachedSetTimeout;
var cachedClearTimeout;

function defaultSetTimout() {
    throw new Error('setTimeout has not been defined');
}
function defaultClearTimeout () {
    throw new Error('clearTimeout has not been defined');
}
(function () {
    try {
        if (typeof setTimeout === 'function') {
            cachedSetTimeout = setTimeout;
        } else {
            cachedSetTimeout = defaultSetTimout;
        }
    } catch (e) {
        cachedSetTimeout = defaultSetTimout;
    }
    try {
        if (typeof clearTimeout === 'function') {
            cachedClearTimeout = clearTimeout;
        } else {
            cachedClearTimeout = defaultClearTimeout;
        }
    } catch (e) {
        cachedClearTimeout = defaultClearTimeout;
    }
} ())
function runTimeout(fun) {
    if (cachedSetTimeout === setTimeout) {
        //normal enviroments in sane situations
        return setTimeout(fun, 0);
    }
    // if setTimeout wasn't available but was latter defined
    if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {
        cachedSetTimeout = setTimeout;
        return setTimeout(fun, 0);
    }
    try {
        // when when somebody has screwed with setTimeout but no I.E. maddness
        return cachedSetTimeout(fun, 0);
    } catch(e){
        try {
            // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
            return cachedSetTimeout.call(null, fun, 0);
        } catch(e){
            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error
            return cachedSetTimeout.call(this, fun, 0);
        }
    }


}
function runClearTimeout(marker) {
    if (cachedClearTimeout === clearTimeout) {
        //normal enviroments in sane situations
        return clearTimeout(marker);
    }
    // if clearTimeout wasn't available but was latter defined
    if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {
        cachedClearTimeout = clearTimeout;
        return clearTimeout(marker);
    }
    try {
        // when when somebody has screwed with setTimeout but no I.E. maddness
        return cachedClearTimeout(marker);
    } catch (e){
        try {
            // When we are in I.E. but the script has been evaled so I.E. doesn't  trust the global object when called normally
            return cachedClearTimeout.call(null, marker);
        } catch (e){
            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.
            // Some versions of I.E. have different rules for clearTimeout vs setTimeout
            return cachedClearTimeout.call(this, marker);
        }
    }



}
var queue = [];
var draining = false;
var currentQueue;
var queueIndex = -1;

function cleanUpNextTick() {
    if (!draining || !currentQueue) {
        return;
    }
    draining = false;
    if (currentQueue.length) {
        queue = currentQueue.concat(queue);
    } else {
        queueIndex = -1;
    }
    if (queue.length) {
        drainQueue();
    }
}

function drainQueue() {
    if (draining) {
        return;
    }
    var timeout = runTimeout(cleanUpNextTick);
    draining = true;

    var len = queue.length;
    while(len) {
        currentQueue = queue;
        queue = [];
        while (++queueIndex < len) {
            if (currentQueue) {
                currentQueue[queueIndex].run();
            }
        }
        queueIndex = -1;
        len = queue.length;
    }
    currentQueue = null;
    draining = false;
    runClearTimeout(timeout);
}

process.nextTick = function (fun) {
    var args = new Array(arguments.length - 1);
    if (arguments.length > 1) {
        for (var i = 1; i < arguments.length; i++) {
            args[i - 1] = arguments[i];
        }
    }
    queue.push(new Item(fun, args));
    if (queue.length === 1 && !draining) {
        runTimeout(drainQueue);
    }
};

// v8 likes predictible objects
function Item(fun, array) {
    this.fun = fun;
    this.array = array;
}
Item.prototype.run = function () {
    this.fun.apply(null, this.array);
};
process.title = 'browser';
process.browser = true;
process.env = {};
process.argv = [];
process.version = ''; // empty string to avoid regexp issues
process.versions = {};

function noop() {}

process.on = noop;
process.addListener = noop;
process.once = noop;
process.off = noop;
process.removeListener = noop;
process.removeAllListeners = noop;
process.emit = noop;

process.binding = function (name) {
    throw new Error('process.binding is not supported');
};

process.cwd = function () { return '/' };
process.chdir = function (dir) {
    throw new Error('process.chdir is not supported');
};
process.umask = function() { return 0; };

},{}],106:[function(require,module,exports){
exports.publicEncrypt = require('./publicEncrypt');
exports.privateDecrypt = require('./privateDecrypt');

exports.privateEncrypt = function privateEncrypt(key, buf) {
  return exports.publicEncrypt(key, buf, true);
};

exports.publicDecrypt = function publicDecrypt(key, buf) {
  return exports.privateDecrypt(key, buf, true);
};
},{"./privateDecrypt":108,"./publicEncrypt":109}],107:[function(require,module,exports){
(function (Buffer){
var createHash = require('create-hash');
module.exports = function (seed, len) {
  var t = new Buffer('');
  var  i = 0, c;
  while (t.length < len) {
    c = i2ops(i++);
    t = Buffer.concat([t, createHash('sha1').update(seed).update(c).digest()]);
  }
  return t.slice(0, len);
};

function i2ops(c) {
  var out = new Buffer(4);
  out.writeUInt32BE(c,0);
  return out;
}
}).call(this,require("buffer").Buffer)
},{"buffer":45,"create-hash":51}],108:[function(require,module,exports){
(function (Buffer){
var parseKeys = require('parse-asn1');
var mgf = require('./mgf');
var xor = require('./xor');
var bn = require('bn.js');
var crt = require('browserify-rsa');
var createHash = require('create-hash');
var withPublic = require('./withPublic');
module.exports = function privateDecrypt(private_key, enc, reverse) {
  var padding;
  if (private_key.padding) {
    padding = private_key.padding;
  } else if (reverse) {
    padding = 1;
  } else {
    padding = 4;
  }
  
  var key = parseKeys(private_key);
  var k = key.modulus.byteLength();
  if (enc.length > k || new bn(enc).cmp(key.modulus) >= 0) {
    throw new Error('decryption error');
  }
  var msg;
  if (reverse) {
    msg = withPublic(new bn(enc), key);
  } else {
    msg = crt(enc, key);
  }
  var zBuffer = new Buffer(k - msg.length);
  zBuffer.fill(0);
  msg = Buffer.concat([zBuffer, msg], k);
  if (padding === 4) {
    return oaep(key, msg);
  } else if (padding === 1) {
    return pkcs1(key, msg, reverse);
  } else if (padding === 3) {
    return msg;
  } else {
    throw new Error('unknown padding');
  }
};

function oaep(key, msg){
  var n = key.modulus;
  var k = key.modulus.byteLength();
  var mLen = msg.length;
  var iHash = createHash('sha1').update(new Buffer('')).digest();
  var hLen = iHash.length;
  var hLen2 = 2 * hLen;
  if (msg[0] !== 0) {
    throw new Error('decryption error');
  }
  var maskedSeed = msg.slice(1, hLen + 1);
  var maskedDb =  msg.slice(hLen + 1);
  var seed = xor(maskedSeed, mgf(maskedDb, hLen));
  var db = xor(maskedDb, mgf(seed, k - hLen - 1));
  if (compare(iHash, db.slice(0, hLen))) {
    throw new Error('decryption error');
  }
  var i = hLen;
  while (db[i] === 0) {
    i++;
  }
  if (db[i++] !== 1) {
    throw new Error('decryption error');
  }
  return db.slice(i);
}

function pkcs1(key, msg, reverse){
  var p1 = msg.slice(0, 2);
  var i = 2;
  var status = 0;
  while (msg[i++] !== 0) {
    if (i >= msg.length) {
      status++;
      break;
    }
  }
  var ps = msg.slice(2, i - 1);
  var p2 = msg.slice(i - 1, i);

  if ((p1.toString('hex') !== '0002' && !reverse) || (p1.toString('hex') !== '0001' && reverse)){
    status++;
  }
  if (ps.length < 8) {
    status++;
  }
  if (status) {
    throw new Error('decryption error');
  }
  return  msg.slice(i);
}
function compare(a, b){
  a = new Buffer(a);
  b = new Buffer(b);
  var dif = 0;
  var len = a.length;
  if (a.length !== b.length) {
    dif++;
    len = Math.min(a.length, b.length);
  }
  var i = -1;
  while (++i < len) {
    dif += (a[i] ^ b[i]);
  }
  return dif;
}
}).call(this,require("buffer").Buffer)
},{"./mgf":107,"./withPublic":110,"./xor":111,"bn.js":16,"browserify-rsa":38,"buffer":45,"create-hash":51,"parse-asn1":101}],109:[function(require,module,exports){
(function (Buffer){
var parseKeys = require('parse-asn1');
var randomBytes = require('randombytes');
var createHash = require('create-hash');
var mgf = require('./mgf');
var xor = require('./xor');
var bn = require('bn.js');
var withPublic = require('./withPublic');
var crt = require('browserify-rsa');

var constants = {
  RSA_PKCS1_OAEP_PADDING: 4,
  RSA_PKCS1_PADDIN: 1,
  RSA_NO_PADDING: 3
};

module.exports = function publicEncrypt(public_key, msg, reverse) {
  var padding;
  if (public_key.padding) {
    padding = public_key.padding;
  } else if (reverse) {
    padding = 1;
  } else {
    padding = 4;
  }
  var key = parseKeys(public_key);
  var paddedMsg;
  if (padding === 4) {
    paddedMsg = oaep(key, msg);
  } else if (padding === 1) {
    paddedMsg = pkcs1(key, msg, reverse);
  } else if (padding === 3) {
    paddedMsg = new bn(msg);
    if (paddedMsg.cmp(key.modulus) >= 0) {
      throw new Error('data too long for modulus');
    }
  } else {
    throw new Error('unknown padding');
  }
  if (reverse) {
    return crt(paddedMsg, key);
  } else {
    return withPublic(paddedMsg, key);
  }
};

function oaep(key, msg){
  var k = key.modulus.byteLength();
  var mLen = msg.length;
  var iHash = createHash('sha1').update(new Buffer('')).digest();
  var hLen = iHash.length;
  var hLen2 = 2 * hLen;
  if (mLen > k - hLen2 - 2) {
    throw new Error('message too long');
  }
  var ps = new Buffer(k - mLen - hLen2 - 2);
  ps.fill(0);
  var dblen = k - hLen - 1;
  var seed = randomBytes(hLen);
  var maskedDb = xor(Buffer.concat([iHash, ps, new Buffer([1]), msg], dblen), mgf(seed, dblen));
  var maskedSeed = xor(seed, mgf(maskedDb, hLen));
  return new bn(Buffer.concat([new Buffer([0]), maskedSeed, maskedDb], k));
}
function pkcs1(key, msg, reverse){
  var mLen = msg.length;
  var k = key.modulus.byteLength();
  if (mLen > k - 11) {
    throw new Error('message too long');
  }
  var ps;
  if (reverse) {
    ps = new Buffer(k - mLen - 3);
    ps.fill(0xff);
  } else {
    ps = nonZero(k - mLen - 3);
  }
  return new bn(Buffer.concat([new Buffer([0, reverse?1:2]), ps, new Buffer([0]), msg], k));
}
function nonZero(len, crypto) {
  var out = new Buffer(len);
  var i = 0;
  var cache = randomBytes(len*2);
  var cur = 0;
  var num;
  while (i < len) {
    if (cur === cache.length) {
      cache = randomBytes(len*2);
      cur = 0;
    }
    num = cache[cur++];
    if (num) {
      out[i++] = num;
    }
  }
  return out;
}
}).call(this,require("buffer").Buffer)
},{"./mgf":107,"./withPublic":110,"./xor":111,"bn.js":16,"browserify-rsa":38,"buffer":45,"create-hash":51,"parse-asn1":101,"randombytes":112}],110:[function(require,module,exports){
(function (Buffer){
var bn = require('bn.js');
function withPublic(paddedMsg, key) {
  return new Buffer(paddedMsg
    .toRed(bn.mont(key.modulus))
    .redPow(new bn(key.publicExponent))
    .fromRed()
    .toArray());
}

module.exports = withPublic;
}).call(this,require("buffer").Buffer)
},{"bn.js":16,"buffer":45}],111:[function(require,module,exports){
module.exports = function xor(a, b) {
  var len = a.length;
  var i = -1;
  while (++i < len) {
    a[i] ^= b[i];
  }
  return a
};
},{}],112:[function(require,module,exports){
(function (process,global,Buffer){
'use strict'

function oldBrowser () {
  throw new Error('secure random number generation not supported by this browser\nuse chrome, FireFox or Internet Explorer 11')
}

var crypto = global.crypto || global.msCrypto

if (crypto && crypto.getRandomValues) {
  module.exports = randomBytes
} else {
  module.exports = oldBrowser
}

function randomBytes (size, cb) {
  // phantomjs needs to throw
  if (size > 65536) throw new Error('requested too many random bytes')
  // in case browserify  isn't using the Uint8Array version
  var rawBytes = new global.Uint8Array(size)

  // This will not work in older browsers.
  // See https://developer.mozilla.org/en-US/docs/Web/API/window.crypto.getRandomValues
  if (size > 0) {  // getRandomValues fails on IE if size == 0
    crypto.getRandomValues(rawBytes)
  }
  // phantomjs doesn't like a buffer being passed here
  var bytes = new Buffer(rawBytes.buffer)

  if (typeof cb === 'function') {
    return process.nextTick(function () {
      cb(null, bytes)
    })
  }

  return bytes
}

}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {},require("buffer").Buffer)
},{"_process":105,"buffer":45}],113:[function(require,module,exports){
module.exports = require("./lib/_stream_duplex.js")

},{"./lib/_stream_duplex.js":114}],114:[function(require,module,exports){
// a duplex stream is just a stream that is both readable and writable.
// Since JS doesn't have multiple prototypal inheritance, this class
// prototypally inherits from Readable, and then parasitically from
// Writable.

'use strict';

/*<replacement>*/

var objectKeys = Object.keys || function (obj) {
  var keys = [];
  for (var key in obj) {
    keys.push(key);
  }return keys;
};
/*</replacement>*/

module.exports = Duplex;

/*<replacement>*/
var processNextTick = require('process-nextick-args');
/*</replacement>*/

/*<replacement>*/
var util = require('core-util-is');
util.inherits = require('inherits');
/*</replacement>*/

var Readable = require('./_stream_readable');
var Writable = require('./_stream_writable');

util.inherits(Duplex, Readable);

var keys = objectKeys(Writable.prototype);
for (var v = 0; v < keys.length; v++) {
  var method = keys[v];
  if (!Duplex.prototype[method]) Duplex.prototype[method] = Writable.prototype[method];
}

function Duplex(options) {
  if (!(this instanceof Duplex)) return new Duplex(options);

  Readable.call(this, options);
  Writable.call(this, options);

  if (options && options.readable === false) this.readable = false;

  if (options && options.writable === false) this.writable = false;

  this.allowHalfOpen = true;
  if (options && options.allowHalfOpen === false) this.allowHalfOpen = false;

  this.once('end', onend);
}

// the no-half-open enforcer
function onend() {
  // if we allow half-open state, or if the writable side ended,
  // then we're ok.
  if (this.allowHalfOpen || this._writableState.ended) return;

  // no more data can be written.
  // But allow more writes to happen in this tick.
  processNextTick(onEndNT, this);
}

function onEndNT(self) {
  self.end();
}

function forEach(xs, f) {
  for (var i = 0, l = xs.length; i < l; i++) {
    f(xs[i], i);
  }
}
},{"./_stream_readable":116,"./_stream_writable":118,"core-util-is":49,"inherits":94,"process-nextick-args":104}],115:[function(require,module,exports){
// a passthrough stream.
// basically just the most minimal sort of Transform stream.
// Every written chunk gets output as-is.

'use strict';

module.exports = PassThrough;

var Transform = require('./_stream_transform');

/*<replacement>*/
var util = require('core-util-is');
util.inherits = require('inherits');
/*</replacement>*/

util.inherits(PassThrough, Transform);

function PassThrough(options) {
  if (!(this instanceof PassThrough)) return new PassThrough(options);

  Transform.call(this, options);
}

PassThrough.prototype._transform = function (chunk, encoding, cb) {
  cb(null, chunk);
};
},{"./_stream_transform":117,"core-util-is":49,"inherits":94}],116:[function(require,module,exports){
(function (process){
'use strict';

module.exports = Readable;

/*<replacement>*/
var processNextTick = require('process-nextick-args');
/*</replacement>*/

/*<replacement>*/
var isArray = require('isarray');
/*</replacement>*/

/*<replacement>*/
var Duplex;
/*</replacement>*/

Readable.ReadableState = ReadableState;

/*<replacement>*/
var EE = require('events').EventEmitter;

var EElistenerCount = function (emitter, type) {
  return emitter.listeners(type).length;
};
/*</replacement>*/

/*<replacement>*/
var Stream;
(function () {
  try {
    Stream = require('st' + 'ream');
  } catch (_) {} finally {
    if (!Stream) Stream = require('events').EventEmitter;
  }
})();
/*</replacement>*/

var Buffer = require('buffer').Buffer;
/*<replacement>*/
var bufferShim = require('buffer-shims');
/*</replacement>*/

/*<replacement>*/
var util = require('core-util-is');
util.inherits = require('inherits');
/*</replacement>*/

/*<replacement>*/
var debugUtil = require('util');
var debug = void 0;
if (debugUtil && debugUtil.debuglog) {
  debug = debugUtil.debuglog('stream');
} else {
  debug = function () {};
}
/*</replacement>*/

var BufferList = require('./internal/streams/BufferList');
var StringDecoder;

util.inherits(Readable, Stream);

function prependListener(emitter, event, fn) {
  // Sadly this is not cacheable as some libraries bundle their own
  // event emitter implementation with them.
  if (typeof emitter.prependListener === 'function') {
    return emitter.prependListener(event, fn);
  } else {
    // This is a hack to make sure that our error handler is attached before any
    // userland ones.  NEVER DO THIS. This is here only because this code needs
    // to continue to work with older versions of Node.js that do not include
    // the prependListener() method. The goal is to eventually remove this hack.
    if (!emitter._events || !emitter._events[event]) emitter.on(event, fn);else if (isArray(emitter._events[event])) emitter._events[event].unshift(fn);else emitter._events[event] = [fn, emitter._events[event]];
  }
}

function ReadableState(options, stream) {
  Duplex = Duplex || require('./_stream_duplex');

  options = options || {};

  // object stream flag. Used to make read(n) ignore n and to
  // make all the buffer merging and length checks go away
  this.objectMode = !!options.objectMode;

  if (stream instanceof Duplex) this.objectMode = this.objectMode || !!options.readableObjectMode;

  // the point at which it stops calling _read() to fill the buffer
  // Note: 0 is a valid value, means "don't call _read preemptively ever"
  var hwm = options.highWaterMark;
  var defaultHwm = this.objectMode ? 16 : 16 * 1024;
  this.highWaterMark = hwm || hwm === 0 ? hwm : defaultHwm;

  // cast to ints.
  this.highWaterMark = ~ ~this.highWaterMark;

  // A linked list is used to store data chunks instead of an array because the
  // linked list can remove elements from the beginning faster than
  // array.shift()
  this.buffer = new BufferList();
  this.length = 0;
  this.pipes = null;
  this.pipesCount = 0;
  this.flowing = null;
  this.ended = false;
  this.endEmitted = false;
  this.reading = false;

  // a flag to be able to tell if the onwrite cb is called immediately,
  // or on a later tick.  We set this to true at first, because any
  // actions that shouldn't happen until "later" should generally also
  // not happen before the first write call.
  this.sync = true;

  // whenever we return null, then we set a flag to say
  // that we're awaiting a 'readable' event emission.
  this.needReadable = false;
  this.emittedReadable = false;
  this.readableListening = false;
  this.resumeScheduled = false;

  // Crypto is kind of old and crusty.  Historically, its default string
  // encoding is 'binary' so we have to make this configurable.
  // Everything else in the universe uses 'utf8', though.
  this.defaultEncoding = options.defaultEncoding || 'utf8';

  // when piping, we only care about 'readable' events that happen
  // after read()ing all the bytes and not getting any pushback.
  this.ranOut = false;

  // the number of writers that are awaiting a drain event in .pipe()s
  this.awaitDrain = 0;

  // if true, a maybeReadMore has been scheduled
  this.readingMore = false;

  this.decoder = null;
  this.encoding = null;
  if (options.encoding) {
    if (!StringDecoder) StringDecoder = require('string_decoder/').StringDecoder;
    this.decoder = new StringDecoder(options.encoding);
    this.encoding = options.encoding;
  }
}

function Readable(options) {
  Duplex = Duplex || require('./_stream_duplex');

  if (!(this instanceof Readable)) return new Readable(options);

  this._readableState = new ReadableState(options, this);

  // legacy
  this.readable = true;

  if (options && typeof options.read === 'function') this._read = options.read;

  Stream.call(this);
}

// Manually shove something into the read() buffer.
// This returns true if the highWaterMark has not been hit yet,
// similar to how Writable.write() returns true if you should
// write() some more.
Readable.prototype.push = function (chunk, encoding) {
  var state = this._readableState;

  if (!state.objectMode && typeof chunk === 'string') {
    encoding = encoding || state.defaultEncoding;
    if (encoding !== state.encoding) {
      chunk = bufferShim.from(chunk, encoding);
      encoding = '';
    }
  }

  return readableAddChunk(this, state, chunk, encoding, false);
};

// Unshift should *always* be something directly out of read()
Readable.prototype.unshift = function (chunk) {
  var state = this._readableState;
  return readableAddChunk(this, state, chunk, '', true);
};

Readable.prototype.isPaused = function () {
  return this._readableState.flowing === false;
};

function readableAddChunk(stream, state, chunk, encoding, addToFront) {
  var er = chunkInvalid(state, chunk);
  if (er) {
    stream.emit('error', er);
  } else if (chunk === null) {
    state.reading = false;
    onEofChunk(stream, state);
  } else if (state.objectMode || chunk && chunk.length > 0) {
    if (state.ended && !addToFront) {
      var e = new Error('stream.push() after EOF');
      stream.emit('error', e);
    } else if (state.endEmitted && addToFront) {
      var _e = new Error('stream.unshift() after end event');
      stream.emit('error', _e);
    } else {
      var skipAdd;
      if (state.decoder && !addToFront && !encoding) {
        chunk = state.decoder.write(chunk);
        skipAdd = !state.objectMode && chunk.length === 0;
      }

      if (!addToFront) state.reading = false;

      // Don't add to the buffer if we've decoded to an empty string chunk and
      // we're not in object mode
      if (!skipAdd) {
        // if we want the data now, just emit it.
        if (state.flowing && state.length === 0 && !state.sync) {
          stream.emit('data', chunk);
          stream.read(0);
        } else {
          // update the buffer info.
          state.length += state.objectMode ? 1 : chunk.length;
          if (addToFront) state.buffer.unshift(chunk);else state.buffer.push(chunk);

          if (state.needReadable) emitReadable(stream);
        }
      }

      maybeReadMore(stream, state);
    }
  } else if (!addToFront) {
    state.reading = false;
  }

  return needMoreData(state);
}

// if it's past the high water mark, we can push in some more.
// Also, if we have no data yet, we can stand some
// more bytes.  This is to work around cases where hwm=0,
// such as the repl.  Also, if the push() triggered a
// readable event, and the user called read(largeNumber) such that
// needReadable was set, then we ought to push more, so that another
// 'readable' event will be triggered.
function needMoreData(state) {
  return !state.ended && (state.needReadable || state.length < state.highWaterMark || state.length === 0);
}

// backwards compatibility.
Readable.prototype.setEncoding = function (enc) {
  if (!StringDecoder) StringDecoder = require('string_decoder/').StringDecoder;
  this._readableState.decoder = new StringDecoder(enc);
  this._readableState.encoding = enc;
  return this;
};

// Don't raise the hwm > 8MB
var MAX_HWM = 0x800000;
function computeNewHighWaterMark(n) {
  if (n >= MAX_HWM) {
    n = MAX_HWM;
  } else {
    // Get the next highest power of 2 to prevent increasing hwm excessively in
    // tiny amounts
    n--;
    n |= n >>> 1;
    n |= n >>> 2;
    n |= n >>> 4;
    n |= n >>> 8;
    n |= n >>> 16;
    n++;
  }
  return n;
}

// This function is designed to be inlinable, so please take care when making
// changes to the function body.
function howMuchToRead(n, state) {
  if (n <= 0 || state.length === 0 && state.ended) return 0;
  if (state.objectMode) return 1;
  if (n !== n) {
    // Only flow one buffer at a time
    if (state.flowing && state.length) return state.buffer.head.data.length;else return state.length;
  }
  // If we're asking for more than the current hwm, then raise the hwm.
  if (n > state.highWaterMark) state.highWaterMark = computeNewHighWaterMark(n);
  if (n <= state.length) return n;
  // Don't have enough
  if (!state.ended) {
    state.needReadable = true;
    return 0;
  }
  return state.length;
}

// you can override either this method, or the async _read(n) below.
Readable.prototype.read = function (n) {
  debug('read', n);
  n = parseInt(n, 10);
  var state = this._readableState;
  var nOrig = n;

  if (n !== 0) state.emittedReadable = false;

  // if we're doing read(0) to trigger a readable event, but we
  // already have a bunch of data in the buffer, then just trigger
  // the 'readable' event and move on.
  if (n === 0 && state.needReadable && (state.length >= state.highWaterMark || state.ended)) {
    debug('read: emitReadable', state.length, state.ended);
    if (state.length === 0 && state.ended) endReadable(this);else emitReadable(this);
    return null;
  }

  n = howMuchToRead(n, state);

  // if we've ended, and we're now clear, then finish it up.
  if (n === 0 && state.ended) {
    if (state.length === 0) endReadable(this);
    return null;
  }

  // All the actual chunk generation logic needs to be
  // *below* the call to _read.  The reason is that in certain
  // synthetic stream cases, such as passthrough streams, _read
  // may be a completely synchronous operation which may change
  // the state of the read buffer, providing enough data when
  // before there was *not* enough.
  //
  // So, the steps are:
  // 1. Figure out what the state of things will be after we do
  // a read from the buffer.
  //
  // 2. If that resulting state will trigger a _read, then call _read.
  // Note that this may be asynchronous, or synchronous.  Yes, it is
  // deeply ugly to write APIs this way, but that still doesn't mean
  // that the Readable class should behave improperly, as streams are
  // designed to be sync/async agnostic.
  // Take note if the _read call is sync or async (ie, if the read call
  // has returned yet), so that we know whether or not it's safe to emit
  // 'readable' etc.
  //
  // 3. Actually pull the requested chunks out of the buffer and return.

  // if we need a readable event, then we need to do some reading.
  var doRead = state.needReadable;
  debug('need readable', doRead);

  // if we currently have less than the highWaterMark, then also read some
  if (state.length === 0 || state.length - n < state.highWaterMark) {
    doRead = true;
    debug('length less than watermark', doRead);
  }

  // however, if we've ended, then there's no point, and if we're already
  // reading, then it's unnecessary.
  if (state.ended || state.reading) {
    doRead = false;
    debug('reading or ended', doRead);
  } else if (doRead) {
    debug('do read');
    state.reading = true;
    state.sync = true;
    // if the length is currently zero, then we *need* a readable event.
    if (state.length === 0) state.needReadable = true;
    // call internal read method
    this._read(state.highWaterMark);
    state.sync = false;
    // If _read pushed data synchronously, then `reading` will be false,
    // and we need to re-evaluate how much data we can return to the user.
    if (!state.reading) n = howMuchToRead(nOrig, state);
  }

  var ret;
  if (n > 0) ret = fromList(n, state);else ret = null;

  if (ret === null) {
    state.needReadable = true;
    n = 0;
  } else {
    state.length -= n;
  }

  if (state.length === 0) {
    // If we have nothing in the buffer, then we want to know
    // as soon as we *do* get something into the buffer.
    if (!state.ended) state.needReadable = true;

    // If we tried to read() past the EOF, then emit end on the next tick.
    if (nOrig !== n && state.ended) endReadable(this);
  }

  if (ret !== null) this.emit('data', ret);

  return ret;
};

function chunkInvalid(state, chunk) {
  var er = null;
  if (!Buffer.isBuffer(chunk) && typeof chunk !== 'string' && chunk !== null && chunk !== undefined && !state.objectMode) {
    er = new TypeError('Invalid non-string/buffer chunk');
  }
  return er;
}

function onEofChunk(stream, state) {
  if (state.ended) return;
  if (state.decoder) {
    var chunk = state.decoder.end();
    if (chunk && chunk.length) {
      state.buffer.push(chunk);
      state.length += state.objectMode ? 1 : chunk.length;
    }
  }
  state.ended = true;

  // emit 'readable' now to make sure it gets picked up.
  emitReadable(stream);
}

// Don't emit readable right away in sync mode, because this can trigger
// another read() call => stack overflow.  This way, it might trigger
// a nextTick recursion warning, but that's not so bad.
function emitReadable(stream) {
  var state = stream._readableState;
  state.needReadable = false;
  if (!state.emittedReadable) {
    debug('emitReadable', state.flowing);
    state.emittedReadable = true;
    if (state.sync) processNextTick(emitReadable_, stream);else emitReadable_(stream);
  }
}

function emitReadable_(stream) {
  debug('emit readable');
  stream.emit('readable');
  flow(stream);
}

// at this point, the user has presumably seen the 'readable' event,
// and called read() to consume some data.  that may have triggered
// in turn another _read(n) call, in which case reading = true if
// it's in progress.
// However, if we're not ended, or reading, and the length < hwm,
// then go ahead and try to read some more preemptively.
function maybeReadMore(stream, state) {
  if (!state.readingMore) {
    state.readingMore = true;
    processNextTick(maybeReadMore_, stream, state);
  }
}

function maybeReadMore_(stream, state) {
  var len = state.length;
  while (!state.reading && !state.flowing && !state.ended && state.length < state.highWaterMark) {
    debug('maybeReadMore read 0');
    stream.read(0);
    if (len === state.length)
      // didn't get any data, stop spinning.
      break;else len = state.length;
  }
  state.readingMore = false;
}

// abstract method.  to be overridden in specific implementation classes.
// call cb(er, data) where data is <= n in length.
// for virtual (non-string, non-buffer) streams, "length" is somewhat
// arbitrary, and perhaps not very meaningful.
Readable.prototype._read = function (n) {
  this.emit('error', new Error('_read() is not implemented'));
};

Readable.prototype.pipe = function (dest, pipeOpts) {
  var src = this;
  var state = this._readableState;

  switch (state.pipesCount) {
    case 0:
      state.pipes = dest;
      break;
    case 1:
      state.pipes = [state.pipes, dest];
      break;
    default:
      state.pipes.push(dest);
      break;
  }
  state.pipesCount += 1;
  debug('pipe count=%d opts=%j', state.pipesCount, pipeOpts);

  var doEnd = (!pipeOpts || pipeOpts.end !== false) && dest !== process.stdout && dest !== process.stderr;

  var endFn = doEnd ? onend : cleanup;
  if (state.endEmitted) processNextTick(endFn);else src.once('end', endFn);

  dest.on('unpipe', onunpipe);
  function onunpipe(readable) {
    debug('onunpipe');
    if (readable === src) {
      cleanup();
    }
  }

  function onend() {
    debug('onend');
    dest.end();
  }

  // when the dest drains, it reduces the awaitDrain counter
  // on the source.  This would be more elegant with a .once()
  // handler in flow(), but adding and removing repeatedly is
  // too slow.
  var ondrain = pipeOnDrain(src);
  dest.on('drain', ondrain);

  var cleanedUp = false;
  function cleanup() {
    debug('cleanup');
    // cleanup event handlers once the pipe is broken
    dest.removeListener('close', onclose);
    dest.removeListener('finish', onfinish);
    dest.removeListener('drain', ondrain);
    dest.removeListener('error', onerror);
    dest.removeListener('unpipe', onunpipe);
    src.removeListener('end', onend);
    src.removeListener('end', cleanup);
    src.removeListener('data', ondata);

    cleanedUp = true;

    // if the reader is waiting for a drain event from this
    // specific writer, then it would cause it to never start
    // flowing again.
    // So, if this is awaiting a drain, then we just call it now.
    // If we don't know, then assume that we are waiting for one.
    if (state.awaitDrain && (!dest._writableState || dest._writableState.needDrain)) ondrain();
  }

  // If the user pushes more data while we're writing to dest then we'll end up
  // in ondata again. However, we only want to increase awaitDrain once because
  // dest will only emit one 'drain' event for the multiple writes.
  // => Introduce a guard on increasing awaitDrain.
  var increasedAwaitDrain = false;
  src.on('data', ondata);
  function ondata(chunk) {
    debug('ondata');
    increasedAwaitDrain = false;
    var ret = dest.write(chunk);
    if (false === ret && !increasedAwaitDrain) {
      // If the user unpiped during `dest.write()`, it is possible
      // to get stuck in a permanently paused state if that write
      // also returned false.
      // => Check whether `dest` is still a piping destination.
      if ((state.pipesCount === 1 && state.pipes === dest || state.pipesCount > 1 && indexOf(state.pipes, dest) !== -1) && !cleanedUp) {
        debug('false write response, pause', src._readableState.awaitDrain);
        src._readableState.awaitDrain++;
        increasedAwaitDrain = true;
      }
      src.pause();
    }
  }

  // if the dest has an error, then stop piping into it.
  // however, don't suppress the throwing behavior for this.
  function onerror(er) {
    debug('onerror', er);
    unpipe();
    dest.removeListener('error', onerror);
    if (EElistenerCount(dest, 'error') === 0) dest.emit('error', er);
  }

  // Make sure our error handler is attached before userland ones.
  prependListener(dest, 'error', onerror);

  // Both close and finish should trigger unpipe, but only once.
  function onclose() {
    dest.removeListener('finish', onfinish);
    unpipe();
  }
  dest.once('close', onclose);
  function onfinish() {
    debug('onfinish');
    dest.removeListener('close', onclose);
    unpipe();
  }
  dest.once('finish', onfinish);

  function unpipe() {
    debug('unpipe');
    src.unpipe(dest);
  }

  // tell the dest that it's being piped to
  dest.emit('pipe', src);

  // start the flow if it hasn't been started already.
  if (!state.flowing) {
    debug('pipe resume');
    src.resume();
  }

  return dest;
};

function pipeOnDrain(src) {
  return function () {
    var state = src._readableState;
    debug('pipeOnDrain', state.awaitDrain);
    if (state.awaitDrain) state.awaitDrain--;
    if (state.awaitDrain === 0 && EElistenerCount(src, 'data')) {
      state.flowing = true;
      flow(src);
    }
  };
}

Readable.prototype.unpipe = function (dest) {
  var state = this._readableState;

  // if we're not piping anywhere, then do nothing.
  if (state.pipesCount === 0) return this;

  // just one destination.  most common case.
  if (state.pipesCount === 1) {
    // passed in one, but it's not the right one.
    if (dest && dest !== state.pipes) return this;

    if (!dest) dest = state.pipes;

    // got a match.
    state.pipes = null;
    state.pipesCount = 0;
    state.flowing = false;
    if (dest) dest.emit('unpipe', this);
    return this;
  }

  // slow case. multiple pipe destinations.

  if (!dest) {
    // remove all.
    var dests = state.pipes;
    var len = state.pipesCount;
    state.pipes = null;
    state.pipesCount = 0;
    state.flowing = false;

    for (var i = 0; i < len; i++) {
      dests[i].emit('unpipe', this);
    }return this;
  }

  // try to find the right one.
  var index = indexOf(state.pipes, dest);
  if (index === -1) return this;

  state.pipes.splice(index, 1);
  state.pipesCount -= 1;
  if (state.pipesCount === 1) state.pipes = state.pipes[0];

  dest.emit('unpipe', this);

  return this;
};

// set up data events if they are asked for
// Ensure readable listeners eventually get something
Readable.prototype.on = function (ev, fn) {
  var res = Stream.prototype.on.call(this, ev, fn);

  if (ev === 'data') {
    // Start flowing on next tick if stream isn't explicitly paused
    if (this._readableState.flowing !== false) this.resume();
  } else if (ev === 'readable') {
    var state = this._readableState;
    if (!state.endEmitted && !state.readableListening) {
      state.readableListening = state.needReadable = true;
      state.emittedReadable = false;
      if (!state.reading) {
        processNextTick(nReadingNextTick, this);
      } else if (state.length) {
        emitReadable(this, state);
      }
    }
  }

  return res;
};
Readable.prototype.addListener = Readable.prototype.on;

function nReadingNextTick(self) {
  debug('readable nexttick read 0');
  self.read(0);
}

// pause() and resume() are remnants of the legacy readable stream API
// If the user uses them, then switch into old mode.
Readable.prototype.resume = function () {
  var state = this._readableState;
  if (!state.flowing) {
    debug('resume');
    state.flowing = true;
    resume(this, state);
  }
  return this;
};

function resume(stream, state) {
  if (!state.resumeScheduled) {
    state.resumeScheduled = true;
    processNextTick(resume_, stream, state);
  }
}

function resume_(stream, state) {
  if (!state.reading) {
    debug('resume read 0');
    stream.read(0);
  }

  state.resumeScheduled = false;
  state.awaitDrain = 0;
  stream.emit('resume');
  flow(stream);
  if (state.flowing && !state.reading) stream.read(0);
}

Readable.prototype.pause = function () {
  debug('call pause flowing=%j', this._readableState.flowing);
  if (false !== this._readableState.flowing) {
    debug('pause');
    this._readableState.flowing = false;
    this.emit('pause');
  }
  return this;
};

function flow(stream) {
  var state = stream._readableState;
  debug('flow', state.flowing);
  while (state.flowing && stream.read() !== null) {}
}

// wrap an old-style stream as the async data source.
// This is *not* part of the readable stream interface.
// It is an ugly unfortunate mess of history.
Readable.prototype.wrap = function (stream) {
  var state = this._readableState;
  var paused = false;

  var self = this;
  stream.on('end', function () {
    debug('wrapped end');
    if (state.decoder && !state.ended) {
      var chunk = state.decoder.end();
      if (chunk && chunk.length) self.push(chunk);
    }

    self.push(null);
  });

  stream.on('data', function (chunk) {
    debug('wrapped data');
    if (state.decoder) chunk = state.decoder.write(chunk);

    // don't skip over falsy values in objectMode
    if (state.objectMode && (chunk === null || chunk === undefined)) return;else if (!state.objectMode && (!chunk || !chunk.length)) return;

    var ret = self.push(chunk);
    if (!ret) {
      paused = true;
      stream.pause();
    }
  });

  // proxy all the other methods.
  // important when wrapping filters and duplexes.
  for (var i in stream) {
    if (this[i] === undefined && typeof stream[i] === 'function') {
      this[i] = function (method) {
        return function () {
          return stream[method].apply(stream, arguments);
        };
      }(i);
    }
  }

  // proxy certain important events.
  var events = ['error', 'close', 'destroy', 'pause', 'resume'];
  forEach(events, function (ev) {
    stream.on(ev, self.emit.bind(self, ev));
  });

  // when we try to consume some more bytes, simply unpause the
  // underlying stream.
  self._read = function (n) {
    debug('wrapped _read', n);
    if (paused) {
      paused = false;
      stream.resume();
    }
  };

  return self;
};

// exposed for testing purposes only.
Readable._fromList = fromList;

// Pluck off n bytes from an array of buffers.
// Length is the combined lengths of all the buffers in the list.
// This function is designed to be inlinable, so please take care when making
// changes to the function body.
function fromList(n, state) {
  // nothing buffered
  if (state.length === 0) return null;

  var ret;
  if (state.objectMode) ret = state.buffer.shift();else if (!n || n >= state.length) {
    // read it all, truncate the list
    if (state.decoder) ret = state.buffer.join('');else if (state.buffer.length === 1) ret = state.buffer.head.data;else ret = state.buffer.concat(state.length);
    state.buffer.clear();
  } else {
    // read part of list
    ret = fromListPartial(n, state.buffer, state.decoder);
  }

  return ret;
}

// Extracts only enough buffered data to satisfy the amount requested.
// This function is designed to be inlinable, so please take care when making
// changes to the function body.
function fromListPartial(n, list, hasStrings) {
  var ret;
  if (n < list.head.data.length) {
    // slice is the same for buffers and strings
    ret = list.head.data.slice(0, n);
    list.head.data = list.head.data.slice(n);
  } else if (n === list.head.data.length) {
    // first chunk is a perfect match
    ret = list.shift();
  } else {
    // result spans more than one buffer
    ret = hasStrings ? copyFromBufferString(n, list) : copyFromBuffer(n, list);
  }
  return ret;
}

// Copies a specified amount of characters from the list of buffered data
// chunks.
// This function is designed to be inlinable, so please take care when making
// changes to the function body.
function copyFromBufferString(n, list) {
  var p = list.head;
  var c = 1;
  var ret = p.data;
  n -= ret.length;
  while (p = p.next) {
    var str = p.data;
    var nb = n > str.length ? str.length : n;
    if (nb === str.length) ret += str;else ret += str.slice(0, n);
    n -= nb;
    if (n === 0) {
      if (nb === str.length) {
        ++c;
        if (p.next) list.head = p.next;else list.head = list.tail = null;
      } else {
        list.head = p;
        p.data = str.slice(nb);
      }
      break;
    }
    ++c;
  }
  list.length -= c;
  return ret;
}

// Copies a specified amount of bytes from the list of buffered data chunks.
// This function is designed to be inlinable, so please take care when making
// changes to the function body.
function copyFromBuffer(n, list) {
  var ret = bufferShim.allocUnsafe(n);
  var p = list.head;
  var c = 1;
  p.data.copy(ret);
  n -= p.data.length;
  while (p = p.next) {
    var buf = p.data;
    var nb = n > buf.length ? buf.length : n;
    buf.copy(ret, ret.length - n, 0, nb);
    n -= nb;
    if (n === 0) {
      if (nb === buf.length) {
        ++c;
        if (p.next) list.head = p.next;else list.head = list.tail = null;
      } else {
        list.head = p;
        p.data = buf.slice(nb);
      }
      break;
    }
    ++c;
  }
  list.length -= c;
  return ret;
}

function endReadable(stream) {
  var state = stream._readableState;

  // If we get here before consuming all the bytes, then that is a
  // bug in node.  Should never happen.
  if (state.length > 0) throw new Error('"endReadable()" called on non-empty stream');

  if (!state.endEmitted) {
    state.ended = true;
    processNextTick(endReadableNT, state, stream);
  }
}

function endReadableNT(state, stream) {
  // Check that we didn't get one last unshift.
  if (!state.endEmitted && state.length === 0) {
    state.endEmitted = true;
    stream.readable = false;
    stream.emit('end');
  }
}

function forEach(xs, f) {
  for (var i = 0, l = xs.length; i < l; i++) {
    f(xs[i], i);
  }
}

function indexOf(xs, x) {
  for (var i = 0, l = xs.length; i < l; i++) {
    if (xs[i] === x) return i;
  }
  return -1;
}
}).call(this,require('_process'))
},{"./_stream_duplex":114,"./internal/streams/BufferList":119,"_process":105,"buffer":45,"buffer-shims":47,"core-util-is":49,"events":84,"inherits":94,"isarray":120,"process-nextick-args":104,"string_decoder/":134,"util":18}],117:[function(require,module,exports){
// a transform stream is a readable/writable stream where you do
// something with the data.  Sometimes it's called a "filter",
// but that's not a great name for it, since that implies a thing where
// some bits pass through, and others are simply ignored.  (That would
// be a valid example of a transform, of course.)
//
// While the output is causally related to the input, it's not a
// necessarily symmetric or synchronous transformation.  For example,
// a zlib stream might take multiple plain-text writes(), and then
// emit a single compressed chunk some time in the future.
//
// Here's how this works:
//
// The Transform stream has all the aspects of the readable and writable
// stream classes.  When you write(chunk), that calls _write(chunk,cb)
// internally, and returns false if there's a lot of pending writes
// buffered up.  When you call read(), that calls _read(n) until
// there's enough pending readable data buffered up.
//
// In a transform stream, the written data is placed in a buffer.  When
// _read(n) is called, it transforms the queued up data, calling the
// buffered _write cb's as it consumes chunks.  If consuming a single
// written chunk would result in multiple output chunks, then the first
// outputted bit calls the readcb, and subsequent chunks just go into
// the read buffer, and will cause it to emit 'readable' if necessary.
//
// This way, back-pressure is actually determined by the reading side,
// since _read has to be called to start processing a new chunk.  However,
// a pathological inflate type of transform can cause excessive buffering
// here.  For example, imagine a stream where every byte of input is
// interpreted as an integer from 0-255, and then results in that many
// bytes of output.  Writing the 4 bytes {ff,ff,ff,ff} would result in
// 1kb of data being output.  In this case, you could write a very small
// amount of input, and end up with a very large amount of output.  In
// such a pathological inflating mechanism, there'd be no way to tell
// the system to stop doing the transform.  A single 4MB write could
// cause the system to run out of memory.
//
// However, even in such a pathological case, only a single written chunk
// would be consumed, and then the rest would wait (un-transformed) until
// the results of the previous transformed chunk were consumed.

'use strict';

module.exports = Transform;

var Duplex = require('./_stream_duplex');

/*<replacement>*/
var util = require('core-util-is');
util.inherits = require('inherits');
/*</replacement>*/

util.inherits(Transform, Duplex);

function TransformState(stream) {
  this.afterTransform = function (er, data) {
    return afterTransform(stream, er, data);
  };

  this.needTransform = false;
  this.transforming = false;
  this.writecb = null;
  this.writechunk = null;
  this.writeencoding = null;
}

function afterTransform(stream, er, data) {
  var ts = stream._transformState;
  ts.transforming = false;

  var cb = ts.writecb;

  if (!cb) return stream.emit('error', new Error('no writecb in Transform class'));

  ts.writechunk = null;
  ts.writecb = null;

  if (data !== null && data !== undefined) stream.push(data);

  cb(er);

  var rs = stream._readableState;
  rs.reading = false;
  if (rs.needReadable || rs.length < rs.highWaterMark) {
    stream._read(rs.highWaterMark);
  }
}

function Transform(options) {
  if (!(this instanceof Transform)) return new Transform(options);

  Duplex.call(this, options);

  this._transformState = new TransformState(this);

  var stream = this;

  // start out asking for a readable event once data is transformed.
  this._readableState.needReadable = true;

  // we have implemented the _read method, and done the other things
  // that Readable wants before the first _read call, so unset the
  // sync guard flag.
  this._readableState.sync = false;

  if (options) {
    if (typeof options.transform === 'function') this._transform = options.transform;

    if (typeof options.flush === 'function') this._flush = options.flush;
  }

  // When the writable side finishes, then flush out anything remaining.
  this.once('prefinish', function () {
    if (typeof this._flush === 'function') this._flush(function (er, data) {
      done(stream, er, data);
    });else done(stream);
  });
}

Transform.prototype.push = function (chunk, encoding) {
  this._transformState.needTransform = false;
  return Duplex.prototype.push.call(this, chunk, encoding);
};

// This is the part where you do stuff!
// override this function in implementation classes.
// 'chunk' is an input chunk.
//
// Call `push(newChunk)` to pass along transformed output
// to the readable side.  You may call 'push' zero or more times.
//
// Call `cb(err)` when you are done with this chunk.  If you pass
// an error, then that'll put the hurt on the whole operation.  If you
// never call cb(), then you'll never get another chunk.
Transform.prototype._transform = function (chunk, encoding, cb) {
  throw new Error('_transform() is not implemented');
};

Transform.prototype._write = function (chunk, encoding, cb) {
  var ts = this._transformState;
  ts.writecb = cb;
  ts.writechunk = chunk;
  ts.writeencoding = encoding;
  if (!ts.transforming) {
    var rs = this._readableState;
    if (ts.needTransform || rs.needReadable || rs.length < rs.highWaterMark) this._read(rs.highWaterMark);
  }
};

// Doesn't matter what the args are here.
// _transform does all the work.
// That we got here means that the readable side wants more data.
Transform.prototype._read = function (n) {
  var ts = this._transformState;

  if (ts.writechunk !== null && ts.writecb && !ts.transforming) {
    ts.transforming = true;
    this._transform(ts.writechunk, ts.writeencoding, ts.afterTransform);
  } else {
    // mark that we need a transform, so that any data that comes in
    // will get processed, now that we've asked for it.
    ts.needTransform = true;
  }
};

function done(stream, er, data) {
  if (er) return stream.emit('error', er);

  if (data !== null && data !== undefined) stream.push(data);

  // if there's nothing in the write buffer, then that means
  // that nothing more will ever be provided
  var ws = stream._writableState;
  var ts = stream._transformState;

  if (ws.length) throw new Error('Calling transform done when ws.length != 0');

  if (ts.transforming) throw new Error('Calling transform done when still transforming');

  return stream.push(null);
}
},{"./_stream_duplex":114,"core-util-is":49,"inherits":94}],118:[function(require,module,exports){
(function (process){
// A bit simpler than readable streams.
// Implement an async ._write(chunk, encoding, cb), and it'll handle all
// the drain event emission and buffering.

'use strict';

module.exports = Writable;

/*<replacement>*/
var processNextTick = require('process-nextick-args');
/*</replacement>*/

/*<replacement>*/
var asyncWrite = !process.browser && ['v0.10', 'v0.9.'].indexOf(process.version.slice(0, 5)) > -1 ? setImmediate : processNextTick;
/*</replacement>*/

/*<replacement>*/
var Duplex;
/*</replacement>*/

Writable.WritableState = WritableState;

/*<replacement>*/
var util = require('core-util-is');
util.inherits = require('inherits');
/*</replacement>*/

/*<replacement>*/
var internalUtil = {
  deprecate: require('util-deprecate')
};
/*</replacement>*/

/*<replacement>*/
var Stream;
(function () {
  try {
    Stream = require('st' + 'ream');
  } catch (_) {} finally {
    if (!Stream) Stream = require('events').EventEmitter;
  }
})();
/*</replacement>*/

var Buffer = require('buffer').Buffer;
/*<replacement>*/
var bufferShim = require('buffer-shims');
/*</replacement>*/

util.inherits(Writable, Stream);

function nop() {}

function WriteReq(chunk, encoding, cb) {
  this.chunk = chunk;
  this.encoding = encoding;
  this.callback = cb;
  this.next = null;
}

function WritableState(options, stream) {
  Duplex = Duplex || require('./_stream_duplex');

  options = options || {};

  // object stream flag to indicate whether or not this stream
  // contains buffers or objects.
  this.objectMode = !!options.objectMode;

  if (stream instanceof Duplex) this.objectMode = this.objectMode || !!options.writableObjectMode;

  // the point at which write() starts returning false
  // Note: 0 is a valid value, means that we always return false if
  // the entire buffer is not flushed immediately on write()
  var hwm = options.highWaterMark;
  var defaultHwm = this.objectMode ? 16 : 16 * 1024;
  this.highWaterMark = hwm || hwm === 0 ? hwm : defaultHwm;

  // cast to ints.
  this.highWaterMark = ~ ~this.highWaterMark;

  // drain event flag.
  this.needDrain = false;
  // at the start of calling end()
  this.ending = false;
  // when end() has been called, and returned
  this.ended = false;
  // when 'finish' is emitted
  this.finished = false;

  // should we decode strings into buffers before passing to _write?
  // this is here so that some node-core streams can optimize string
  // handling at a lower level.
  var noDecode = options.decodeStrings === false;
  this.decodeStrings = !noDecode;

  // Crypto is kind of old and crusty.  Historically, its default string
  // encoding is 'binary' so we have to make this configurable.
  // Everything else in the universe uses 'utf8', though.
  this.defaultEncoding = options.defaultEncoding || 'utf8';

  // not an actual buffer we keep track of, but a measurement
  // of how much we're waiting to get pushed to some underlying
  // socket or file.
  this.length = 0;

  // a flag to see when we're in the middle of a write.
  this.writing = false;

  // when true all writes will be buffered until .uncork() call
  this.corked = 0;

  // a flag to be able to tell if the onwrite cb is called immediately,
  // or on a later tick.  We set this to true at first, because any
  // actions that shouldn't happen until "later" should generally also
  // not happen before the first write call.
  this.sync = true;

  // a flag to know if we're processing previously buffered items, which
  // may call the _write() callback in the same tick, so that we don't
  // end up in an overlapped onwrite situation.
  this.bufferProcessing = false;

  // the callback that's passed to _write(chunk,cb)
  this.onwrite = function (er) {
    onwrite(stream, er);
  };

  // the callback that the user supplies to write(chunk,encoding,cb)
  this.writecb = null;

  // the amount that is being written when _write is called.
  this.writelen = 0;

  this.bufferedRequest = null;
  this.lastBufferedRequest = null;

  // number of pending user-supplied write callbacks
  // this must be 0 before 'finish' can be emitted
  this.pendingcb = 0;

  // emit prefinish if the only thing we're waiting for is _write cbs
  // This is relevant for synchronous Transform streams
  this.prefinished = false;

  // True if the error was already emitted and should not be thrown again
  this.errorEmitted = false;

  // count buffered requests
  this.bufferedRequestCount = 0;

  // allocate the first CorkedRequest, there is always
  // one allocated and free to use, and we maintain at most two
  this.corkedRequestsFree = new CorkedRequest(this);
}

WritableState.prototype.getBuffer = function getBuffer() {
  var current = this.bufferedRequest;
  var out = [];
  while (current) {
    out.push(current);
    current = current.next;
  }
  return out;
};

(function () {
  try {
    Object.defineProperty(WritableState.prototype, 'buffer', {
      get: internalUtil.deprecate(function () {
        return this.getBuffer();
      }, '_writableState.buffer is deprecated. Use _writableState.getBuffer ' + 'instead.')
    });
  } catch (_) {}
})();

// Test _writableState for inheritance to account for Duplex streams,
// whose prototype chain only points to Readable.
var realHasInstance;
if (typeof Symbol === 'function' && Symbol.hasInstance && typeof Function.prototype[Symbol.hasInstance] === 'function') {
  realHasInstance = Function.prototype[Symbol.hasInstance];
  Object.defineProperty(Writable, Symbol.hasInstance, {
    value: function (object) {
      if (realHasInstance.call(this, object)) return true;

      return object && object._writableState instanceof WritableState;
    }
  });
} else {
  realHasInstance = function (object) {
    return object instanceof this;
  };
}

function Writable(options) {
  Duplex = Duplex || require('./_stream_duplex');

  // Writable ctor is applied to Duplexes, too.
  // `realHasInstance` is necessary because using plain `instanceof`
  // would return false, as no `_writableState` property is attached.

  // Trying to use the custom `instanceof` for Writable here will also break the
  // Node.js LazyTransform implementation, which has a non-trivial getter for
  // `_writableState` that would lead to infinite recursion.
  if (!realHasInstance.call(Writable, this) && !(this instanceof Duplex)) {
    return new Writable(options);
  }

  this._writableState = new WritableState(options, this);

  // legacy.
  this.writable = true;

  if (options) {
    if (typeof options.write === 'function') this._write = options.write;

    if (typeof options.writev === 'function') this._writev = options.writev;
  }

  Stream.call(this);
}

// Otherwise people can pipe Writable streams, which is just wrong.
Writable.prototype.pipe = function () {
  this.emit('error', new Error('Cannot pipe, not readable'));
};

function writeAfterEnd(stream, cb) {
  var er = new Error('write after end');
  // TODO: defer error events consistently everywhere, not just the cb
  stream.emit('error', er);
  processNextTick(cb, er);
}

// If we get something that is not a buffer, string, null, or undefined,
// and we're not in objectMode, then that's an error.
// Otherwise stream chunks are all considered to be of length=1, and the
// watermarks determine how many objects to keep in the buffer, rather than
// how many bytes or characters.
function validChunk(stream, state, chunk, cb) {
  var valid = true;
  var er = false;
  // Always throw error if a null is written
  // if we are not in object mode then throw
  // if it is not a buffer, string, or undefined.
  if (chunk === null) {
    er = new TypeError('May not write null values to stream');
  } else if (!Buffer.isBuffer(chunk) && typeof chunk !== 'string' && chunk !== undefined && !state.objectMode) {
    er = new TypeError('Invalid non-string/buffer chunk');
  }
  if (er) {
    stream.emit('error', er);
    processNextTick(cb, er);
    valid = false;
  }
  return valid;
}

Writable.prototype.write = function (chunk, encoding, cb) {
  var state = this._writableState;
  var ret = false;

  if (typeof encoding === 'function') {
    cb = encoding;
    encoding = null;
  }

  if (Buffer.isBuffer(chunk)) encoding = 'buffer';else if (!encoding) encoding = state.defaultEncoding;

  if (typeof cb !== 'function') cb = nop;

  if (state.ended) writeAfterEnd(this, cb);else if (validChunk(this, state, chunk, cb)) {
    state.pendingcb++;
    ret = writeOrBuffer(this, state, chunk, encoding, cb);
  }

  return ret;
};

Writable.prototype.cork = function () {
  var state = this._writableState;

  state.corked++;
};

Writable.prototype.uncork = function () {
  var state = this._writableState;

  if (state.corked) {
    state.corked--;

    if (!state.writing && !state.corked && !state.finished && !state.bufferProcessing && state.bufferedRequest) clearBuffer(this, state);
  }
};

Writable.prototype.setDefaultEncoding = function setDefaultEncoding(encoding) {
  // node::ParseEncoding() requires lower case.
  if (typeof encoding === 'string') encoding = encoding.toLowerCase();
  if (!(['hex', 'utf8', 'utf-8', 'ascii', 'binary', 'base64', 'ucs2', 'ucs-2', 'utf16le', 'utf-16le', 'raw'].indexOf((encoding + '').toLowerCase()) > -1)) throw new TypeError('Unknown encoding: ' + encoding);
  this._writableState.defaultEncoding = encoding;
  return this;
};

function decodeChunk(state, chunk, encoding) {
  if (!state.objectMode && state.decodeStrings !== false && typeof chunk === 'string') {
    chunk = bufferShim.from(chunk, encoding);
  }
  return chunk;
}

// if we're already writing something, then just put this
// in the queue, and wait our turn.  Otherwise, call _write
// If we return false, then we need a drain event, so set that flag.
function writeOrBuffer(stream, state, chunk, encoding, cb) {
  chunk = decodeChunk(state, chunk, encoding);

  if (Buffer.isBuffer(chunk)) encoding = 'buffer';
  var len = state.objectMode ? 1 : chunk.length;

  state.length += len;

  var ret = state.length < state.highWaterMark;
  // we must ensure that previous needDrain will not be reset to false.
  if (!ret) state.needDrain = true;

  if (state.writing || state.corked) {
    var last = state.lastBufferedRequest;
    state.lastBufferedRequest = new WriteReq(chunk, encoding, cb);
    if (last) {
      last.next = state.lastBufferedRequest;
    } else {
      state.bufferedRequest = state.lastBufferedRequest;
    }
    state.bufferedRequestCount += 1;
  } else {
    doWrite(stream, state, false, len, chunk, encoding, cb);
  }

  return ret;
}

function doWrite(stream, state, writev, len, chunk, encoding, cb) {
  state.writelen = len;
  state.writecb = cb;
  state.writing = true;
  state.sync = true;
  if (writev) stream._writev(chunk, state.onwrite);else stream._write(chunk, encoding, state.onwrite);
  state.sync = false;
}

function onwriteError(stream, state, sync, er, cb) {
  --state.pendingcb;
  if (sync) processNextTick(cb, er);else cb(er);

  stream._writableState.errorEmitted = true;
  stream.emit('error', er);
}

function onwriteStateUpdate(state) {
  state.writing = false;
  state.writecb = null;
  state.length -= state.writelen;
  state.writelen = 0;
}

function onwrite(stream, er) {
  var state = stream._writableState;
  var sync = state.sync;
  var cb = state.writecb;

  onwriteStateUpdate(state);

  if (er) onwriteError(stream, state, sync, er, cb);else {
    // Check if we're actually ready to finish, but don't emit yet
    var finished = needFinish(state);

    if (!finished && !state.corked && !state.bufferProcessing && state.bufferedRequest) {
      clearBuffer(stream, state);
    }

    if (sync) {
      /*<replacement>*/
      asyncWrite(afterWrite, stream, state, finished, cb);
      /*</replacement>*/
    } else {
        afterWrite(stream, state, finished, cb);
      }
  }
}

function afterWrite(stream, state, finished, cb) {
  if (!finished) onwriteDrain(stream, state);
  state.pendingcb--;
  cb();
  finishMaybe(stream, state);
}

// Must force callback to be called on nextTick, so that we don't
// emit 'drain' before the write() consumer gets the 'false' return
// value, and has a chance to attach a 'drain' listener.
function onwriteDrain(stream, state) {
  if (state.length === 0 && state.needDrain) {
    state.needDrain = false;
    stream.emit('drain');
  }
}

// if there's something in the buffer waiting, then process it
function clearBuffer(stream, state) {
  state.bufferProcessing = true;
  var entry = state.bufferedRequest;

  if (stream._writev && entry && entry.next) {
    // Fast case, write everything using _writev()
    var l = state.bufferedRequestCount;
    var buffer = new Array(l);
    var holder = state.corkedRequestsFree;
    holder.entry = entry;

    var count = 0;
    while (entry) {
      buffer[count] = entry;
      entry = entry.next;
      count += 1;
    }

    doWrite(stream, state, true, state.length, buffer, '', holder.finish);

    // doWrite is almost always async, defer these to save a bit of time
    // as the hot path ends with doWrite
    state.pendingcb++;
    state.lastBufferedRequest = null;
    if (holder.next) {
      state.corkedRequestsFree = holder.next;
      holder.next = null;
    } else {
      state.corkedRequestsFree = new CorkedRequest(state);
    }
  } else {
    // Slow case, write chunks one-by-one
    while (entry) {
      var chunk = entry.chunk;
      var encoding = entry.encoding;
      var cb = entry.callback;
      var len = state.objectMode ? 1 : chunk.length;

      doWrite(stream, state, false, len, chunk, encoding, cb);
      entry = entry.next;
      // if we didn't call the onwrite immediately, then
      // it means that we need to wait until it does.
      // also, that means that the chunk and cb are currently
      // being processed, so move the buffer counter past them.
      if (state.writing) {
        break;
      }
    }

    if (entry === null) state.lastBufferedRequest = null;
  }

  state.bufferedRequestCount = 0;
  state.bufferedRequest = entry;
  state.bufferProcessing = false;
}

Writable.prototype._write = function (chunk, encoding, cb) {
  cb(new Error('_write() is not implemented'));
};

Writable.prototype._writev = null;

Writable.prototype.end = function (chunk, encoding, cb) {
  var state = this._writableState;

  if (typeof chunk === 'function') {
    cb = chunk;
    chunk = null;
    encoding = null;
  } else if (typeof encoding === 'function') {
    cb = encoding;
    encoding = null;
  }

  if (chunk !== null && chunk !== undefined) this.write(chunk, encoding);

  // .end() fully uncorks
  if (state.corked) {
    state.corked = 1;
    this.uncork();
  }

  // ignore unnecessary end() calls.
  if (!state.ending && !state.finished) endWritable(this, state, cb);
};

function needFinish(state) {
  return state.ending && state.length === 0 && state.bufferedRequest === null && !state.finished && !state.writing;
}

function prefinish(stream, state) {
  if (!state.prefinished) {
    state.prefinished = true;
    stream.emit('prefinish');
  }
}

function finishMaybe(stream, state) {
  var need = needFinish(state);
  if (need) {
    if (state.pendingcb === 0) {
      prefinish(stream, state);
      state.finished = true;
      stream.emit('finish');
    } else {
      prefinish(stream, state);
    }
  }
  return need;
}

function endWritable(stream, state, cb) {
  state.ending = true;
  finishMaybe(stream, state);
  if (cb) {
    if (state.finished) processNextTick(cb);else stream.once('finish', cb);
  }
  state.ended = true;
  stream.writable = false;
}

// It seems a linked list but it is not
// there will be only 2 of these for each stream
function CorkedRequest(state) {
  var _this = this;

  this.next = null;
  this.entry = null;

  this.finish = function (err) {
    var entry = _this.entry;
    _this.entry = null;
    while (entry) {
      var cb = entry.callback;
      state.pendingcb--;
      cb(err);
      entry = entry.next;
    }
    if (state.corkedRequestsFree) {
      state.corkedRequestsFree.next = _this;
    } else {
      state.corkedRequestsFree = _this;
    }
  };
}
}).call(this,require('_process'))
},{"./_stream_duplex":114,"_process":105,"buffer":45,"buffer-shims":47,"core-util-is":49,"events":84,"inherits":94,"process-nextick-args":104,"util-deprecate":135}],119:[function(require,module,exports){
'use strict';

var Buffer = require('buffer').Buffer;
/*<replacement>*/
var bufferShim = require('buffer-shims');
/*</replacement>*/

module.exports = BufferList;

function BufferList() {
  this.head = null;
  this.tail = null;
  this.length = 0;
}

BufferList.prototype.push = function (v) {
  var entry = { data: v, next: null };
  if (this.length > 0) this.tail.next = entry;else this.head = entry;
  this.tail = entry;
  ++this.length;
};

BufferList.prototype.unshift = function (v) {
  var entry = { data: v, next: this.head };
  if (this.length === 0) this.tail = entry;
  this.head = entry;
  ++this.length;
};

BufferList.prototype.shift = function () {
  if (this.length === 0) return;
  var ret = this.head.data;
  if (this.length === 1) this.head = this.tail = null;else this.head = this.head.next;
  --this.length;
  return ret;
};

BufferList.prototype.clear = function () {
  this.head = this.tail = null;
  this.length = 0;
};

BufferList.prototype.join = function (s) {
  if (this.length === 0) return '';
  var p = this.head;
  var ret = '' + p.data;
  while (p = p.next) {
    ret += s + p.data;
  }return ret;
};

BufferList.prototype.concat = function (n) {
  if (this.length === 0) return bufferShim.alloc(0);
  if (this.length === 1) return this.head.data;
  var ret = bufferShim.allocUnsafe(n >>> 0);
  var p = this.head;
  var i = 0;
  while (p) {
    p.data.copy(ret, i);
    i += p.data.length;
    p = p.next;
  }
  return ret;
};
},{"buffer":45,"buffer-shims":47}],120:[function(require,module,exports){
arguments[4][46][0].apply(exports,arguments)
},{"dup":46}],121:[function(require,module,exports){
module.exports = require("./lib/_stream_passthrough.js")

},{"./lib/_stream_passthrough.js":115}],122:[function(require,module,exports){
(function (process){
var Stream = (function (){
  try {
    return require('st' + 'ream'); // hack to fix a circular dependency issue when used with browserify
  } catch(_){}
}());
exports = module.exports = require('./lib/_stream_readable.js');
exports.Stream = Stream || exports;
exports.Readable = exports;
exports.Writable = require('./lib/_stream_writable.js');
exports.Duplex = require('./lib/_stream_duplex.js');
exports.Transform = require('./lib/_stream_transform.js');
exports.PassThrough = require('./lib/_stream_passthrough.js');

if (!process.browser && process.env.READABLE_STREAM === 'disable' && Stream) {
  module.exports = Stream;
}

}).call(this,require('_process'))
},{"./lib/_stream_duplex.js":114,"./lib/_stream_passthrough.js":115,"./lib/_stream_readable.js":116,"./lib/_stream_transform.js":117,"./lib/_stream_writable.js":118,"_process":105}],123:[function(require,module,exports){
module.exports = require("./lib/_stream_transform.js")

},{"./lib/_stream_transform.js":117}],124:[function(require,module,exports){
module.exports = require("./lib/_stream_writable.js")

},{"./lib/_stream_writable.js":118}],125:[function(require,module,exports){
(function (Buffer){
// prototype class for hash functions
function Hash (blockSize, finalSize) {
  this._block = new Buffer(blockSize)
  this._finalSize = finalSize
  this._blockSize = blockSize
  this._len = 0
  this._s = 0
}

Hash.prototype.update = function (data, enc) {
  if (typeof data === 'string') {
    enc = enc || 'utf8'
    data = new Buffer(data, enc)
  }

  var l = this._len += data.length
  var s = this._s || 0
  var f = 0
  var buffer = this._block

  while (s < l) {
    var t = Math.min(data.length, f + this._blockSize - (s % this._blockSize))
    var ch = (t - f)

    for (var i = 0; i < ch; i++) {
      buffer[(s % this._blockSize) + i] = data[i + f]
    }

    s += ch
    f += ch

    if ((s % this._blockSize) === 0) {
      this._update(buffer)
    }
  }
  this._s = s

  return this
}

Hash.prototype.digest = function (enc) {
  // Suppose the length of the message M, in bits, is l
  var l = this._len * 8

  // Append the bit 1 to the end of the message
  this._block[this._len % this._blockSize] = 0x80

  // and then k zero bits, where k is the smallest non-negative solution to the equation (l + 1 + k) === finalSize mod blockSize
  this._block.fill(0, this._len % this._blockSize + 1)

  if (l % (this._blockSize * 8) >= this._finalSize * 8) {
    this._update(this._block)
    this._block.fill(0)
  }

  // to this append the block which is equal to the number l written in binary
  // TODO: handle case where l is > Math.pow(2, 29)
  this._block.writeInt32BE(l, this._blockSize - 4)

  var hash = this._update(this._block) || this._hash()

  return enc ? hash.toString(enc) : hash
}

Hash.prototype._update = function () {
  throw new Error('_update must be implemented by subclass')
}

module.exports = Hash

}).call(this,require("buffer").Buffer)
},{"buffer":45}],126:[function(require,module,exports){
var exports = module.exports = function SHA (algorithm) {
  algorithm = algorithm.toLowerCase()

  var Algorithm = exports[algorithm]
  if (!Algorithm) throw new Error(algorithm + ' is not supported (we accept pull requests)')

  return new Algorithm()
}

exports.sha = require('./sha')
exports.sha1 = require('./sha1')
exports.sha224 = require('./sha224')
exports.sha256 = require('./sha256')
exports.sha384 = require('./sha384')
exports.sha512 = require('./sha512')

},{"./sha":127,"./sha1":128,"./sha224":129,"./sha256":130,"./sha384":131,"./sha512":132}],127:[function(require,module,exports){
(function (Buffer){
/*
 * A JavaScript implementation of the Secure Hash Algorithm, SHA-0, as defined
 * in FIPS PUB 180-1
 * This source code is derived from sha1.js of the same repository.
 * The difference between SHA-0 and SHA-1 is just a bitwise rotate left
 * operation was added.
 */

var inherits = require('inherits')
var Hash = require('./hash')

var K = [
  0x5a827999, 0x6ed9eba1, 0x8f1bbcdc | 0, 0xca62c1d6 | 0
]

var W = new Array(80)

function Sha () {
  this.init()
  this._w = W

  Hash.call(this, 64, 56)
}

inherits(Sha, Hash)

Sha.prototype.init = function () {
  this._a = 0x67452301
  this._b = 0xefcdab89
  this._c = 0x98badcfe
  this._d = 0x10325476
  this._e = 0xc3d2e1f0

  return this
}

function rotl5 (num) {
  return (num << 5) | (num >>> 27)
}

function rotl30 (num) {
  return (num << 30) | (num >>> 2)
}

function ft (s, b, c, d) {
  if (s === 0) return (b & c) | ((~b) & d)
  if (s === 2) return (b & c) | (b & d) | (c & d)
  return b ^ c ^ d
}

Sha.prototype._update = function (M) {
  var W = this._w

  var a = this._a | 0
  var b = this._b | 0
  var c = this._c | 0
  var d = this._d | 0
  var e = this._e | 0

  for (var i = 0; i < 16; ++i) W[i] = M.readInt32BE(i * 4)
  for (; i < 80; ++i) W[i] = W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16]

  for (var j = 0; j < 80; ++j) {
    var s = ~~(j / 20)
    var t = (rotl5(a) + ft(s, b, c, d) + e + W[j] + K[s]) | 0

    e = d
    d = c
    c = rotl30(b)
    b = a
    a = t
  }

  this._a = (a + this._a) | 0
  this._b = (b + this._b) | 0
  this._c = (c + this._c) | 0
  this._d = (d + this._d) | 0
  this._e = (e + this._e) | 0
}

Sha.prototype._hash = function () {
  var H = new Buffer(20)

  H.writeInt32BE(this._a | 0, 0)
  H.writeInt32BE(this._b | 0, 4)
  H.writeInt32BE(this._c | 0, 8)
  H.writeInt32BE(this._d | 0, 12)
  H.writeInt32BE(this._e | 0, 16)

  return H
}

module.exports = Sha

}).call(this,require("buffer").Buffer)
},{"./hash":125,"buffer":45,"inherits":94}],128:[function(require,module,exports){
(function (Buffer){
/*
 * A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined
 * in FIPS PUB 180-1
 * Version 2.1a Copyright Paul Johnston 2000 - 2002.
 * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
 * Distributed under the BSD License
 * See http://pajhome.org.uk/crypt/md5 for details.
 */

var inherits = require('inherits')
var Hash = require('./hash')

var K = [
  0x5a827999, 0x6ed9eba1, 0x8f1bbcdc | 0, 0xca62c1d6 | 0
]

var W = new Array(80)

function Sha1 () {
  this.init()
  this._w = W

  Hash.call(this, 64, 56)
}

inherits(Sha1, Hash)

Sha1.prototype.init = function () {
  this._a = 0x67452301
  this._b = 0xefcdab89
  this._c = 0x98badcfe
  this._d = 0x10325476
  this._e = 0xc3d2e1f0

  return this
}

function rotl1 (num) {
  return (num << 1) | (num >>> 31)
}

function rotl5 (num) {
  return (num << 5) | (num >>> 27)
}

function rotl30 (num) {
  return (num << 30) | (num >>> 2)
}

function ft (s, b, c, d) {
  if (s === 0) return (b & c) | ((~b) & d)
  if (s === 2) return (b & c) | (b & d) | (c & d)
  return b ^ c ^ d
}

Sha1.prototype._update = function (M) {
  var W = this._w

  var a = this._a | 0
  var b = this._b | 0
  var c = this._c | 0
  var d = this._d | 0
  var e = this._e | 0

  for (var i = 0; i < 16; ++i) W[i] = M.readInt32BE(i * 4)
  for (; i < 80; ++i) W[i] = rotl1(W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16])

  for (var j = 0; j < 80; ++j) {
    var s = ~~(j / 20)
    var t = (rotl5(a) + ft(s, b, c, d) + e + W[j] + K[s]) | 0

    e = d
    d = c
    c = rotl30(b)
    b = a
    a = t
  }

  this._a = (a + this._a) | 0
  this._b = (b + this._b) | 0
  this._c = (c + this._c) | 0
  this._d = (d + this._d) | 0
  this._e = (e + this._e) | 0
}

Sha1.prototype._hash = function () {
  var H = new Buffer(20)

  H.writeInt32BE(this._a | 0, 0)
  H.writeInt32BE(this._b | 0, 4)
  H.writeInt32BE(this._c | 0, 8)
  H.writeInt32BE(this._d | 0, 12)
  H.writeInt32BE(this._e | 0, 16)

  return H
}

module.exports = Sha1

}).call(this,require("buffer").Buffer)
},{"./hash":125,"buffer":45,"inherits":94}],129:[function(require,module,exports){
(function (Buffer){
/**
 * A JavaScript implementation of the Secure Hash Algorithm, SHA-256, as defined
 * in FIPS 180-2
 * Version 2.2-beta Copyright Angel Marin, Paul Johnston 2000 - 2009.
 * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
 *
 */

var inherits = require('inherits')
var Sha256 = require('./sha256')
var Hash = require('./hash')

var W = new Array(64)

function Sha224 () {
  this.init()

  this._w = W // new Array(64)

  Hash.call(this, 64, 56)
}

inherits(Sha224, Sha256)

Sha224.prototype.init = function () {
  this._a = 0xc1059ed8
  this._b = 0x367cd507
  this._c = 0x3070dd17
  this._d = 0xf70e5939
  this._e = 0xffc00b31
  this._f = 0x68581511
  this._g = 0x64f98fa7
  this._h = 0xbefa4fa4

  return this
}

Sha224.prototype._hash = function () {
  var H = new Buffer(28)

  H.writeInt32BE(this._a, 0)
  H.writeInt32BE(this._b, 4)
  H.writeInt32BE(this._c, 8)
  H.writeInt32BE(this._d, 12)
  H.writeInt32BE(this._e, 16)
  H.writeInt32BE(this._f, 20)
  H.writeInt32BE(this._g, 24)

  return H
}

module.exports = Sha224

}).call(this,require("buffer").Buffer)
},{"./hash":125,"./sha256":130,"buffer":45,"inherits":94}],130:[function(require,module,exports){
(function (Buffer){
/**
 * A JavaScript implementation of the Secure Hash Algorithm, SHA-256, as defined
 * in FIPS 180-2
 * Version 2.2-beta Copyright Angel Marin, Paul Johnston 2000 - 2009.
 * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
 *
 */

var inherits = require('inherits')
var Hash = require('./hash')

var K = [
  0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5,
  0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5,
  0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3,
  0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174,
  0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC,
  0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA,
  0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7,
  0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967,
  0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13,
  0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85,
  0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3,
  0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070,
  0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5,
  0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3,
  0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208,
  0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2
]

var W = new Array(64)

function Sha256 () {
  this.init()

  this._w = W // new Array(64)

  Hash.call(this, 64, 56)
}

inherits(Sha256, Hash)

Sha256.prototype.init = function () {
  this._a = 0x6a09e667
  this._b = 0xbb67ae85
  this._c = 0x3c6ef372
  this._d = 0xa54ff53a
  this._e = 0x510e527f
  this._f = 0x9b05688c
  this._g = 0x1f83d9ab
  this._h = 0x5be0cd19

  return this
}

function ch (x, y, z) {
  return z ^ (x & (y ^ z))
}

function maj (x, y, z) {
  return (x & y) | (z & (x | y))
}

function sigma0 (x) {
  return (x >>> 2 | x << 30) ^ (x >>> 13 | x << 19) ^ (x >>> 22 | x << 10)
}

function sigma1 (x) {
  return (x >>> 6 | x << 26) ^ (x >>> 11 | x << 21) ^ (x >>> 25 | x << 7)
}

function gamma0 (x) {
  return (x >>> 7 | x << 25) ^ (x >>> 18 | x << 14) ^ (x >>> 3)
}

function gamma1 (x) {
  return (x >>> 17 | x << 15) ^ (x >>> 19 | x << 13) ^ (x >>> 10)
}

Sha256.prototype._update = function (M) {
  var W = this._w

  var a = this._a | 0
  var b = this._b | 0
  var c = this._c | 0
  var d = this._d | 0
  var e = this._e | 0
  var f = this._f | 0
  var g = this._g | 0
  var h = this._h | 0

  for (var i = 0; i < 16; ++i) W[i] = M.readInt32BE(i * 4)
  for (; i < 64; ++i) W[i] = (gamma1(W[i - 2]) + W[i - 7] + gamma0(W[i - 15]) + W[i - 16]) | 0

  for (var j = 0; j < 64; ++j) {
    var T1 = (h + sigma1(e) + ch(e, f, g) + K[j] + W[j]) | 0
    var T2 = (sigma0(a) + maj(a, b, c)) | 0

    h = g
    g = f
    f = e
    e = (d + T1) | 0
    d = c
    c = b
    b = a
    a = (T1 + T2) | 0
  }

  this._a = (a + this._a) | 0
  this._b = (b + this._b) | 0
  this._c = (c + this._c) | 0
  this._d = (d + this._d) | 0
  this._e = (e + this._e) | 0
  this._f = (f + this._f) | 0
  this._g = (g + this._g) | 0
  this._h = (h + this._h) | 0
}

Sha256.prototype._hash = function () {
  var H = new Buffer(32)

  H.writeInt32BE(this._a, 0)
  H.writeInt32BE(this._b, 4)
  H.writeInt32BE(this._c, 8)
  H.writeInt32BE(this._d, 12)
  H.writeInt32BE(this._e, 16)
  H.writeInt32BE(this._f, 20)
  H.writeInt32BE(this._g, 24)
  H.writeInt32BE(this._h, 28)

  return H
}

module.exports = Sha256

}).call(this,require("buffer").Buffer)
},{"./hash":125,"buffer":45,"inherits":94}],131:[function(require,module,exports){
(function (Buffer){
var inherits = require('inherits')
var SHA512 = require('./sha512')
var Hash = require('./hash')

var W = new Array(160)

function Sha384 () {
  this.init()
  this._w = W

  Hash.call(this, 128, 112)
}

inherits(Sha384, SHA512)

Sha384.prototype.init = function () {
  this._ah = 0xcbbb9d5d
  this._bh = 0x629a292a
  this._ch = 0x9159015a
  this._dh = 0x152fecd8
  this._eh = 0x67332667
  this._fh = 0x8eb44a87
  this._gh = 0xdb0c2e0d
  this._hh = 0x47b5481d

  this._al = 0xc1059ed8
  this._bl = 0x367cd507
  this._cl = 0x3070dd17
  this._dl = 0xf70e5939
  this._el = 0xffc00b31
  this._fl = 0x68581511
  this._gl = 0x64f98fa7
  this._hl = 0xbefa4fa4

  return this
}

Sha384.prototype._hash = function () {
  var H = new Buffer(48)

  function writeInt64BE (h, l, offset) {
    H.writeInt32BE(h, offset)
    H.writeInt32BE(l, offset + 4)
  }

  writeInt64BE(this._ah, this._al, 0)
  writeInt64BE(this._bh, this._bl, 8)
  writeInt64BE(this._ch, this._cl, 16)
  writeInt64BE(this._dh, this._dl, 24)
  writeInt64BE(this._eh, this._el, 32)
  writeInt64BE(this._fh, this._fl, 40)

  return H
}

module.exports = Sha384

}).call(this,require("buffer").Buffer)
},{"./hash":125,"./sha512":132,"buffer":45,"inherits":94}],132:[function(require,module,exports){
(function (Buffer){
var inherits = require('inherits')
var Hash = require('./hash')

var K = [
  0x428a2f98, 0xd728ae22, 0x71374491, 0x23ef65cd,
  0xb5c0fbcf, 0xec4d3b2f, 0xe9b5dba5, 0x8189dbbc,
  0x3956c25b, 0xf348b538, 0x59f111f1, 0xb605d019,
  0x923f82a4, 0xaf194f9b, 0xab1c5ed5, 0xda6d8118,
  0xd807aa98, 0xa3030242, 0x12835b01, 0x45706fbe,
  0x243185be, 0x4ee4b28c, 0x550c7dc3, 0xd5ffb4e2,
  0x72be5d74, 0xf27b896f, 0x80deb1fe, 0x3b1696b1,
  0x9bdc06a7, 0x25c71235, 0xc19bf174, 0xcf692694,
  0xe49b69c1, 0x9ef14ad2, 0xefbe4786, 0x384f25e3,
  0x0fc19dc6, 0x8b8cd5b5, 0x240ca1cc, 0x77ac9c65,
  0x2de92c6f, 0x592b0275, 0x4a7484aa, 0x6ea6e483,
  0x5cb0a9dc, 0xbd41fbd4, 0x76f988da, 0x831153b5,
  0x983e5152, 0xee66dfab, 0xa831c66d, 0x2db43210,
  0xb00327c8, 0x98fb213f, 0xbf597fc7, 0xbeef0ee4,
  0xc6e00bf3, 0x3da88fc2, 0xd5a79147, 0x930aa725,
  0x06ca6351, 0xe003826f, 0x14292967, 0x0a0e6e70,
  0x27b70a85, 0x46d22ffc, 0x2e1b2138, 0x5c26c926,
  0x4d2c6dfc, 0x5ac42aed, 0x53380d13, 0x9d95b3df,
  0x650a7354, 0x8baf63de, 0x766a0abb, 0x3c77b2a8,
  0x81c2c92e, 0x47edaee6, 0x92722c85, 0x1482353b,
  0xa2bfe8a1, 0x4cf10364, 0xa81a664b, 0xbc423001,
  0xc24b8b70, 0xd0f89791, 0xc76c51a3, 0x0654be30,
  0xd192e819, 0xd6ef5218, 0xd6990624, 0x5565a910,
  0xf40e3585, 0x5771202a, 0x106aa070, 0x32bbd1b8,
  0x19a4c116, 0xb8d2d0c8, 0x1e376c08, 0x5141ab53,
  0x2748774c, 0xdf8eeb99, 0x34b0bcb5, 0xe19b48a8,
  0x391c0cb3, 0xc5c95a63, 0x4ed8aa4a, 0xe3418acb,
  0x5b9cca4f, 0x7763e373, 0x682e6ff3, 0xd6b2b8a3,
  0x748f82ee, 0x5defb2fc, 0x78a5636f, 0x43172f60,
  0x84c87814, 0xa1f0ab72, 0x8cc70208, 0x1a6439ec,
  0x90befffa, 0x23631e28, 0xa4506ceb, 0xde82bde9,
  0xbef9a3f7, 0xb2c67915, 0xc67178f2, 0xe372532b,
  0xca273ece, 0xea26619c, 0xd186b8c7, 0x21c0c207,
  0xeada7dd6, 0xcde0eb1e, 0xf57d4f7f, 0xee6ed178,
  0x06f067aa, 0x72176fba, 0x0a637dc5, 0xa2c898a6,
  0x113f9804, 0xbef90dae, 0x1b710b35, 0x131c471b,
  0x28db77f5, 0x23047d84, 0x32caab7b, 0x40c72493,
  0x3c9ebe0a, 0x15c9bebc, 0x431d67c4, 0x9c100d4c,
  0x4cc5d4be, 0xcb3e42b6, 0x597f299c, 0xfc657e2a,
  0x5fcb6fab, 0x3ad6faec, 0x6c44198c, 0x4a475817
]

var W = new Array(160)

function Sha512 () {
  this.init()
  this._w = W

  Hash.call(this, 128, 112)
}

inherits(Sha512, Hash)

Sha512.prototype.init = function () {
  this._ah = 0x6a09e667
  this._bh = 0xbb67ae85
  this._ch = 0x3c6ef372
  this._dh = 0xa54ff53a
  this._eh = 0x510e527f
  this._fh = 0x9b05688c
  this._gh = 0x1f83d9ab
  this._hh = 0x5be0cd19

  this._al = 0xf3bcc908
  this._bl = 0x84caa73b
  this._cl = 0xfe94f82b
  this._dl = 0x5f1d36f1
  this._el = 0xade682d1
  this._fl = 0x2b3e6c1f
  this._gl = 0xfb41bd6b
  this._hl = 0x137e2179

  return this
}

function Ch (x, y, z) {
  return z ^ (x & (y ^ z))
}

function maj (x, y, z) {
  return (x & y) | (z & (x | y))
}

function sigma0 (x, xl) {
  return (x >>> 28 | xl << 4) ^ (xl >>> 2 | x << 30) ^ (xl >>> 7 | x << 25)
}

function sigma1 (x, xl) {
  return (x >>> 14 | xl << 18) ^ (x >>> 18 | xl << 14) ^ (xl >>> 9 | x << 23)
}

function Gamma0 (x, xl) {
  return (x >>> 1 | xl << 31) ^ (x >>> 8 | xl << 24) ^ (x >>> 7)
}

function Gamma0l (x, xl) {
  return (x >>> 1 | xl << 31) ^ (x >>> 8 | xl << 24) ^ (x >>> 7 | xl << 25)
}

function Gamma1 (x, xl) {
  return (x >>> 19 | xl << 13) ^ (xl >>> 29 | x << 3) ^ (x >>> 6)
}

function Gamma1l (x, xl) {
  return (x >>> 19 | xl << 13) ^ (xl >>> 29 | x << 3) ^ (x >>> 6 | xl << 26)
}

function getCarry (a, b) {
  return (a >>> 0) < (b >>> 0) ? 1 : 0
}

Sha512.prototype._update = function (M) {
  var W = this._w

  var ah = this._ah | 0
  var bh = this._bh | 0
  var ch = this._ch | 0
  var dh = this._dh | 0
  var eh = this._eh | 0
  var fh = this._fh | 0
  var gh = this._gh | 0
  var hh = this._hh | 0

  var al = this._al | 0
  var bl = this._bl | 0
  var cl = this._cl | 0
  var dl = this._dl | 0
  var el = this._el | 0
  var fl = this._fl | 0
  var gl = this._gl | 0
  var hl = this._hl | 0

  for (var i = 0; i < 32; i += 2) {
    W[i] = M.readInt32BE(i * 4)
    W[i + 1] = M.readInt32BE(i * 4 + 4)
  }
  for (; i < 160; i += 2) {
    var xh = W[i - 15 * 2]
    var xl = W[i - 15 * 2 + 1]
    var gamma0 = Gamma0(xh, xl)
    var gamma0l = Gamma0l(xl, xh)

    xh = W[i - 2 * 2]
    xl = W[i - 2 * 2 + 1]
    var gamma1 = Gamma1(xh, xl)
    var gamma1l = Gamma1l(xl, xh)

    // W[i] = gamma0 + W[i - 7] + gamma1 + W[i - 16]
    var Wi7h = W[i - 7 * 2]
    var Wi7l = W[i - 7 * 2 + 1]

    var Wi16h = W[i - 16 * 2]
    var Wi16l = W[i - 16 * 2 + 1]

    var Wil = (gamma0l + Wi7l) | 0
    var Wih = (gamma0 + Wi7h + getCarry(Wil, gamma0l)) | 0
    Wil = (Wil + gamma1l) | 0
    Wih = (Wih + gamma1 + getCarry(Wil, gamma1l)) | 0
    Wil = (Wil + Wi16l) | 0
    Wih = (Wih + Wi16h + getCarry(Wil, Wi16l)) | 0

    W[i] = Wih
    W[i + 1] = Wil
  }

  for (var j = 0; j < 160; j += 2) {
    Wih = W[j]
    Wil = W[j + 1]

    var majh = maj(ah, bh, ch)
    var majl = maj(al, bl, cl)

    var sigma0h = sigma0(ah, al)
    var sigma0l = sigma0(al, ah)
    var sigma1h = sigma1(eh, el)
    var sigma1l = sigma1(el, eh)

    // t1 = h + sigma1 + ch + K[j] + W[j]
    var Kih = K[j]
    var Kil = K[j + 1]

    var chh = Ch(eh, fh, gh)
    var chl = Ch(el, fl, gl)

    var t1l = (hl + sigma1l) | 0
    var t1h = (hh + sigma1h + getCarry(t1l, hl)) | 0
    t1l = (t1l + chl) | 0
    t1h = (t1h + chh + getCarry(t1l, chl)) | 0
    t1l = (t1l + Kil) | 0
    t1h = (t1h + Kih + getCarry(t1l, Kil)) | 0
    t1l = (t1l + Wil) | 0
    t1h = (t1h + Wih + getCarry(t1l, Wil)) | 0

    // t2 = sigma0 + maj
    var t2l = (sigma0l + majl) | 0
    var t2h = (sigma0h + majh + getCarry(t2l, sigma0l)) | 0

    hh = gh
    hl = gl
    gh = fh
    gl = fl
    fh = eh
    fl = el
    el = (dl + t1l) | 0
    eh = (dh + t1h + getCarry(el, dl)) | 0
    dh = ch
    dl = cl
    ch = bh
    cl = bl
    bh = ah
    bl = al
    al = (t1l + t2l) | 0
    ah = (t1h + t2h + getCarry(al, t1l)) | 0
  }

  this._al = (this._al + al) | 0
  this._bl = (this._bl + bl) | 0
  this._cl = (this._cl + cl) | 0
  this._dl = (this._dl + dl) | 0
  this._el = (this._el + el) | 0
  this._fl = (this._fl + fl) | 0
  this._gl = (this._gl + gl) | 0
  this._hl = (this._hl + hl) | 0

  this._ah = (this._ah + ah + getCarry(this._al, al)) | 0
  this._bh = (this._bh + bh + getCarry(this._bl, bl)) | 0
  this._ch = (this._ch + ch + getCarry(this._cl, cl)) | 0
  this._dh = (this._dh + dh + getCarry(this._dl, dl)) | 0
  this._eh = (this._eh + eh + getCarry(this._el, el)) | 0
  this._fh = (this._fh + fh + getCarry(this._fl, fl)) | 0
  this._gh = (this._gh + gh + getCarry(this._gl, gl)) | 0
  this._hh = (this._hh + hh + getCarry(this._hl, hl)) | 0
}

Sha512.prototype._hash = function () {
  var H = new Buffer(64)

  function writeInt64BE (h, l, offset) {
    H.writeInt32BE(h, offset)
    H.writeInt32BE(l, offset + 4)
  }

  writeInt64BE(this._ah, this._al, 0)
  writeInt64BE(this._bh, this._bl, 8)
  writeInt64BE(this._ch, this._cl, 16)
  writeInt64BE(this._dh, this._dl, 24)
  writeInt64BE(this._eh, this._el, 32)
  writeInt64BE(this._fh, this._fl, 40)
  writeInt64BE(this._gh, this._gl, 48)
  writeInt64BE(this._hh, this._hl, 56)

  return H
}

module.exports = Sha512

}).call(this,require("buffer").Buffer)
},{"./hash":125,"buffer":45,"inherits":94}],133:[function(require,module,exports){
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.

module.exports = Stream;

var EE = require('events').EventEmitter;
var inherits = require('inherits');

inherits(Stream, EE);
Stream.Readable = require('readable-stream/readable.js');
Stream.Writable = require('readable-stream/writable.js');
Stream.Duplex = require('readable-stream/duplex.js');
Stream.Transform = require('readable-stream/transform.js');
Stream.PassThrough = require('readable-stream/passthrough.js');

// Backwards-compat with node 0.4.x
Stream.Stream = Stream;



// old-style streams.  Note that the pipe method (the only relevant
// part of this class) is overridden in the Readable class.

function Stream() {
  EE.call(this);
}

Stream.prototype.pipe = function(dest, options) {
  var source = this;

  function ondata(chunk) {
    if (dest.writable) {
      if (false === dest.write(chunk) && source.pause) {
        source.pause();
      }
    }
  }

  source.on('data', ondata);

  function ondrain() {
    if (source.readable && source.resume) {
      source.resume();
    }
  }

  dest.on('drain', ondrain);

  // If the 'end' option is not supplied, dest.end() will be called when
  // source gets the 'end' or 'close' events.  Only dest.end() once.
  if (!dest._isStdio && (!options || options.end !== false)) {
    source.on('end', onend);
    source.on('close', onclose);
  }

  var didOnEnd = false;
  function onend() {
    if (didOnEnd) return;
    didOnEnd = true;

    dest.end();
  }


  function onclose() {
    if (didOnEnd) return;
    didOnEnd = true;

    if (typeof dest.destroy === 'function') dest.destroy();
  }

  // don't leave dangling pipes when there are errors.
  function onerror(er) {
    cleanup();
    if (EE.listenerCount(this, 'error') === 0) {
      throw er; // Unhandled stream error in pipe.
    }
  }

  source.on('error', onerror);
  dest.on('error', onerror);

  // remove all the event listeners that were added.
  function cleanup() {
    source.removeListener('data', ondata);
    dest.removeListener('drain', ondrain);

    source.removeListener('end', onend);
    source.removeListener('close', onclose);

    source.removeListener('error', onerror);
    dest.removeListener('error', onerror);

    source.removeListener('end', cleanup);
    source.removeListener('close', cleanup);

    dest.removeListener('close', cleanup);
  }

  source.on('end', cleanup);
  source.on('close', cleanup);

  dest.on('close', cleanup);

  dest.emit('pipe', source);

  // Allow for unix-like usage: A.pipe(B).pipe(C)
  return dest;
};

},{"events":84,"inherits":94,"readable-stream/duplex.js":113,"readable-stream/passthrough.js":121,"readable-stream/readable.js":122,"readable-stream/transform.js":123,"readable-stream/writable.js":124}],134:[function(require,module,exports){
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.

var Buffer = require('buffer').Buffer;

var isBufferEncoding = Buffer.isEncoding
  || function(encoding) {
       switch (encoding && encoding.toLowerCase()) {
         case 'hex': case 'utf8': case 'utf-8': case 'ascii': case 'binary': case 'base64': case 'ucs2': case 'ucs-2': case 'utf16le': case 'utf-16le': case 'raw': return true;
         default: return false;
       }
     }


function assertEncoding(encoding) {
  if (encoding && !isBufferEncoding(encoding)) {
    throw new Error('Unknown encoding: ' + encoding);
  }
}

// StringDecoder provides an interface for efficiently splitting a series of
// buffers into a series of JS strings without breaking apart multi-byte
// characters. CESU-8 is handled as part of the UTF-8 encoding.
//
// @TODO Handling all encodings inside a single object makes it very difficult
// to reason about this code, so it should be split up in the future.
// @TODO There should be a utf8-strict encoding that rejects invalid UTF-8 code
// points as used by CESU-8.
var StringDecoder = exports.StringDecoder = function(encoding) {
  this.encoding = (encoding || 'utf8').toLowerCase().replace(/[-_]/, '');
  assertEncoding(encoding);
  switch (this.encoding) {
    case 'utf8':
      // CESU-8 represents each of Surrogate Pair by 3-bytes
      this.surrogateSize = 3;
      break;
    case 'ucs2':
    case 'utf16le':
      // UTF-16 represents each of Surrogate Pair by 2-bytes
      this.surrogateSize = 2;
      this.detectIncompleteChar = utf16DetectIncompleteChar;
      break;
    case 'base64':
      // Base-64 stores 3 bytes in 4 chars, and pads the remainder.
      this.surrogateSize = 3;
      this.detectIncompleteChar = base64DetectIncompleteChar;
      break;
    default:
      this.write = passThroughWrite;
      return;
  }

  // Enough space to store all bytes of a single character. UTF-8 needs 4
  // bytes, but CESU-8 may require up to 6 (3 bytes per surrogate).
  this.charBuffer = new Buffer(6);
  // Number of bytes received for the current incomplete multi-byte character.
  this.charReceived = 0;
  // Number of bytes expected for the current incomplete multi-byte character.
  this.charLength = 0;
};


// write decodes the given buffer and returns it as JS string that is
// guaranteed to not contain any partial multi-byte characters. Any partial
// character found at the end of the buffer is buffered up, and will be
// returned when calling write again with the remaining bytes.
//
// Note: Converting a Buffer containing an orphan surrogate to a String
// currently works, but converting a String to a Buffer (via `new Buffer`, or
// Buffer#write) will replace incomplete surrogates with the unicode
// replacement character. See https://codereview.chromium.org/121173009/ .
StringDecoder.prototype.write = function(buffer) {
  var charStr = '';
  // if our last write ended with an incomplete multibyte character
  while (this.charLength) {
    // determine how many remaining bytes this buffer has to offer for this char
    var available = (buffer.length >= this.charLength - this.charReceived) ?
        this.charLength - this.charReceived :
        buffer.length;

    // add the new bytes to the char buffer
    buffer.copy(this.charBuffer, this.charReceived, 0, available);
    this.charReceived += available;

    if (this.charReceived < this.charLength) {
      // still not enough chars in this buffer? wait for more ...
      return '';
    }

    // remove bytes belonging to the current character from the buffer
    buffer = buffer.slice(available, buffer.length);

    // get the character that was split
    charStr = this.charBuffer.slice(0, this.charLength).toString(this.encoding);

    // CESU-8: lead surrogate (D800-DBFF) is also the incomplete character
    var charCode = charStr.charCodeAt(charStr.length - 1);
    if (charCode >= 0xD800 && charCode <= 0xDBFF) {
      this.charLength += this.surrogateSize;
      charStr = '';
      continue;
    }
    this.charReceived = this.charLength = 0;

    // if there are no more bytes in this buffer, just emit our char
    if (buffer.length === 0) {
      return charStr;
    }
    break;
  }

  // determine and set charLength / charReceived
  this.detectIncompleteChar(buffer);

  var end = buffer.length;
  if (this.charLength) {
    // buffer the incomplete character bytes we got
    buffer.copy(this.charBuffer, 0, buffer.length - this.charReceived, end);
    end -= this.charReceived;
  }

  charStr += buffer.toString(this.encoding, 0, end);

  var end = charStr.length - 1;
  var charCode = charStr.charCodeAt(end);
  // CESU-8: lead surrogate (D800-DBFF) is also the incomplete character
  if (charCode >= 0xD800 && charCode <= 0xDBFF) {
    var size = this.surrogateSize;
    this.charLength += size;
    this.charReceived += size;
    this.charBuffer.copy(this.charBuffer, size, 0, size);
    buffer.copy(this.charBuffer, 0, 0, size);
    return charStr.substring(0, end);
  }

  // or just emit the charStr
  return charStr;
};

// detectIncompleteChar determines if there is an incomplete UTF-8 character at
// the end of the given buffer. If so, it sets this.charLength to the byte
// length that character, and sets this.charReceived to the number of bytes
// that are available for this character.
StringDecoder.prototype.detectIncompleteChar = function(buffer) {
  // determine how many bytes we have to check at the end of this buffer
  var i = (buffer.length >= 3) ? 3 : buffer.length;

  // Figure out if one of the last i bytes of our buffer announces an
  // incomplete char.
  for (; i > 0; i--) {
    var c = buffer[buffer.length - i];

    // See http://en.wikipedia.org/wiki/UTF-8#Description

    // 110XXXXX
    if (i == 1 && c >> 5 == 0x06) {
      this.charLength = 2;
      break;
    }

    // 1110XXXX
    if (i <= 2 && c >> 4 == 0x0E) {
      this.charLength = 3;
      break;
    }

    // 11110XXX
    if (i <= 3 && c >> 3 == 0x1E) {
      this.charLength = 4;
      break;
    }
  }
  this.charReceived = i;
};

StringDecoder.prototype.end = function(buffer) {
  var res = '';
  if (buffer && buffer.length)
    res = this.write(buffer);

  if (this.charReceived) {
    var cr = this.charReceived;
    var buf = this.charBuffer;
    var enc = this.encoding;
    res += buf.slice(0, cr).toString(enc);
  }

  return res;
};

function passThroughWrite(buffer) {
  return buffer.toString(this.encoding);
}

function utf16DetectIncompleteChar(buffer) {
  this.charReceived = buffer.length % 2;
  this.charLength = this.charReceived ? 2 : 0;
}

function base64DetectIncompleteChar(buffer) {
  this.charReceived = buffer.length % 3;
  this.charLength = this.charReceived ? 3 : 0;
}

},{"buffer":45}],135:[function(require,module,exports){
(function (global){

/**
 * Module exports.
 */

module.exports = deprecate;

/**
 * Mark that a method should not be used.
 * Returns a modified function which warns once by default.
 *
 * If `localStorage.noDeprecation = true` is set, then it is a no-op.
 *
 * If `localStorage.throwDeprecation = true` is set, then deprecated functions
 * will throw an Error when invoked.
 *
 * If `localStorage.traceDeprecation = true` is set, then deprecated functions
 * will invoke `console.trace()` instead of `console.error()`.
 *
 * @param {Function} fn - the function to deprecate
 * @param {String} msg - the string to print to the console when `fn` is invoked
 * @returns {Function} a new "deprecated" version of `fn`
 * @api public
 */

function deprecate (fn, msg) {
  if (config('noDeprecation')) {
    return fn;
  }

  var warned = false;
  function deprecated() {
    if (!warned) {
      if (config('throwDeprecation')) {
        throw new Error(msg);
      } else if (config('traceDeprecation')) {
        console.trace(msg);
      } else {
        console.warn(msg);
      }
      warned = true;
    }
    return fn.apply(this, arguments);
  }

  return deprecated;
}

/**
 * Checks `localStorage` for boolean values for the given `name`.
 *
 * @param {String} name
 * @returns {Boolean}
 * @api private
 */

function config (name) {
  // accessing global.localStorage can trigger a DOMException in sandboxed iframes
  try {
    if (!global.localStorage) return false;
  } catch (_) {
    return false;
  }
  var val = global.localStorage[name];
  if (null == val) return false;
  return String(val).toLowerCase() === 'true';
}

}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{}],136:[function(require,module,exports){
var indexOf = require('indexof');

var Object_keys = function (obj) {
    if (Object.keys) return Object.keys(obj)
    else {
        var res = [];
        for (var key in obj) res.push(key)
        return res;
    }
};

var forEach = function (xs, fn) {
    if (xs.forEach) return xs.forEach(fn)
    else for (var i = 0; i < xs.length; i++) {
        fn(xs[i], i, xs);
    }
};

var defineProp = (function() {
    try {
        Object.defineProperty({}, '_', {});
        return function(obj, name, value) {
            Object.defineProperty(obj, name, {
                writable: true,
                enumerable: false,
                configurable: true,
                value: value
            })
        };
    } catch(e) {
        return function(obj, name, value) {
            obj[name] = value;
        };
    }
}());

var globals = ['Array', 'Boolean', 'Date', 'Error', 'EvalError', 'Function',
'Infinity', 'JSON', 'Math', 'NaN', 'Number', 'Object', 'RangeError',
'ReferenceError', 'RegExp', 'String', 'SyntaxError', 'TypeError', 'URIError',
'decodeURI', 'decodeURIComponent', 'encodeURI', 'encodeURIComponent', 'escape',
'eval', 'isFinite', 'isNaN', 'parseFloat', 'parseInt', 'undefined', 'unescape'];

function Context() {}
Context.prototype = {};

var Script = exports.Script = function NodeScript (code) {
    if (!(this instanceof Script)) return new Script(code);
    this.code = code;
};

Script.prototype.runInContext = function (context) {
    if (!(context instanceof Context)) {
        throw new TypeError("needs a 'context' argument.");
    }
    
    var iframe = document.createElement('iframe');
    if (!iframe.style) iframe.style = {};
    iframe.style.display = 'none';
    
    document.body.appendChild(iframe);
    
    var win = iframe.contentWindow;
    var wEval = win.eval, wExecScript = win.execScript;

    if (!wEval && wExecScript) {
        // win.eval() magically appears when this is called in IE:
        wExecScript.call(win, 'null');
        wEval = win.eval;
    }
    
    forEach(Object_keys(context), function (key) {
        win[key] = context[key];
    });
    forEach(globals, function (key) {
        if (context[key]) {
            win[key] = context[key];
        }
    });
    
    var winKeys = Object_keys(win);

    var res = wEval.call(win, this.code);
    
    forEach(Object_keys(win), function (key) {
        // Avoid copying circular objects like `top` and `window` by only
        // updating existing context properties or new properties in the `win`
        // that was only introduced after the eval.
        if (key in context || indexOf(winKeys, key) === -1) {
            context[key] = win[key];
        }
    });

    forEach(globals, function (key) {
        if (!(key in context)) {
            defineProp(context, key, win[key]);
        }
    });
    
    document.body.removeChild(iframe);
    
    return res;
};

Script.prototype.runInThisContext = function () {
    return eval(this.code); // maybe...
};

Script.prototype.runInNewContext = function (context) {
    var ctx = Script.createContext(context);
    var res = this.runInContext(ctx);

    forEach(Object_keys(ctx), function (key) {
        context[key] = ctx[key];
    });

    return res;
};

forEach(Object_keys(Script.prototype), function (name) {
    exports[name] = Script[name] = function (code) {
        var s = Script(code);
        return s[name].apply(s, [].slice.call(arguments, 1));
    };
});

exports.createScript = function (code) {
    return exports.Script(code);
};

exports.createContext = Script.createContext = function (context) {
    var copy = new Context();
    if(typeof context === 'object') {
        forEach(Object_keys(context), function (key) {
            copy[key] = context[key];
        });
    }
    return copy;
};

},{"indexof":93}],137:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickDC.DEVICE_IDENTIFIER = 11;
BrickDC.DEVICE_DISPLAY_NAME = 'DC Brick';
BrickDC.CALLBACK_UNDER_VOLTAGE = 21;
BrickDC.CALLBACK_EMERGENCY_SHUTDOWN = 22;
BrickDC.CALLBACK_VELOCITY_REACHED = 23;
BrickDC.CALLBACK_CURRENT_VELOCITY = 24;
BrickDC.FUNCTION_SET_VELOCITY = 1;
BrickDC.FUNCTION_GET_VELOCITY = 2;
BrickDC.FUNCTION_GET_CURRENT_VELOCITY = 3;
BrickDC.FUNCTION_SET_ACCELERATION = 4;
BrickDC.FUNCTION_GET_ACCELERATION = 5;
BrickDC.FUNCTION_SET_PWM_FREQUENCY = 6;
BrickDC.FUNCTION_GET_PWM_FREQUENCY = 7;
BrickDC.FUNCTION_FULL_BRAKE = 8;
BrickDC.FUNCTION_GET_STACK_INPUT_VOLTAGE = 9;
BrickDC.FUNCTION_GET_EXTERNAL_INPUT_VOLTAGE = 10;
BrickDC.FUNCTION_GET_CURRENT_CONSUMPTION = 11;
BrickDC.FUNCTION_ENABLE = 12;
BrickDC.FUNCTION_DISABLE = 13;
BrickDC.FUNCTION_IS_ENABLED = 14;
BrickDC.FUNCTION_SET_MINIMUM_VOLTAGE = 15;
BrickDC.FUNCTION_GET_MINIMUM_VOLTAGE = 16;
BrickDC.FUNCTION_SET_DRIVE_MODE = 17;
BrickDC.FUNCTION_GET_DRIVE_MODE = 18;
BrickDC.FUNCTION_SET_CURRENT_VELOCITY_PERIOD = 19;
BrickDC.FUNCTION_GET_CURRENT_VELOCITY_PERIOD = 20;
BrickDC.FUNCTION_SET_SPITFP_BAUDRATE_CONFIG = 231;
BrickDC.FUNCTION_GET_SPITFP_BAUDRATE_CONFIG = 232;
BrickDC.FUNCTION_GET_SEND_TIMEOUT_COUNT = 233;
BrickDC.FUNCTION_SET_SPITFP_BAUDRATE = 234;
BrickDC.FUNCTION_GET_SPITFP_BAUDRATE = 235;
BrickDC.FUNCTION_GET_SPITFP_ERROR_COUNT = 237;
BrickDC.FUNCTION_ENABLE_STATUS_LED = 238;
BrickDC.FUNCTION_DISABLE_STATUS_LED = 239;
BrickDC.FUNCTION_IS_STATUS_LED_ENABLED = 240;
BrickDC.FUNCTION_GET_PROTOCOL1_BRICKLET_NAME = 241;
BrickDC.FUNCTION_GET_CHIP_TEMPERATURE = 242;
BrickDC.FUNCTION_RESET = 243;
BrickDC.FUNCTION_WRITE_BRICKLET_PLUGIN = 246;
BrickDC.FUNCTION_READ_BRICKLET_PLUGIN = 247;
BrickDC.FUNCTION_GET_IDENTITY = 255;
BrickDC.DRIVE_MODE_DRIVE_BRAKE = 0;
BrickDC.DRIVE_MODE_DRIVE_COAST = 1;
BrickDC.COMMUNICATION_METHOD_NONE = 0;
BrickDC.COMMUNICATION_METHOD_USB = 1;
BrickDC.COMMUNICATION_METHOD_SPI_STACK = 2;
BrickDC.COMMUNICATION_METHOD_CHIBI = 3;
BrickDC.COMMUNICATION_METHOD_RS485 = 4;
BrickDC.COMMUNICATION_METHOD_WIFI = 5;
BrickDC.COMMUNICATION_METHOD_ETHERNET = 6;
BrickDC.COMMUNICATION_METHOD_WIFI_V2 = 7;

function BrickDC(uid, ipcon) {
	//Drives one brushed DC motor with up to 28V and 5A (peak)

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickDC.DEVICE_IDENTIFIER, BrickDC.DEVICE_DISPLAY_NAME);
	BrickDC.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 3];
	this.responseExpected[BrickDC.FUNCTION_SET_VELOCITY] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickDC.FUNCTION_GET_VELOCITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickDC.FUNCTION_GET_CURRENT_VELOCITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickDC.FUNCTION_SET_ACCELERATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickDC.FUNCTION_GET_ACCELERATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickDC.FUNCTION_SET_PWM_FREQUENCY] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickDC.FUNCTION_GET_PWM_FREQUENCY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickDC.FUNCTION_FULL_BRAKE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickDC.FUNCTION_GET_STACK_INPUT_VOLTAGE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickDC.FUNCTION_GET_EXTERNAL_INPUT_VOLTAGE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickDC.FUNCTION_GET_CURRENT_CONSUMPTION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickDC.FUNCTION_ENABLE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickDC.FUNCTION_DISABLE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickDC.FUNCTION_IS_ENABLED] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickDC.FUNCTION_SET_MINIMUM_VOLTAGE] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickDC.FUNCTION_GET_MINIMUM_VOLTAGE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickDC.FUNCTION_SET_DRIVE_MODE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickDC.FUNCTION_GET_DRIVE_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickDC.FUNCTION_SET_CURRENT_VELOCITY_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickDC.FUNCTION_GET_CURRENT_VELOCITY_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickDC.FUNCTION_SET_SPITFP_BAUDRATE_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickDC.FUNCTION_GET_SPITFP_BAUDRATE_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickDC.FUNCTION_GET_SEND_TIMEOUT_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickDC.FUNCTION_SET_SPITFP_BAUDRATE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickDC.FUNCTION_GET_SPITFP_BAUDRATE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickDC.FUNCTION_GET_SPITFP_ERROR_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickDC.FUNCTION_ENABLE_STATUS_LED] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickDC.FUNCTION_DISABLE_STATUS_LED] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickDC.FUNCTION_IS_STATUS_LED_ENABLED] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickDC.FUNCTION_GET_PROTOCOL1_BRICKLET_NAME] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickDC.FUNCTION_GET_CHIP_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickDC.FUNCTION_RESET] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickDC.FUNCTION_WRITE_BRICKLET_PLUGIN] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickDC.FUNCTION_READ_BRICKLET_PLUGIN] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickDC.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickDC.CALLBACK_UNDER_VOLTAGE] = [10, 'H'];
	this.callbackFormats[BrickDC.CALLBACK_EMERGENCY_SHUTDOWN] = [8, ''];
	this.callbackFormats[BrickDC.CALLBACK_VELOCITY_REACHED] = [10, 'h'];
	this.callbackFormats[BrickDC.CALLBACK_CURRENT_VELOCITY] = [10, 'h'];



	this.setVelocity = function(velocity, returnCallback, errorCallback) {
		/*
		Sets the velocity of the motor. Whereas -32767 is full speed backward,
		0 is stop and 32767 is full speed forward. Depending on the
		acceleration (see :func:`Set Acceleration`), the motor is not immediately
		brought to the velocity but smoothly accelerated.
		
		The velocity describes the duty cycle of the PWM with which the motor is
		controlled, e.g. a velocity of 3277 sets a PWM with a 10% duty cycle.
		You can not only control the duty cycle of the PWM but also the frequency,
		see :func:`Set PWM Frequency`.
		*/
		this.ipcon.sendRequest(this, BrickDC.FUNCTION_SET_VELOCITY, [velocity], 'h', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getVelocity = function(returnCallback, errorCallback) {
		/*
		Returns the velocity as set by :func:`Set Velocity`.
		*/
		this.ipcon.sendRequest(this, BrickDC.FUNCTION_GET_VELOCITY, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.getCurrentVelocity = function(returnCallback, errorCallback) {
		/*
		Returns the *current* velocity of the motor. This value is different
		from :func:`Get Velocity` whenever the motor is currently accelerating
		to a goal set by :func:`Set Velocity`.
		*/
		this.ipcon.sendRequest(this, BrickDC.FUNCTION_GET_CURRENT_VELOCITY, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.setAcceleration = function(acceleration, returnCallback, errorCallback) {
		/*
		Sets the acceleration of the motor. It is given in *velocity/s*. An
		acceleration of 10000 means, that every second the velocity is increased
		by 10000 (or about 30% duty cycle).
		
		For example: If the current velocity is 0 and you want to accelerate to a
		velocity of 16000 (about 50% duty cycle) in 10 seconds, you should set
		an acceleration of 1600.
		
		If acceleration is set to 0, there is no speed ramping, i.e. a new velocity
		is immediately given to the motor.
		*/
		this.ipcon.sendRequest(this, BrickDC.FUNCTION_SET_ACCELERATION, [acceleration], 'H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getAcceleration = function(returnCallback, errorCallback) {
		/*
		Returns the acceleration as set by :func:`Set Acceleration`.
		*/
		this.ipcon.sendRequest(this, BrickDC.FUNCTION_GET_ACCELERATION, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.setPWMFrequency = function(frequency, returnCallback, errorCallback) {
		/*
		Sets the frequency of the PWM with which the motor is driven.
		Often a high frequency
		is less noisy and the motor runs smoother. However, with a low frequency
		there are less switches and therefore fewer switching losses. Also with
		most motors lower frequencies enable higher torque.
		
		If you have no idea what all this means, just ignore this function and use
		the default frequency, it will very likely work fine.
		*/
		this.ipcon.sendRequest(this, BrickDC.FUNCTION_SET_PWM_FREQUENCY, [frequency], 'H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getPWMFrequency = function(returnCallback, errorCallback) {
		/*
		Returns the PWM frequency as set by :func:`Set PWM Frequency`.
		*/
		this.ipcon.sendRequest(this, BrickDC.FUNCTION_GET_PWM_FREQUENCY, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.fullBrake = function(returnCallback, errorCallback) {
		/*
		Executes an active full brake.
		
		.. warning::
		 This function is for emergency purposes,
		 where an immediate brake is necessary. Depending on the current velocity and
		 the strength of the motor, a full brake can be quite violent.
		
		Call :func:`Set Velocity` with 0 if you just want to stop the motor.
		*/
		this.ipcon.sendRequest(this, BrickDC.FUNCTION_FULL_BRAKE, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getStackInputVoltage = function(returnCallback, errorCallback) {
		/*
		Returns the stack input voltage. The stack input voltage is the
		voltage that is supplied via the stack, i.e. it is given by a
		Step-Down or Step-Up Power Supply.
		*/
		this.ipcon.sendRequest(this, BrickDC.FUNCTION_GET_STACK_INPUT_VOLTAGE, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.getExternalInputVoltage = function(returnCallback, errorCallback) {
		/*
		Returns the external input voltage. The external input voltage is
		given via the black power input connector on the DC Brick.
		
		If there is an external input voltage and a stack input voltage, the motor
		will be driven by the external input voltage. If there is only a stack
		voltage present, the motor will be driven by this voltage.
		
		.. warning::
		 This means, if you have a high stack voltage and a low external voltage,
		 the motor will be driven with the low external voltage. If you then remove
		 the external connection, it will immediately be driven by the high
		 stack voltage.
		*/
		this.ipcon.sendRequest(this, BrickDC.FUNCTION_GET_EXTERNAL_INPUT_VOLTAGE, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.getCurrentConsumption = function(returnCallback, errorCallback) {
		/*
		Returns the current consumption of the motor.
		*/
		this.ipcon.sendRequest(this, BrickDC.FUNCTION_GET_CURRENT_CONSUMPTION, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.enable = function(returnCallback, errorCallback) {
		/*
		Enables the driver chip. The driver parameters can be configured (velocity,
		acceleration, etc) before it is enabled.
		*/
		this.ipcon.sendRequest(this, BrickDC.FUNCTION_ENABLE, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.disable = function(returnCallback, errorCallback) {
		/*
		Disables the driver chip. The configurations are kept (velocity,
		acceleration, etc) but the motor is not driven until it is enabled again.
		
		.. warning::
		 Disabling the driver chip while the motor is still turning can damage the
		 driver chip. The motor should be stopped calling :func:`Set Velocity` with 0
		 before disabling the motor power. The :func:`Set Velocity` function will **not**
		 wait until the motor is actually stopped. You have to explicitly wait for the
		 appropriate time after calling the :func:`Set Velocity` function before calling
		 the :func:`Disable` function.
		*/
		this.ipcon.sendRequest(this, BrickDC.FUNCTION_DISABLE, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.isEnabled = function(returnCallback, errorCallback) {
		/*
		Returns *true* if the driver chip is enabled, *false* otherwise.
		*/
		this.ipcon.sendRequest(this, BrickDC.FUNCTION_IS_ENABLED, [], '', 9, '?', returnCallback, errorCallback, false, true);
	};
	this.setMinimumVoltage = function(voltage, returnCallback, errorCallback) {
		/*
		Sets the minimum voltage, below which the :cb:`Under Voltage` callback
		is triggered. The minimum possible value that works with the DC Brick is 6V.
		You can use this function to detect the discharge of a battery that is used
		to drive the motor. If you have a fixed power supply, you likely do not need
		this functionality.
		*/
		this.ipcon.sendRequest(this, BrickDC.FUNCTION_SET_MINIMUM_VOLTAGE, [voltage], 'H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getMinimumVoltage = function(returnCallback, errorCallback) {
		/*
		Returns the minimum voltage as set by :func:`Set Minimum Voltage`
		*/
		this.ipcon.sendRequest(this, BrickDC.FUNCTION_GET_MINIMUM_VOLTAGE, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.setDriveMode = function(mode, returnCallback, errorCallback) {
		/*
		Sets the drive mode. Possible modes are:
		
		* 0 = Drive/Brake
		* 1 = Drive/Coast
		
		These modes are different kinds of motor controls.
		
		In Drive/Brake mode, the motor is always either driving or braking. There
		is no freewheeling. Advantages are: A more linear correlation between
		PWM and velocity, more exact accelerations and the possibility to drive
		with slower velocities.
		
		In Drive/Coast mode, the motor is always either driving or freewheeling.
		Advantages are: Less current consumption and less demands on the motor and
		driver chip.
		*/
		this.ipcon.sendRequest(this, BrickDC.FUNCTION_SET_DRIVE_MODE, [mode], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getDriveMode = function(returnCallback, errorCallback) {
		/*
		Returns the drive mode, as set by :func:`Set Drive Mode`.
		*/
		this.ipcon.sendRequest(this, BrickDC.FUNCTION_GET_DRIVE_MODE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setCurrentVelocityPeriod = function(period, returnCallback, errorCallback) {
		/*
		Sets a period with which the :cb:`Current Velocity` callback is triggered.
		A period of 0 turns the callback off.
		*/
		this.ipcon.sendRequest(this, BrickDC.FUNCTION_SET_CURRENT_VELOCITY_PERIOD, [period], 'H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getCurrentVelocityPeriod = function(returnCallback, errorCallback) {
		/*
		Returns the period as set by :func:`Set Current Velocity Period`.
		*/
		this.ipcon.sendRequest(this, BrickDC.FUNCTION_GET_CURRENT_VELOCITY_PERIOD, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.setSPITFPBaudrateConfig = function(enableDynamicBaudrate, minimumDynamicBaudrate, returnCallback, errorCallback) {
		/*
		The SPITF protocol can be used with a dynamic baudrate. If the dynamic baudrate is
		enabled, the Brick will try to adapt the baudrate for the communication
		between Bricks and Bricklets according to the amount of data that is transferred.
		
		The baudrate will be increased exponentially if lots of data is sent/received and
		decreased linearly if little data is sent/received.
		
		This lowers the baudrate in applications where little data is transferred (e.g.
		a weather station) and increases the robustness. If there is lots of data to transfer
		(e.g. Thermal Imaging Bricklet) it automatically increases the baudrate as needed.
		
		In cases where some data has to transferred as fast as possible every few seconds
		(e.g. RS485 Bricklet with a high baudrate but small payload) you may want to turn
		the dynamic baudrate off to get the highest possible performance.
		
		The maximum value of the baudrate can be set per port with the function
		:func:`Set SPITFP Baudrate`. If the dynamic baudrate is disabled, the baudrate
		as set by :func:`Set SPITFP Baudrate` will be used statically.
		
		.. versionadded:: 2.3.5$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickDC.FUNCTION_SET_SPITFP_BAUDRATE_CONFIG, [enableDynamicBaudrate, minimumDynamicBaudrate], '? I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPBaudrateConfig = function(returnCallback, errorCallback) {
		/*
		Returns the baudrate config, see :func:`Set SPITFP Baudrate Config`.
		
		.. versionadded:: 2.3.5$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickDC.FUNCTION_GET_SPITFP_BAUDRATE_CONFIG, [], '', 13, '? I', returnCallback, errorCallback, false, true);
	};
	this.getSendTimeoutCount = function(communicationMethod, returnCallback, errorCallback) {
		/*
		Returns the timeout count for the different communication methods.
		
		The methods 0-2 are available for all Bricks, 3-7 only for Master Bricks.
		
		This function is mostly used for debugging during development, in normal operation
		the counters should nearly always stay at 0.
		
		.. versionadded:: 2.3.3$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickDC.FUNCTION_GET_SEND_TIMEOUT_COUNT, [communicationMethod], 'B', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setSPITFPBaudrate = function(brickletPort, baudrate, returnCallback, errorCallback) {
		/*
		Sets the baudrate for a specific Bricklet port.
		
		If you want to increase the throughput of Bricklets you can increase
		the baudrate. If you get a high error count because of high
		interference (see :func:`Get SPITFP Error Count`) you can decrease the
		baudrate.
		
		If the dynamic baudrate feature is enabled, the baudrate set by this
		function corresponds to the maximum baudrate (see :func:`Set SPITFP Baudrate Config`).
		
		Regulatory testing is done with the default baudrate. If CE compatibility
		or similar is necessary in your applications we recommend to not change
		the baudrate.
		
		.. versionadded:: 2.3.3$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickDC.FUNCTION_SET_SPITFP_BAUDRATE, [brickletPort, baudrate], 'c I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPBaudrate = function(brickletPort, returnCallback, errorCallback) {
		/*
		Returns the baudrate for a given Bricklet port, see :func:`Set SPITFP Baudrate`.
		
		.. versionadded:: 2.3.3$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickDC.FUNCTION_GET_SPITFP_BAUDRATE, [brickletPort], 'c', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPErrorCount = function(brickletPort, returnCallback, errorCallback) {
		/*
		Returns the error count for the communication between Brick and Bricklet.
		
		The errors are divided into
		
		* ACK checksum errors,
		* message checksum errors,
		* framing errors and
		* overflow errors.
		
		The errors counts are for errors that occur on the Brick side. All
		Bricklets have a similar function that returns the errors on the Bricklet side.
		
		.. versionadded:: 2.3.3$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickDC.FUNCTION_GET_SPITFP_ERROR_COUNT, [brickletPort], 'c', 24, 'I I I I', returnCallback, errorCallback, false, true);
	};
	this.enableStatusLED = function(returnCallback, errorCallback) {
		/*
		Enables the status LED.
		
		The status LED is the blue LED next to the USB connector. If enabled is is
		on and it flickers if data is transfered. If disabled it is always off.
		
		The default state is enabled.
		
		.. versionadded:: 2.3.1$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickDC.FUNCTION_ENABLE_STATUS_LED, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.disableStatusLED = function(returnCallback, errorCallback) {
		/*
		Disables the status LED.
		
		The status LED is the blue LED next to the USB connector. If enabled is is
		on and it flickers if data is transfered. If disabled it is always off.
		
		The default state is enabled.
		
		.. versionadded:: 2.3.1$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickDC.FUNCTION_DISABLE_STATUS_LED, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.isStatusLEDEnabled = function(returnCallback, errorCallback) {
		/*
		Returns *true* if the status LED is enabled, *false* otherwise.
		
		.. versionadded:: 2.3.1$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickDC.FUNCTION_IS_STATUS_LED_ENABLED, [], '', 9, '?', returnCallback, errorCallback, false, true);
	};
	this.getProtocol1BrickletName = function(port, returnCallback, errorCallback) {
		/*
		Returns the firmware and protocol version and the name of the Bricklet for a
		given port.
		
		This functions sole purpose is to allow automatic flashing of v1.x.y Bricklet
		plugins.
		*/
		this.ipcon.sendRequest(this, BrickDC.FUNCTION_GET_PROTOCOL1_BRICKLET_NAME, [port], 'c', 52, 'B B3 s40', returnCallback, errorCallback, false, true);
	};
	this.getChipTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature as measured inside the microcontroller. The
		value returned is not the ambient temperature!
		
		The temperature is only proportional to the real temperature and it has an
		accuracy of ±15%. Practically it is only useful as an indicator for
		temperature changes.
		*/
		this.ipcon.sendRequest(this, BrickDC.FUNCTION_GET_CHIP_TEMPERATURE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.reset = function(returnCallback, errorCallback) {
		/*
		Calling this function will reset the Brick. Calling this function
		on a Brick inside of a stack will reset the whole stack.
		
		After a reset you have to create new device objects,
		calling functions on the existing ones will result in
		undefined behavior!
		*/
		this.ipcon.sendRequest(this, BrickDC.FUNCTION_RESET, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeBrickletPlugin = function(port, offset, chunk, returnCallback, errorCallback) {
		/*
		Writes 32 bytes of firmware to the bricklet attached at the given port.
		The bytes are written to the position offset * 32.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickDC.FUNCTION_WRITE_BRICKLET_PLUGIN, [port, offset, chunk], 'c B B32', 0, '', returnCallback, errorCallback, false, true);
	};
	this.readBrickletPlugin = function(port, offset, returnCallback, errorCallback) {
		/*
		Reads 32 bytes of firmware from the bricklet attached at the given port.
		The bytes are read starting at the position offset * 32.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickDC.FUNCTION_READ_BRICKLET_PLUGIN, [port, offset], 'c B', 40, 'B32', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Brick is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position is the position in the stack from '0' (bottom) to '8' (top).
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickDC.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickDC;

},{"./Device":279,"./IPConnection":280}],138:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickHAT.DEVICE_IDENTIFIER = 111;
BrickHAT.DEVICE_DISPLAY_NAME = 'HAT Brick';
BrickHAT.CALLBACK_VOLTAGES = 8;
BrickHAT.FUNCTION_SET_SLEEP_MODE = 1;
BrickHAT.FUNCTION_GET_SLEEP_MODE = 2;
BrickHAT.FUNCTION_SET_BRICKLET_POWER = 3;
BrickHAT.FUNCTION_GET_BRICKLET_POWER = 4;
BrickHAT.FUNCTION_GET_VOLTAGES = 5;
BrickHAT.FUNCTION_SET_VOLTAGES_CALLBACK_CONFIGURATION = 6;
BrickHAT.FUNCTION_GET_VOLTAGES_CALLBACK_CONFIGURATION = 7;
BrickHAT.FUNCTION_GET_SPITFP_ERROR_COUNT = 234;
BrickHAT.FUNCTION_SET_BOOTLOADER_MODE = 235;
BrickHAT.FUNCTION_GET_BOOTLOADER_MODE = 236;
BrickHAT.FUNCTION_SET_WRITE_FIRMWARE_POINTER = 237;
BrickHAT.FUNCTION_WRITE_FIRMWARE = 238;
BrickHAT.FUNCTION_SET_STATUS_LED_CONFIG = 239;
BrickHAT.FUNCTION_GET_STATUS_LED_CONFIG = 240;
BrickHAT.FUNCTION_GET_CHIP_TEMPERATURE = 242;
BrickHAT.FUNCTION_RESET = 243;
BrickHAT.FUNCTION_WRITE_UID = 248;
BrickHAT.FUNCTION_READ_UID = 249;
BrickHAT.FUNCTION_GET_IDENTITY = 255;
BrickHAT.BOOTLOADER_MODE_BOOTLOADER = 0;
BrickHAT.BOOTLOADER_MODE_FIRMWARE = 1;
BrickHAT.BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT = 2;
BrickHAT.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT = 3;
BrickHAT.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT = 4;
BrickHAT.BOOTLOADER_STATUS_OK = 0;
BrickHAT.BOOTLOADER_STATUS_INVALID_MODE = 1;
BrickHAT.BOOTLOADER_STATUS_NO_CHANGE = 2;
BrickHAT.BOOTLOADER_STATUS_ENTRY_FUNCTION_NOT_PRESENT = 3;
BrickHAT.BOOTLOADER_STATUS_DEVICE_IDENTIFIER_INCORRECT = 4;
BrickHAT.BOOTLOADER_STATUS_CRC_MISMATCH = 5;
BrickHAT.STATUS_LED_CONFIG_OFF = 0;
BrickHAT.STATUS_LED_CONFIG_ON = 1;
BrickHAT.STATUS_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickHAT.STATUS_LED_CONFIG_SHOW_STATUS = 3;

function BrickHAT(uid, ipcon) {
	//HAT for Raspberry Pi with 8 Bricklets ports and real-time clock

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickHAT.DEVICE_IDENTIFIER, BrickHAT.DEVICE_DISPLAY_NAME);
	BrickHAT.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 1];
	this.responseExpected[BrickHAT.FUNCTION_SET_SLEEP_MODE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickHAT.FUNCTION_GET_SLEEP_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickHAT.FUNCTION_SET_BRICKLET_POWER] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickHAT.FUNCTION_GET_BRICKLET_POWER] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickHAT.FUNCTION_GET_VOLTAGES] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickHAT.FUNCTION_SET_VOLTAGES_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickHAT.FUNCTION_GET_VOLTAGES_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickHAT.FUNCTION_GET_SPITFP_ERROR_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickHAT.FUNCTION_SET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickHAT.FUNCTION_GET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickHAT.FUNCTION_SET_WRITE_FIRMWARE_POINTER] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickHAT.FUNCTION_WRITE_FIRMWARE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickHAT.FUNCTION_SET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickHAT.FUNCTION_GET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickHAT.FUNCTION_GET_CHIP_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickHAT.FUNCTION_RESET] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickHAT.FUNCTION_WRITE_UID] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickHAT.FUNCTION_READ_UID] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickHAT.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickHAT.CALLBACK_VOLTAGES] = [12, 'H H'];



	this.setSleepMode = function(powerOffDelay, powerOffDuration, raspberryPiOff, brickletsOff, enableSleepIndicator, returnCallback, errorCallback) {
		/*
		Sets the sleep mode.
		
		.. note::
		 Calling this function will cut the Raspberry Pi's power after Power Off Delay seconds.
		 You have to shut down the operating system yourself, e.g. by calling 'sudo shutdown -h now'.
		
		Parameters:
		
		* Power Off Delay: Time before the RPi/Bricklets are powered off.
		* Power Off Duration: Duration that the RPi/Bricklets stay powered off.
		* Raspberry Pi Off: RPi is powered off if set to true.
		* Bricklets Off: Bricklets are powered off if set to true.
		* Enable Sleep Indicator: If set to true, the status LED will blink in a 1s interval
		  during the whole power off duration. This will draw additional 0.3mA.
		
		Example: To turn RPi and Bricklets off in 5 seconds for 10 minutes with sleep
		indicator enabled, call (5, 60*10, true, true, true).
		
		This function can also be used to implement a watchdog. To do this you can
		write a program that calls this function once per second in a loop with
		(10, 2, true, false, false). If the RPi crashes or gets stuck
		the HAT will reset the RPi after 10 seconds.
		*/
		this.ipcon.sendRequest(this, BrickHAT.FUNCTION_SET_SLEEP_MODE, [powerOffDelay, powerOffDuration, raspberryPiOff, brickletsOff, enableSleepIndicator], 'I I ? ? ?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getSleepMode = function(returnCallback, errorCallback) {
		/*
		Returns the sleep mode settings as set by :func:`Set Sleep Mode`.
		*/
		this.ipcon.sendRequest(this, BrickHAT.FUNCTION_GET_SLEEP_MODE, [], '', 19, 'I I ? ? ?', returnCallback, errorCallback, false, true);
	};
	this.setBrickletPower = function(brickletPower, returnCallback, errorCallback) {
		/*
		Set to true/false to turn the power supply of the connected Bricklets on/off.
		*/
		this.ipcon.sendRequest(this, BrickHAT.FUNCTION_SET_BRICKLET_POWER, [brickletPower], '?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getBrickletPower = function(returnCallback, errorCallback) {
		/*
		Returns the power status of the connected Bricklets as set by :func:`Set Bricklet Power`.
		*/
		this.ipcon.sendRequest(this, BrickHAT.FUNCTION_GET_BRICKLET_POWER, [], '', 9, '?', returnCallback, errorCallback, false, true);
	};
	this.getVoltages = function(returnCallback, errorCallback) {
		/*
		Returns the USB supply voltage and the DC input supply voltage.
		
		There are three possible combinations:
		
		* Only USB connected: The USB supply voltage will be fed back to the
		  DC input connector. You will read the USB voltage and a slightly lower
		  voltage on the DC input.
		* Only DC input connected: The DC voltage will not be fed back to the
		  USB connector. You will read the DC input voltage and the USB voltage
		  will be 0.
		* USB and DC input connected: You will read both voltages. In this case
		  the USB supply will be without load, but it will work as backup if you
		  disconnect the DC input (or if the DC input voltage falls below the
		  USB voltage).
		*/
		this.ipcon.sendRequest(this, BrickHAT.FUNCTION_GET_VOLTAGES, [], '', 12, 'H H', returnCallback, errorCallback, false, true);
	};
	this.setVoltagesCallbackConfiguration = function(period, valueHasToChange, returnCallback, errorCallback) {
		/*
		The period is the period with which the :cb:`Voltages`
		callback is triggered periodically. A value of 0 turns the callback off.
		
		If the `value has to change`-parameter is set to true, the callback is only
		triggered after the value has changed. If the value didn't change within the
		period, the callback is triggered immediately on change.
		
		If it is set to false, the callback is continuously triggered with the period,
		independent of the value.
		
		.. versionadded:: 2.0.1$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickHAT.FUNCTION_SET_VOLTAGES_CALLBACK_CONFIGURATION, [period, valueHasToChange], 'I ?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getVoltagesCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the callback configuration as set by
		:func:`Set Voltages Callback Configuration`.
		
		.. versionadded:: 2.0.1$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickHAT.FUNCTION_GET_VOLTAGES_CALLBACK_CONFIGURATION, [], '', 13, 'I ?', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPErrorCount = function(returnCallback, errorCallback) {
		/*
		Returns the error count for the communication between Brick and Bricklet.
		
		The errors are divided into
		
		* ACK checksum errors,
		* message checksum errors,
		* framing errors and
		* overflow errors.
		
		The errors counts are for errors that occur on the Bricklet side. All
		Bricks have a similar function that returns the errors on the Brick side.
		*/
		this.ipcon.sendRequest(this, BrickHAT.FUNCTION_GET_SPITFP_ERROR_COUNT, [], '', 24, 'I I I I', returnCallback, errorCallback, false, true);
	};
	this.setBootloaderMode = function(mode, returnCallback, errorCallback) {
		/*
		Sets the bootloader mode and returns the status after the requested
		mode change was instigated.
		
		You can change from bootloader mode to firmware mode and vice versa. A change
		from bootloader mode to firmware mode will only take place if the entry function,
		device identifier and CRC are present and correct.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickHAT.FUNCTION_SET_BOOTLOADER_MODE, [mode], 'B', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getBootloaderMode = function(returnCallback, errorCallback) {
		/*
		Returns the current bootloader mode, see :func:`Set Bootloader Mode`.
		*/
		this.ipcon.sendRequest(this, BrickHAT.FUNCTION_GET_BOOTLOADER_MODE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setWriteFirmwarePointer = function(pointer, returnCallback, errorCallback) {
		/*
		Sets the firmware pointer for :func:`Write Firmware`. The pointer has
		to be increased by chunks of size 64. The data is written to flash
		every 4 chunks (which equals to one page of size 256).
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickHAT.FUNCTION_SET_WRITE_FIRMWARE_POINTER, [pointer], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeFirmware = function(data, returnCallback, errorCallback) {
		/*
		Writes 64 Bytes of firmware at the position as written by
		:func:`Set Write Firmware Pointer` before. The firmware is written
		to flash every 4 chunks.
		
		You can only write firmware in bootloader mode.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickHAT.FUNCTION_WRITE_FIRMWARE, [data], 'B64', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setStatusLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Sets the status LED configuration. By default the LED shows
		communication traffic between Brick and Bricklet, it flickers once
		for every 10 received data packets.
		
		You can also turn the LED permanently on/off or show a heartbeat.
		
		If the Bricklet is in bootloader mode, the LED is will show heartbeat by default.
		*/
		this.ipcon.sendRequest(this, BrickHAT.FUNCTION_SET_STATUS_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getStatusLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Status LED Config`
		*/
		this.ipcon.sendRequest(this, BrickHAT.FUNCTION_GET_STATUS_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getChipTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature as measured inside the microcontroller. The
		value returned is not the ambient temperature!
		
		The temperature is only proportional to the real temperature and it has bad
		accuracy. Practically it is only useful as an indicator for
		temperature changes.
		*/
		this.ipcon.sendRequest(this, BrickHAT.FUNCTION_GET_CHIP_TEMPERATURE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.reset = function(returnCallback, errorCallback) {
		/*
		Calling this function will reset the Bricklet. All configurations
		will be lost.
		
		After a reset you have to create new device objects,
		calling functions on the existing ones will result in
		undefined behavior!
		*/
		this.ipcon.sendRequest(this, BrickHAT.FUNCTION_RESET, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeUID = function(uid, returnCallback, errorCallback) {
		/*
		Writes a new UID into flash. If you want to set a new UID
		you have to decode the Base58 encoded UID string into an
		integer first.
		
		We recommend that you use Brick Viewer to change the UID.
		*/
		this.ipcon.sendRequest(this, BrickHAT.FUNCTION_WRITE_UID, [uid], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.readUID = function(returnCallback, errorCallback) {
		/*
		Returns the current UID as an integer. Encode as
		Base58 to get the usual string version.
		*/
		this.ipcon.sendRequest(this, BrickHAT.FUNCTION_READ_UID, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the HAT is connected to
		(typically '0' as the HAT is the root device in the topology),
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The HAT (Zero) Brick is always at position 'i'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickHAT.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickHAT;

},{"./Device":279,"./IPConnection":280}],139:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickHATZero.DEVICE_IDENTIFIER = 112;
BrickHATZero.DEVICE_DISPLAY_NAME = 'HAT Zero Brick';
BrickHATZero.CALLBACK_USB_VOLTAGE = 4;
BrickHATZero.FUNCTION_GET_USB_VOLTAGE = 1;
BrickHATZero.FUNCTION_SET_USB_VOLTAGE_CALLBACK_CONFIGURATION = 2;
BrickHATZero.FUNCTION_GET_USB_VOLTAGE_CALLBACK_CONFIGURATION = 3;
BrickHATZero.FUNCTION_GET_SPITFP_ERROR_COUNT = 234;
BrickHATZero.FUNCTION_SET_BOOTLOADER_MODE = 235;
BrickHATZero.FUNCTION_GET_BOOTLOADER_MODE = 236;
BrickHATZero.FUNCTION_SET_WRITE_FIRMWARE_POINTER = 237;
BrickHATZero.FUNCTION_WRITE_FIRMWARE = 238;
BrickHATZero.FUNCTION_SET_STATUS_LED_CONFIG = 239;
BrickHATZero.FUNCTION_GET_STATUS_LED_CONFIG = 240;
BrickHATZero.FUNCTION_GET_CHIP_TEMPERATURE = 242;
BrickHATZero.FUNCTION_RESET = 243;
BrickHATZero.FUNCTION_WRITE_UID = 248;
BrickHATZero.FUNCTION_READ_UID = 249;
BrickHATZero.FUNCTION_GET_IDENTITY = 255;
BrickHATZero.THRESHOLD_OPTION_OFF = 'x';
BrickHATZero.THRESHOLD_OPTION_OUTSIDE = 'o';
BrickHATZero.THRESHOLD_OPTION_INSIDE = 'i';
BrickHATZero.THRESHOLD_OPTION_SMALLER = '<';
BrickHATZero.THRESHOLD_OPTION_GREATER = '>';
BrickHATZero.BOOTLOADER_MODE_BOOTLOADER = 0;
BrickHATZero.BOOTLOADER_MODE_FIRMWARE = 1;
BrickHATZero.BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT = 2;
BrickHATZero.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT = 3;
BrickHATZero.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT = 4;
BrickHATZero.BOOTLOADER_STATUS_OK = 0;
BrickHATZero.BOOTLOADER_STATUS_INVALID_MODE = 1;
BrickHATZero.BOOTLOADER_STATUS_NO_CHANGE = 2;
BrickHATZero.BOOTLOADER_STATUS_ENTRY_FUNCTION_NOT_PRESENT = 3;
BrickHATZero.BOOTLOADER_STATUS_DEVICE_IDENTIFIER_INCORRECT = 4;
BrickHATZero.BOOTLOADER_STATUS_CRC_MISMATCH = 5;
BrickHATZero.STATUS_LED_CONFIG_OFF = 0;
BrickHATZero.STATUS_LED_CONFIG_ON = 1;
BrickHATZero.STATUS_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickHATZero.STATUS_LED_CONFIG_SHOW_STATUS = 3;

function BrickHATZero(uid, ipcon) {
	//HAT for Raspberry Pi Zero with 4 Bricklets ports

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickHATZero.DEVICE_IDENTIFIER, BrickHATZero.DEVICE_DISPLAY_NAME);
	BrickHATZero.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 1];
	this.responseExpected[BrickHATZero.FUNCTION_GET_USB_VOLTAGE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickHATZero.FUNCTION_SET_USB_VOLTAGE_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickHATZero.FUNCTION_GET_USB_VOLTAGE_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickHATZero.FUNCTION_GET_SPITFP_ERROR_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickHATZero.FUNCTION_SET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickHATZero.FUNCTION_GET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickHATZero.FUNCTION_SET_WRITE_FIRMWARE_POINTER] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickHATZero.FUNCTION_WRITE_FIRMWARE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickHATZero.FUNCTION_SET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickHATZero.FUNCTION_GET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickHATZero.FUNCTION_GET_CHIP_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickHATZero.FUNCTION_RESET] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickHATZero.FUNCTION_WRITE_UID] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickHATZero.FUNCTION_READ_UID] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickHATZero.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickHATZero.CALLBACK_USB_VOLTAGE] = [10, 'H'];



	this.getUSBVoltage = function(returnCallback, errorCallback) {
		/*
		Returns the USB supply voltage of the Raspberry Pi.
		
		
		If you want to get the value periodically, it is recommended to use the
		:cb:`USB Voltage` callback. You can set the callback configuration
		with :func:`Set USB Voltage Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickHATZero.FUNCTION_GET_USB_VOLTAGE, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.setUSBVoltageCallbackConfiguration = function(period, valueHasToChange, option, min, max, returnCallback, errorCallback) {
		/*
		The period is the period with which the :cb:`USB Voltage` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		If the `value has to change`-parameter is set to true, the callback is only
		triggered after the value has changed. If the value didn't change
		within the period, the callback is triggered immediately on change.
		
		If it is set to false, the callback is continuously triggered with the period,
		independent of the value.
		
		It is furthermore possible to constrain the callback with thresholds.
		
		The `option`-parameter together with min/max sets a threshold for the :cb:`USB Voltage` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Threshold is turned off"
		 "'o'",    "Threshold is triggered when the value is *outside* the min and max values"
		 "'i'",    "Threshold is triggered when the value is *inside* or equal to the min and max values"
		 "'<'",    "Threshold is triggered when the value is smaller than the min value (max is ignored)"
		 "'>'",    "Threshold is triggered when the value is greater than the min value (max is ignored)"
		
		If the option is set to 'x' (threshold turned off) the callback is triggered with the fixed period.
		
		.. versionadded:: 2.0.1$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickHATZero.FUNCTION_SET_USB_VOLTAGE_CALLBACK_CONFIGURATION, [period, valueHasToChange, option, min, max], 'I ? c H H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getUSBVoltageCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the callback configuration as set by :func:`Set USB Voltage Callback Configuration`.
		
		.. versionadded:: 2.0.1$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickHATZero.FUNCTION_GET_USB_VOLTAGE_CALLBACK_CONFIGURATION, [], '', 18, 'I ? c H H', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPErrorCount = function(returnCallback, errorCallback) {
		/*
		Returns the error count for the communication between Brick and Bricklet.
		
		The errors are divided into
		
		* ACK checksum errors,
		* message checksum errors,
		* framing errors and
		* overflow errors.
		
		The errors counts are for errors that occur on the Bricklet side. All
		Bricks have a similar function that returns the errors on the Brick side.
		*/
		this.ipcon.sendRequest(this, BrickHATZero.FUNCTION_GET_SPITFP_ERROR_COUNT, [], '', 24, 'I I I I', returnCallback, errorCallback, false, true);
	};
	this.setBootloaderMode = function(mode, returnCallback, errorCallback) {
		/*
		Sets the bootloader mode and returns the status after the requested
		mode change was instigated.
		
		You can change from bootloader mode to firmware mode and vice versa. A change
		from bootloader mode to firmware mode will only take place if the entry function,
		device identifier and CRC are present and correct.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickHATZero.FUNCTION_SET_BOOTLOADER_MODE, [mode], 'B', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getBootloaderMode = function(returnCallback, errorCallback) {
		/*
		Returns the current bootloader mode, see :func:`Set Bootloader Mode`.
		*/
		this.ipcon.sendRequest(this, BrickHATZero.FUNCTION_GET_BOOTLOADER_MODE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setWriteFirmwarePointer = function(pointer, returnCallback, errorCallback) {
		/*
		Sets the firmware pointer for :func:`Write Firmware`. The pointer has
		to be increased by chunks of size 64. The data is written to flash
		every 4 chunks (which equals to one page of size 256).
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickHATZero.FUNCTION_SET_WRITE_FIRMWARE_POINTER, [pointer], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeFirmware = function(data, returnCallback, errorCallback) {
		/*
		Writes 64 Bytes of firmware at the position as written by
		:func:`Set Write Firmware Pointer` before. The firmware is written
		to flash every 4 chunks.
		
		You can only write firmware in bootloader mode.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickHATZero.FUNCTION_WRITE_FIRMWARE, [data], 'B64', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setStatusLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Sets the status LED configuration. By default the LED shows
		communication traffic between Brick and Bricklet, it flickers once
		for every 10 received data packets.
		
		You can also turn the LED permanently on/off or show a heartbeat.
		
		If the Bricklet is in bootloader mode, the LED is will show heartbeat by default.
		*/
		this.ipcon.sendRequest(this, BrickHATZero.FUNCTION_SET_STATUS_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getStatusLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Status LED Config`
		*/
		this.ipcon.sendRequest(this, BrickHATZero.FUNCTION_GET_STATUS_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getChipTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature as measured inside the microcontroller. The
		value returned is not the ambient temperature!
		
		The temperature is only proportional to the real temperature and it has bad
		accuracy. Practically it is only useful as an indicator for
		temperature changes.
		*/
		this.ipcon.sendRequest(this, BrickHATZero.FUNCTION_GET_CHIP_TEMPERATURE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.reset = function(returnCallback, errorCallback) {
		/*
		Calling this function will reset the Bricklet. All configurations
		will be lost.
		
		After a reset you have to create new device objects,
		calling functions on the existing ones will result in
		undefined behavior!
		*/
		this.ipcon.sendRequest(this, BrickHATZero.FUNCTION_RESET, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeUID = function(uid, returnCallback, errorCallback) {
		/*
		Writes a new UID into flash. If you want to set a new UID
		you have to decode the Base58 encoded UID string into an
		integer first.
		
		We recommend that you use Brick Viewer to change the UID.
		*/
		this.ipcon.sendRequest(this, BrickHATZero.FUNCTION_WRITE_UID, [uid], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.readUID = function(returnCallback, errorCallback) {
		/*
		Returns the current UID as an integer. Encode as
		Base58 to get the usual string version.
		*/
		this.ipcon.sendRequest(this, BrickHATZero.FUNCTION_READ_UID, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the HAT is connected to
		(typically '0' as the HAT is the root device in the topology),
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The HAT (Zero) Brick is always at position 'i'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickHATZero.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickHATZero;

},{"./Device":279,"./IPConnection":280}],140:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickIMU.DEVICE_IDENTIFIER = 16;
BrickIMU.DEVICE_DISPLAY_NAME = 'IMU Brick';
BrickIMU.CALLBACK_ACCELERATION = 31;
BrickIMU.CALLBACK_MAGNETIC_FIELD = 32;
BrickIMU.CALLBACK_ANGULAR_VELOCITY = 33;
BrickIMU.CALLBACK_ALL_DATA = 34;
BrickIMU.CALLBACK_ORIENTATION = 35;
BrickIMU.CALLBACK_QUATERNION = 36;
BrickIMU.FUNCTION_GET_ACCELERATION = 1;
BrickIMU.FUNCTION_GET_MAGNETIC_FIELD = 2;
BrickIMU.FUNCTION_GET_ANGULAR_VELOCITY = 3;
BrickIMU.FUNCTION_GET_ALL_DATA = 4;
BrickIMU.FUNCTION_GET_ORIENTATION = 5;
BrickIMU.FUNCTION_GET_QUATERNION = 6;
BrickIMU.FUNCTION_GET_IMU_TEMPERATURE = 7;
BrickIMU.FUNCTION_LEDS_ON = 8;
BrickIMU.FUNCTION_LEDS_OFF = 9;
BrickIMU.FUNCTION_ARE_LEDS_ON = 10;
BrickIMU.FUNCTION_SET_ACCELERATION_RANGE = 11;
BrickIMU.FUNCTION_GET_ACCELERATION_RANGE = 12;
BrickIMU.FUNCTION_SET_MAGNETOMETER_RANGE = 13;
BrickIMU.FUNCTION_GET_MAGNETOMETER_RANGE = 14;
BrickIMU.FUNCTION_SET_CONVERGENCE_SPEED = 15;
BrickIMU.FUNCTION_GET_CONVERGENCE_SPEED = 16;
BrickIMU.FUNCTION_SET_CALIBRATION = 17;
BrickIMU.FUNCTION_GET_CALIBRATION = 18;
BrickIMU.FUNCTION_SET_ACCELERATION_PERIOD = 19;
BrickIMU.FUNCTION_GET_ACCELERATION_PERIOD = 20;
BrickIMU.FUNCTION_SET_MAGNETIC_FIELD_PERIOD = 21;
BrickIMU.FUNCTION_GET_MAGNETIC_FIELD_PERIOD = 22;
BrickIMU.FUNCTION_SET_ANGULAR_VELOCITY_PERIOD = 23;
BrickIMU.FUNCTION_GET_ANGULAR_VELOCITY_PERIOD = 24;
BrickIMU.FUNCTION_SET_ALL_DATA_PERIOD = 25;
BrickIMU.FUNCTION_GET_ALL_DATA_PERIOD = 26;
BrickIMU.FUNCTION_SET_ORIENTATION_PERIOD = 27;
BrickIMU.FUNCTION_GET_ORIENTATION_PERIOD = 28;
BrickIMU.FUNCTION_SET_QUATERNION_PERIOD = 29;
BrickIMU.FUNCTION_GET_QUATERNION_PERIOD = 30;
BrickIMU.FUNCTION_ORIENTATION_CALCULATION_ON = 37;
BrickIMU.FUNCTION_ORIENTATION_CALCULATION_OFF = 38;
BrickIMU.FUNCTION_IS_ORIENTATION_CALCULATION_ON = 39;
BrickIMU.FUNCTION_SET_SPITFP_BAUDRATE_CONFIG = 231;
BrickIMU.FUNCTION_GET_SPITFP_BAUDRATE_CONFIG = 232;
BrickIMU.FUNCTION_GET_SEND_TIMEOUT_COUNT = 233;
BrickIMU.FUNCTION_SET_SPITFP_BAUDRATE = 234;
BrickIMU.FUNCTION_GET_SPITFP_BAUDRATE = 235;
BrickIMU.FUNCTION_GET_SPITFP_ERROR_COUNT = 237;
BrickIMU.FUNCTION_ENABLE_STATUS_LED = 238;
BrickIMU.FUNCTION_DISABLE_STATUS_LED = 239;
BrickIMU.FUNCTION_IS_STATUS_LED_ENABLED = 240;
BrickIMU.FUNCTION_GET_PROTOCOL1_BRICKLET_NAME = 241;
BrickIMU.FUNCTION_GET_CHIP_TEMPERATURE = 242;
BrickIMU.FUNCTION_RESET = 243;
BrickIMU.FUNCTION_WRITE_BRICKLET_PLUGIN = 246;
BrickIMU.FUNCTION_READ_BRICKLET_PLUGIN = 247;
BrickIMU.FUNCTION_GET_IDENTITY = 255;
BrickIMU.CALIBRATION_TYPE_ACCELEROMETER_GAIN = 0;
BrickIMU.CALIBRATION_TYPE_ACCELEROMETER_BIAS = 1;
BrickIMU.CALIBRATION_TYPE_MAGNETOMETER_GAIN = 2;
BrickIMU.CALIBRATION_TYPE_MAGNETOMETER_BIAS = 3;
BrickIMU.CALIBRATION_TYPE_GYROSCOPE_GAIN = 4;
BrickIMU.CALIBRATION_TYPE_GYROSCOPE_BIAS = 5;
BrickIMU.COMMUNICATION_METHOD_NONE = 0;
BrickIMU.COMMUNICATION_METHOD_USB = 1;
BrickIMU.COMMUNICATION_METHOD_SPI_STACK = 2;
BrickIMU.COMMUNICATION_METHOD_CHIBI = 3;
BrickIMU.COMMUNICATION_METHOD_RS485 = 4;
BrickIMU.COMMUNICATION_METHOD_WIFI = 5;
BrickIMU.COMMUNICATION_METHOD_ETHERNET = 6;
BrickIMU.COMMUNICATION_METHOD_WIFI_V2 = 7;

function BrickIMU(uid, ipcon) {
	//Full fledged AHRS with 9 degrees of freedom

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickIMU.DEVICE_IDENTIFIER, BrickIMU.DEVICE_DISPLAY_NAME);
	BrickIMU.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 4];
	this.responseExpected[BrickIMU.FUNCTION_GET_ACCELERATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickIMU.FUNCTION_GET_MAGNETIC_FIELD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickIMU.FUNCTION_GET_ANGULAR_VELOCITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickIMU.FUNCTION_GET_ALL_DATA] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickIMU.FUNCTION_GET_ORIENTATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickIMU.FUNCTION_GET_QUATERNION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickIMU.FUNCTION_GET_IMU_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickIMU.FUNCTION_LEDS_ON] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickIMU.FUNCTION_LEDS_OFF] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickIMU.FUNCTION_ARE_LEDS_ON] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickIMU.FUNCTION_SET_ACCELERATION_RANGE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickIMU.FUNCTION_GET_ACCELERATION_RANGE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickIMU.FUNCTION_SET_MAGNETOMETER_RANGE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickIMU.FUNCTION_GET_MAGNETOMETER_RANGE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickIMU.FUNCTION_SET_CONVERGENCE_SPEED] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickIMU.FUNCTION_GET_CONVERGENCE_SPEED] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickIMU.FUNCTION_SET_CALIBRATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickIMU.FUNCTION_GET_CALIBRATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickIMU.FUNCTION_SET_ACCELERATION_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickIMU.FUNCTION_GET_ACCELERATION_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickIMU.FUNCTION_SET_MAGNETIC_FIELD_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickIMU.FUNCTION_GET_MAGNETIC_FIELD_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickIMU.FUNCTION_SET_ANGULAR_VELOCITY_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickIMU.FUNCTION_GET_ANGULAR_VELOCITY_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickIMU.FUNCTION_SET_ALL_DATA_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickIMU.FUNCTION_GET_ALL_DATA_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickIMU.FUNCTION_SET_ORIENTATION_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickIMU.FUNCTION_GET_ORIENTATION_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickIMU.FUNCTION_SET_QUATERNION_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickIMU.FUNCTION_GET_QUATERNION_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickIMU.FUNCTION_ORIENTATION_CALCULATION_ON] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickIMU.FUNCTION_ORIENTATION_CALCULATION_OFF] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickIMU.FUNCTION_IS_ORIENTATION_CALCULATION_ON] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickIMU.FUNCTION_SET_SPITFP_BAUDRATE_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickIMU.FUNCTION_GET_SPITFP_BAUDRATE_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickIMU.FUNCTION_GET_SEND_TIMEOUT_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickIMU.FUNCTION_SET_SPITFP_BAUDRATE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickIMU.FUNCTION_GET_SPITFP_BAUDRATE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickIMU.FUNCTION_GET_SPITFP_ERROR_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickIMU.FUNCTION_ENABLE_STATUS_LED] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickIMU.FUNCTION_DISABLE_STATUS_LED] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickIMU.FUNCTION_IS_STATUS_LED_ENABLED] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickIMU.FUNCTION_GET_PROTOCOL1_BRICKLET_NAME] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickIMU.FUNCTION_GET_CHIP_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickIMU.FUNCTION_RESET] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickIMU.FUNCTION_WRITE_BRICKLET_PLUGIN] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickIMU.FUNCTION_READ_BRICKLET_PLUGIN] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickIMU.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickIMU.CALLBACK_ACCELERATION] = [14, 'h h h'];
	this.callbackFormats[BrickIMU.CALLBACK_MAGNETIC_FIELD] = [14, 'h h h'];
	this.callbackFormats[BrickIMU.CALLBACK_ANGULAR_VELOCITY] = [14, 'h h h'];
	this.callbackFormats[BrickIMU.CALLBACK_ALL_DATA] = [28, 'h h h h h h h h h h'];
	this.callbackFormats[BrickIMU.CALLBACK_ORIENTATION] = [14, 'h h h'];
	this.callbackFormats[BrickIMU.CALLBACK_QUATERNION] = [24, 'f f f f'];



	this.getAcceleration = function(returnCallback, errorCallback) {
		/*
		Returns the calibrated acceleration from the accelerometer for the
		x, y and z axis.
		
		If you want to get the acceleration periodically, it is recommended
		to use the :cb:`Acceleration` callback and set the period with
		:func:`Set Acceleration Period`.
		*/
		this.ipcon.sendRequest(this, BrickIMU.FUNCTION_GET_ACCELERATION, [], '', 14, 'h h h', returnCallback, errorCallback, false, true);
	};
	this.getMagneticField = function(returnCallback, errorCallback) {
		/*
		Returns the calibrated magnetic field from the magnetometer for the
		x, y and z axis.
		
		If you want to get the magnetic field periodically, it is recommended
		to use the :cb:`Magnetic Field` callback and set the period with
		:func:`Set Magnetic Field Period`.
		*/
		this.ipcon.sendRequest(this, BrickIMU.FUNCTION_GET_MAGNETIC_FIELD, [], '', 14, 'h h h', returnCallback, errorCallback, false, true);
	};
	this.getAngularVelocity = function(returnCallback, errorCallback) {
		/*
		Returns the calibrated angular velocity from the gyroscope for the
		x, y and z axis in °/14.375s (you have to divide by 14.375 to
		get the value in °/s).
		
		If you want to get the angular velocity periodically, it is recommended
		to use the :cb:`Angular Velocity` callback and set the period with
		:func:`Set Angular Velocity Period`.
		*/
		this.ipcon.sendRequest(this, BrickIMU.FUNCTION_GET_ANGULAR_VELOCITY, [], '', 14, 'h h h', returnCallback, errorCallback, false, true);
	};
	this.getAllData = function(returnCallback, errorCallback) {
		/*
		Returns the data from :func:`Get Acceleration`, :func:`Get Magnetic Field`
		and :func:`Get Angular Velocity` as well as the temperature of the IMU Brick.
		
		If you want to get the data periodically, it is recommended
		to use the :cb:`All Data` callback and set the period with
		:func:`Set All Data Period`.
		*/
		this.ipcon.sendRequest(this, BrickIMU.FUNCTION_GET_ALL_DATA, [], '', 28, 'h h h h h h h h h h', returnCallback, errorCallback, false, true);
	};
	this.getOrientation = function(returnCallback, errorCallback) {
		/*
		Returns the current orientation (roll, pitch, yaw) of the IMU Brick as Euler
		angles. Note that Euler angles always experience a
		`gimbal lock <https://en.wikipedia.org/wiki/Gimbal_lock>`__.
		
		We recommend that you use quaternions instead.
		
		The order to sequence in which the orientation values should be applied is
		roll, yaw, pitch.
		
		If you want to get the orientation periodically, it is recommended
		to use the :cb:`Orientation` callback and set the period with
		:func:`Set Orientation Period`.
		*/
		this.ipcon.sendRequest(this, BrickIMU.FUNCTION_GET_ORIENTATION, [], '', 14, 'h h h', returnCallback, errorCallback, false, true);
	};
	this.getQuaternion = function(returnCallback, errorCallback) {
		/*
		Returns the current orientation (x, y, z, w) of the IMU as
		`quaternions <https://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation>`__.
		
		You can go from quaternions to Euler angles with the following formula::
		
		 xAngle = atan2(2*y*w - 2*x*z, 1 - 2*y*y - 2*z*z)
		 yAngle = atan2(2*x*w - 2*y*z, 1 - 2*x*x - 2*z*z)
		 zAngle =  asin(2*x*y + 2*z*w)
		
		This process is not reversible, because of the
		`gimbal lock <https://en.wikipedia.org/wiki/Gimbal_lock>`__.
		
		It is also possible to calculate independent angles. You can calculate
		yaw, pitch and roll in a right-handed vehicle coordinate system according to
		DIN70000 with::
		
		 yaw   =  atan2(2*x*y + 2*w*z, w*w + x*x - y*y - z*z)
		 pitch = -asin(2*w*y - 2*x*z)
		 roll  = -atan2(2*y*z + 2*w*x, -w*w + x*x + y*y - z*z))
		
		Converting the quaternions to an OpenGL transformation matrix is
		possible with the following formula::
		
		 matrix = [[1 - 2*(y*y + z*z),     2*(x*y - w*z),     2*(x*z + w*y), 0],
		           [    2*(x*y + w*z), 1 - 2*(x*x + z*z),     2*(y*z - w*x), 0],
		           [    2*(x*z - w*y),     2*(y*z + w*x), 1 - 2*(x*x + y*y), 0],
		           [                0,                 0,                 0, 1]]
		
		If you want to get the quaternions periodically, it is recommended
		to use the :cb:`Quaternion` callback and set the period with
		:func:`Set Quaternion Period`.
		*/
		this.ipcon.sendRequest(this, BrickIMU.FUNCTION_GET_QUATERNION, [], '', 24, 'f f f f', returnCallback, errorCallback, false, true);
	};
	this.getIMUTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature of the IMU Brick.
		*/
		this.ipcon.sendRequest(this, BrickIMU.FUNCTION_GET_IMU_TEMPERATURE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.ledsOn = function(returnCallback, errorCallback) {
		/*
		Turns the orientation and direction LEDs of the IMU Brick on.
		*/
		this.ipcon.sendRequest(this, BrickIMU.FUNCTION_LEDS_ON, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.ledsOff = function(returnCallback, errorCallback) {
		/*
		Turns the orientation and direction LEDs of the IMU Brick off.
		*/
		this.ipcon.sendRequest(this, BrickIMU.FUNCTION_LEDS_OFF, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.areLedsOn = function(returnCallback, errorCallback) {
		/*
		Returns *true* if the orientation and direction LEDs of the IMU Brick
		are on, *false* otherwise.
		*/
		this.ipcon.sendRequest(this, BrickIMU.FUNCTION_ARE_LEDS_ON, [], '', 9, '?', returnCallback, errorCallback, false, true);
	};
	this.setAccelerationRange = function(range, returnCallback, errorCallback) {
		/*
		Not implemented yet.
		*/
		this.ipcon.sendRequest(this, BrickIMU.FUNCTION_SET_ACCELERATION_RANGE, [range], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getAccelerationRange = function(returnCallback, errorCallback) {
		/*
		Not implemented yet.
		*/
		this.ipcon.sendRequest(this, BrickIMU.FUNCTION_GET_ACCELERATION_RANGE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setMagnetometerRange = function(range, returnCallback, errorCallback) {
		/*
		Not implemented yet.
		*/
		this.ipcon.sendRequest(this, BrickIMU.FUNCTION_SET_MAGNETOMETER_RANGE, [range], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getMagnetometerRange = function(returnCallback, errorCallback) {
		/*
		Not implemented yet.
		*/
		this.ipcon.sendRequest(this, BrickIMU.FUNCTION_GET_MAGNETOMETER_RANGE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setConvergenceSpeed = function(speed, returnCallback, errorCallback) {
		/*
		Sets the convergence speed of the IMU Brick. The convergence speed
		determines how the different sensor measurements are fused.
		
		If the orientation of the IMU Brick is off by 10° and the convergence speed is
		set to 20°/s, it will take 0.5s until the orientation is corrected. However,
		if the correct orientation is reached and the convergence speed is too high,
		the orientation will fluctuate with the fluctuations of the accelerometer and
		the magnetometer.
		
		If you set the convergence speed to 0, practically only the gyroscope is used
		to calculate the orientation. This gives very smooth movements, but errors of the
		gyroscope will not be corrected. If you set the convergence speed to something
		above 500, practically only the magnetometer and the accelerometer are used to
		calculate the orientation. In this case the movements are abrupt and the values
		will fluctuate, but there won't be any errors that accumulate over time.
		
		In an application with high angular velocities, we recommend a high convergence
		speed, so the errors of the gyroscope can be corrected fast. In applications with
		only slow movements we recommend a low convergence speed. You can change the
		convergence speed on the fly. So it is possible (and recommended) to increase
		the convergence speed before an abrupt movement and decrease it afterwards
		again.
		
		You might want to play around with the convergence speed in the Brick Viewer to
		get a feeling for a good value for your application.
		*/
		this.ipcon.sendRequest(this, BrickIMU.FUNCTION_SET_CONVERGENCE_SPEED, [speed], 'H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getConvergenceSpeed = function(returnCallback, errorCallback) {
		/*
		Returns the convergence speed as set by :func:`Set Convergence Speed`.
		*/
		this.ipcon.sendRequest(this, BrickIMU.FUNCTION_GET_CONVERGENCE_SPEED, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.setCalibration = function(typ, data, returnCallback, errorCallback) {
		/*
		There are several different types that can be calibrated:
		
		.. csv-table::
		 :header: "Type", "Description", "Values"
		 :widths: 10, 30, 110
		
		 "0",    "Accelerometer Gain", "``[mul x, mul y, mul z, div x, div y, div z, 0, 0, 0, 0]``"
		 "1",    "Accelerometer Bias", "``[bias x, bias y, bias z, 0, 0, 0, 0, 0, 0, 0]``"
		 "2",    "Magnetometer Gain",  "``[mul x, mul y, mul z, div x, div y, div z, 0, 0, 0, 0]``"
		 "3",    "Magnetometer Bias",  "``[bias x, bias y, bias z, 0, 0, 0, 0, 0, 0, 0]``"
		 "4",    "Gyroscope Gain",     "``[mul x, mul y, mul z, div x, div y, div z, 0, 0, 0, 0]``"
		 "5",    "Gyroscope Bias",     "``[bias xl, bias yl, bias zl, temp l, bias xh, bias yh, bias zh, temp h, 0, 0]``"
		
		The calibration via gain and bias is done with the following formula::
		
		 new_value = (bias + orig_value) * gain_mul / gain_div
		
		If you really want to write your own calibration software, please keep
		in mind that you first have to undo the old calibration (set bias to 0 and
		gain to 1/1) and that you have to average over several thousand values
		to obtain a usable result in the end.
		
		The gyroscope bias is highly dependent on the temperature, so you have to
		calibrate the bias two times with different temperatures. The values ``xl``,
		``yl``, ``zl`` and ``temp l`` are the bias for ``x``, ``y``, ``z`` and the
		corresponding temperature for a low temperature. The values ``xh``, ``yh``,
		``zh`` and ``temp h`` are the same for a high temperatures. The temperature
		difference should be at least 5°C. If you have a temperature where the
		IMU Brick is mostly used, you should use this temperature for one of the
		sampling points.
		
		.. note::
		 We highly recommend that you use the Brick Viewer to calibrate your
		 IMU Brick.
		*/
		this.ipcon.sendRequest(this, BrickIMU.FUNCTION_SET_CALIBRATION, [typ, data], 'B h10', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getCalibration = function(typ, returnCallback, errorCallback) {
		/*
		Returns the calibration for a given type as set by :func:`Set Calibration`.
		*/
		this.ipcon.sendRequest(this, BrickIMU.FUNCTION_GET_CALIBRATION, [typ], 'B', 28, 'h10', returnCallback, errorCallback, false, true);
	};
	this.setAccelerationPeriod = function(period, returnCallback, errorCallback) {
		/*
		Sets the period with which the :cb:`Acceleration` callback is triggered
		periodically. A value of 0 turns the callback off.
		*/
		this.ipcon.sendRequest(this, BrickIMU.FUNCTION_SET_ACCELERATION_PERIOD, [period], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getAccelerationPeriod = function(returnCallback, errorCallback) {
		/*
		Returns the period as set by :func:`Set Acceleration Period`.
		*/
		this.ipcon.sendRequest(this, BrickIMU.FUNCTION_GET_ACCELERATION_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setMagneticFieldPeriod = function(period, returnCallback, errorCallback) {
		/*
		Sets the period with which the :cb:`Magnetic Field` callback is
		triggered periodically. A value of 0 turns the callback off.
		*/
		this.ipcon.sendRequest(this, BrickIMU.FUNCTION_SET_MAGNETIC_FIELD_PERIOD, [period], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getMagneticFieldPeriod = function(returnCallback, errorCallback) {
		/*
		Returns the period as set by :func:`Set Magnetic Field Period`.
		*/
		this.ipcon.sendRequest(this, BrickIMU.FUNCTION_GET_MAGNETIC_FIELD_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setAngularVelocityPeriod = function(period, returnCallback, errorCallback) {
		/*
		Sets the period with which the :cb:`Angular Velocity` callback is
		triggered periodically. A value of 0 turns the callback off.
		*/
		this.ipcon.sendRequest(this, BrickIMU.FUNCTION_SET_ANGULAR_VELOCITY_PERIOD, [period], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getAngularVelocityPeriod = function(returnCallback, errorCallback) {
		/*
		Returns the period as set by :func:`Set Angular Velocity Period`.
		*/
		this.ipcon.sendRequest(this, BrickIMU.FUNCTION_GET_ANGULAR_VELOCITY_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setAllDataPeriod = function(period, returnCallback, errorCallback) {
		/*
		Sets the period with which the :cb:`All Data` callback is triggered
		periodically. A value of 0 turns the callback off.
		*/
		this.ipcon.sendRequest(this, BrickIMU.FUNCTION_SET_ALL_DATA_PERIOD, [period], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getAllDataPeriod = function(returnCallback, errorCallback) {
		/*
		Returns the period as set by :func:`Set All Data Period`.
		*/
		this.ipcon.sendRequest(this, BrickIMU.FUNCTION_GET_ALL_DATA_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setOrientationPeriod = function(period, returnCallback, errorCallback) {
		/*
		Sets the period with which the :cb:`Orientation` callback is triggered
		periodically. A value of 0 turns the callback off.
		*/
		this.ipcon.sendRequest(this, BrickIMU.FUNCTION_SET_ORIENTATION_PERIOD, [period], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getOrientationPeriod = function(returnCallback, errorCallback) {
		/*
		Returns the period as set by :func:`Set Orientation Period`.
		*/
		this.ipcon.sendRequest(this, BrickIMU.FUNCTION_GET_ORIENTATION_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setQuaternionPeriod = function(period, returnCallback, errorCallback) {
		/*
		Sets the period with which the :cb:`Quaternion` callback is triggered
		periodically. A value of 0 turns the callback off.
		*/
		this.ipcon.sendRequest(this, BrickIMU.FUNCTION_SET_QUATERNION_PERIOD, [period], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getQuaternionPeriod = function(returnCallback, errorCallback) {
		/*
		Returns the period as set by :func:`Set Quaternion Period`.
		*/
		this.ipcon.sendRequest(this, BrickIMU.FUNCTION_GET_QUATERNION_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.orientationCalculationOn = function(returnCallback, errorCallback) {
		/*
		Turns the orientation calculation of the IMU Brick on.
		
		As default the calculation is on.
		
		.. versionadded:: 2.0.2$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickIMU.FUNCTION_ORIENTATION_CALCULATION_ON, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.orientationCalculationOff = function(returnCallback, errorCallback) {
		/*
		Turns the orientation calculation of the IMU Brick off.
		
		If the calculation is off, :func:`Get Orientation` will return
		the last calculated value until the calculation is turned on again.
		
		The trigonometric functions that are needed to calculate the orientation
		are very expensive. We recommend to turn the orientation calculation
		off if the orientation is not needed, to free calculation time for the
		sensor fusion algorithm.
		
		As default the calculation is on.
		
		.. versionadded:: 2.0.2$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickIMU.FUNCTION_ORIENTATION_CALCULATION_OFF, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.isOrientationCalculationOn = function(returnCallback, errorCallback) {
		/*
		Returns *true* if the orientation calculation of the IMU Brick
		is on, *false* otherwise.
		
		.. versionadded:: 2.0.2$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickIMU.FUNCTION_IS_ORIENTATION_CALCULATION_ON, [], '', 9, '?', returnCallback, errorCallback, false, true);
	};
	this.setSPITFPBaudrateConfig = function(enableDynamicBaudrate, minimumDynamicBaudrate, returnCallback, errorCallback) {
		/*
		The SPITF protocol can be used with a dynamic baudrate. If the dynamic baudrate is
		enabled, the Brick will try to adapt the baudrate for the communication
		between Bricks and Bricklets according to the amount of data that is transferred.
		
		The baudrate will be increased exponentially if lots of data is sent/received and
		decreased linearly if little data is sent/received.
		
		This lowers the baudrate in applications where little data is transferred (e.g.
		a weather station) and increases the robustness. If there is lots of data to transfer
		(e.g. Thermal Imaging Bricklet) it automatically increases the baudrate as needed.
		
		In cases where some data has to transferred as fast as possible every few seconds
		(e.g. RS485 Bricklet with a high baudrate but small payload) you may want to turn
		the dynamic baudrate off to get the highest possible performance.
		
		The maximum value of the baudrate can be set per port with the function
		:func:`Set SPITFP Baudrate`. If the dynamic baudrate is disabled, the baudrate
		as set by :func:`Set SPITFP Baudrate` will be used statically.
		
		.. versionadded:: 2.3.5$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickIMU.FUNCTION_SET_SPITFP_BAUDRATE_CONFIG, [enableDynamicBaudrate, minimumDynamicBaudrate], '? I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPBaudrateConfig = function(returnCallback, errorCallback) {
		/*
		Returns the baudrate config, see :func:`Set SPITFP Baudrate Config`.
		
		.. versionadded:: 2.3.5$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickIMU.FUNCTION_GET_SPITFP_BAUDRATE_CONFIG, [], '', 13, '? I', returnCallback, errorCallback, false, true);
	};
	this.getSendTimeoutCount = function(communicationMethod, returnCallback, errorCallback) {
		/*
		Returns the timeout count for the different communication methods.
		
		The methods 0-2 are available for all Bricks, 3-7 only for Master Bricks.
		
		This function is mostly used for debugging during development, in normal operation
		the counters should nearly always stay at 0.
		
		.. versionadded:: 2.3.3$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickIMU.FUNCTION_GET_SEND_TIMEOUT_COUNT, [communicationMethod], 'B', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setSPITFPBaudrate = function(brickletPort, baudrate, returnCallback, errorCallback) {
		/*
		Sets the baudrate for a specific Bricklet port.
		
		If you want to increase the throughput of Bricklets you can increase
		the baudrate. If you get a high error count because of high
		interference (see :func:`Get SPITFP Error Count`) you can decrease the
		baudrate.
		
		If the dynamic baudrate feature is enabled, the baudrate set by this
		function corresponds to the maximum baudrate (see :func:`Set SPITFP Baudrate Config`).
		
		Regulatory testing is done with the default baudrate. If CE compatibility
		or similar is necessary in your applications we recommend to not change
		the baudrate.
		
		.. versionadded:: 2.3.3$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickIMU.FUNCTION_SET_SPITFP_BAUDRATE, [brickletPort, baudrate], 'c I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPBaudrate = function(brickletPort, returnCallback, errorCallback) {
		/*
		Returns the baudrate for a given Bricklet port, see :func:`Set SPITFP Baudrate`.
		
		.. versionadded:: 2.3.3$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickIMU.FUNCTION_GET_SPITFP_BAUDRATE, [brickletPort], 'c', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPErrorCount = function(brickletPort, returnCallback, errorCallback) {
		/*
		Returns the error count for the communication between Brick and Bricklet.
		
		The errors are divided into
		
		* ACK checksum errors,
		* message checksum errors,
		* framing errors and
		* overflow errors.
		
		The errors counts are for errors that occur on the Brick side. All
		Bricklets have a similar function that returns the errors on the Bricklet side.
		
		.. versionadded:: 2.3.3$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickIMU.FUNCTION_GET_SPITFP_ERROR_COUNT, [brickletPort], 'c', 24, 'I I I I', returnCallback, errorCallback, false, true);
	};
	this.enableStatusLED = function(returnCallback, errorCallback) {
		/*
		Enables the status LED.
		
		The status LED is the blue LED next to the USB connector. If enabled is is
		on and it flickers if data is transfered. If disabled it is always off.
		
		The default state is enabled.
		
		.. versionadded:: 2.3.1$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickIMU.FUNCTION_ENABLE_STATUS_LED, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.disableStatusLED = function(returnCallback, errorCallback) {
		/*
		Disables the status LED.
		
		The status LED is the blue LED next to the USB connector. If enabled is is
		on and it flickers if data is transfered. If disabled it is always off.
		
		The default state is enabled.
		
		.. versionadded:: 2.3.1$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickIMU.FUNCTION_DISABLE_STATUS_LED, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.isStatusLEDEnabled = function(returnCallback, errorCallback) {
		/*
		Returns *true* if the status LED is enabled, *false* otherwise.
		
		.. versionadded:: 2.3.1$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickIMU.FUNCTION_IS_STATUS_LED_ENABLED, [], '', 9, '?', returnCallback, errorCallback, false, true);
	};
	this.getProtocol1BrickletName = function(port, returnCallback, errorCallback) {
		/*
		Returns the firmware and protocol version and the name of the Bricklet for a
		given port.
		
		This functions sole purpose is to allow automatic flashing of v1.x.y Bricklet
		plugins.
		*/
		this.ipcon.sendRequest(this, BrickIMU.FUNCTION_GET_PROTOCOL1_BRICKLET_NAME, [port], 'c', 52, 'B B3 s40', returnCallback, errorCallback, false, true);
	};
	this.getChipTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature as measured inside the microcontroller. The
		value returned is not the ambient temperature!
		
		The temperature is only proportional to the real temperature and it has an
		accuracy of ±15%. Practically it is only useful as an indicator for
		temperature changes.
		*/
		this.ipcon.sendRequest(this, BrickIMU.FUNCTION_GET_CHIP_TEMPERATURE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.reset = function(returnCallback, errorCallback) {
		/*
		Calling this function will reset the Brick. Calling this function
		on a Brick inside of a stack will reset the whole stack.
		
		After a reset you have to create new device objects,
		calling functions on the existing ones will result in
		undefined behavior!
		*/
		this.ipcon.sendRequest(this, BrickIMU.FUNCTION_RESET, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeBrickletPlugin = function(port, offset, chunk, returnCallback, errorCallback) {
		/*
		Writes 32 bytes of firmware to the bricklet attached at the given port.
		The bytes are written to the position offset * 32.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickIMU.FUNCTION_WRITE_BRICKLET_PLUGIN, [port, offset, chunk], 'c B B32', 0, '', returnCallback, errorCallback, false, true);
	};
	this.readBrickletPlugin = function(port, offset, returnCallback, errorCallback) {
		/*
		Reads 32 bytes of firmware from the bricklet attached at the given port.
		The bytes are read starting at the position offset * 32.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickIMU.FUNCTION_READ_BRICKLET_PLUGIN, [port, offset], 'c B', 40, 'B32', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Brick is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position is the position in the stack from '0' (bottom) to '8' (top).
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickIMU.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickIMU;

},{"./Device":279,"./IPConnection":280}],141:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickIMUV2.DEVICE_IDENTIFIER = 18;
BrickIMUV2.DEVICE_DISPLAY_NAME = 'IMU Brick 2.0';
BrickIMUV2.CALLBACK_ACCELERATION = 32;
BrickIMUV2.CALLBACK_MAGNETIC_FIELD = 33;
BrickIMUV2.CALLBACK_ANGULAR_VELOCITY = 34;
BrickIMUV2.CALLBACK_TEMPERATURE = 35;
BrickIMUV2.CALLBACK_LINEAR_ACCELERATION = 36;
BrickIMUV2.CALLBACK_GRAVITY_VECTOR = 37;
BrickIMUV2.CALLBACK_ORIENTATION = 38;
BrickIMUV2.CALLBACK_QUATERNION = 39;
BrickIMUV2.CALLBACK_ALL_DATA = 40;
BrickIMUV2.FUNCTION_GET_ACCELERATION = 1;
BrickIMUV2.FUNCTION_GET_MAGNETIC_FIELD = 2;
BrickIMUV2.FUNCTION_GET_ANGULAR_VELOCITY = 3;
BrickIMUV2.FUNCTION_GET_TEMPERATURE = 4;
BrickIMUV2.FUNCTION_GET_ORIENTATION = 5;
BrickIMUV2.FUNCTION_GET_LINEAR_ACCELERATION = 6;
BrickIMUV2.FUNCTION_GET_GRAVITY_VECTOR = 7;
BrickIMUV2.FUNCTION_GET_QUATERNION = 8;
BrickIMUV2.FUNCTION_GET_ALL_DATA = 9;
BrickIMUV2.FUNCTION_LEDS_ON = 10;
BrickIMUV2.FUNCTION_LEDS_OFF = 11;
BrickIMUV2.FUNCTION_ARE_LEDS_ON = 12;
BrickIMUV2.FUNCTION_SAVE_CALIBRATION = 13;
BrickIMUV2.FUNCTION_SET_ACCELERATION_PERIOD = 14;
BrickIMUV2.FUNCTION_GET_ACCELERATION_PERIOD = 15;
BrickIMUV2.FUNCTION_SET_MAGNETIC_FIELD_PERIOD = 16;
BrickIMUV2.FUNCTION_GET_MAGNETIC_FIELD_PERIOD = 17;
BrickIMUV2.FUNCTION_SET_ANGULAR_VELOCITY_PERIOD = 18;
BrickIMUV2.FUNCTION_GET_ANGULAR_VELOCITY_PERIOD = 19;
BrickIMUV2.FUNCTION_SET_TEMPERATURE_PERIOD = 20;
BrickIMUV2.FUNCTION_GET_TEMPERATURE_PERIOD = 21;
BrickIMUV2.FUNCTION_SET_ORIENTATION_PERIOD = 22;
BrickIMUV2.FUNCTION_GET_ORIENTATION_PERIOD = 23;
BrickIMUV2.FUNCTION_SET_LINEAR_ACCELERATION_PERIOD = 24;
BrickIMUV2.FUNCTION_GET_LINEAR_ACCELERATION_PERIOD = 25;
BrickIMUV2.FUNCTION_SET_GRAVITY_VECTOR_PERIOD = 26;
BrickIMUV2.FUNCTION_GET_GRAVITY_VECTOR_PERIOD = 27;
BrickIMUV2.FUNCTION_SET_QUATERNION_PERIOD = 28;
BrickIMUV2.FUNCTION_GET_QUATERNION_PERIOD = 29;
BrickIMUV2.FUNCTION_SET_ALL_DATA_PERIOD = 30;
BrickIMUV2.FUNCTION_GET_ALL_DATA_PERIOD = 31;
BrickIMUV2.FUNCTION_SET_SENSOR_CONFIGURATION = 41;
BrickIMUV2.FUNCTION_GET_SENSOR_CONFIGURATION = 42;
BrickIMUV2.FUNCTION_SET_SENSOR_FUSION_MODE = 43;
BrickIMUV2.FUNCTION_GET_SENSOR_FUSION_MODE = 44;
BrickIMUV2.FUNCTION_SET_SPITFP_BAUDRATE_CONFIG = 231;
BrickIMUV2.FUNCTION_GET_SPITFP_BAUDRATE_CONFIG = 232;
BrickIMUV2.FUNCTION_GET_SEND_TIMEOUT_COUNT = 233;
BrickIMUV2.FUNCTION_SET_SPITFP_BAUDRATE = 234;
BrickIMUV2.FUNCTION_GET_SPITFP_BAUDRATE = 235;
BrickIMUV2.FUNCTION_GET_SPITFP_ERROR_COUNT = 237;
BrickIMUV2.FUNCTION_ENABLE_STATUS_LED = 238;
BrickIMUV2.FUNCTION_DISABLE_STATUS_LED = 239;
BrickIMUV2.FUNCTION_IS_STATUS_LED_ENABLED = 240;
BrickIMUV2.FUNCTION_GET_PROTOCOL1_BRICKLET_NAME = 241;
BrickIMUV2.FUNCTION_GET_CHIP_TEMPERATURE = 242;
BrickIMUV2.FUNCTION_RESET = 243;
BrickIMUV2.FUNCTION_WRITE_BRICKLET_PLUGIN = 246;
BrickIMUV2.FUNCTION_READ_BRICKLET_PLUGIN = 247;
BrickIMUV2.FUNCTION_GET_IDENTITY = 255;
BrickIMUV2.MAGNETOMETER_RATE_2HZ = 0;
BrickIMUV2.MAGNETOMETER_RATE_6HZ = 1;
BrickIMUV2.MAGNETOMETER_RATE_8HZ = 2;
BrickIMUV2.MAGNETOMETER_RATE_10HZ = 3;
BrickIMUV2.MAGNETOMETER_RATE_15HZ = 4;
BrickIMUV2.MAGNETOMETER_RATE_20HZ = 5;
BrickIMUV2.MAGNETOMETER_RATE_25HZ = 6;
BrickIMUV2.MAGNETOMETER_RATE_30HZ = 7;
BrickIMUV2.GYROSCOPE_RANGE_2000DPS = 0;
BrickIMUV2.GYROSCOPE_RANGE_1000DPS = 1;
BrickIMUV2.GYROSCOPE_RANGE_500DPS = 2;
BrickIMUV2.GYROSCOPE_RANGE_250DPS = 3;
BrickIMUV2.GYROSCOPE_RANGE_125DPS = 4;
BrickIMUV2.GYROSCOPE_BANDWIDTH_523HZ = 0;
BrickIMUV2.GYROSCOPE_BANDWIDTH_230HZ = 1;
BrickIMUV2.GYROSCOPE_BANDWIDTH_116HZ = 2;
BrickIMUV2.GYROSCOPE_BANDWIDTH_47HZ = 3;
BrickIMUV2.GYROSCOPE_BANDWIDTH_23HZ = 4;
BrickIMUV2.GYROSCOPE_BANDWIDTH_12HZ = 5;
BrickIMUV2.GYROSCOPE_BANDWIDTH_64HZ = 6;
BrickIMUV2.GYROSCOPE_BANDWIDTH_32HZ = 7;
BrickIMUV2.ACCELEROMETER_RANGE_2G = 0;
BrickIMUV2.ACCELEROMETER_RANGE_4G = 1;
BrickIMUV2.ACCELEROMETER_RANGE_8G = 2;
BrickIMUV2.ACCELEROMETER_RANGE_16G = 3;
BrickIMUV2.ACCELEROMETER_BANDWIDTH_7_81HZ = 0;
BrickIMUV2.ACCELEROMETER_BANDWIDTH_15_63HZ = 1;
BrickIMUV2.ACCELEROMETER_BANDWIDTH_31_25HZ = 2;
BrickIMUV2.ACCELEROMETER_BANDWIDTH_62_5HZ = 3;
BrickIMUV2.ACCELEROMETER_BANDWIDTH_125HZ = 4;
BrickIMUV2.ACCELEROMETER_BANDWIDTH_250HZ = 5;
BrickIMUV2.ACCELEROMETER_BANDWIDTH_500HZ = 6;
BrickIMUV2.ACCELEROMETER_BANDWIDTH_1000HZ = 7;
BrickIMUV2.SENSOR_FUSION_OFF = 0;
BrickIMUV2.SENSOR_FUSION_ON = 1;
BrickIMUV2.SENSOR_FUSION_ON_WITHOUT_MAGNETOMETER = 2;
BrickIMUV2.SENSOR_FUSION_ON_WITHOUT_FAST_MAGNETOMETER_CALIBRATION = 3;
BrickIMUV2.COMMUNICATION_METHOD_NONE = 0;
BrickIMUV2.COMMUNICATION_METHOD_USB = 1;
BrickIMUV2.COMMUNICATION_METHOD_SPI_STACK = 2;
BrickIMUV2.COMMUNICATION_METHOD_CHIBI = 3;
BrickIMUV2.COMMUNICATION_METHOD_RS485 = 4;
BrickIMUV2.COMMUNICATION_METHOD_WIFI = 5;
BrickIMUV2.COMMUNICATION_METHOD_ETHERNET = 6;
BrickIMUV2.COMMUNICATION_METHOD_WIFI_V2 = 7;

function BrickIMUV2(uid, ipcon) {
	//Full fledged AHRS with 9 degrees of freedom

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickIMUV2.DEVICE_IDENTIFIER, BrickIMUV2.DEVICE_DISPLAY_NAME);
	BrickIMUV2.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 3];
	this.responseExpected[BrickIMUV2.FUNCTION_GET_ACCELERATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickIMUV2.FUNCTION_GET_MAGNETIC_FIELD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickIMUV2.FUNCTION_GET_ANGULAR_VELOCITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickIMUV2.FUNCTION_GET_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickIMUV2.FUNCTION_GET_ORIENTATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickIMUV2.FUNCTION_GET_LINEAR_ACCELERATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickIMUV2.FUNCTION_GET_GRAVITY_VECTOR] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickIMUV2.FUNCTION_GET_QUATERNION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickIMUV2.FUNCTION_GET_ALL_DATA] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickIMUV2.FUNCTION_LEDS_ON] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickIMUV2.FUNCTION_LEDS_OFF] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickIMUV2.FUNCTION_ARE_LEDS_ON] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickIMUV2.FUNCTION_SAVE_CALIBRATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickIMUV2.FUNCTION_SET_ACCELERATION_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickIMUV2.FUNCTION_GET_ACCELERATION_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickIMUV2.FUNCTION_SET_MAGNETIC_FIELD_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickIMUV2.FUNCTION_GET_MAGNETIC_FIELD_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickIMUV2.FUNCTION_SET_ANGULAR_VELOCITY_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickIMUV2.FUNCTION_GET_ANGULAR_VELOCITY_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickIMUV2.FUNCTION_SET_TEMPERATURE_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickIMUV2.FUNCTION_GET_TEMPERATURE_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickIMUV2.FUNCTION_SET_ORIENTATION_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickIMUV2.FUNCTION_GET_ORIENTATION_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickIMUV2.FUNCTION_SET_LINEAR_ACCELERATION_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickIMUV2.FUNCTION_GET_LINEAR_ACCELERATION_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickIMUV2.FUNCTION_SET_GRAVITY_VECTOR_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickIMUV2.FUNCTION_GET_GRAVITY_VECTOR_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickIMUV2.FUNCTION_SET_QUATERNION_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickIMUV2.FUNCTION_GET_QUATERNION_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickIMUV2.FUNCTION_SET_ALL_DATA_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickIMUV2.FUNCTION_GET_ALL_DATA_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickIMUV2.FUNCTION_SET_SENSOR_CONFIGURATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickIMUV2.FUNCTION_GET_SENSOR_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickIMUV2.FUNCTION_SET_SENSOR_FUSION_MODE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickIMUV2.FUNCTION_GET_SENSOR_FUSION_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickIMUV2.FUNCTION_SET_SPITFP_BAUDRATE_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickIMUV2.FUNCTION_GET_SPITFP_BAUDRATE_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickIMUV2.FUNCTION_GET_SEND_TIMEOUT_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickIMUV2.FUNCTION_SET_SPITFP_BAUDRATE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickIMUV2.FUNCTION_GET_SPITFP_BAUDRATE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickIMUV2.FUNCTION_GET_SPITFP_ERROR_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickIMUV2.FUNCTION_ENABLE_STATUS_LED] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickIMUV2.FUNCTION_DISABLE_STATUS_LED] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickIMUV2.FUNCTION_IS_STATUS_LED_ENABLED] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickIMUV2.FUNCTION_GET_PROTOCOL1_BRICKLET_NAME] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickIMUV2.FUNCTION_GET_CHIP_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickIMUV2.FUNCTION_RESET] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickIMUV2.FUNCTION_WRITE_BRICKLET_PLUGIN] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickIMUV2.FUNCTION_READ_BRICKLET_PLUGIN] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickIMUV2.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickIMUV2.CALLBACK_ACCELERATION] = [14, 'h h h'];
	this.callbackFormats[BrickIMUV2.CALLBACK_MAGNETIC_FIELD] = [14, 'h h h'];
	this.callbackFormats[BrickIMUV2.CALLBACK_ANGULAR_VELOCITY] = [14, 'h h h'];
	this.callbackFormats[BrickIMUV2.CALLBACK_TEMPERATURE] = [9, 'b'];
	this.callbackFormats[BrickIMUV2.CALLBACK_LINEAR_ACCELERATION] = [14, 'h h h'];
	this.callbackFormats[BrickIMUV2.CALLBACK_GRAVITY_VECTOR] = [14, 'h h h'];
	this.callbackFormats[BrickIMUV2.CALLBACK_ORIENTATION] = [14, 'h h h'];
	this.callbackFormats[BrickIMUV2.CALLBACK_QUATERNION] = [16, 'h h h h'];
	this.callbackFormats[BrickIMUV2.CALLBACK_ALL_DATA] = [54, 'h3 h3 h3 h3 h4 h3 h3 b B'];



	this.getAcceleration = function(returnCallback, errorCallback) {
		/*
		Returns the calibrated acceleration from the accelerometer for the
		x, y and z axis. The acceleration is in the range configured with
		:func:`Set Sensor Configuration`.
		
		If you want to get the acceleration periodically, it is recommended
		to use the :cb:`Acceleration` callback and set the period with
		:func:`Set Acceleration Period`.
		*/
		this.ipcon.sendRequest(this, BrickIMUV2.FUNCTION_GET_ACCELERATION, [], '', 14, 'h h h', returnCallback, errorCallback, false, true);
	};
	this.getMagneticField = function(returnCallback, errorCallback) {
		/*
		Returns the calibrated magnetic field from the magnetometer for the
		x, y and z axis.
		
		If you want to get the magnetic field periodically, it is recommended
		to use the :cb:`Magnetic Field` callback and set the period with
		:func:`Set Magnetic Field Period`.
		*/
		this.ipcon.sendRequest(this, BrickIMUV2.FUNCTION_GET_MAGNETIC_FIELD, [], '', 14, 'h h h', returnCallback, errorCallback, false, true);
	};
	this.getAngularVelocity = function(returnCallback, errorCallback) {
		/*
		Returns the calibrated angular velocity from the gyroscope for the
		x, y and z axis. The angular velocity is in the range configured with
		:func:`Set Sensor Configuration`.
		
		If you want to get the angular velocity periodically, it is recommended
		to use the :cb:`Angular Velocity` acallback nd set the period with
		:func:`Set Angular Velocity Period`.
		*/
		this.ipcon.sendRequest(this, BrickIMUV2.FUNCTION_GET_ANGULAR_VELOCITY, [], '', 14, 'h h h', returnCallback, errorCallback, false, true);
	};
	this.getTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature of the IMU Brick.
		The temperature is measured in the core of the BNO055 IC, it is not the
		ambient temperature
		*/
		this.ipcon.sendRequest(this, BrickIMUV2.FUNCTION_GET_TEMPERATURE, [], '', 9, 'b', returnCallback, errorCallback, false, true);
	};
	this.getOrientation = function(returnCallback, errorCallback) {
		/*
		Returns the current orientation (heading, roll, pitch) of the IMU Brick as
		independent Euler angles. Note that Euler angles always
		experience a `gimbal lock <https://en.wikipedia.org/wiki/Gimbal_lock>`__.
		We recommend that you use quaternions instead, if you need the absolute
		orientation.
		
		If you want to get the orientation periodically, it is recommended
		to use the :cb:`Orientation` callback and set the period with
		:func:`Set Orientation Period`.
		*/
		this.ipcon.sendRequest(this, BrickIMUV2.FUNCTION_GET_ORIENTATION, [], '', 14, 'h h h', returnCallback, errorCallback, false, true);
	};
	this.getLinearAcceleration = function(returnCallback, errorCallback) {
		/*
		Returns the linear acceleration of the IMU Brick for the
		x, y and z axis. The acceleration is in the range configured with
		:func:`Set Sensor Configuration`.
		
		The linear acceleration is the acceleration in each of the three
		axis of the IMU Brick with the influences of gravity removed.
		
		It is also possible to get the gravity vector with the influence of linear
		acceleration removed, see :func:`Get Gravity Vector`.
		
		If you want to get the linear acceleration periodically, it is recommended
		to use the :cb:`Linear Acceleration` callback and set the period with
		:func:`Set Linear Acceleration Period`.
		*/
		this.ipcon.sendRequest(this, BrickIMUV2.FUNCTION_GET_LINEAR_ACCELERATION, [], '', 14, 'h h h', returnCallback, errorCallback, false, true);
	};
	this.getGravityVector = function(returnCallback, errorCallback) {
		/*
		Returns the current gravity vector of the IMU Brick for the
		x, y and z axis.
		
		The gravity vector is the acceleration that occurs due to gravity.
		Influences of additional linear acceleration are removed.
		
		It is also possible to get the linear acceleration with the influence
		of gravity removed, see :func:`Get Linear Acceleration`.
		
		If you want to get the gravity vector periodically, it is recommended
		to use the :cb:`Gravity Vector` callback and set the period with
		:func:`Set Gravity Vector Period`.
		*/
		this.ipcon.sendRequest(this, BrickIMUV2.FUNCTION_GET_GRAVITY_VECTOR, [], '', 14, 'h h h', returnCallback, errorCallback, false, true);
	};
	this.getQuaternion = function(returnCallback, errorCallback) {
		/*
		Returns the current orientation (w, x, y, z) of the IMU Brick as
		`quaternions <https://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation>`__.
		
		You have to divide the return values by 16383 (14 bit) to get
		the usual range of -1.0 to +1.0 for quaternions.
		
		If you want to get the quaternions periodically, it is recommended
		to use the :cb:`Quaternion` callback and set the period with
		:func:`Set Quaternion Period`.
		*/
		this.ipcon.sendRequest(this, BrickIMUV2.FUNCTION_GET_QUATERNION, [], '', 16, 'h h h h', returnCallback, errorCallback, false, true);
	};
	this.getAllData = function(returnCallback, errorCallback) {
		/*
		Return all of the available data of the IMU Brick.
		
		* acceleration (see :func:`Get Acceleration`)
		* magnetic field (see :func:`Get Magnetic Field`)
		* angular velocity (see :func:`Get Angular Velocity`)
		* Euler angles (see :func:`Get Orientation`)
		* quaternion (see :func:`Get Quaternion`)
		* linear acceleration (see :func:`Get Linear Acceleration`)
		* gravity vector (see :func:`Get Gravity Vector`)
		* temperature (see :func:`Get Temperature`)
		* calibration status (see below)
		
		The calibration status consists of four pairs of two bits. Each pair
		of bits represents the status of the current calibration.
		
		* bit 0-1: Magnetometer
		* bit 2-3: Accelerometer
		* bit 4-5: Gyroscope
		* bit 6-7: System
		
		A value of 0 means for "not calibrated" and a value of 3 means
		"fully calibrated". In your program you should always be able to
		ignore the calibration status, it is used by the calibration
		window of the Brick Viewer and it can be ignored after the first
		calibration. See the documentation in the calibration window for
		more information regarding the calibration of the IMU Brick.
		
		If you want to get the data periodically, it is recommended
		to use the :cb:`All Data` callback and set the period with
		:func:`Set All Data Period`.
		*/
		this.ipcon.sendRequest(this, BrickIMUV2.FUNCTION_GET_ALL_DATA, [], '', 54, 'h3 h3 h3 h3 h4 h3 h3 b B', returnCallback, errorCallback, false, true);
	};
	this.ledsOn = function(returnCallback, errorCallback) {
		/*
		Turns the orientation and direction LEDs of the IMU Brick on.
		*/
		this.ipcon.sendRequest(this, BrickIMUV2.FUNCTION_LEDS_ON, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.ledsOff = function(returnCallback, errorCallback) {
		/*
		Turns the orientation and direction LEDs of the IMU Brick off.
		*/
		this.ipcon.sendRequest(this, BrickIMUV2.FUNCTION_LEDS_OFF, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.areLedsOn = function(returnCallback, errorCallback) {
		/*
		Returns *true* if the orientation and direction LEDs of the IMU Brick
		are on, *false* otherwise.
		*/
		this.ipcon.sendRequest(this, BrickIMUV2.FUNCTION_ARE_LEDS_ON, [], '', 9, '?', returnCallback, errorCallback, false, true);
	};
	this.saveCalibration = function(returnCallback, errorCallback) {
		/*
		A call of this function saves the current calibration to be used
		as a starting point for the next restart of continuous calibration
		of the IMU Brick.
		
		A return value of *true* means that the calibration could be used and
		*false* means that it could not be used (this happens if the calibration
		status is not "fully calibrated").
		
		This function is used by the calibration window of the Brick Viewer, you
		should not need to call it in your program.
		*/
		this.ipcon.sendRequest(this, BrickIMUV2.FUNCTION_SAVE_CALIBRATION, [], '', 9, '?', returnCallback, errorCallback, false, true);
	};
	this.setAccelerationPeriod = function(period, returnCallback, errorCallback) {
		/*
		Sets the period with which the :cb:`Acceleration` callback is triggered
		periodically. A value of 0 turns the callback off.
		*/
		this.ipcon.sendRequest(this, BrickIMUV2.FUNCTION_SET_ACCELERATION_PERIOD, [period], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getAccelerationPeriod = function(returnCallback, errorCallback) {
		/*
		Returns the period as set by :func:`Set Acceleration Period`.
		*/
		this.ipcon.sendRequest(this, BrickIMUV2.FUNCTION_GET_ACCELERATION_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setMagneticFieldPeriod = function(period, returnCallback, errorCallback) {
		/*
		Sets the period with which the :cb:`Magnetic Field` callback is triggered
		periodically. A value of 0 turns the callback off.
		*/
		this.ipcon.sendRequest(this, BrickIMUV2.FUNCTION_SET_MAGNETIC_FIELD_PERIOD, [period], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getMagneticFieldPeriod = function(returnCallback, errorCallback) {
		/*
		Returns the period as set by :func:`Set Magnetic Field Period`.
		*/
		this.ipcon.sendRequest(this, BrickIMUV2.FUNCTION_GET_MAGNETIC_FIELD_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setAngularVelocityPeriod = function(period, returnCallback, errorCallback) {
		/*
		Sets the period with which the :cb:`Angular Velocity` callback is
		triggered periodically. A value of 0 turns the callback off.
		*/
		this.ipcon.sendRequest(this, BrickIMUV2.FUNCTION_SET_ANGULAR_VELOCITY_PERIOD, [period], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getAngularVelocityPeriod = function(returnCallback, errorCallback) {
		/*
		Returns the period as set by :func:`Set Angular Velocity Period`.
		*/
		this.ipcon.sendRequest(this, BrickIMUV2.FUNCTION_GET_ANGULAR_VELOCITY_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setTemperaturePeriod = function(period, returnCallback, errorCallback) {
		/*
		Sets the period with which the :cb:`Temperature` callback is triggered
		periodically. A value of 0 turns the callback off.
		*/
		this.ipcon.sendRequest(this, BrickIMUV2.FUNCTION_SET_TEMPERATURE_PERIOD, [period], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getTemperaturePeriod = function(returnCallback, errorCallback) {
		/*
		Returns the period as set by :func:`Set Temperature Period`.
		*/
		this.ipcon.sendRequest(this, BrickIMUV2.FUNCTION_GET_TEMPERATURE_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setOrientationPeriod = function(period, returnCallback, errorCallback) {
		/*
		Sets the period with which the :cb:`Orientation` callback is triggered
		periodically. A value of 0 turns the callback off.
		*/
		this.ipcon.sendRequest(this, BrickIMUV2.FUNCTION_SET_ORIENTATION_PERIOD, [period], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getOrientationPeriod = function(returnCallback, errorCallback) {
		/*
		Returns the period as set by :func:`Set Orientation Period`.
		*/
		this.ipcon.sendRequest(this, BrickIMUV2.FUNCTION_GET_ORIENTATION_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setLinearAccelerationPeriod = function(period, returnCallback, errorCallback) {
		/*
		Sets the period with which the :cb:`Linear Acceleration` callback is
		triggered periodically. A value of 0 turns the callback off.
		*/
		this.ipcon.sendRequest(this, BrickIMUV2.FUNCTION_SET_LINEAR_ACCELERATION_PERIOD, [period], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getLinearAccelerationPeriod = function(returnCallback, errorCallback) {
		/*
		Returns the period as set by :func:`Set Linear Acceleration Period`.
		*/
		this.ipcon.sendRequest(this, BrickIMUV2.FUNCTION_GET_LINEAR_ACCELERATION_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setGravityVectorPeriod = function(period, returnCallback, errorCallback) {
		/*
		Sets the period with which the :cb:`Gravity Vector` callback is triggered
		periodically. A value of 0 turns the callback off.
		*/
		this.ipcon.sendRequest(this, BrickIMUV2.FUNCTION_SET_GRAVITY_VECTOR_PERIOD, [period], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getGravityVectorPeriod = function(returnCallback, errorCallback) {
		/*
		Returns the period as set by :func:`Set Gravity Vector Period`.
		*/
		this.ipcon.sendRequest(this, BrickIMUV2.FUNCTION_GET_GRAVITY_VECTOR_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setQuaternionPeriod = function(period, returnCallback, errorCallback) {
		/*
		Sets the period with which the :cb:`Quaternion` callback is triggered
		periodically. A value of 0 turns the callback off.
		*/
		this.ipcon.sendRequest(this, BrickIMUV2.FUNCTION_SET_QUATERNION_PERIOD, [period], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getQuaternionPeriod = function(returnCallback, errorCallback) {
		/*
		Returns the period as set by :func:`Set Quaternion Period`.
		*/
		this.ipcon.sendRequest(this, BrickIMUV2.FUNCTION_GET_QUATERNION_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setAllDataPeriod = function(period, returnCallback, errorCallback) {
		/*
		Sets the period with which the :cb:`All Data` callback is triggered
		periodically. A value of 0 turns the callback off.
		*/
		this.ipcon.sendRequest(this, BrickIMUV2.FUNCTION_SET_ALL_DATA_PERIOD, [period], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getAllDataPeriod = function(returnCallback, errorCallback) {
		/*
		Returns the period as set by :func:`Set All Data Period`.
		*/
		this.ipcon.sendRequest(this, BrickIMUV2.FUNCTION_GET_ALL_DATA_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setSensorConfiguration = function(magnetometerRate, gyroscopeRange, gyroscopeBandwidth, accelerometerRange, accelerometerBandwidth, returnCallback, errorCallback) {
		/*
		Sets the available sensor configuration for the Magnetometer, Gyroscope and
		Accelerometer. The Accelerometer Range is user selectable in all fusion modes,
		all other configurations are auto-controlled in fusion mode.
		
		.. versionadded:: 2.0.5$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickIMUV2.FUNCTION_SET_SENSOR_CONFIGURATION, [magnetometerRate, gyroscopeRange, gyroscopeBandwidth, accelerometerRange, accelerometerBandwidth], 'B B B B B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getSensorConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the sensor configuration as set by :func:`Set Sensor Configuration`.
		
		.. versionadded:: 2.0.5$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickIMUV2.FUNCTION_GET_SENSOR_CONFIGURATION, [], '', 13, 'B B B B B', returnCallback, errorCallback, false, true);
	};
	this.setSensorFusionMode = function(mode, returnCallback, errorCallback) {
		/*
		If the fusion mode is turned off, the functions :func:`Get Acceleration`,
		:func:`Get Magnetic Field` and :func:`Get Angular Velocity` return uncalibrated
		and uncompensated sensor data. All other sensor data getters return no data.
		
		Since firmware version 2.0.6 you can also use a fusion mode without magnetometer.
		In this mode the calculated orientation is relative (with magnetometer it is
		absolute with respect to the earth). However, the calculation can't be influenced
		by spurious magnetic fields.
		
		Since firmware version 2.0.13 you can also use a fusion mode without fast
		magnetometer calibration. This mode is the same as the normal fusion mode,
		but the fast magnetometer calibration is turned off. So to find the orientation
		the first time will likely take longer, but small magnetic influences might
		not affect the automatic calibration as much.
		
		.. versionadded:: 2.0.5$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickIMUV2.FUNCTION_SET_SENSOR_FUSION_MODE, [mode], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getSensorFusionMode = function(returnCallback, errorCallback) {
		/*
		Returns the sensor fusion mode as set by :func:`Set Sensor Fusion Mode`.
		
		.. versionadded:: 2.0.5$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickIMUV2.FUNCTION_GET_SENSOR_FUSION_MODE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setSPITFPBaudrateConfig = function(enableDynamicBaudrate, minimumDynamicBaudrate, returnCallback, errorCallback) {
		/*
		The SPITF protocol can be used with a dynamic baudrate. If the dynamic baudrate is
		enabled, the Brick will try to adapt the baudrate for the communication
		between Bricks and Bricklets according to the amount of data that is transferred.
		
		The baudrate will be increased exponentially if lots of data is sent/received and
		decreased linearly if little data is sent/received.
		
		This lowers the baudrate in applications where little data is transferred (e.g.
		a weather station) and increases the robustness. If there is lots of data to transfer
		(e.g. Thermal Imaging Bricklet) it automatically increases the baudrate as needed.
		
		In cases where some data has to transferred as fast as possible every few seconds
		(e.g. RS485 Bricklet with a high baudrate but small payload) you may want to turn
		the dynamic baudrate off to get the highest possible performance.
		
		The maximum value of the baudrate can be set per port with the function
		:func:`Set SPITFP Baudrate`. If the dynamic baudrate is disabled, the baudrate
		as set by :func:`Set SPITFP Baudrate` will be used statically.
		
		.. versionadded:: 2.0.10$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickIMUV2.FUNCTION_SET_SPITFP_BAUDRATE_CONFIG, [enableDynamicBaudrate, minimumDynamicBaudrate], '? I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPBaudrateConfig = function(returnCallback, errorCallback) {
		/*
		Returns the baudrate config, see :func:`Set SPITFP Baudrate Config`.
		
		.. versionadded:: 2.0.10$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickIMUV2.FUNCTION_GET_SPITFP_BAUDRATE_CONFIG, [], '', 13, '? I', returnCallback, errorCallback, false, true);
	};
	this.getSendTimeoutCount = function(communicationMethod, returnCallback, errorCallback) {
		/*
		Returns the timeout count for the different communication methods.
		
		The methods 0-2 are available for all Bricks, 3-7 only for Master Bricks.
		
		This function is mostly used for debugging during development, in normal operation
		the counters should nearly always stay at 0.
		
		.. versionadded:: 2.0.7$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickIMUV2.FUNCTION_GET_SEND_TIMEOUT_COUNT, [communicationMethod], 'B', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setSPITFPBaudrate = function(brickletPort, baudrate, returnCallback, errorCallback) {
		/*
		Sets the baudrate for a specific Bricklet port.
		
		If you want to increase the throughput of Bricklets you can increase
		the baudrate. If you get a high error count because of high
		interference (see :func:`Get SPITFP Error Count`) you can decrease the
		baudrate.
		
		If the dynamic baudrate feature is enabled, the baudrate set by this
		function corresponds to the maximum baudrate (see :func:`Set SPITFP Baudrate Config`).
		
		Regulatory testing is done with the default baudrate. If CE compatibility
		or similar is necessary in your applications we recommend to not change
		the baudrate.
		
		.. versionadded:: 2.0.5$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickIMUV2.FUNCTION_SET_SPITFP_BAUDRATE, [brickletPort, baudrate], 'c I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPBaudrate = function(brickletPort, returnCallback, errorCallback) {
		/*
		Returns the baudrate for a given Bricklet port, see :func:`Set SPITFP Baudrate`.
		
		.. versionadded:: 2.0.5$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickIMUV2.FUNCTION_GET_SPITFP_BAUDRATE, [brickletPort], 'c', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPErrorCount = function(brickletPort, returnCallback, errorCallback) {
		/*
		Returns the error count for the communication between Brick and Bricklet.
		
		The errors are divided into
		
		* ACK checksum errors,
		* message checksum errors,
		* framing errors and
		* overflow errors.
		
		The errors counts are for errors that occur on the Brick side. All
		Bricklets have a similar function that returns the errors on the Bricklet side.
		
		.. versionadded:: 2.0.5$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickIMUV2.FUNCTION_GET_SPITFP_ERROR_COUNT, [brickletPort], 'c', 24, 'I I I I', returnCallback, errorCallback, false, true);
	};
	this.enableStatusLED = function(returnCallback, errorCallback) {
		/*
		Enables the status LED.
		
		The status LED is the blue LED next to the USB connector. If enabled is is
		on and it flickers if data is transfered. If disabled it is always off.
		
		The default state is enabled.
		*/
		this.ipcon.sendRequest(this, BrickIMUV2.FUNCTION_ENABLE_STATUS_LED, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.disableStatusLED = function(returnCallback, errorCallback) {
		/*
		Disables the status LED.
		
		The status LED is the blue LED next to the USB connector. If enabled is is
		on and it flickers if data is transfered. If disabled it is always off.
		
		The default state is enabled.
		*/
		this.ipcon.sendRequest(this, BrickIMUV2.FUNCTION_DISABLE_STATUS_LED, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.isStatusLEDEnabled = function(returnCallback, errorCallback) {
		/*
		Returns *true* if the status LED is enabled, *false* otherwise.
		*/
		this.ipcon.sendRequest(this, BrickIMUV2.FUNCTION_IS_STATUS_LED_ENABLED, [], '', 9, '?', returnCallback, errorCallback, false, true);
	};
	this.getProtocol1BrickletName = function(port, returnCallback, errorCallback) {
		/*
		Returns the firmware and protocol version and the name of the Bricklet for a
		given port.
		
		This functions sole purpose is to allow automatic flashing of v1.x.y Bricklet
		plugins.
		*/
		this.ipcon.sendRequest(this, BrickIMUV2.FUNCTION_GET_PROTOCOL1_BRICKLET_NAME, [port], 'c', 52, 'B B3 s40', returnCallback, errorCallback, false, true);
	};
	this.getChipTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature as measured inside the microcontroller. The
		value returned is not the ambient temperature!
		
		The temperature is only proportional to the real temperature and it has an
		accuracy of ±15%. Practically it is only useful as an indicator for
		temperature changes.
		*/
		this.ipcon.sendRequest(this, BrickIMUV2.FUNCTION_GET_CHIP_TEMPERATURE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.reset = function(returnCallback, errorCallback) {
		/*
		Calling this function will reset the Brick. Calling this function
		on a Brick inside of a stack will reset the whole stack.
		
		After a reset you have to create new device objects,
		calling functions on the existing ones will result in
		undefined behavior!
		*/
		this.ipcon.sendRequest(this, BrickIMUV2.FUNCTION_RESET, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeBrickletPlugin = function(port, offset, chunk, returnCallback, errorCallback) {
		/*
		Writes 32 bytes of firmware to the bricklet attached at the given port.
		The bytes are written to the position offset * 32.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickIMUV2.FUNCTION_WRITE_BRICKLET_PLUGIN, [port, offset, chunk], 'c B B32', 0, '', returnCallback, errorCallback, false, true);
	};
	this.readBrickletPlugin = function(port, offset, returnCallback, errorCallback) {
		/*
		Reads 32 bytes of firmware from the bricklet attached at the given port.
		The bytes are read starting at the position offset * 32.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickIMUV2.FUNCTION_READ_BRICKLET_PLUGIN, [port, offset], 'c B', 40, 'B32', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Brick is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position is the position in the stack from '0' (bottom) to '8' (top).
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickIMUV2.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickIMUV2;

},{"./Device":279,"./IPConnection":280}],142:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickMaster.DEVICE_IDENTIFIER = 13;
BrickMaster.DEVICE_DISPLAY_NAME = 'Master Brick';
BrickMaster.CALLBACK_STACK_CURRENT = 59;
BrickMaster.CALLBACK_STACK_VOLTAGE = 60;
BrickMaster.CALLBACK_USB_VOLTAGE = 61;
BrickMaster.CALLBACK_STACK_CURRENT_REACHED = 62;
BrickMaster.CALLBACK_STACK_VOLTAGE_REACHED = 63;
BrickMaster.CALLBACK_USB_VOLTAGE_REACHED = 64;
BrickMaster.FUNCTION_GET_STACK_VOLTAGE = 1;
BrickMaster.FUNCTION_GET_STACK_CURRENT = 2;
BrickMaster.FUNCTION_SET_EXTENSION_TYPE = 3;
BrickMaster.FUNCTION_GET_EXTENSION_TYPE = 4;
BrickMaster.FUNCTION_IS_CHIBI_PRESENT = 5;
BrickMaster.FUNCTION_SET_CHIBI_ADDRESS = 6;
BrickMaster.FUNCTION_GET_CHIBI_ADDRESS = 7;
BrickMaster.FUNCTION_SET_CHIBI_MASTER_ADDRESS = 8;
BrickMaster.FUNCTION_GET_CHIBI_MASTER_ADDRESS = 9;
BrickMaster.FUNCTION_SET_CHIBI_SLAVE_ADDRESS = 10;
BrickMaster.FUNCTION_GET_CHIBI_SLAVE_ADDRESS = 11;
BrickMaster.FUNCTION_GET_CHIBI_SIGNAL_STRENGTH = 12;
BrickMaster.FUNCTION_GET_CHIBI_ERROR_LOG = 13;
BrickMaster.FUNCTION_SET_CHIBI_FREQUENCY = 14;
BrickMaster.FUNCTION_GET_CHIBI_FREQUENCY = 15;
BrickMaster.FUNCTION_SET_CHIBI_CHANNEL = 16;
BrickMaster.FUNCTION_GET_CHIBI_CHANNEL = 17;
BrickMaster.FUNCTION_IS_RS485_PRESENT = 18;
BrickMaster.FUNCTION_SET_RS485_ADDRESS = 19;
BrickMaster.FUNCTION_GET_RS485_ADDRESS = 20;
BrickMaster.FUNCTION_SET_RS485_SLAVE_ADDRESS = 21;
BrickMaster.FUNCTION_GET_RS485_SLAVE_ADDRESS = 22;
BrickMaster.FUNCTION_GET_RS485_ERROR_LOG = 23;
BrickMaster.FUNCTION_SET_RS485_CONFIGURATION = 24;
BrickMaster.FUNCTION_GET_RS485_CONFIGURATION = 25;
BrickMaster.FUNCTION_IS_WIFI_PRESENT = 26;
BrickMaster.FUNCTION_SET_WIFI_CONFIGURATION = 27;
BrickMaster.FUNCTION_GET_WIFI_CONFIGURATION = 28;
BrickMaster.FUNCTION_SET_WIFI_ENCRYPTION = 29;
BrickMaster.FUNCTION_GET_WIFI_ENCRYPTION = 30;
BrickMaster.FUNCTION_GET_WIFI_STATUS = 31;
BrickMaster.FUNCTION_REFRESH_WIFI_STATUS = 32;
BrickMaster.FUNCTION_SET_WIFI_CERTIFICATE = 33;
BrickMaster.FUNCTION_GET_WIFI_CERTIFICATE = 34;
BrickMaster.FUNCTION_SET_WIFI_POWER_MODE = 35;
BrickMaster.FUNCTION_GET_WIFI_POWER_MODE = 36;
BrickMaster.FUNCTION_GET_WIFI_BUFFER_INFO = 37;
BrickMaster.FUNCTION_SET_WIFI_REGULATORY_DOMAIN = 38;
BrickMaster.FUNCTION_GET_WIFI_REGULATORY_DOMAIN = 39;
BrickMaster.FUNCTION_GET_USB_VOLTAGE = 40;
BrickMaster.FUNCTION_SET_LONG_WIFI_KEY = 41;
BrickMaster.FUNCTION_GET_LONG_WIFI_KEY = 42;
BrickMaster.FUNCTION_SET_WIFI_HOSTNAME = 43;
BrickMaster.FUNCTION_GET_WIFI_HOSTNAME = 44;
BrickMaster.FUNCTION_SET_STACK_CURRENT_CALLBACK_PERIOD = 45;
BrickMaster.FUNCTION_GET_STACK_CURRENT_CALLBACK_PERIOD = 46;
BrickMaster.FUNCTION_SET_STACK_VOLTAGE_CALLBACK_PERIOD = 47;
BrickMaster.FUNCTION_GET_STACK_VOLTAGE_CALLBACK_PERIOD = 48;
BrickMaster.FUNCTION_SET_USB_VOLTAGE_CALLBACK_PERIOD = 49;
BrickMaster.FUNCTION_GET_USB_VOLTAGE_CALLBACK_PERIOD = 50;
BrickMaster.FUNCTION_SET_STACK_CURRENT_CALLBACK_THRESHOLD = 51;
BrickMaster.FUNCTION_GET_STACK_CURRENT_CALLBACK_THRESHOLD = 52;
BrickMaster.FUNCTION_SET_STACK_VOLTAGE_CALLBACK_THRESHOLD = 53;
BrickMaster.FUNCTION_GET_STACK_VOLTAGE_CALLBACK_THRESHOLD = 54;
BrickMaster.FUNCTION_SET_USB_VOLTAGE_CALLBACK_THRESHOLD = 55;
BrickMaster.FUNCTION_GET_USB_VOLTAGE_CALLBACK_THRESHOLD = 56;
BrickMaster.FUNCTION_SET_DEBOUNCE_PERIOD = 57;
BrickMaster.FUNCTION_GET_DEBOUNCE_PERIOD = 58;
BrickMaster.FUNCTION_IS_ETHERNET_PRESENT = 65;
BrickMaster.FUNCTION_SET_ETHERNET_CONFIGURATION = 66;
BrickMaster.FUNCTION_GET_ETHERNET_CONFIGURATION = 67;
BrickMaster.FUNCTION_GET_ETHERNET_STATUS = 68;
BrickMaster.FUNCTION_SET_ETHERNET_HOSTNAME = 69;
BrickMaster.FUNCTION_SET_ETHERNET_MAC_ADDRESS = 70;
BrickMaster.FUNCTION_SET_ETHERNET_WEBSOCKET_CONFIGURATION = 71;
BrickMaster.FUNCTION_GET_ETHERNET_WEBSOCKET_CONFIGURATION = 72;
BrickMaster.FUNCTION_SET_ETHERNET_AUTHENTICATION_SECRET = 73;
BrickMaster.FUNCTION_GET_ETHERNET_AUTHENTICATION_SECRET = 74;
BrickMaster.FUNCTION_SET_WIFI_AUTHENTICATION_SECRET = 75;
BrickMaster.FUNCTION_GET_WIFI_AUTHENTICATION_SECRET = 76;
BrickMaster.FUNCTION_GET_CONNECTION_TYPE = 77;
BrickMaster.FUNCTION_IS_WIFI2_PRESENT = 78;
BrickMaster.FUNCTION_START_WIFI2_BOOTLOADER = 79;
BrickMaster.FUNCTION_WRITE_WIFI2_SERIAL_PORT = 80;
BrickMaster.FUNCTION_READ_WIFI2_SERIAL_PORT = 81;
BrickMaster.FUNCTION_SET_WIFI2_AUTHENTICATION_SECRET = 82;
BrickMaster.FUNCTION_GET_WIFI2_AUTHENTICATION_SECRET = 83;
BrickMaster.FUNCTION_SET_WIFI2_CONFIGURATION = 84;
BrickMaster.FUNCTION_GET_WIFI2_CONFIGURATION = 85;
BrickMaster.FUNCTION_GET_WIFI2_STATUS = 86;
BrickMaster.FUNCTION_SET_WIFI2_CLIENT_CONFIGURATION = 87;
BrickMaster.FUNCTION_GET_WIFI2_CLIENT_CONFIGURATION = 88;
BrickMaster.FUNCTION_SET_WIFI2_CLIENT_HOSTNAME = 89;
BrickMaster.FUNCTION_GET_WIFI2_CLIENT_HOSTNAME = 90;
BrickMaster.FUNCTION_SET_WIFI2_CLIENT_PASSWORD = 91;
BrickMaster.FUNCTION_GET_WIFI2_CLIENT_PASSWORD = 92;
BrickMaster.FUNCTION_SET_WIFI2_AP_CONFIGURATION = 93;
BrickMaster.FUNCTION_GET_WIFI2_AP_CONFIGURATION = 94;
BrickMaster.FUNCTION_SET_WIFI2_AP_PASSWORD = 95;
BrickMaster.FUNCTION_GET_WIFI2_AP_PASSWORD = 96;
BrickMaster.FUNCTION_SAVE_WIFI2_CONFIGURATION = 97;
BrickMaster.FUNCTION_GET_WIFI2_FIRMWARE_VERSION = 98;
BrickMaster.FUNCTION_ENABLE_WIFI2_STATUS_LED = 99;
BrickMaster.FUNCTION_DISABLE_WIFI2_STATUS_LED = 100;
BrickMaster.FUNCTION_IS_WIFI2_STATUS_LED_ENABLED = 101;
BrickMaster.FUNCTION_SET_WIFI2_MESH_CONFIGURATION = 102;
BrickMaster.FUNCTION_GET_WIFI2_MESH_CONFIGURATION = 103;
BrickMaster.FUNCTION_SET_WIFI2_MESH_ROUTER_SSID = 104;
BrickMaster.FUNCTION_GET_WIFI2_MESH_ROUTER_SSID = 105;
BrickMaster.FUNCTION_SET_WIFI2_MESH_ROUTER_PASSWORD = 106;
BrickMaster.FUNCTION_GET_WIFI2_MESH_ROUTER_PASSWORD = 107;
BrickMaster.FUNCTION_GET_WIFI2_MESH_COMMON_STATUS = 108;
BrickMaster.FUNCTION_GET_WIFI2_MESH_CLIENT_STATUS = 109;
BrickMaster.FUNCTION_GET_WIFI2_MESH_AP_STATUS = 110;
BrickMaster.FUNCTION_SET_BRICKLET_XMC_FLASH_CONFIG = 111;
BrickMaster.FUNCTION_SET_BRICKLET_XMC_FLASH_DATA = 112;
BrickMaster.FUNCTION_SET_BRICKLETS_ENABLED = 113;
BrickMaster.FUNCTION_GET_BRICKLETS_ENABLED = 114;
BrickMaster.FUNCTION_SET_SPITFP_BAUDRATE_CONFIG = 231;
BrickMaster.FUNCTION_GET_SPITFP_BAUDRATE_CONFIG = 232;
BrickMaster.FUNCTION_GET_SEND_TIMEOUT_COUNT = 233;
BrickMaster.FUNCTION_SET_SPITFP_BAUDRATE = 234;
BrickMaster.FUNCTION_GET_SPITFP_BAUDRATE = 235;
BrickMaster.FUNCTION_GET_SPITFP_ERROR_COUNT = 237;
BrickMaster.FUNCTION_ENABLE_STATUS_LED = 238;
BrickMaster.FUNCTION_DISABLE_STATUS_LED = 239;
BrickMaster.FUNCTION_IS_STATUS_LED_ENABLED = 240;
BrickMaster.FUNCTION_GET_PROTOCOL1_BRICKLET_NAME = 241;
BrickMaster.FUNCTION_GET_CHIP_TEMPERATURE = 242;
BrickMaster.FUNCTION_RESET = 243;
BrickMaster.FUNCTION_WRITE_BRICKLET_PLUGIN = 246;
BrickMaster.FUNCTION_READ_BRICKLET_PLUGIN = 247;
BrickMaster.FUNCTION_GET_IDENTITY = 255;
BrickMaster.EXTENSION_TYPE_CHIBI = 1;
BrickMaster.EXTENSION_TYPE_RS485 = 2;
BrickMaster.EXTENSION_TYPE_WIFI = 3;
BrickMaster.EXTENSION_TYPE_ETHERNET = 4;
BrickMaster.EXTENSION_TYPE_WIFI2 = 5;
BrickMaster.CHIBI_FREQUENCY_OQPSK_868_MHZ = 0;
BrickMaster.CHIBI_FREQUENCY_OQPSK_915_MHZ = 1;
BrickMaster.CHIBI_FREQUENCY_OQPSK_780_MHZ = 2;
BrickMaster.CHIBI_FREQUENCY_BPSK40_915_MHZ = 3;
BrickMaster.RS485_PARITY_NONE = 'n';
BrickMaster.RS485_PARITY_EVEN = 'e';
BrickMaster.RS485_PARITY_ODD = 'o';
BrickMaster.WIFI_CONNECTION_DHCP = 0;
BrickMaster.WIFI_CONNECTION_STATIC_IP = 1;
BrickMaster.WIFI_CONNECTION_ACCESS_POINT_DHCP = 2;
BrickMaster.WIFI_CONNECTION_ACCESS_POINT_STATIC_IP = 3;
BrickMaster.WIFI_CONNECTION_AD_HOC_DHCP = 4;
BrickMaster.WIFI_CONNECTION_AD_HOC_STATIC_IP = 5;
BrickMaster.WIFI_ENCRYPTION_WPA_WPA2 = 0;
BrickMaster.WIFI_ENCRYPTION_WPA_ENTERPRISE = 1;
BrickMaster.WIFI_ENCRYPTION_WEP = 2;
BrickMaster.WIFI_ENCRYPTION_NO_ENCRYPTION = 3;
BrickMaster.WIFI_EAP_OPTION_OUTER_AUTH_EAP_FAST = 0;
BrickMaster.WIFI_EAP_OPTION_OUTER_AUTH_EAP_TLS = 1;
BrickMaster.WIFI_EAP_OPTION_OUTER_AUTH_EAP_TTLS = 2;
BrickMaster.WIFI_EAP_OPTION_OUTER_AUTH_EAP_PEAP = 3;
BrickMaster.WIFI_EAP_OPTION_INNER_AUTH_EAP_MSCHAP = 0;
BrickMaster.WIFI_EAP_OPTION_INNER_AUTH_EAP_GTC = 4;
BrickMaster.WIFI_EAP_OPTION_CERT_TYPE_CA_CERT = 0;
BrickMaster.WIFI_EAP_OPTION_CERT_TYPE_CLIENT_CERT = 8;
BrickMaster.WIFI_EAP_OPTION_CERT_TYPE_PRIVATE_KEY = 16;
BrickMaster.WIFI_STATE_DISASSOCIATED = 0;
BrickMaster.WIFI_STATE_ASSOCIATED = 1;
BrickMaster.WIFI_STATE_ASSOCIATING = 2;
BrickMaster.WIFI_STATE_ERROR = 3;
BrickMaster.WIFI_STATE_NOT_INITIALIZED_YET = 255;
BrickMaster.WIFI_POWER_MODE_FULL_SPEED = 0;
BrickMaster.WIFI_POWER_MODE_LOW_POWER = 1;
BrickMaster.WIFI_DOMAIN_CHANNEL_1TO11 = 0;
BrickMaster.WIFI_DOMAIN_CHANNEL_1TO13 = 1;
BrickMaster.WIFI_DOMAIN_CHANNEL_1TO14 = 2;
BrickMaster.THRESHOLD_OPTION_OFF = 'x';
BrickMaster.THRESHOLD_OPTION_OUTSIDE = 'o';
BrickMaster.THRESHOLD_OPTION_INSIDE = 'i';
BrickMaster.THRESHOLD_OPTION_SMALLER = '<';
BrickMaster.THRESHOLD_OPTION_GREATER = '>';
BrickMaster.ETHERNET_CONNECTION_DHCP = 0;
BrickMaster.ETHERNET_CONNECTION_STATIC_IP = 1;
BrickMaster.CONNECTION_TYPE_NONE = 0;
BrickMaster.CONNECTION_TYPE_USB = 1;
BrickMaster.CONNECTION_TYPE_SPI_STACK = 2;
BrickMaster.CONNECTION_TYPE_CHIBI = 3;
BrickMaster.CONNECTION_TYPE_RS485 = 4;
BrickMaster.CONNECTION_TYPE_WIFI = 5;
BrickMaster.CONNECTION_TYPE_ETHERNET = 6;
BrickMaster.CONNECTION_TYPE_WIFI2 = 7;
BrickMaster.WIFI2_PHY_MODE_B = 0;
BrickMaster.WIFI2_PHY_MODE_G = 1;
BrickMaster.WIFI2_PHY_MODE_N = 2;
BrickMaster.WIFI2_CLIENT_STATUS_IDLE = 0;
BrickMaster.WIFI2_CLIENT_STATUS_CONNECTING = 1;
BrickMaster.WIFI2_CLIENT_STATUS_WRONG_PASSWORD = 2;
BrickMaster.WIFI2_CLIENT_STATUS_NO_AP_FOUND = 3;
BrickMaster.WIFI2_CLIENT_STATUS_CONNECT_FAILED = 4;
BrickMaster.WIFI2_CLIENT_STATUS_GOT_IP = 5;
BrickMaster.WIFI2_CLIENT_STATUS_UNKNOWN = 255;
BrickMaster.WIFI2_AP_ENCRYPTION_OPEN = 0;
BrickMaster.WIFI2_AP_ENCRYPTION_WEP = 1;
BrickMaster.WIFI2_AP_ENCRYPTION_WPA_PSK = 2;
BrickMaster.WIFI2_AP_ENCRYPTION_WPA2_PSK = 3;
BrickMaster.WIFI2_AP_ENCRYPTION_WPA_WPA2_PSK = 4;
BrickMaster.WIFI2_MESH_STATUS_DISABLED = 0;
BrickMaster.WIFI2_MESH_STATUS_WIFI_CONNECTING = 1;
BrickMaster.WIFI2_MESH_STATUS_GOT_IP = 2;
BrickMaster.WIFI2_MESH_STATUS_MESH_LOCAL = 3;
BrickMaster.WIFI2_MESH_STATUS_MESH_ONLINE = 4;
BrickMaster.WIFI2_MESH_STATUS_AP_AVAILABLE = 5;
BrickMaster.WIFI2_MESH_STATUS_AP_SETUP = 6;
BrickMaster.WIFI2_MESH_STATUS_LEAF_AVAILABLE = 7;
BrickMaster.COMMUNICATION_METHOD_NONE = 0;
BrickMaster.COMMUNICATION_METHOD_USB = 1;
BrickMaster.COMMUNICATION_METHOD_SPI_STACK = 2;
BrickMaster.COMMUNICATION_METHOD_CHIBI = 3;
BrickMaster.COMMUNICATION_METHOD_RS485 = 4;
BrickMaster.COMMUNICATION_METHOD_WIFI = 5;
BrickMaster.COMMUNICATION_METHOD_ETHERNET = 6;
BrickMaster.COMMUNICATION_METHOD_WIFI_V2 = 7;

function BrickMaster(uid, ipcon) {
	//Basis to build stacks and has 4 Bricklet ports

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickMaster.DEVICE_IDENTIFIER, BrickMaster.DEVICE_DISPLAY_NAME);
	BrickMaster.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 10];
	this.responseExpected[BrickMaster.FUNCTION_GET_STACK_VOLTAGE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickMaster.FUNCTION_GET_STACK_CURRENT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickMaster.FUNCTION_SET_EXTENSION_TYPE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickMaster.FUNCTION_GET_EXTENSION_TYPE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickMaster.FUNCTION_IS_CHIBI_PRESENT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickMaster.FUNCTION_SET_CHIBI_ADDRESS] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickMaster.FUNCTION_GET_CHIBI_ADDRESS] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickMaster.FUNCTION_SET_CHIBI_MASTER_ADDRESS] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickMaster.FUNCTION_GET_CHIBI_MASTER_ADDRESS] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickMaster.FUNCTION_SET_CHIBI_SLAVE_ADDRESS] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickMaster.FUNCTION_GET_CHIBI_SLAVE_ADDRESS] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickMaster.FUNCTION_GET_CHIBI_SIGNAL_STRENGTH] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickMaster.FUNCTION_GET_CHIBI_ERROR_LOG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickMaster.FUNCTION_SET_CHIBI_FREQUENCY] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickMaster.FUNCTION_GET_CHIBI_FREQUENCY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickMaster.FUNCTION_SET_CHIBI_CHANNEL] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickMaster.FUNCTION_GET_CHIBI_CHANNEL] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickMaster.FUNCTION_IS_RS485_PRESENT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickMaster.FUNCTION_SET_RS485_ADDRESS] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickMaster.FUNCTION_GET_RS485_ADDRESS] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickMaster.FUNCTION_SET_RS485_SLAVE_ADDRESS] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickMaster.FUNCTION_GET_RS485_SLAVE_ADDRESS] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickMaster.FUNCTION_GET_RS485_ERROR_LOG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickMaster.FUNCTION_SET_RS485_CONFIGURATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickMaster.FUNCTION_GET_RS485_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickMaster.FUNCTION_IS_WIFI_PRESENT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickMaster.FUNCTION_SET_WIFI_CONFIGURATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickMaster.FUNCTION_GET_WIFI_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickMaster.FUNCTION_SET_WIFI_ENCRYPTION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickMaster.FUNCTION_GET_WIFI_ENCRYPTION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickMaster.FUNCTION_GET_WIFI_STATUS] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickMaster.FUNCTION_REFRESH_WIFI_STATUS] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickMaster.FUNCTION_SET_WIFI_CERTIFICATE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickMaster.FUNCTION_GET_WIFI_CERTIFICATE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickMaster.FUNCTION_SET_WIFI_POWER_MODE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickMaster.FUNCTION_GET_WIFI_POWER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickMaster.FUNCTION_GET_WIFI_BUFFER_INFO] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickMaster.FUNCTION_SET_WIFI_REGULATORY_DOMAIN] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickMaster.FUNCTION_GET_WIFI_REGULATORY_DOMAIN] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickMaster.FUNCTION_GET_USB_VOLTAGE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickMaster.FUNCTION_SET_LONG_WIFI_KEY] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickMaster.FUNCTION_GET_LONG_WIFI_KEY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickMaster.FUNCTION_SET_WIFI_HOSTNAME] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickMaster.FUNCTION_GET_WIFI_HOSTNAME] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickMaster.FUNCTION_SET_STACK_CURRENT_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickMaster.FUNCTION_GET_STACK_CURRENT_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickMaster.FUNCTION_SET_STACK_VOLTAGE_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickMaster.FUNCTION_GET_STACK_VOLTAGE_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickMaster.FUNCTION_SET_USB_VOLTAGE_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickMaster.FUNCTION_GET_USB_VOLTAGE_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickMaster.FUNCTION_SET_STACK_CURRENT_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickMaster.FUNCTION_GET_STACK_CURRENT_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickMaster.FUNCTION_SET_STACK_VOLTAGE_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickMaster.FUNCTION_GET_STACK_VOLTAGE_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickMaster.FUNCTION_SET_USB_VOLTAGE_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickMaster.FUNCTION_GET_USB_VOLTAGE_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickMaster.FUNCTION_SET_DEBOUNCE_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickMaster.FUNCTION_GET_DEBOUNCE_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickMaster.FUNCTION_IS_ETHERNET_PRESENT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickMaster.FUNCTION_SET_ETHERNET_CONFIGURATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickMaster.FUNCTION_GET_ETHERNET_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickMaster.FUNCTION_GET_ETHERNET_STATUS] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickMaster.FUNCTION_SET_ETHERNET_HOSTNAME] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickMaster.FUNCTION_SET_ETHERNET_MAC_ADDRESS] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickMaster.FUNCTION_SET_ETHERNET_WEBSOCKET_CONFIGURATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickMaster.FUNCTION_GET_ETHERNET_WEBSOCKET_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickMaster.FUNCTION_SET_ETHERNET_AUTHENTICATION_SECRET] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickMaster.FUNCTION_GET_ETHERNET_AUTHENTICATION_SECRET] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickMaster.FUNCTION_SET_WIFI_AUTHENTICATION_SECRET] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickMaster.FUNCTION_GET_WIFI_AUTHENTICATION_SECRET] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickMaster.FUNCTION_GET_CONNECTION_TYPE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickMaster.FUNCTION_IS_WIFI2_PRESENT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickMaster.FUNCTION_START_WIFI2_BOOTLOADER] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickMaster.FUNCTION_WRITE_WIFI2_SERIAL_PORT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickMaster.FUNCTION_READ_WIFI2_SERIAL_PORT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickMaster.FUNCTION_SET_WIFI2_AUTHENTICATION_SECRET] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickMaster.FUNCTION_GET_WIFI2_AUTHENTICATION_SECRET] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickMaster.FUNCTION_SET_WIFI2_CONFIGURATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickMaster.FUNCTION_GET_WIFI2_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickMaster.FUNCTION_GET_WIFI2_STATUS] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickMaster.FUNCTION_SET_WIFI2_CLIENT_CONFIGURATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickMaster.FUNCTION_GET_WIFI2_CLIENT_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickMaster.FUNCTION_SET_WIFI2_CLIENT_HOSTNAME] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickMaster.FUNCTION_GET_WIFI2_CLIENT_HOSTNAME] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickMaster.FUNCTION_SET_WIFI2_CLIENT_PASSWORD] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickMaster.FUNCTION_GET_WIFI2_CLIENT_PASSWORD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickMaster.FUNCTION_SET_WIFI2_AP_CONFIGURATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickMaster.FUNCTION_GET_WIFI2_AP_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickMaster.FUNCTION_SET_WIFI2_AP_PASSWORD] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickMaster.FUNCTION_GET_WIFI2_AP_PASSWORD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickMaster.FUNCTION_SAVE_WIFI2_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickMaster.FUNCTION_GET_WIFI2_FIRMWARE_VERSION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickMaster.FUNCTION_ENABLE_WIFI2_STATUS_LED] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickMaster.FUNCTION_DISABLE_WIFI2_STATUS_LED] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickMaster.FUNCTION_IS_WIFI2_STATUS_LED_ENABLED] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickMaster.FUNCTION_SET_WIFI2_MESH_CONFIGURATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickMaster.FUNCTION_GET_WIFI2_MESH_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickMaster.FUNCTION_SET_WIFI2_MESH_ROUTER_SSID] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickMaster.FUNCTION_GET_WIFI2_MESH_ROUTER_SSID] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickMaster.FUNCTION_SET_WIFI2_MESH_ROUTER_PASSWORD] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickMaster.FUNCTION_GET_WIFI2_MESH_ROUTER_PASSWORD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickMaster.FUNCTION_GET_WIFI2_MESH_COMMON_STATUS] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickMaster.FUNCTION_GET_WIFI2_MESH_CLIENT_STATUS] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickMaster.FUNCTION_GET_WIFI2_MESH_AP_STATUS] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickMaster.FUNCTION_SET_BRICKLET_XMC_FLASH_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickMaster.FUNCTION_SET_BRICKLET_XMC_FLASH_DATA] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickMaster.FUNCTION_SET_BRICKLETS_ENABLED] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickMaster.FUNCTION_GET_BRICKLETS_ENABLED] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickMaster.FUNCTION_SET_SPITFP_BAUDRATE_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickMaster.FUNCTION_GET_SPITFP_BAUDRATE_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickMaster.FUNCTION_GET_SEND_TIMEOUT_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickMaster.FUNCTION_SET_SPITFP_BAUDRATE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickMaster.FUNCTION_GET_SPITFP_BAUDRATE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickMaster.FUNCTION_GET_SPITFP_ERROR_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickMaster.FUNCTION_ENABLE_STATUS_LED] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickMaster.FUNCTION_DISABLE_STATUS_LED] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickMaster.FUNCTION_IS_STATUS_LED_ENABLED] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickMaster.FUNCTION_GET_PROTOCOL1_BRICKLET_NAME] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickMaster.FUNCTION_GET_CHIP_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickMaster.FUNCTION_RESET] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickMaster.FUNCTION_WRITE_BRICKLET_PLUGIN] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickMaster.FUNCTION_READ_BRICKLET_PLUGIN] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickMaster.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickMaster.CALLBACK_STACK_CURRENT] = [10, 'H'];
	this.callbackFormats[BrickMaster.CALLBACK_STACK_VOLTAGE] = [10, 'H'];
	this.callbackFormats[BrickMaster.CALLBACK_USB_VOLTAGE] = [10, 'H'];
	this.callbackFormats[BrickMaster.CALLBACK_STACK_CURRENT_REACHED] = [10, 'H'];
	this.callbackFormats[BrickMaster.CALLBACK_STACK_VOLTAGE_REACHED] = [10, 'H'];
	this.callbackFormats[BrickMaster.CALLBACK_USB_VOLTAGE_REACHED] = [10, 'H'];



	this.getStackVoltage = function(returnCallback, errorCallback) {
		/*
		Returns the stack voltage. The stack voltage is the
		voltage that is supplied via the stack, i.e. it is given by a
		Step-Down or Step-Up Power Supply.
		
		.. note::
		 It is not possible to measure voltages supplied per PoE or USB with this function.
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_GET_STACK_VOLTAGE, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.getStackCurrent = function(returnCallback, errorCallback) {
		/*
		Returns the stack current. The stack current is the
		current that is drawn via the stack, i.e. it is given by a
		Step-Down or Step-Up Power Supply.
		
		.. note::
		 It is not possible to measure the current drawn via PoE or USB with this function.
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_GET_STACK_CURRENT, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.setExtensionType = function(extension, exttype, returnCallback, errorCallback) {
		/*
		Writes the extension type to the EEPROM of a specified extension.
		The extension is either 0 or 1 (0 is the lower one, 1 is the upper one,
		if only one extension is present use 0).
		
		Possible extension types:
		
		.. csv-table::
		 :header: "Type", "Description"
		 :widths: 10, 100
		
		 "1",    "Chibi"
		 "2",    "RS485"
		 "3",    "WIFI"
		 "4",    "Ethernet"
		 "5",    "WIFI 2.0"
		
		The extension type is already set when bought and it can be set with the
		Brick Viewer, it is unlikely that you need this function.
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_SET_EXTENSION_TYPE, [extension, exttype], 'B I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getExtensionType = function(extension, returnCallback, errorCallback) {
		/*
		Returns the type for a given extension as set by :func:`Set Extension Type`.
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_GET_EXTENSION_TYPE, [extension], 'B', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.isChibiPresent = function(returnCallback, errorCallback) {
		/*
		Returns *true* if the Master Brick is at position 0 in the stack and a Chibi
		Extension is available.
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_IS_CHIBI_PRESENT, [], '', 9, '?', returnCallback, errorCallback, false, true);
	};
	this.setChibiAddress = function(address, returnCallback, errorCallback) {
		/*
		Sets the address belonging to the Chibi Extension.
		
		It is possible to set the address with the Brick Viewer and it will be
		saved in the EEPROM of the Chibi Extension, it does not
		have to be set on every startup.
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_SET_CHIBI_ADDRESS, [address], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getChibiAddress = function(returnCallback, errorCallback) {
		/*
		Returns the address as set by :func:`Set Chibi Address`.
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_GET_CHIBI_ADDRESS, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setChibiMasterAddress = function(address, returnCallback, errorCallback) {
		/*
		Sets the address of the Chibi Master. This address is used if the
		Chibi Extension is used as slave (i.e. it does not have a USB connection).
		
		It is possible to set the address with the Brick Viewer and it will be
		saved in the EEPROM of the Chibi Extension, it does not
		have to be set on every startup.
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_SET_CHIBI_MASTER_ADDRESS, [address], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getChibiMasterAddress = function(returnCallback, errorCallback) {
		/*
		Returns the address as set by :func:`Set Chibi Master Address`.
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_GET_CHIBI_MASTER_ADDRESS, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setChibiSlaveAddress = function(num, address, returnCallback, errorCallback) {
		/*
		Sets up to 254 slave addresses. 0 has a
		special meaning, it is used as list terminator and not allowed as normal slave
		address. The address numeration (via ``num`` parameter) has to be used
		ascending from 0. For example: If you use the Chibi Extension in Master mode
		(i.e. the stack has an USB connection) and you want to talk to three other
		Chibi stacks with the slave addresses 17, 23, and 42, you should call with
		``(0, 17)``, ``(1, 23)``, ``(2, 42)`` and ``(3, 0)``. The last call with
		``(3, 0)`` is a list terminator and indicates that the Chibi slave address
		list contains 3 addresses in this case.
		
		It is possible to set the addresses with the Brick Viewer, that will take care
		of correct address numeration and list termination.
		
		The slave addresses will be saved in the EEPROM of the Chibi Extension, they
		don't have to be set on every startup.
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_SET_CHIBI_SLAVE_ADDRESS, [num, address], 'B B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getChibiSlaveAddress = function(num, returnCallback, errorCallback) {
		/*
		Returns the slave address for a given ``num`` as set by
		:func:`Set Chibi Slave Address`.
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_GET_CHIBI_SLAVE_ADDRESS, [num], 'B', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getChibiSignalStrength = function(returnCallback, errorCallback) {
		/*
		Returns the signal strength in dBm. The signal strength updates every time a
		packet is received.
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_GET_CHIBI_SIGNAL_STRENGTH, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getChibiErrorLog = function(returnCallback, errorCallback) {
		/*
		Returns underrun, CRC error, no ACK and overflow error counts of the Chibi
		communication. If these errors start rising, it is likely that either the
		distance between two Chibi stacks is becoming too big or there are
		interferences.
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_GET_CHIBI_ERROR_LOG, [], '', 16, 'H H H H', returnCallback, errorCallback, false, true);
	};
	this.setChibiFrequency = function(frequency, returnCallback, errorCallback) {
		/*
		Sets the Chibi frequency range for the Chibi Extension. Possible values are:
		
		.. csv-table::
		 :header: "Type", "Description"
		 :widths: 10, 100
		
		 "0",    "OQPSK 868MHz (Europe)"
		 "1",    "OQPSK 915MHz (US)"
		 "2",    "OQPSK 780MHz (China)"
		 "3",    "BPSK40 915MHz"
		
		It is possible to set the frequency with the Brick Viewer and it will be
		saved in the EEPROM of the Chibi Extension, it does not
		have to be set on every startup.
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_SET_CHIBI_FREQUENCY, [frequency], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getChibiFrequency = function(returnCallback, errorCallback) {
		/*
		Returns the frequency value as set by :func:`Set Chibi Frequency`.
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_GET_CHIBI_FREQUENCY, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setChibiChannel = function(channel, returnCallback, errorCallback) {
		/*
		Sets the channel used by the Chibi Extension. Possible channels are
		different for different frequencies:
		
		.. csv-table::
		 :header: "Frequency", "Possible Channels"
		 :widths: 40, 60
		
		 "OQPSK 868MHz (Europe)", "0"
		 "OQPSK 915MHz (US)",     "1, 2, 3, 4, 5, 6, 7, 8, 9, 10"
		 "OQPSK 780MHz (China)",  "0, 1, 2, 3"
		 "BPSK40 915MHz",         "1, 2, 3, 4, 5, 6, 7, 8, 9, 10"
		
		It is possible to set the channel with the Brick Viewer and it will be
		saved in the EEPROM of the Chibi Extension, it does not
		have to be set on every startup.
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_SET_CHIBI_CHANNEL, [channel], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getChibiChannel = function(returnCallback, errorCallback) {
		/*
		Returns the channel as set by :func:`Set Chibi Channel`.
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_GET_CHIBI_CHANNEL, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.isRS485Present = function(returnCallback, errorCallback) {
		/*
		Returns *true* if the Master Brick is at position 0 in the stack and a RS485
		Extension is available.
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_IS_RS485_PRESENT, [], '', 9, '?', returnCallback, errorCallback, false, true);
	};
	this.setRS485Address = function(address, returnCallback, errorCallback) {
		/*
		Sets the address (0-255) belonging to the RS485 Extension.
		
		Set to 0 if the RS485 Extension should be the RS485 Master (i.e.
		connected to a PC via USB).
		
		It is possible to set the address with the Brick Viewer and it will be
		saved in the EEPROM of the RS485 Extension, it does not
		have to be set on every startup.
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_SET_RS485_ADDRESS, [address], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getRS485Address = function(returnCallback, errorCallback) {
		/*
		Returns the address as set by :func:`Set RS485 Address`.
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_GET_RS485_ADDRESS, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setRS485SlaveAddress = function(num, address, returnCallback, errorCallback) {
		/*
		Sets up to 255 slave addresses. Valid addresses are in range 1-255. 0 has a
		special meaning, it is used as list terminator and not allowed as normal slave
		address. The address numeration (via ``num`` parameter) has to be used
		ascending from 0. For example: If you use the RS485 Extension in Master mode
		(i.e. the stack has an USB connection) and you want to talk to three other
		RS485 stacks with the addresses 17, 23, and 42, you should call with
		``(0, 17)``, ``(1, 23)``, ``(2, 42)`` and ``(3, 0)``. The last call with
		``(3, 0)`` is a list terminator and indicates that the RS485 slave address list
		contains 3 addresses in this case.
		
		It is possible to set the addresses with the Brick Viewer, that will take care
		of correct address numeration and list termination.
		
		The slave addresses will be saved in the EEPROM of the Chibi Extension, they
		don't have to be set on every startup.
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_SET_RS485_SLAVE_ADDRESS, [num, address], 'B B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getRS485SlaveAddress = function(num, returnCallback, errorCallback) {
		/*
		Returns the slave address for a given ``num`` as set by
		:func:`Set RS485 Slave Address`.
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_GET_RS485_SLAVE_ADDRESS, [num], 'B', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getRS485ErrorLog = function(returnCallback, errorCallback) {
		/*
		Returns CRC error counts of the RS485 communication.
		If this counter starts rising, it is likely that the distance
		between the RS485 nodes is too big or there is some kind of
		interference.
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_GET_RS485_ERROR_LOG, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.setRS485Configuration = function(speed, parity, stopbits, returnCallback, errorCallback) {
		/*
		Sets the configuration of the RS485 Extension. The
		Master Brick will try to match the given baud rate as exactly as possible.
		The maximum recommended baud rate is 2000000 (2MBd).
		Possible values for parity are 'n' (none), 'e' (even) and 'o' (odd).
		
		If your RS485 is unstable (lost messages etc.), the first thing you should
		try is to decrease the speed. On very large bus (e.g. 1km), you probably
		should use a value in the range of 100000 (100kBd).
		
		The values are stored in the EEPROM and only applied on startup. That means
		you have to restart the Master Brick after configuration.
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_SET_RS485_CONFIGURATION, [speed, parity, stopbits], 'I c B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getRS485Configuration = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set RS485 Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_GET_RS485_CONFIGURATION, [], '', 14, 'I c B', returnCallback, errorCallback, false, true);
	};
	this.isWifiPresent = function(returnCallback, errorCallback) {
		/*
		Returns *true* if the Master Brick is at position 0 in the stack and a WIFI
		Extension is available.
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_IS_WIFI_PRESENT, [], '', 9, '?', returnCallback, errorCallback, false, true);
	};
	this.setWifiConfiguration = function(ssid, connection, ip, subnetMask, gateway, port, returnCallback, errorCallback) {
		/*
		Sets the configuration of the WIFI Extension. The ``ssid`` can have a max length
		of 32 characters. Possible values for ``connection`` are:
		
		.. csv-table::
		 :header: "Value", "Description"
		 :widths: 10, 90
		
		 "0", "DHCP"
		 "1", "Static IP"
		 "2", "Access Point: DHCP"
		 "3", "Access Point: Static IP"
		 "4", "Ad Hoc: DHCP"
		 "5", "Ad Hoc: Static IP"
		
		If you set ``connection`` to one of the static IP options then you have to
		supply ``ip``, ``subnet_mask`` and ``gateway`` as an array of size 4 (first
		element of the array is the least significant byte of the address). If
		``connection`` is set to one of the DHCP options then ``ip``, ``subnet_mask``
		and ``gateway`` are ignored, you can set them to 0.
		
		The last parameter is the port that your program will connect to.
		
		The values are stored in the EEPROM and only applied on startup. That means
		you have to restart the Master Brick after configuration.
		
		It is recommended to use the Brick Viewer to set the WIFI configuration.
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_SET_WIFI_CONFIGURATION, [ssid, connection, ip, subnetMask, gateway, port], 's32 B B4 B4 B4 H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getWifiConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Wifi Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_GET_WIFI_CONFIGURATION, [], '', 55, 's32 B B4 B4 B4 H', returnCallback, errorCallback, false, true);
	};
	this.setWifiEncryption = function(encryption, key, keyIndex, eapOptions, caCertificateLength, clientCertificateLength, privateKeyLength, returnCallback, errorCallback) {
		/*
		Sets the encryption of the WIFI Extension. The first parameter is the
		type of the encryption. Possible values are:
		
		.. csv-table::
		 :header: "Value", "Description"
		 :widths: 10, 90
		
		 "0", "WPA/WPA2"
		 "1", "WPA Enterprise (EAP-FAST, EAP-TLS, EAP-TTLS, PEAP)"
		 "2", "WEP"
		 "3", "No Encryption"
		
		The ``key`` has a max length of 50 characters and is used if ``encryption``
		is set to 0 or 2 (WPA/WPA2 or WEP). Otherwise the value is ignored.
		
		For WPA/WPA2 the key has to be at least 8 characters long. If you want to set
		a key with more than 50 characters, see :func:`Set Long Wifi Key`.
		
		For WEP the key has to be either 10 or 26 hexadecimal digits long. It is
		possible to set the WEP ``key_index`` (1-4). If you don't know your
		``key_index``, it is likely 1.
		
		If you choose WPA Enterprise as encryption, you have to set ``eap_options`` and
		the length of the certificates (for other encryption types these parameters
		are ignored). The certificates
		themselves can be set with :func:`Set Wifi Certificate`. ``eap_options`` consist
		of the outer authentication (bits 1-2), inner authentication (bit 3) and
		certificate type (bits 4-5):
		
		.. csv-table::
		 :header: "Option", "Bits", "Description"
		 :widths: 20, 10, 70
		
		 "outer authentication", "1-2", "0=EAP-FAST, 1=EAP-TLS, 2=EAP-TTLS, 3=EAP-PEAP"
		 "inner authentication", "3", "0=EAP-MSCHAP, 1=EAP-GTC"
		 "certificate type", "4-5", "0=CA Certificate, 1=Client Certificate, 2=Private Key"
		
		Example for EAP-TTLS + EAP-GTC + Private Key: ``option = 2 | (1 << 2) | (2 << 3)``.
		
		The values are stored in the EEPROM and only applied on startup. That means
		you have to restart the Master Brick after configuration.
		
		It is recommended to use the Brick Viewer to set the Wi-Fi encryption.
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_SET_WIFI_ENCRYPTION, [encryption, key, keyIndex, eapOptions, caCertificateLength, clientCertificateLength, privateKeyLength], 'B s50 B B H H H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getWifiEncryption = function(returnCallback, errorCallback) {
		/*
		Returns the encryption as set by :func:`Set Wifi Encryption`.
		
		.. note::
		 Since Master Brick Firmware version 2.4.4 the key is not returned anymore.
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_GET_WIFI_ENCRYPTION, [], '', 67, 'B s50 B B H H H', returnCallback, errorCallback, false, true);
	};
	this.getWifiStatus = function(returnCallback, errorCallback) {
		/*
		Returns the status of the WIFI Extension. The ``state`` is updated automatically,
		all of the other parameters are updated on startup and every time
		:func:`Refresh Wifi Status` is called.
		
		Possible states are:
		
		.. csv-table::
		 :header: "State", "Description"
		 :widths: 10, 90
		
		 "0", "Disassociated"
		 "1", "Associated"
		 "2", "Associating"
		 "3", "Error"
		 "255", "Not initialized yet"
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_GET_WIFI_STATUS, [], '', 44, 'B6 B6 B h B4 B4 B4 I I B', returnCallback, errorCallback, false, true);
	};
	this.refreshWifiStatus = function(returnCallback, errorCallback) {
		/*
		Refreshes the Wi-Fi status (see :func:`Get Wifi Status`). To read the status
		of the Wi-Fi module, the Master Brick has to change from data mode to
		command mode and back. This transaction and the readout itself is
		unfortunately time consuming. This means, that it might take some ms
		until the stack with attached WIFI Extension reacts again after this
		function is called.
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_REFRESH_WIFI_STATUS, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.setWifiCertificate = function(index, data, dataLength, returnCallback, errorCallback) {
		/*
		This function is used to set the certificate as well as password and username
		for WPA Enterprise. To set the username use index 0xFFFF,
		to set the password use index 0xFFFE. The max length of username and
		password is 32.
		
		The certificate is written in chunks of size 32 and the index is used as
		the index of the chunk. ``data_length`` should nearly always be 32. Only
		the last chunk can have a length that is not equal to 32.
		
		The starting index of the CA Certificate is 0, of the Client Certificate
		10000 and for the Private Key 20000. Maximum sizes are 1312, 1312 and
		4320 byte respectively.
		
		The values are stored in the EEPROM and only applied on startup. That means
		you have to restart the Master Brick after uploading the certificate.
		
		It is recommended to use the Brick Viewer to set the certificate, username
		and password.
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_SET_WIFI_CERTIFICATE, [index, data, dataLength], 'H B32 B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getWifiCertificate = function(index, returnCallback, errorCallback) {
		/*
		Returns the certificate for a given index as set by :func:`Set Wifi Certificate`.
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_GET_WIFI_CERTIFICATE, [index], 'H', 41, 'B32 B', returnCallback, errorCallback, false, true);
	};
	this.setWifiPowerMode = function(mode, returnCallback, errorCallback) {
		/*
		Sets the power mode of the WIFI Extension. Possible modes are:
		
		.. csv-table::
		 :header: "Mode", "Description"
		 :widths: 10, 90
		
		 "0", "Full Speed (high power consumption, high throughput)"
		 "1", "Low Power (low power consumption, low throughput)"
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_SET_WIFI_POWER_MODE, [mode], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getWifiPowerMode = function(returnCallback, errorCallback) {
		/*
		Returns the power mode as set by :func:`Set Wifi Power Mode`.
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_GET_WIFI_POWER_MODE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getWifiBufferInfo = function(returnCallback, errorCallback) {
		/*
		Returns informations about the Wi-Fi receive buffer. The Wi-Fi
		receive buffer has a max size of 1500 byte and if data is transfered
		too fast, it might overflow.
		
		The return values are the number of overflows, the low watermark
		(i.e. the smallest number of bytes that were free in the buffer) and
		the bytes that are currently used.
		
		You should always try to keep the buffer empty, otherwise you will
		have a permanent latency. A good rule of thumb is, that you can transfer
		1000 messages per second without problems.
		
		Try to not send more then 50 messages at a time without any kind of
		break between them.
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_GET_WIFI_BUFFER_INFO, [], '', 16, 'I H H', returnCallback, errorCallback, false, true);
	};
	this.setWifiRegulatoryDomain = function(domain, returnCallback, errorCallback) {
		/*
		Sets the regulatory domain of the WIFI Extension. Possible domains are:
		
		.. csv-table::
		 :header: "Domain", "Description"
		 :widths: 10, 90
		
		 "0", "FCC: Channel 1-11 (N/S America, Australia, New Zealand)"
		 "1", "ETSI: Channel 1-13 (Europe, Middle East, Africa)"
		 "2", "TELEC: Channel 1-14 (Japan)"
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_SET_WIFI_REGULATORY_DOMAIN, [domain], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getWifiRegulatoryDomain = function(returnCallback, errorCallback) {
		/*
		Returns the regulatory domain as set by :func:`Set Wifi Regulatory Domain`.
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_GET_WIFI_REGULATORY_DOMAIN, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getUSBVoltage = function(returnCallback, errorCallback) {
		/*
		Returns the USB voltage. Does not work with hardware version 2.1.
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_GET_USB_VOLTAGE, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.setLongWifiKey = function(key, returnCallback, errorCallback) {
		/*
		Sets a long Wi-Fi key (up to 63 chars, at least 8 chars) for WPA encryption.
		This key will be used
		if the key in :func:`Set Wifi Encryption` is set to "-". In the old protocol,
		a payload of size 63 was not possible, so the maximum key length was 50 chars.
		
		With the new protocol this is possible, since we didn't want to break API,
		this function was added additionally.
		
		.. versionadded:: 2.0.2$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_SET_LONG_WIFI_KEY, [key], 's64', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getLongWifiKey = function(returnCallback, errorCallback) {
		/*
		Returns the encryption key as set by :func:`Set Long Wifi Key`.
		
		.. note::
		 Since Master Brick firmware version 2.4.4 the key is not returned anymore.
		
		.. versionadded:: 2.0.2$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_GET_LONG_WIFI_KEY, [], '', 72, 's64', returnCallback, errorCallback, false, true);
	};
	this.setWifiHostname = function(hostname, returnCallback, errorCallback) {
		/*
		Sets the hostname of the WIFI Extension. The hostname will be displayed
		by access points as the hostname in the DHCP clients table.
		
		Setting an empty String will restore the default hostname.
		
		.. versionadded:: 2.0.5$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_SET_WIFI_HOSTNAME, [hostname], 's16', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getWifiHostname = function(returnCallback, errorCallback) {
		/*
		Returns the hostname as set by :func:`Set Wifi Hostname`.
		
		An empty String means, that the default hostname is used.
		
		.. versionadded:: 2.0.5$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_GET_WIFI_HOSTNAME, [], '', 24, 's16', returnCallback, errorCallback, false, true);
	};
	this.setStackCurrentCallbackPeriod = function(period, returnCallback, errorCallback) {
		/*
		Sets the period with which the :cb:`Stack Current` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		The :cb:`Stack Current` callback is only triggered if the current has changed
		since the last triggering.
		
		.. versionadded:: 2.0.5$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_SET_STACK_CURRENT_CALLBACK_PERIOD, [period], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getStackCurrentCallbackPeriod = function(returnCallback, errorCallback) {
		/*
		Returns the period as set by :func:`Set Stack Current Callback Period`.
		
		.. versionadded:: 2.0.5$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_GET_STACK_CURRENT_CALLBACK_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setStackVoltageCallbackPeriod = function(period, returnCallback, errorCallback) {
		/*
		Sets the period with which the :cb:`Stack Voltage` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		The :cb:`Stack Voltage` callback is only triggered if the voltage has changed
		since the last triggering.
		
		.. versionadded:: 2.0.5$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_SET_STACK_VOLTAGE_CALLBACK_PERIOD, [period], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getStackVoltageCallbackPeriod = function(returnCallback, errorCallback) {
		/*
		Returns the period as set by :func:`Set Stack Voltage Callback Period`.
		
		.. versionadded:: 2.0.5$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_GET_STACK_VOLTAGE_CALLBACK_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setUSBVoltageCallbackPeriod = function(period, returnCallback, errorCallback) {
		/*
		Sets the period with which the :cb:`USB Voltage` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		The :cb:`USB Voltage` callback is only triggered if the voltage has changed
		since the last triggering.
		
		.. versionadded:: 2.0.5$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_SET_USB_VOLTAGE_CALLBACK_PERIOD, [period], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getUSBVoltageCallbackPeriod = function(returnCallback, errorCallback) {
		/*
		Returns the period as set by :func:`Set USB Voltage Callback Period`.
		
		.. versionadded:: 2.0.5$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_GET_USB_VOLTAGE_CALLBACK_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setStackCurrentCallbackThreshold = function(option, min, max, returnCallback, errorCallback) {
		/*
		Sets the thresholds for the :cb:`Stack Current Reached` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Callback is turned off"
		 "'o'",    "Callback is triggered when the current is *outside* the min and max values"
		 "'i'",    "Callback is triggered when the current is *inside* the min and max values"
		 "'<'",    "Callback is triggered when the current is smaller than the min value (max is ignored)"
		 "'>'",    "Callback is triggered when the current is greater than the min value (max is ignored)"
		
		.. versionadded:: 2.0.5$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_SET_STACK_CURRENT_CALLBACK_THRESHOLD, [option, min, max], 'c H H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getStackCurrentCallbackThreshold = function(returnCallback, errorCallback) {
		/*
		Returns the threshold as set by :func:`Set Stack Current Callback Threshold`.
		
		.. versionadded:: 2.0.5$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_GET_STACK_CURRENT_CALLBACK_THRESHOLD, [], '', 13, 'c H H', returnCallback, errorCallback, false, true);
	};
	this.setStackVoltageCallbackThreshold = function(option, min, max, returnCallback, errorCallback) {
		/*
		Sets the thresholds for the :cb:`Stack Voltage Reached` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Callback is turned off"
		 "'o'",    "Callback is triggered when the voltage is *outside* the min and max values"
		 "'i'",    "Callback is triggered when the voltage is *inside* the min and max values"
		 "'<'",    "Callback is triggered when the voltage is smaller than the min value (max is ignored)"
		 "'>'",    "Callback is triggered when the voltage is greater than the min value (max is ignored)"
		
		.. versionadded:: 2.0.5$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_SET_STACK_VOLTAGE_CALLBACK_THRESHOLD, [option, min, max], 'c H H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getStackVoltageCallbackThreshold = function(returnCallback, errorCallback) {
		/*
		Returns the threshold as set by :func:`Set Stack Voltage Callback Threshold`.
		
		.. versionadded:: 2.0.5$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_GET_STACK_VOLTAGE_CALLBACK_THRESHOLD, [], '', 13, 'c H H', returnCallback, errorCallback, false, true);
	};
	this.setUSBVoltageCallbackThreshold = function(option, min, max, returnCallback, errorCallback) {
		/*
		Sets the thresholds for the :cb:`USB Voltage Reached` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Callback is turned off"
		 "'o'",    "Callback is triggered when the voltage is *outside* the min and max values"
		 "'i'",    "Callback is triggered when the voltage is *inside* the min and max values"
		 "'<'",    "Callback is triggered when the voltage is smaller than the min value (max is ignored)"
		 "'>'",    "Callback is triggered when the voltage is greater than the min value (max is ignored)"
		
		.. versionadded:: 2.0.5$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_SET_USB_VOLTAGE_CALLBACK_THRESHOLD, [option, min, max], 'c H H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getUSBVoltageCallbackThreshold = function(returnCallback, errorCallback) {
		/*
		Returns the threshold as set by :func:`Set USB Voltage Callback Threshold`.
		
		.. versionadded:: 2.0.5$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_GET_USB_VOLTAGE_CALLBACK_THRESHOLD, [], '', 13, 'c H H', returnCallback, errorCallback, false, true);
	};
	this.setDebouncePeriod = function(debounce, returnCallback, errorCallback) {
		/*
		Sets the period with which the threshold callbacks
		
		* :cb:`Stack Current Reached`,
		* :cb:`Stack Voltage Reached`,
		* :cb:`USB Voltage Reached`
		
		are triggered, if the thresholds
		
		* :func:`Set Stack Current Callback Threshold`,
		* :func:`Set Stack Voltage Callback Threshold`,
		* :func:`Set USB Voltage Callback Threshold`
		
		keep being reached.
		
		.. versionadded:: 2.0.5$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_SET_DEBOUNCE_PERIOD, [debounce], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getDebouncePeriod = function(returnCallback, errorCallback) {
		/*
		Returns the debounce period as set by :func:`Set Debounce Period`.
		
		.. versionadded:: 2.0.5$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_GET_DEBOUNCE_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.isEthernetPresent = function(returnCallback, errorCallback) {
		/*
		Returns *true* if the Master Brick is at position 0 in the stack and an Ethernet
		Extension is available.
		
		.. versionadded:: 2.1.0$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_IS_ETHERNET_PRESENT, [], '', 9, '?', returnCallback, errorCallback, false, true);
	};
	this.setEthernetConfiguration = function(connection, ip, subnetMask, gateway, port, returnCallback, errorCallback) {
		/*
		Sets the configuration of the Ethernet Extension. Possible values for
		``connection`` are:
		
		.. csv-table::
		 :header: "Value", "Description"
		 :widths: 10, 90
		
		 "0", "DHCP"
		 "1", "Static IP"
		
		If you set ``connection`` to static IP options then you have to supply ``ip``,
		``subnet_mask`` and ``gateway`` as an array of size 4 (first element of the
		array is the least significant byte of the address). If ``connection`` is set
		to the DHCP options then ``ip``, ``subnet_mask`` and ``gateway`` are ignored,
		you can set them to 0.
		
		The last parameter is the port that your program will connect to.
		
		The values are stored in the EEPROM and only applied on startup. That means
		you have to restart the Master Brick after configuration.
		
		It is recommended to use the Brick Viewer to set the Ethernet configuration.
		
		.. versionadded:: 2.1.0$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_SET_ETHERNET_CONFIGURATION, [connection, ip, subnetMask, gateway, port], 'B B4 B4 B4 H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getEthernetConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Ethernet Configuration`.
		
		.. versionadded:: 2.1.0$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_GET_ETHERNET_CONFIGURATION, [], '', 23, 'B B4 B4 B4 H', returnCallback, errorCallback, false, true);
	};
	this.getEthernetStatus = function(returnCallback, errorCallback) {
		/*
		Returns the status of the Ethernet Extension.
		
		``mac_address``, ``ip``, ``subnet_mask`` and ``gateway`` are given as an array.
		The first element of the array is the least significant byte of the address.
		
		``rx_count`` and ``tx_count`` are the number of bytes that have been
		received/send since last restart.
		
		``hostname`` is the currently used hostname.
		
		.. versionadded:: 2.1.0$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_GET_ETHERNET_STATUS, [], '', 66, 'B6 B4 B4 B4 I I s32', returnCallback, errorCallback, false, true);
	};
	this.setEthernetHostname = function(hostname, returnCallback, errorCallback) {
		/*
		Sets the hostname of the Ethernet Extension. The hostname will be displayed
		by access points as the hostname in the DHCP clients table.
		
		Setting an empty String will restore the default hostname.
		
		The current hostname can be discovered with :func:`Get Ethernet Status`.
		
		.. versionadded:: 2.1.0$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_SET_ETHERNET_HOSTNAME, [hostname], 's32', 0, '', returnCallback, errorCallback, false, true);
	};
	this.setEthernetMACAddress = function(macAddress, returnCallback, errorCallback) {
		/*
		Sets the MAC address of the Ethernet Extension. The Ethernet Extension should
		come configured with a valid MAC address, that is also written on a
		sticker of the extension itself.
		
		The MAC address can be read out again with :func:`Get Ethernet Status`.
		
		.. versionadded:: 2.1.0$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_SET_ETHERNET_MAC_ADDRESS, [macAddress], 'B6', 0, '', returnCallback, errorCallback, false, true);
	};
	this.setEthernetWebsocketConfiguration = function(sockets, port, returnCallback, errorCallback) {
		/*
		Sets the Ethernet WebSocket configuration. The first parameter sets the number of socket
		connections that are reserved for WebSockets. The range is 0-7. The connections
		are shared with the plain sockets. Example: If you set the connections to 3,
		there will be 3 WebSocket and 4 plain socket connections available.
		
		The second parameter is the port for the WebSocket connections. The port can
		not be the same as the port for the plain socket connections.
		
		The values are stored in the EEPROM and only applied on startup. That means
		you have to restart the Master Brick after configuration.
		
		It is recommended to use the Brick Viewer to set the Ethernet configuration.
		
		.. versionadded:: 2.2.0$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_SET_ETHERNET_WEBSOCKET_CONFIGURATION, [sockets, port], 'B H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getEthernetWebsocketConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Ethernet Configuration`.
		
		.. versionadded:: 2.2.0$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_GET_ETHERNET_WEBSOCKET_CONFIGURATION, [], '', 11, 'B H', returnCallback, errorCallback, false, true);
	};
	this.setEthernetAuthenticationSecret = function(secret, returnCallback, errorCallback) {
		/*
		Sets the Ethernet authentication secret. The secret can be a string of up to 64
		characters. An empty string disables the authentication.
		
		See the :ref:`authentication tutorial <tutorial_authentication>` for more
		information.
		
		The secret is stored in the EEPROM and only applied on startup. That means
		you have to restart the Master Brick after configuration.
		
		It is recommended to use the Brick Viewer to set the Ethernet authentication secret.
		
		The default value is an empty string (authentication disabled).
		
		.. versionadded:: 2.2.0$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_SET_ETHERNET_AUTHENTICATION_SECRET, [secret], 's64', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getEthernetAuthenticationSecret = function(returnCallback, errorCallback) {
		/*
		Returns the authentication secret as set by
		:func:`Set Ethernet Authentication Secret`.
		
		.. versionadded:: 2.2.0$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_GET_ETHERNET_AUTHENTICATION_SECRET, [], '', 72, 's64', returnCallback, errorCallback, false, true);
	};
	this.setWifiAuthenticationSecret = function(secret, returnCallback, errorCallback) {
		/*
		Sets the WIFI authentication secret. The secret can be a string of up to 64
		characters. An empty string disables the authentication.
		
		See the :ref:`authentication tutorial <tutorial_authentication>` for more
		information.
		
		The secret is stored in the EEPROM and only applied on startup. That means
		you have to restart the Master Brick after configuration.
		
		It is recommended to use the Brick Viewer to set the WIFI authentication secret.
		
		The default value is an empty string (authentication disabled).
		
		.. versionadded:: 2.2.0$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_SET_WIFI_AUTHENTICATION_SECRET, [secret], 's64', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getWifiAuthenticationSecret = function(returnCallback, errorCallback) {
		/*
		Returns the authentication secret as set by
		:func:`Set Wifi Authentication Secret`.
		
		.. versionadded:: 2.2.0$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_GET_WIFI_AUTHENTICATION_SECRET, [], '', 72, 's64', returnCallback, errorCallback, false, true);
	};
	this.getConnectionType = function(returnCallback, errorCallback) {
		/*
		Returns the type of the connection over which this function was called.
		
		.. versionadded:: 2.4.0$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_GET_CONNECTION_TYPE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.isWifi2Present = function(returnCallback, errorCallback) {
		/*
		Returns *true* if the Master Brick is at position 0 in the stack and a WIFI
		Extension 2.0 is available.
		
		.. versionadded:: 2.4.0$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_IS_WIFI2_PRESENT, [], '', 9, '?', returnCallback, errorCallback, false, true);
	};
	this.startWifi2Bootloader = function(returnCallback, errorCallback) {
		/*
		Starts the bootloader of the WIFI Extension 2.0. Returns 0 on success.
		Afterwards the :func:`Write Wifi2 Serial Port` and :func:`Read Wifi2 Serial Port`
		functions can be used to communicate with the bootloader to flash a new
		firmware.
		
		The bootloader should only be started over a USB connection. It cannot be
		started over a WIFI2 connection, see the :func:`Get Connection Type` function.
		
		It is recommended to use the Brick Viewer to update the firmware of the WIFI
		Extension 2.0.
		
		.. versionadded:: 2.4.0$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_START_WIFI2_BOOTLOADER, [], '', 9, 'b', returnCallback, errorCallback, false, true);
	};
	this.writeWifi2SerialPort = function(data, length, returnCallback, errorCallback) {
		/*
		Writes up to 60 bytes (number of bytes to be written specified by ``length``)
		to the serial port of the bootloader of the WIFI Extension 2.0. Returns 0 on
		success.
		
		Before this function can be used the bootloader has to be started using the
		:func:`Start Wifi2 Bootloader` function.
		
		It is recommended to use the Brick Viewer to update the firmware of the WIFI
		Extension 2.0.
		
		.. versionadded:: 2.4.0$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_WRITE_WIFI2_SERIAL_PORT, [data, length], 'B60 B', 9, 'b', returnCallback, errorCallback, false, true);
	};
	this.readWifi2SerialPort = function(length, returnCallback, errorCallback) {
		/*
		Reads up to 60 bytes (number of bytes to be read specified by ``length``)
		from the serial port of the bootloader of the WIFI Extension 2.0.
		Returns the number of actually read bytes.
		
		Before this function can be used the bootloader has to be started using the
		:func:`Start Wifi2 Bootloader` function.
		
		It is recommended to use the Brick Viewer to update the firmware of the WIFI
		Extension 2.0.
		
		.. versionadded:: 2.4.0$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_READ_WIFI2_SERIAL_PORT, [length], 'B', 69, 'B60 B', returnCallback, errorCallback, false, true);
	};
	this.setWifi2AuthenticationSecret = function(secret, returnCallback, errorCallback) {
		/*
		Sets the WIFI authentication secret. The secret can be a string of up to 64
		characters. An empty string disables the authentication. The default value is
		an empty string (authentication disabled).
		
		See the :ref:`authentication tutorial <tutorial_authentication>` for more
		information.
		
		To apply configuration changes to the WIFI Extension 2.0 the
		:func:`Save Wifi2 Configuration` function has to be called and the Master Brick
		has to be restarted afterwards.
		
		It is recommended to use the Brick Viewer to configure the WIFI Extension 2.0.
		
		.. versionadded:: 2.4.0$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_SET_WIFI2_AUTHENTICATION_SECRET, [secret], 's64', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getWifi2AuthenticationSecret = function(returnCallback, errorCallback) {
		/*
		Returns the WIFI authentication secret as set by
		:func:`Set Wifi2 Authentication Secret`.
		
		.. versionadded:: 2.4.0$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_GET_WIFI2_AUTHENTICATION_SECRET, [], '', 72, 's64', returnCallback, errorCallback, false, true);
	};
	this.setWifi2Configuration = function(port, websocketPort, websitePort, phyMode, sleepMode, website, returnCallback, errorCallback) {
		/*
		Sets the general configuration of the WIFI Extension 2.0.
		
		The ``port`` parameter sets the port number that your programm will connect
		to.
		
		The ``websocket_port`` parameter sets the WebSocket port number that your
		JavaScript programm will connect to.
		
		The ``website_port`` parameter sets the port number for the website of the
		WIFI Extension 2.0.
		
		The ``phy_mode`` parameter sets the specific wireless network mode to be used.
		Possible values are B, G and N.
		
		The ``sleep_mode`` parameter is currently unused.
		
		The ``website`` parameter is used to enable or disable the web interface of
		the WIFI Extension 2.0, which is available from firmware version 2.0.1. Note
		that, for firmware version 2.0.3 and older, to disable the the web interface
		the ``website_port`` parameter must be set to 1 and greater than 1 to enable
		the web interface. For firmware version 2.0.4 and later, setting this parameter
		to 1 will enable the web interface and setting it to 0 will disable the web
		interface.
		
		To apply configuration changes to the WIFI Extension 2.0 the
		:func:`Save Wifi2 Configuration` function has to be called and the Master Brick
		has to be restarted afterwards.
		
		It is recommended to use the Brick Viewer to configure the WIFI Extension 2.0.
		
		.. versionadded:: 2.4.0$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_SET_WIFI2_CONFIGURATION, [port, websocketPort, websitePort, phyMode, sleepMode, website], 'H H H B B B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getWifi2Configuration = function(returnCallback, errorCallback) {
		/*
		Returns the general configuration as set by :func:`Set Wifi2 Configuration`.
		
		.. versionadded:: 2.4.0$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_GET_WIFI2_CONFIGURATION, [], '', 17, 'H H H B B B', returnCallback, errorCallback, false, true);
	};
	this.getWifi2Status = function(returnCallback, errorCallback) {
		/*
		Returns the client and access point status of the WIFI Extension 2.0.
		
		.. versionadded:: 2.4.0$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_GET_WIFI2_STATUS, [], '', 65, '? B B4 B4 B4 B6 I I b ? B4 B4 B4 B6 I I B', returnCallback, errorCallback, false, true);
	};
	this.setWifi2ClientConfiguration = function(enable, ssid, ip, subnetMask, gateway, macAddress, bssid, returnCallback, errorCallback) {
		/*
		Sets the client specific configuration of the WIFI Extension 2.0.
		
		The ``enable`` parameter enables or disables the client part of the
		WIFI Extension 2.0.
		
		The ``ssid`` parameter sets the SSID (up to 32 characters) of the access point
		to connect to.
		
		If the ``ip`` parameter is set to all zero then ``subnet_mask`` and ``gateway``
		parameters are also set to all zero and DHCP is used for IP address configuration.
		Otherwise those three parameters can be used to configure a static IP address.
		The default configuration is DHCP.
		
		If the ``mac_address`` parameter is set to all zero then the factory MAC
		address is used. Otherwise this parameter can be used to set a custom MAC
		address.
		
		If the ``bssid`` parameter is set to all zero then WIFI Extension 2.0 will
		connect to any access point that matches the configured SSID. Otherwise this
		parameter can be used to make the WIFI Extension 2.0 only connect to an
		access point if SSID and BSSID match.
		
		To apply configuration changes to the WIFI Extension 2.0 the
		:func:`Save Wifi2 Configuration` function has to be called and the Master Brick
		has to be restarted afterwards.
		
		It is recommended to use the Brick Viewer to configure the WIFI Extension 2.0.
		
		.. versionadded:: 2.4.0$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_SET_WIFI2_CLIENT_CONFIGURATION, [enable, ssid, ip, subnetMask, gateway, macAddress, bssid], '? s32 B4 B4 B4 B6 B6', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getWifi2ClientConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the client configuration as set by :func:`Set Wifi2 Client Configuration`.
		
		.. versionadded:: 2.4.0$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_GET_WIFI2_CLIENT_CONFIGURATION, [], '', 65, '? s32 B4 B4 B4 B6 B6', returnCallback, errorCallback, false, true);
	};
	this.setWifi2ClientHostname = function(hostname, returnCallback, errorCallback) {
		/*
		Sets the client hostname (up to 32 characters) of the WIFI Extension 2.0. The
		hostname will be displayed by access points as the hostname in the DHCP clients
		table.
		
		To apply configuration changes to the WIFI Extension 2.0 the
		:func:`Save Wifi2 Configuration` function has to be called and the Master Brick
		has to be restarted afterwards.
		
		It is recommended to use the Brick Viewer to configure the WIFI Extension 2.0.
		
		.. versionadded:: 2.4.0$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_SET_WIFI2_CLIENT_HOSTNAME, [hostname], 's32', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getWifi2ClientHostname = function(returnCallback, errorCallback) {
		/*
		Returns the client hostname as set by :func:`Set Wifi2 Client Hostname`.
		
		.. versionadded:: 2.4.0$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_GET_WIFI2_CLIENT_HOSTNAME, [], '', 40, 's32', returnCallback, errorCallback, false, true);
	};
	this.setWifi2ClientPassword = function(password, returnCallback, errorCallback) {
		/*
		Sets the client password (up to 63 chars) for WPA/WPA2 encryption.
		
		To apply configuration changes to the WIFI Extension 2.0 the
		:func:`Save Wifi2 Configuration` function has to be called and the Master Brick
		has to be restarted afterwards.
		
		It is recommended to use the Brick Viewer to configure the WIFI Extension 2.0.
		
		.. versionadded:: 2.4.0$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_SET_WIFI2_CLIENT_PASSWORD, [password], 's64', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getWifi2ClientPassword = function(returnCallback, errorCallback) {
		/*
		Returns the client password as set by :func:`Set Wifi2 Client Password`.
		
		.. note::
		 Since WIFI Extension 2.0 firmware version 2.1.3 the password is not
		 returned anymore.
		
		.. versionadded:: 2.4.0$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_GET_WIFI2_CLIENT_PASSWORD, [], '', 72, 's64', returnCallback, errorCallback, false, true);
	};
	this.setWifi2APConfiguration = function(enable, ssid, ip, subnetMask, gateway, encryption, hidden, channel, macAddress, returnCallback, errorCallback) {
		/*
		Sets the access point specific configuration of the WIFI Extension 2.0.
		
		The ``enable`` parameter enables or disables the access point part of the
		WIFI Extension 2.0.
		
		The ``ssid`` parameter sets the SSID (up to 32 characters) of the access point.
		
		If the ``ip`` parameter is set to all zero then ``subnet_mask`` and ``gateway``
		parameters are also set to all zero and DHCP is used for IP address configuration.
		Otherwise those three parameters can be used to configure a static IP address.
		The default configuration is DHCP.
		
		The ``encryption`` parameter sets the encryption mode to be used. Possible
		values are Open (no encryption), WEP or WPA/WPA2 PSK.
		Use the :func:`Set Wifi2 AP Password` function to set the encryption
		password.
		
		The ``hidden`` parameter makes the access point hide or show its SSID.
		
		The ``channel`` parameter sets the channel (1 to 13) of the access point.
		
		If the ``mac_address`` parameter is set to all zero then the factory MAC
		address is used. Otherwise this parameter can be used to set a custom MAC
		address.
		
		To apply configuration changes to the WIFI Extension 2.0 the
		:func:`Save Wifi2 Configuration` function has to be called and the Master Brick
		has to be restarted afterwards.
		
		It is recommended to use the Brick Viewer to configure the WIFI Extension 2.0.
		
		.. versionadded:: 2.4.0$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_SET_WIFI2_AP_CONFIGURATION, [enable, ssid, ip, subnetMask, gateway, encryption, hidden, channel, macAddress], '? s32 B4 B4 B4 B ? B B6', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getWifi2APConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the access point configuration as set by :func:`Set Wifi2 AP Configuration`.
		
		.. versionadded:: 2.4.0$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_GET_WIFI2_AP_CONFIGURATION, [], '', 62, '? s32 B4 B4 B4 B ? B B6', returnCallback, errorCallback, false, true);
	};
	this.setWifi2APPassword = function(password, returnCallback, errorCallback) {
		/*
		Sets the access point password (at least 8 and up to 63 chars) for the configured encryption
		mode, see :func:`Set Wifi2 AP Configuration`.
		
		To apply configuration changes to the WIFI Extension 2.0 the
		:func:`Save Wifi2 Configuration` function has to be called and the Master Brick
		has to be restarted afterwards.
		
		It is recommended to use the Brick Viewer to configure the WIFI Extension 2.0.
		
		.. versionadded:: 2.4.0$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_SET_WIFI2_AP_PASSWORD, [password], 's64', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getWifi2APPassword = function(returnCallback, errorCallback) {
		/*
		Returns the access point password as set by :func:`Set Wifi2 AP Password`.
		
		.. note::
		 Since WIFI Extension 2.0 firmware version 2.1.3 the password is not
		 returned anymore.
		
		.. versionadded:: 2.4.0$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_GET_WIFI2_AP_PASSWORD, [], '', 72, 's64', returnCallback, errorCallback, false, true);
	};
	this.saveWifi2Configuration = function(returnCallback, errorCallback) {
		/*
		All configuration functions for the WIFI Extension 2.0 do not change the
		values permanently. After configuration this function has to be called to
		permanently store the values.
		
		The values are stored in the EEPROM and only applied on startup. That means
		you have to restart the Master Brick after configuration.
		
		.. versionadded:: 2.4.0$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_SAVE_WIFI2_CONFIGURATION, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getWifi2FirmwareVersion = function(returnCallback, errorCallback) {
		/*
		Returns the current version of the WIFI Extension 2.0 firmware.
		
		.. versionadded:: 2.4.0$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_GET_WIFI2_FIRMWARE_VERSION, [], '', 11, 'B3', returnCallback, errorCallback, false, true);
	};
	this.enableWifi2StatusLED = function(returnCallback, errorCallback) {
		/*
		Turns the green status LED of the WIFI Extension 2.0 on.
		
		.. versionadded:: 2.4.0$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_ENABLE_WIFI2_STATUS_LED, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.disableWifi2StatusLED = function(returnCallback, errorCallback) {
		/*
		Turns the green status LED of the WIFI Extension 2.0 off.
		
		.. versionadded:: 2.4.0$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_DISABLE_WIFI2_STATUS_LED, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.isWifi2StatusLEDEnabled = function(returnCallback, errorCallback) {
		/*
		Returns *true* if the green status LED of the WIFI Extension 2.0 is turned on.
		
		.. versionadded:: 2.4.0$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_IS_WIFI2_STATUS_LED_ENABLED, [], '', 9, '?', returnCallback, errorCallback, false, true);
	};
	this.setWifi2MeshConfiguration = function(enable, rootIP, rootSubnetMask, rootGateway, routerBSSID, groupID, groupSSIDPrefix, gatewayIP, gatewayPort, returnCallback, errorCallback) {
		/*
		Requires WIFI Extension 2.0 firmware 2.1.0.
		
		Sets the mesh specific configuration of the WIFI Extension 2.0.
		
		The ``enable`` parameter enables or disables the mesh part of the
		WIFI Extension 2.0. The mesh part cannot be
		enabled together with the client and access-point part.
		
		If the ``root_ip`` parameter is set to all zero then ``root_subnet_mask``
		and ``root_gateway`` parameters are also set to all zero and DHCP is used for
		IP address configuration. Otherwise those three parameters can be used to
		configure a static IP address. The default configuration is DHCP.
		
		If the ``router_bssid`` parameter is set to all zero then the information is
		taken from Wi-Fi scan when connecting the SSID as set by
		:func:`Set Wifi2 Mesh Router SSID`. This only works if the the SSID is not hidden.
		In case the router has hidden SSID this parameter must be specified, otherwise
		the node will not be able to reach the mesh router.
		
		The ``group_id`` and the ``group_ssid_prefix`` parameters identifies a
		particular mesh network and nodes configured with same ``group_id`` and the
		``group_ssid_prefix`` are considered to be in the same mesh network.
		
		The ``gateway_ip`` and the ``gateway_port`` parameters specifies the location
		of the brickd that supports mesh feature.
		
		To apply configuration changes to the WIFI Extension 2.0 the
		:func:`Save Wifi2 Configuration` function has to be called and the Master Brick
		has to be restarted afterwards.
		
		It is recommended to use the Brick Viewer to configure the WIFI Extension 2.0.
		
		.. versionadded:: 2.4.2$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_SET_WIFI2_MESH_CONFIGURATION, [enable, rootIP, rootSubnetMask, rootGateway, routerBSSID, groupID, groupSSIDPrefix, gatewayIP, gatewayPort], '? B4 B4 B4 B6 B6 s16 B4 H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getWifi2MeshConfiguration = function(returnCallback, errorCallback) {
		/*
		Requires WIFI Extension 2.0 firmware 2.1.0.
		
		Returns the mesh configuration as set by :func:`Set Wifi2 Mesh Configuration`.
		
		.. versionadded:: 2.4.2$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_GET_WIFI2_MESH_CONFIGURATION, [], '', 55, '? B4 B4 B4 B6 B6 s16 B4 H', returnCallback, errorCallback, false, true);
	};
	this.setWifi2MeshRouterSSID = function(ssid, returnCallback, errorCallback) {
		/*
		Requires WIFI Extension 2.0 firmware 2.1.0.
		
		Sets the mesh router SSID of the WIFI Extension 2.0.
		It is used to specify the mesh router to connect to.
		
		Note that even though in the argument of this function a 32 characters long SSID
		is allowed, in practice valid SSID should have a maximum of 31 characters. This
		is due to a bug in the mesh library that we use in the firmware of the extension.
		
		To apply configuration changes to the WIFI Extension 2.0 the
		:func:`Save Wifi2 Configuration` function has to be called and the Master Brick
		has to be restarted afterwards.
		
		It is recommended to use the Brick Viewer to configure the WIFI Extension 2.0.
		
		.. versionadded:: 2.4.2$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_SET_WIFI2_MESH_ROUTER_SSID, [ssid], 's32', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getWifi2MeshRouterSSID = function(returnCallback, errorCallback) {
		/*
		Requires WIFI Extension 2.0 firmware 2.1.0.
		
		Returns the mesh router SSID as set by :func:`Set Wifi2 Mesh Router SSID`.
		
		.. versionadded:: 2.4.2$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_GET_WIFI2_MESH_ROUTER_SSID, [], '', 40, 's32', returnCallback, errorCallback, false, true);
	};
	this.setWifi2MeshRouterPassword = function(password, returnCallback, errorCallback) {
		/*
		Requires WIFI Extension 2.0 firmware 2.1.0.
		
		Sets the mesh router password (up to 64 characters) for WPA/WPA2 encryption.
		The password will be used to connect to the mesh router.
		
		To apply configuration changes to the WIFI Extension 2.0 the
		:func:`Save Wifi2 Configuration` function has to be called and the Master Brick
		has to be restarted afterwards.
		
		It is recommended to use the Brick Viewer to configure the WIFI Extension 2.0.
		
		.. versionadded:: 2.4.2$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_SET_WIFI2_MESH_ROUTER_PASSWORD, [password], 's64', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getWifi2MeshRouterPassword = function(returnCallback, errorCallback) {
		/*
		Requires WIFI Extension 2.0 firmware 2.1.0.
		
		Returns the mesh router password as set by :func:`Set Wifi2 Mesh Router Password`.
		
		.. versionadded:: 2.4.2$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_GET_WIFI2_MESH_ROUTER_PASSWORD, [], '', 72, 's64', returnCallback, errorCallback, false, true);
	};
	this.getWifi2MeshCommonStatus = function(returnCallback, errorCallback) {
		/*
		Requires WIFI Extension 2.0 firmware 2.1.0.
		
		Returns the common mesh status of the WIFI Extension 2.0.
		
		.. versionadded:: 2.4.2$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_GET_WIFI2_MESH_COMMON_STATUS, [], '', 21, 'B ? ? H I I', returnCallback, errorCallback, false, true);
	};
	this.getWifi2MeshClientStatus = function(returnCallback, errorCallback) {
		/*
		Requires WIFI Extension 2.0 firmware 2.1.0.
		
		Returns the mesh client status of the WIFI Extension 2.0.
		
		.. versionadded:: 2.4.2$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_GET_WIFI2_MESH_CLIENT_STATUS, [], '', 58, 's32 B4 B4 B4 B6', returnCallback, errorCallback, false, true);
	};
	this.getWifi2MeshAPStatus = function(returnCallback, errorCallback) {
		/*
		Requires WIFI Extension 2.0 firmware 2.1.0.
		
		Returns the mesh AP status of the WIFI Extension 2.0.
		
		.. versionadded:: 2.4.2$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_GET_WIFI2_MESH_AP_STATUS, [], '', 58, 's32 B4 B4 B4 B6', returnCallback, errorCallback, false, true);
	};
	this.setBrickletXMCFlashConfig = function(config, parameter1, parameter2, data, returnCallback, errorCallback) {
		/*
		This function is for internal use to flash the initial
		bootstrapper and bootloader to the Bricklets.
		
		If you need to flash a boostrapper/bootloader (for exmaple
		because you made your own Bricklet from scratch) please
		take a look at our open source flash and test tool at
		`https://github.com/Tinkerforge/flash-test <https://github.com/Tinkerforge/flash-test>`__
		
		Don't use this function directly.
		
		.. versionadded:: 2.5.0$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_SET_BRICKLET_XMC_FLASH_CONFIG, [config, parameter1, parameter2, data], 'I I I B52', 72, 'I B60', returnCallback, errorCallback, false, true);
	};
	this.setBrickletXMCFlashData = function(data, returnCallback, errorCallback) {
		/*
		This function is for internal use to flash the initial
		bootstrapper and bootloader to the Bricklets.
		
		If you need to flash a boostrapper/bootloader (for exmaple
		because you made your own Bricklet from scratch) please
		take a look at our open source flash and test tool at
		`https://github.com/Tinkerforge/flash-test <https://github.com/Tinkerforge/flash-test>`__
		
		Don't use this function directly.
		
		.. versionadded:: 2.5.0$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_SET_BRICKLET_XMC_FLASH_DATA, [data], 'B64', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setBrickletsEnabled = function(brickletsEnabled, returnCallback, errorCallback) {
		/*
		This function is only available in Master Brick hardware version >= 3.0.
		
		Enables/disables all four Bricklets if set to true/false.
		
		If you disable the Bricklets the power supply to the Bricklets will be disconnected.
		The Bricklets will lose all configurations if disabled.
		
		.. versionadded:: 2.5.0$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_SET_BRICKLETS_ENABLED, [brickletsEnabled], '?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getBrickletsEnabled = function(returnCallback, errorCallback) {
		/*
		Returns *true* if the Bricklets are enabled, *false* otherwise.
		
		.. versionadded:: 2.5.0$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_GET_BRICKLETS_ENABLED, [], '', 9, '?', returnCallback, errorCallback, false, true);
	};
	this.setSPITFPBaudrateConfig = function(enableDynamicBaudrate, minimumDynamicBaudrate, returnCallback, errorCallback) {
		/*
		The SPITF protocol can be used with a dynamic baudrate. If the dynamic baudrate is
		enabled, the Brick will try to adapt the baudrate for the communication
		between Bricks and Bricklets according to the amount of data that is transferred.
		
		The baudrate will be increased exponentially if lots of data is sent/received and
		decreased linearly if little data is sent/received.
		
		This lowers the baudrate in applications where little data is transferred (e.g.
		a weather station) and increases the robustness. If there is lots of data to transfer
		(e.g. Thermal Imaging Bricklet) it automatically increases the baudrate as needed.
		
		In cases where some data has to transferred as fast as possible every few seconds
		(e.g. RS485 Bricklet with a high baudrate but small payload) you may want to turn
		the dynamic baudrate off to get the highest possible performance.
		
		The maximum value of the baudrate can be set per port with the function
		:func:`Set SPITFP Baudrate`. If the dynamic baudrate is disabled, the baudrate
		as set by :func:`Set SPITFP Baudrate` will be used statically.
		
		.. versionadded:: 2.4.6$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_SET_SPITFP_BAUDRATE_CONFIG, [enableDynamicBaudrate, minimumDynamicBaudrate], '? I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPBaudrateConfig = function(returnCallback, errorCallback) {
		/*
		Returns the baudrate config, see :func:`Set SPITFP Baudrate Config`.
		
		.. versionadded:: 2.4.6$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_GET_SPITFP_BAUDRATE_CONFIG, [], '', 13, '? I', returnCallback, errorCallback, false, true);
	};
	this.getSendTimeoutCount = function(communicationMethod, returnCallback, errorCallback) {
		/*
		Returns the timeout count for the different communication methods.
		
		The methods 0-2 are available for all Bricks, 3-7 only for Master Bricks.
		
		This function is mostly used for debugging during development, in normal operation
		the counters should nearly always stay at 0.
		
		.. versionadded:: 2.4.3$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_GET_SEND_TIMEOUT_COUNT, [communicationMethod], 'B', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setSPITFPBaudrate = function(brickletPort, baudrate, returnCallback, errorCallback) {
		/*
		Sets the baudrate for a specific Bricklet port.
		
		If you want to increase the throughput of Bricklets you can increase
		the baudrate. If you get a high error count because of high
		interference (see :func:`Get SPITFP Error Count`) you can decrease the
		baudrate.
		
		If the dynamic baudrate feature is enabled, the baudrate set by this
		function corresponds to the maximum baudrate (see :func:`Set SPITFP Baudrate Config`).
		
		Regulatory testing is done with the default baudrate. If CE compatibility
		or similar is necessary in your applications we recommend to not change
		the baudrate.
		
		.. versionadded:: 2.4.3$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_SET_SPITFP_BAUDRATE, [brickletPort, baudrate], 'c I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPBaudrate = function(brickletPort, returnCallback, errorCallback) {
		/*
		Returns the baudrate for a given Bricklet port, see :func:`Set SPITFP Baudrate`.
		
		.. versionadded:: 2.4.3$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_GET_SPITFP_BAUDRATE, [brickletPort], 'c', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPErrorCount = function(brickletPort, returnCallback, errorCallback) {
		/*
		Returns the error count for the communication between Brick and Bricklet.
		
		The errors are divided into
		
		* ACK checksum errors,
		* message checksum errors,
		* framing errors and
		* overflow errors.
		
		The errors counts are for errors that occur on the Brick side. All
		Bricklets have a similar function that returns the errors on the Bricklet side.
		
		.. versionadded:: 2.4.3$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_GET_SPITFP_ERROR_COUNT, [brickletPort], 'c', 24, 'I I I I', returnCallback, errorCallback, false, true);
	};
	this.enableStatusLED = function(returnCallback, errorCallback) {
		/*
		Enables the status LED.
		
		The status LED is the blue LED next to the USB connector. If enabled is is
		on and it flickers if data is transfered. If disabled it is always off.
		
		The default state is enabled.
		
		.. versionadded:: 2.3.2$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_ENABLE_STATUS_LED, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.disableStatusLED = function(returnCallback, errorCallback) {
		/*
		Disables the status LED.
		
		The status LED is the blue LED next to the USB connector. If enabled is is
		on and it flickers if data is transfered. If disabled it is always off.
		
		The default state is enabled.
		
		.. versionadded:: 2.3.2$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_DISABLE_STATUS_LED, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.isStatusLEDEnabled = function(returnCallback, errorCallback) {
		/*
		Returns *true* if the status LED is enabled, *false* otherwise.
		
		.. versionadded:: 2.3.2$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_IS_STATUS_LED_ENABLED, [], '', 9, '?', returnCallback, errorCallback, false, true);
	};
	this.getProtocol1BrickletName = function(port, returnCallback, errorCallback) {
		/*
		Returns the firmware and protocol version and the name of the Bricklet for a
		given port.
		
		This functions sole purpose is to allow automatic flashing of v1.x.y Bricklet
		plugins.
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_GET_PROTOCOL1_BRICKLET_NAME, [port], 'c', 52, 'B B3 s40', returnCallback, errorCallback, false, true);
	};
	this.getChipTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature as measured inside the microcontroller. The
		value returned is not the ambient temperature!
		
		The temperature is only proportional to the real temperature and it has an
		accuracy of ±15%. Practically it is only useful as an indicator for
		temperature changes.
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_GET_CHIP_TEMPERATURE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.reset = function(returnCallback, errorCallback) {
		/*
		Calling this function will reset the Brick. Calling this function
		on a Brick inside of a stack will reset the whole stack.
		
		After a reset you have to create new device objects,
		calling functions on the existing ones will result in
		undefined behavior!
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_RESET, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeBrickletPlugin = function(port, offset, chunk, returnCallback, errorCallback) {
		/*
		Writes 32 bytes of firmware to the bricklet attached at the given port.
		The bytes are written to the position offset * 32.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_WRITE_BRICKLET_PLUGIN, [port, offset, chunk], 'c B B32', 0, '', returnCallback, errorCallback, false, true);
	};
	this.readBrickletPlugin = function(port, offset, returnCallback, errorCallback) {
		/*
		Reads 32 bytes of firmware from the bricklet attached at the given port.
		The bytes are read starting at the position offset * 32.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_READ_BRICKLET_PLUGIN, [port, offset], 'c B', 40, 'B32', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Brick is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position is the position in the stack from '0' (bottom) to '8' (top).
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickMaster.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickMaster;

},{"./Device":279,"./IPConnection":280}],143:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickRED.DEVICE_IDENTIFIER = 17;
BrickRED.DEVICE_DISPLAY_NAME = 'RED Brick';
BrickRED.CALLBACK_ASYNC_FILE_READ = 30;
BrickRED.CALLBACK_ASYNC_FILE_WRITE = 31;
BrickRED.CALLBACK_FILE_EVENTS_OCCURRED = 32;
BrickRED.CALLBACK_PROCESS_STATE_CHANGED = 45;
BrickRED.CALLBACK_PROGRAM_SCHEDULER_STATE_CHANGED = 65;
BrickRED.CALLBACK_PROGRAM_PROCESS_SPAWNED = 66;
BrickRED.FUNCTION_CREATE_SESSION = 1;
BrickRED.FUNCTION_EXPIRE_SESSION = 2;
BrickRED.FUNCTION_EXPIRE_SESSION_UNCHECKED = 3;
BrickRED.FUNCTION_KEEP_SESSION_ALIVE = 4;
BrickRED.FUNCTION_RELEASE_OBJECT = 5;
BrickRED.FUNCTION_RELEASE_OBJECT_UNCHECKED = 6;
BrickRED.FUNCTION_ALLOCATE_STRING = 7;
BrickRED.FUNCTION_TRUNCATE_STRING = 8;
BrickRED.FUNCTION_GET_STRING_LENGTH = 9;
BrickRED.FUNCTION_SET_STRING_CHUNK = 10;
BrickRED.FUNCTION_GET_STRING_CHUNK = 11;
BrickRED.FUNCTION_ALLOCATE_LIST = 12;
BrickRED.FUNCTION_GET_LIST_LENGTH = 13;
BrickRED.FUNCTION_GET_LIST_ITEM = 14;
BrickRED.FUNCTION_APPEND_TO_LIST = 15;
BrickRED.FUNCTION_REMOVE_FROM_LIST = 16;
BrickRED.FUNCTION_OPEN_FILE = 17;
BrickRED.FUNCTION_CREATE_PIPE = 18;
BrickRED.FUNCTION_GET_FILE_INFO = 19;
BrickRED.FUNCTION_READ_FILE = 20;
BrickRED.FUNCTION_READ_FILE_ASYNC = 21;
BrickRED.FUNCTION_ABORT_ASYNC_FILE_READ = 22;
BrickRED.FUNCTION_WRITE_FILE = 23;
BrickRED.FUNCTION_WRITE_FILE_UNCHECKED = 24;
BrickRED.FUNCTION_WRITE_FILE_ASYNC = 25;
BrickRED.FUNCTION_SET_FILE_POSITION = 26;
BrickRED.FUNCTION_GET_FILE_POSITION = 27;
BrickRED.FUNCTION_SET_FILE_EVENTS = 28;
BrickRED.FUNCTION_GET_FILE_EVENTS = 29;
BrickRED.FUNCTION_OPEN_DIRECTORY = 33;
BrickRED.FUNCTION_GET_DIRECTORY_NAME = 34;
BrickRED.FUNCTION_GET_NEXT_DIRECTORY_ENTRY = 35;
BrickRED.FUNCTION_REWIND_DIRECTORY = 36;
BrickRED.FUNCTION_CREATE_DIRECTORY = 37;
BrickRED.FUNCTION_GET_PROCESSES = 38;
BrickRED.FUNCTION_SPAWN_PROCESS = 39;
BrickRED.FUNCTION_KILL_PROCESS = 40;
BrickRED.FUNCTION_GET_PROCESS_COMMAND = 41;
BrickRED.FUNCTION_GET_PROCESS_IDENTITY = 42;
BrickRED.FUNCTION_GET_PROCESS_STDIO = 43;
BrickRED.FUNCTION_GET_PROCESS_STATE = 44;
BrickRED.FUNCTION_GET_PROGRAMS = 46;
BrickRED.FUNCTION_DEFINE_PROGRAM = 47;
BrickRED.FUNCTION_PURGE_PROGRAM = 48;
BrickRED.FUNCTION_GET_PROGRAM_IDENTIFIER = 49;
BrickRED.FUNCTION_GET_PROGRAM_ROOT_DIRECTORY = 50;
BrickRED.FUNCTION_SET_PROGRAM_COMMAND = 51;
BrickRED.FUNCTION_GET_PROGRAM_COMMAND = 52;
BrickRED.FUNCTION_SET_PROGRAM_STDIO_REDIRECTION = 53;
BrickRED.FUNCTION_GET_PROGRAM_STDIO_REDIRECTION = 54;
BrickRED.FUNCTION_SET_PROGRAM_SCHEDULE = 55;
BrickRED.FUNCTION_GET_PROGRAM_SCHEDULE = 56;
BrickRED.FUNCTION_GET_PROGRAM_SCHEDULER_STATE = 57;
BrickRED.FUNCTION_CONTINUE_PROGRAM_SCHEDULE = 58;
BrickRED.FUNCTION_START_PROGRAM = 59;
BrickRED.FUNCTION_GET_LAST_SPAWNED_PROGRAM_PROCESS = 60;
BrickRED.FUNCTION_GET_CUSTOM_PROGRAM_OPTION_NAMES = 61;
BrickRED.FUNCTION_SET_CUSTOM_PROGRAM_OPTION_VALUE = 62;
BrickRED.FUNCTION_GET_CUSTOM_PROGRAM_OPTION_VALUE = 63;
BrickRED.FUNCTION_REMOVE_CUSTOM_PROGRAM_OPTION = 64;
BrickRED.FUNCTION_GET_IDENTITY = 255;
BrickRED.ERROR_CODE_SUCCESS = 0;
BrickRED.ERROR_CODE_UNKNOWN_ERROR = 1;
BrickRED.ERROR_CODE_INVALID_OPERATION = 2;
BrickRED.ERROR_CODE_OPERATION_ABORTED = 3;
BrickRED.ERROR_CODE_INTERNAL_ERROR = 4;
BrickRED.ERROR_CODE_UNKNOWN_SESSION_ID = 5;
BrickRED.ERROR_CODE_NO_FREE_SESSION_ID = 6;
BrickRED.ERROR_CODE_UNKNOWN_OBJECT_ID = 7;
BrickRED.ERROR_CODE_NO_FREE_OBJECT_ID = 8;
BrickRED.ERROR_CODE_OBJECT_IS_LOCKED = 9;
BrickRED.ERROR_CODE_NO_MORE_DATA = 10;
BrickRED.ERROR_CODE_WRONG_LIST_ITEM_TYPE = 11;
BrickRED.ERROR_CODE_PROGRAM_IS_PURGED = 12;
BrickRED.ERROR_CODE_INVALID_PARAMETER = 128;
BrickRED.ERROR_CODE_NO_FREE_MEMORY = 129;
BrickRED.ERROR_CODE_NO_FREE_SPACE = 130;
BrickRED.ERROR_CODE_ACCESS_DENIED = 121;
BrickRED.ERROR_CODE_ALREADY_EXISTS = 132;
BrickRED.ERROR_CODE_DOES_NOT_EXIST = 133;
BrickRED.ERROR_CODE_INTERRUPTED = 134;
BrickRED.ERROR_CODE_IS_DIRECTORY = 135;
BrickRED.ERROR_CODE_NOT_A_DIRECTORY = 136;
BrickRED.ERROR_CODE_WOULD_BLOCK = 137;
BrickRED.ERROR_CODE_OVERFLOW = 138;
BrickRED.ERROR_CODE_BAD_FILE_DESCRIPTOR = 139;
BrickRED.ERROR_CODE_OUT_OF_RANGE = 140;
BrickRED.ERROR_CODE_NAME_TOO_LONG = 141;
BrickRED.ERROR_CODE_INVALID_SEEK = 142;
BrickRED.ERROR_CODE_NOT_SUPPORTED = 143;
BrickRED.ERROR_CODE_TOO_MANY_OPEN_FILES = 144;
BrickRED.OBJECT_TYPE_STRING = 0;
BrickRED.OBJECT_TYPE_LIST = 1;
BrickRED.OBJECT_TYPE_FILE = 2;
BrickRED.OBJECT_TYPE_DIRECTORY = 3;
BrickRED.OBJECT_TYPE_PROCESS = 4;
BrickRED.OBJECT_TYPE_PROGRAM = 5;
BrickRED.FILE_FLAG_READ_ONLY = 1;
BrickRED.FILE_FLAG_WRITE_ONLY = 2;
BrickRED.FILE_FLAG_READ_WRITE = 4;
BrickRED.FILE_FLAG_APPEND = 8;
BrickRED.FILE_FLAG_CREATE = 16;
BrickRED.FILE_FLAG_EXCLUSIVE = 32;
BrickRED.FILE_FLAG_NON_BLOCKING = 64;
BrickRED.FILE_FLAG_TRUNCATE = 128;
BrickRED.FILE_FLAG_TEMPORARY = 256;
BrickRED.FILE_FLAG_REPLACE = 512;
BrickRED.FILE_PERMISSION_USER_ALL = 448;
BrickRED.FILE_PERMISSION_USER_READ = 256;
BrickRED.FILE_PERMISSION_USER_WRITE = 128;
BrickRED.FILE_PERMISSION_USER_EXECUTE = 64;
BrickRED.FILE_PERMISSION_GROUP_ALL = 56;
BrickRED.FILE_PERMISSION_GROUP_READ = 32;
BrickRED.FILE_PERMISSION_GROUP_WRITE = 16;
BrickRED.FILE_PERMISSION_GROUP_EXECUTE = 8;
BrickRED.FILE_PERMISSION_OTHERS_ALL = 7;
BrickRED.FILE_PERMISSION_OTHERS_READ = 4;
BrickRED.FILE_PERMISSION_OTHERS_WRITE = 2;
BrickRED.FILE_PERMISSION_OTHERS_EXECUTE = 1;
BrickRED.PIPE_FLAG_NON_BLOCKING_READ = 1;
BrickRED.PIPE_FLAG_NON_BLOCKING_WRITE = 2;
BrickRED.FILE_TYPE_UNKNOWN = 0;
BrickRED.FILE_TYPE_REGULAR = 1;
BrickRED.FILE_TYPE_DIRECTORY = 2;
BrickRED.FILE_TYPE_CHARACTER = 3;
BrickRED.FILE_TYPE_BLOCK = 4;
BrickRED.FILE_TYPE_FIFO = 5;
BrickRED.FILE_TYPE_SYMLINK = 6;
BrickRED.FILE_TYPE_SOCKET = 7;
BrickRED.FILE_TYPE_PIPE = 8;
BrickRED.FILE_ORIGIN_BEGINNING = 0;
BrickRED.FILE_ORIGIN_CURRENT = 1;
BrickRED.FILE_ORIGIN_END = 2;
BrickRED.FILE_EVENT_READABLE = 1;
BrickRED.FILE_EVENT_WRITABLE = 2;
BrickRED.DIRECTORY_ENTRY_TYPE_UNKNOWN = 0;
BrickRED.DIRECTORY_ENTRY_TYPE_REGULAR = 1;
BrickRED.DIRECTORY_ENTRY_TYPE_DIRECTORY = 2;
BrickRED.DIRECTORY_ENTRY_TYPE_CHARACTER = 3;
BrickRED.DIRECTORY_ENTRY_TYPE_BLOCK = 4;
BrickRED.DIRECTORY_ENTRY_TYPE_FIFO = 5;
BrickRED.DIRECTORY_ENTRY_TYPE_SYMLINK = 6;
BrickRED.DIRECTORY_ENTRY_TYPE_SOCKET = 7;
BrickRED.DIRECTORY_FLAG_RECURSIVE = 1;
BrickRED.DIRECTORY_FLAG_EXCLUSIVE = 2;
BrickRED.PROCESS_SIGNAL_INTERRUPT = 2;
BrickRED.PROCESS_SIGNAL_QUIT = 3;
BrickRED.PROCESS_SIGNAL_ABORT = 6;
BrickRED.PROCESS_SIGNAL_KILL = 9;
BrickRED.PROCESS_SIGNAL_USER1 = 10;
BrickRED.PROCESS_SIGNAL_USER2 = 12;
BrickRED.PROCESS_SIGNAL_TERMINATE = 15;
BrickRED.PROCESS_SIGNAL_CONTINUE = 18;
BrickRED.PROCESS_SIGNAL_STOP = 19;
BrickRED.PROCESS_STATE_UNKNOWN = 0;
BrickRED.PROCESS_STATE_RUNNING = 1;
BrickRED.PROCESS_STATE_ERROR = 2;
BrickRED.PROCESS_STATE_EXITED = 3;
BrickRED.PROCESS_STATE_KILLED = 4;
BrickRED.PROCESS_STATE_STOPPED = 5;
BrickRED.PROGRAM_STDIO_REDIRECTION_DEV_NULL = 0;
BrickRED.PROGRAM_STDIO_REDIRECTION_PIPE = 1;
BrickRED.PROGRAM_STDIO_REDIRECTION_FILE = 2;
BrickRED.PROGRAM_STDIO_REDIRECTION_INDIVIDUAL_LOG = 3;
BrickRED.PROGRAM_STDIO_REDIRECTION_CONTINUOUS_LOG = 4;
BrickRED.PROGRAM_STDIO_REDIRECTION_STDOUT = 5;
BrickRED.PROGRAM_START_MODE_NEVER = 0;
BrickRED.PROGRAM_START_MODE_ALWAYS = 1;
BrickRED.PROGRAM_START_MODE_INTERVAL = 2;
BrickRED.PROGRAM_START_MODE_CRON = 3;
BrickRED.PROGRAM_SCHEDULER_STATE_STOPPED = 0;
BrickRED.PROGRAM_SCHEDULER_STATE_RUNNING = 1;

function BrickRED(uid, ipcon) {
	//Executes user programs and controls other Bricks/Bricklets standalone

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickRED.DEVICE_IDENTIFIER, BrickRED.DEVICE_DISPLAY_NAME);
	BrickRED.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickRED.FUNCTION_CREATE_SESSION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickRED.FUNCTION_EXPIRE_SESSION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickRED.FUNCTION_EXPIRE_SESSION_UNCHECKED] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickRED.FUNCTION_KEEP_SESSION_ALIVE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickRED.FUNCTION_RELEASE_OBJECT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickRED.FUNCTION_RELEASE_OBJECT_UNCHECKED] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickRED.FUNCTION_ALLOCATE_STRING] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickRED.FUNCTION_TRUNCATE_STRING] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickRED.FUNCTION_GET_STRING_LENGTH] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickRED.FUNCTION_SET_STRING_CHUNK] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickRED.FUNCTION_GET_STRING_CHUNK] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickRED.FUNCTION_ALLOCATE_LIST] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickRED.FUNCTION_GET_LIST_LENGTH] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickRED.FUNCTION_GET_LIST_ITEM] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickRED.FUNCTION_APPEND_TO_LIST] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickRED.FUNCTION_REMOVE_FROM_LIST] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickRED.FUNCTION_OPEN_FILE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickRED.FUNCTION_CREATE_PIPE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickRED.FUNCTION_GET_FILE_INFO] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickRED.FUNCTION_READ_FILE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickRED.FUNCTION_READ_FILE_ASYNC] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickRED.FUNCTION_ABORT_ASYNC_FILE_READ] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickRED.FUNCTION_WRITE_FILE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickRED.FUNCTION_WRITE_FILE_UNCHECKED] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickRED.FUNCTION_WRITE_FILE_ASYNC] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickRED.FUNCTION_SET_FILE_POSITION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickRED.FUNCTION_GET_FILE_POSITION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickRED.FUNCTION_SET_FILE_EVENTS] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickRED.FUNCTION_GET_FILE_EVENTS] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickRED.FUNCTION_OPEN_DIRECTORY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickRED.FUNCTION_GET_DIRECTORY_NAME] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickRED.FUNCTION_GET_NEXT_DIRECTORY_ENTRY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickRED.FUNCTION_REWIND_DIRECTORY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickRED.FUNCTION_CREATE_DIRECTORY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickRED.FUNCTION_GET_PROCESSES] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickRED.FUNCTION_SPAWN_PROCESS] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickRED.FUNCTION_KILL_PROCESS] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickRED.FUNCTION_GET_PROCESS_COMMAND] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickRED.FUNCTION_GET_PROCESS_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickRED.FUNCTION_GET_PROCESS_STDIO] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickRED.FUNCTION_GET_PROCESS_STATE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickRED.FUNCTION_GET_PROGRAMS] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickRED.FUNCTION_DEFINE_PROGRAM] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickRED.FUNCTION_PURGE_PROGRAM] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickRED.FUNCTION_GET_PROGRAM_IDENTIFIER] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickRED.FUNCTION_GET_PROGRAM_ROOT_DIRECTORY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickRED.FUNCTION_SET_PROGRAM_COMMAND] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickRED.FUNCTION_GET_PROGRAM_COMMAND] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickRED.FUNCTION_SET_PROGRAM_STDIO_REDIRECTION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickRED.FUNCTION_GET_PROGRAM_STDIO_REDIRECTION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickRED.FUNCTION_SET_PROGRAM_SCHEDULE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickRED.FUNCTION_GET_PROGRAM_SCHEDULE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickRED.FUNCTION_GET_PROGRAM_SCHEDULER_STATE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickRED.FUNCTION_CONTINUE_PROGRAM_SCHEDULE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickRED.FUNCTION_START_PROGRAM] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickRED.FUNCTION_GET_LAST_SPAWNED_PROGRAM_PROCESS] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickRED.FUNCTION_GET_CUSTOM_PROGRAM_OPTION_NAMES] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickRED.FUNCTION_SET_CUSTOM_PROGRAM_OPTION_VALUE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickRED.FUNCTION_GET_CUSTOM_PROGRAM_OPTION_VALUE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickRED.FUNCTION_REMOVE_CUSTOM_PROGRAM_OPTION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickRED.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickRED.CALLBACK_ASYNC_FILE_READ] = [72, 'H B B60 B'];
	this.callbackFormats[BrickRED.CALLBACK_ASYNC_FILE_WRITE] = [12, 'H B B'];
	this.callbackFormats[BrickRED.CALLBACK_FILE_EVENTS_OCCURRED] = [12, 'H H'];
	this.callbackFormats[BrickRED.CALLBACK_PROCESS_STATE_CHANGED] = [20, 'H B Q B'];
	this.callbackFormats[BrickRED.CALLBACK_PROGRAM_SCHEDULER_STATE_CHANGED] = [10, 'H'];
	this.callbackFormats[BrickRED.CALLBACK_PROGRAM_PROCESS_SPAWNED] = [10, 'H'];



	this.createSession = function(lifetime, returnCallback, errorCallback) {
		/*
		
		*/
		this.ipcon.sendRequest(this, BrickRED.FUNCTION_CREATE_SESSION, [lifetime], 'I', 11, 'B H', returnCallback, errorCallback, false, true);
	};
	this.expireSession = function(sessionId, returnCallback, errorCallback) {
		/*
		
		*/
		this.ipcon.sendRequest(this, BrickRED.FUNCTION_EXPIRE_SESSION, [sessionId], 'H', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.expireSessionUnchecked = function(sessionId, returnCallback, errorCallback) {
		/*
		
		*/
		this.ipcon.sendRequest(this, BrickRED.FUNCTION_EXPIRE_SESSION_UNCHECKED, [sessionId], 'H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.keepSessionAlive = function(sessionId, lifetime, returnCallback, errorCallback) {
		/*
		
		*/
		this.ipcon.sendRequest(this, BrickRED.FUNCTION_KEEP_SESSION_ALIVE, [sessionId, lifetime], 'H I', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.releaseObject = function(objectId, sessionId, returnCallback, errorCallback) {
		/*
		Decreases the reference count of an object by one and returns the resulting
		error code. If the reference count reaches zero the object gets destroyed.
		*/
		this.ipcon.sendRequest(this, BrickRED.FUNCTION_RELEASE_OBJECT, [objectId, sessionId], 'H H', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.releaseObjectUnchecked = function(objectId, sessionId, returnCallback, errorCallback) {
		/*
		
		*/
		this.ipcon.sendRequest(this, BrickRED.FUNCTION_RELEASE_OBJECT_UNCHECKED, [objectId, sessionId], 'H H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.allocateString = function(lengthToReserve, buffer, sessionId, returnCallback, errorCallback) {
		/*
		Allocates a new string object, reserves ``length_to_reserve`` bytes memory
		for it and sets up to the first 60 bytes. Set ``length_to_reserve`` to the
		length of the string that should be stored in the string object.
		
		Returns the object ID of the new string object and the resulting error code.
		*/
		this.ipcon.sendRequest(this, BrickRED.FUNCTION_ALLOCATE_STRING, [lengthToReserve, buffer, sessionId], 'I s58 H', 11, 'B H', returnCallback, errorCallback, false, true);
	};
	this.truncateString = function(stringId, length, returnCallback, errorCallback) {
		/*
		Truncates a string object to ``length`` bytes and returns the resulting
		error code.
		*/
		this.ipcon.sendRequest(this, BrickRED.FUNCTION_TRUNCATE_STRING, [stringId, length], 'H I', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getStringLength = function(stringId, returnCallback, errorCallback) {
		/*
		Returns the length of a string object and the resulting error code.
		*/
		this.ipcon.sendRequest(this, BrickRED.FUNCTION_GET_STRING_LENGTH, [stringId], 'H', 13, 'B I', returnCallback, errorCallback, false, true);
	};
	this.setStringChunk = function(stringId, offset, buffer, returnCallback, errorCallback) {
		/*
		Sets a chunk of up to 58 bytes in a string object beginning at ``offset``.
		
		Returns the resulting error code.
		*/
		this.ipcon.sendRequest(this, BrickRED.FUNCTION_SET_STRING_CHUNK, [stringId, offset, buffer], 'H I s58', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getStringChunk = function(stringId, offset, returnCallback, errorCallback) {
		/*
		Returns a chunk up to 63 bytes from a string object beginning at ``offset`` and
		returns the resulting error code.
		*/
		this.ipcon.sendRequest(this, BrickRED.FUNCTION_GET_STRING_CHUNK, [stringId, offset], 'H I', 72, 'B s63', returnCallback, errorCallback, false, true);
	};
	this.allocateList = function(lengthToReserve, sessionId, returnCallback, errorCallback) {
		/*
		Allocates a new list object and reserves memory for ``length_to_reserve``
		items. Set ``length_to_reserve`` to the number of items that should be stored
		in the list object.
		
		Returns the object ID of the new list object and the resulting error code.
		
		When a list object gets destroyed then the reference count of each object in
		the list object is decreased by one.
		*/
		this.ipcon.sendRequest(this, BrickRED.FUNCTION_ALLOCATE_LIST, [lengthToReserve, sessionId], 'H H', 11, 'B H', returnCallback, errorCallback, false, true);
	};
	this.getListLength = function(listId, returnCallback, errorCallback) {
		/*
		Returns the length of a list object in items and the resulting error code.
		*/
		this.ipcon.sendRequest(this, BrickRED.FUNCTION_GET_LIST_LENGTH, [listId], 'H', 11, 'B H', returnCallback, errorCallback, false, true);
	};
	this.getListItem = function(listId, index, sessionId, returnCallback, errorCallback) {
		/*
		Returns the object ID and type of the object stored at ``index`` in a list
		object and returns the resulting error code.
		
		Possible object types are:
		
		* String = 0
		* List = 1
		* File = 2
		* Directory = 3
		* Process = 4
		* Program = 5
		*/
		this.ipcon.sendRequest(this, BrickRED.FUNCTION_GET_LIST_ITEM, [listId, index, sessionId], 'H H H', 12, 'B H B', returnCallback, errorCallback, false, true);
	};
	this.appendToList = function(listId, itemObjectId, returnCallback, errorCallback) {
		/*
		Appends an object to a list object and increases the reference count of the
		appended object by one.
		
		Returns the resulting error code.
		*/
		this.ipcon.sendRequest(this, BrickRED.FUNCTION_APPEND_TO_LIST, [listId, itemObjectId], 'H H', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.removeFromList = function(listId, index, returnCallback, errorCallback) {
		/*
		Removes the object stored at ``index`` from a list object and decreases the
		reference count of the removed object by one.
		
		Returns the resulting error code.
		*/
		this.ipcon.sendRequest(this, BrickRED.FUNCTION_REMOVE_FROM_LIST, [listId, index], 'H H', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.openFile = function(nameStringId, flags, permissions, uid, gid, sessionId, returnCallback, errorCallback) {
		/*
		Opens an existing file or creates a new file and allocates a new file object
		for it.
		
		FIXME: name has to be absolute
		
		The reference count of the name string object is increased by one. When the
		file object gets destroyed then the reference count of the name string object is
		decreased by one. Also the name string object is locked and cannot be modified
		while the file object holds a reference to it.
		
		The ``flags`` parameter takes a ORed combination of the following possible file
		flags (in hexadecimal notation):
		
		* ReadOnly = 0x0001 (O_RDONLY)
		* WriteOnly = 0x0002 (O_WRONLY)
		* ReadWrite = 0x0004 (O_RDWR)
		* Append = 0x0008 (O_APPEND)
		* Create = 0x0010 (O_CREAT)
		* Exclusive = 0x0020 (O_EXCL)
		* NonBlocking = 0x0040 (O_NONBLOCK)
		* Truncate = 0x0080 (O_TRUNC)
		* Temporary = 0x0100
		* Replace = 0x0200
		
		FIXME: explain *Temporary* and *Replace* flag
		
		The ``permissions`` parameter takes a ORed combination of the following
		possible file permissions (in octal notation) that match the common UNIX
		permission bits:
		
		* UserRead = 00400
		* UserWrite = 00200
		* UserExecute = 00100
		* GroupRead = 00040
		* GroupWrite = 00020
		* GroupExecute = 00010
		* OthersRead = 00004
		* OthersWrite = 00002
		* OthersExecute = 00001
		
		Returns the object ID of the new file object and the resulting error code.
		*/
		this.ipcon.sendRequest(this, BrickRED.FUNCTION_OPEN_FILE, [nameStringId, flags, permissions, uid, gid, sessionId], 'H I H I I H', 11, 'B H', returnCallback, errorCallback, false, true);
	};
	this.createPipe = function(flags, length, sessionId, returnCallback, errorCallback) {
		/*
		Creates a new pipe and allocates a new file object for it.
		
		The ``flags`` parameter takes a ORed combination of the following possible
		pipe flags (in hexadecimal notation):
		
		* NonBlockingRead = 0x0001
		* NonBlockingWrite = 0x0002
		
		The length of the pipe buffer can be specified with the ``length`` parameter
		in bytes. If length is set to zero, then the default pipe buffer length is used.
		
		Returns the object ID of the new file object and the resulting error code.
		*/
		this.ipcon.sendRequest(this, BrickRED.FUNCTION_CREATE_PIPE, [flags, length, sessionId], 'I Q H', 11, 'B H', returnCallback, errorCallback, false, true);
	};
	this.getFileInfo = function(fileId, sessionId, returnCallback, errorCallback) {
		/*
		Returns various information about a file and the resulting error code.
		
		Possible file types are:
		
		* Unknown = 0
		* Regular = 1
		* Directory = 2
		* Character = 3
		* Block = 4
		* FIFO = 5
		* Symlink = 6
		* Socket = 7
		* Pipe = 8
		
		If the file type is *Pipe* then the returned name string object is invalid,
		because a pipe has no name. Otherwise the returned name string object was used
		to open or create the file object, as passed to :func:`Open File`.
		
		The returned flags were used to open or create the file object, as passed to
		:func:`Open File` or :func:`Create Pipe`. See the respective function for a list
		of possible file and pipe flags.
		
		FIXME: everything except flags and length is invalid if file type is *Pipe*
		*/
		this.ipcon.sendRequest(this, BrickRED.FUNCTION_GET_FILE_INFO, [fileId, sessionId], 'H H', 58, 'B B H I H I I Q Q Q Q', returnCallback, errorCallback, false, true);
	};
	this.readFile = function(fileId, lengthToRead, returnCallback, errorCallback) {
		/*
		Reads up to 62 bytes from a file object.
		
		Returns the bytes read, the actual number of bytes read and the resulting
		error code.
		
		If there is not data to be read, either because the file position reached
		end-of-file or because there is not data in the pipe, then zero bytes are
		returned.
		
		If the file object was created by :func:`Open File` without the *NonBlocking*
		flag or by :func:`Create Pipe` without the *NonBlockingRead* flag then the
		error code *NotSupported* is returned.
		*/
		this.ipcon.sendRequest(this, BrickRED.FUNCTION_READ_FILE, [fileId, lengthToRead], 'H B', 72, 'B B62 B', returnCallback, errorCallback, false, true);
	};
	this.readFileAsync = function(fileId, lengthToRead, returnCallback, errorCallback) {
		/*
		Reads up to 2\ :sup:`63`\  - 1 bytes from a file object asynchronously.
		
		Reports the bytes read (in 60 byte chunks), the actual number of bytes read and
		the resulting error code via the :cb:`Async File Read` callback.
		
		If there is not data to be read, either because the file position reached
		end-of-file or because there is not data in the pipe, then zero bytes are
		reported.
		
		If the file object was created by :func:`Open File` without the *NonBlocking*
		flag or by :func:`Create Pipe` without the *NonBlockingRead* flag then the error
		code *NotSupported* is reported via the :cb:`Async File Read` callback.
		*/
		this.ipcon.sendRequest(this, BrickRED.FUNCTION_READ_FILE_ASYNC, [fileId, lengthToRead], 'H Q', 0, '', returnCallback, errorCallback, false, true);
	};
	this.abortAsyncFileRead = function(fileId, returnCallback, errorCallback) {
		/*
		Aborts a :func:`Read File Async` operation in progress.
		
		Returns the resulting error code.
		
		On success the :cb:`Async File Read` callback will report *OperationAborted*.
		*/
		this.ipcon.sendRequest(this, BrickRED.FUNCTION_ABORT_ASYNC_FILE_READ, [fileId], 'H', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.writeFile = function(fileId, buffer, lengthToWrite, returnCallback, errorCallback) {
		/*
		Writes up to 61 bytes to a file object.
		
		Returns the actual number of bytes written and the resulting error code.
		
		If the file object was created by :func:`Open File` without the *NonBlocking*
		flag or by :func:`Create Pipe` without the *NonBlockingWrite* flag then the
		error code *NotSupported* is returned.
		*/
		this.ipcon.sendRequest(this, BrickRED.FUNCTION_WRITE_FILE, [fileId, buffer, lengthToWrite], 'H B61 B', 10, 'B B', returnCallback, errorCallback, false, true);
	};
	this.writeFileUnchecked = function(fileId, buffer, lengthToWrite, returnCallback, errorCallback) {
		/*
		Writes up to 61 bytes to a file object.
		
		Does neither report the actual number of bytes written nor the resulting error
		code.
		
		If the file object was created by :func:`Open File` without the *NonBlocking*
		flag or by :func:`Create Pipe` without the *NonBlockingWrite* flag then the
		write operation will fail silently.
		*/
		this.ipcon.sendRequest(this, BrickRED.FUNCTION_WRITE_FILE_UNCHECKED, [fileId, buffer, lengthToWrite], 'H B61 B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeFileAsync = function(fileId, buffer, lengthToWrite, returnCallback, errorCallback) {
		/*
		Writes up to 61 bytes to a file object.
		
		Reports the actual number of bytes written and the resulting error code via the
		:cb:`Async File Write` callback.
		
		If the file object was created by :func:`Open File` without the *NonBlocking*
		flag or by :func:`Create Pipe` without the *NonBlockingWrite* flag then the
		error code *NotSupported* is reported via the :cb:`Async File Write` callback.
		*/
		this.ipcon.sendRequest(this, BrickRED.FUNCTION_WRITE_FILE_ASYNC, [fileId, buffer, lengthToWrite], 'H B61 B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.setFilePosition = function(fileId, offset, origin, returnCallback, errorCallback) {
		/*
		Set the current seek position of a file object relative to ``origin``.
		
		Possible file origins are:
		
		* Beginning = 0
		* Current = 1
		* End = 2
		
		Returns the resulting absolute seek position and error code.
		
		If the file object was created by :func:`Create Pipe` then it has no seek
		position and the error code *InvalidSeek* is returned.
		*/
		this.ipcon.sendRequest(this, BrickRED.FUNCTION_SET_FILE_POSITION, [fileId, offset, origin], 'H q B', 17, 'B Q', returnCallback, errorCallback, false, true);
	};
	this.getFilePosition = function(fileId, returnCallback, errorCallback) {
		/*
		Returns the current seek position of a file object and returns the
		resulting error code.
		
		If the file object was created by :func:`Create Pipe` then it has no seek
		position and the error code *InvalidSeek* is returned.
		*/
		this.ipcon.sendRequest(this, BrickRED.FUNCTION_GET_FILE_POSITION, [fileId], 'H', 17, 'B Q', returnCallback, errorCallback, false, true);
	};
	this.setFileEvents = function(fileId, events, returnCallback, errorCallback) {
		/*
		
		*/
		this.ipcon.sendRequest(this, BrickRED.FUNCTION_SET_FILE_EVENTS, [fileId, events], 'H H', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getFileEvents = function(fileId, returnCallback, errorCallback) {
		/*
		
		*/
		this.ipcon.sendRequest(this, BrickRED.FUNCTION_GET_FILE_EVENTS, [fileId], 'H', 11, 'B H', returnCallback, errorCallback, false, true);
	};
	this.openDirectory = function(nameStringId, sessionId, returnCallback, errorCallback) {
		/*
		Opens an existing directory and allocates a new directory object for it.
		
		FIXME: name has to be absolute
		
		The reference count of the name string object is increased by one. When the
		directory object is destroyed then the reference count of the name string
		object is decreased by one. Also the name string object is locked and cannot be
		modified while the directory object holds a reference to it.
		
		Returns the object ID of the new directory object and the resulting error code.
		*/
		this.ipcon.sendRequest(this, BrickRED.FUNCTION_OPEN_DIRECTORY, [nameStringId, sessionId], 'H H', 11, 'B H', returnCallback, errorCallback, false, true);
	};
	this.getDirectoryName = function(directoryId, sessionId, returnCallback, errorCallback) {
		/*
		Returns the name of a directory object, as passed to :func:`Open Directory`, and
		the resulting error code.
		*/
		this.ipcon.sendRequest(this, BrickRED.FUNCTION_GET_DIRECTORY_NAME, [directoryId, sessionId], 'H H', 11, 'B H', returnCallback, errorCallback, false, true);
	};
	this.getNextDirectoryEntry = function(directoryId, sessionId, returnCallback, errorCallback) {
		/*
		Returns the next entry in a directory object and the resulting error code.
		
		If there is not next entry then error code *NoMoreData* is returned. To rewind
		a directory object call :func:`Rewind Directory`.
		
		Possible directory entry types are:
		
		* Unknown = 0
		* Regular = 1
		* Directory = 2
		* Character = 3
		* Block = 4
		* FIFO = 5
		* Symlink = 6
		* Socket = 7
		*/
		this.ipcon.sendRequest(this, BrickRED.FUNCTION_GET_NEXT_DIRECTORY_ENTRY, [directoryId, sessionId], 'H H', 12, 'B H B', returnCallback, errorCallback, false, true);
	};
	this.rewindDirectory = function(directoryId, returnCallback, errorCallback) {
		/*
		Rewinds a directory object and returns the resulting error code.
		*/
		this.ipcon.sendRequest(this, BrickRED.FUNCTION_REWIND_DIRECTORY, [directoryId], 'H', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.createDirectory = function(nameStringId, flags, permissions, uid, gid, returnCallback, errorCallback) {
		/*
		FIXME: name has to be absolute
		*/
		this.ipcon.sendRequest(this, BrickRED.FUNCTION_CREATE_DIRECTORY, [nameStringId, flags, permissions, uid, gid], 'H I H I I', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getProcesses = function(sessionId, returnCallback, errorCallback) {
		/*
		
		*/
		this.ipcon.sendRequest(this, BrickRED.FUNCTION_GET_PROCESSES, [sessionId], 'H', 11, 'B H', returnCallback, errorCallback, false, true);
	};
	this.spawnProcess = function(executableStringId, argumentsListId, environmentListId, workingDirectoryStringId, uid, gid, stdinFileId, stdoutFileId, stderrFileId, sessionId, returnCallback, errorCallback) {
		/*
		
		*/
		this.ipcon.sendRequest(this, BrickRED.FUNCTION_SPAWN_PROCESS, [executableStringId, argumentsListId, environmentListId, workingDirectoryStringId, uid, gid, stdinFileId, stdoutFileId, stderrFileId, sessionId], 'H H H H I I H H H H', 11, 'B H', returnCallback, errorCallback, false, true);
	};
	this.killProcess = function(processId, signal, returnCallback, errorCallback) {
		/*
		Sends a UNIX signal to a process object and returns the resulting error code.
		
		Possible UNIX signals are:
		
		* Interrupt = 2
		* Quit = 3
		* Abort = 6
		* Kill = 9
		* User1 = 10
		* User2 = 12
		* Terminate = 15
		* Continue =  18
		* Stop = 19
		*/
		this.ipcon.sendRequest(this, BrickRED.FUNCTION_KILL_PROCESS, [processId, signal], 'H B', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getProcessCommand = function(processId, sessionId, returnCallback, errorCallback) {
		/*
		Returns the executable, arguments, environment and working directory used to
		spawn a process object, as passed to :func:`Spawn Process`, and the resulting
		error code.
		*/
		this.ipcon.sendRequest(this, BrickRED.FUNCTION_GET_PROCESS_COMMAND, [processId, sessionId], 'H H', 17, 'B H H H H', returnCallback, errorCallback, false, true);
	};
	this.getProcessIdentity = function(processId, returnCallback, errorCallback) {
		/*
		Returns the process ID and the user and group ID used to spawn a process object,
		as passed to :func:`Spawn Process`, and the resulting error code.
		
		The process ID is only valid if the state is *Running* or *Stopped*, see
		:func:`Get Process State`.
		*/
		this.ipcon.sendRequest(this, BrickRED.FUNCTION_GET_PROCESS_IDENTITY, [processId], 'H', 21, 'B I I I', returnCallback, errorCallback, false, true);
	};
	this.getProcessStdio = function(processId, sessionId, returnCallback, errorCallback) {
		/*
		Returns the stdin, stdout and stderr files used to spawn a process object, as
		passed to :func:`Spawn Process`, and the resulting error code.
		*/
		this.ipcon.sendRequest(this, BrickRED.FUNCTION_GET_PROCESS_STDIO, [processId, sessionId], 'H H', 15, 'B H H H', returnCallback, errorCallback, false, true);
	};
	this.getProcessState = function(processId, returnCallback, errorCallback) {
		/*
		Returns the current state, timestamp and exit code of a process object, and
		the resulting error code.
		
		Possible process states are:
		
		* Unknown = 0
		* Running = 1
		* Error = 2
		* Exited = 3
		* Killed = 4
		* Stopped = 5
		
		The timestamp represents the UNIX time since when the process is in its current
		state.
		
		The exit code is only valid if the state is *Error*, *Exited*, *Killed* or
		*Stopped* and has different meanings depending on the state:
		
		* Error: error code for error occurred while spawning the process (see below)
		* Exited: exit status of the process
		* Killed: UNIX signal number used to kill the process
		* Stopped: UNIX signal number used to stop the process
		
		Possible exit/error codes in *Error* state are:
		
		* InternalError = 125
		* CannotExecute = 126
		* DoesNotExist = 127
		
		The *CannotExecute* error can be caused by the executable being opened for
		writing.
		*/
		this.ipcon.sendRequest(this, BrickRED.FUNCTION_GET_PROCESS_STATE, [processId], 'H', 19, 'B B Q B', returnCallback, errorCallback, false, true);
	};
	this.getPrograms = function(sessionId, returnCallback, errorCallback) {
		/*
		
		*/
		this.ipcon.sendRequest(this, BrickRED.FUNCTION_GET_PROGRAMS, [sessionId], 'H', 11, 'B H', returnCallback, errorCallback, false, true);
	};
	this.defineProgram = function(identifierStringId, sessionId, returnCallback, errorCallback) {
		/*
		
		*/
		this.ipcon.sendRequest(this, BrickRED.FUNCTION_DEFINE_PROGRAM, [identifierStringId, sessionId], 'H H', 11, 'B H', returnCallback, errorCallback, false, true);
	};
	this.purgeProgram = function(programId, cookie, returnCallback, errorCallback) {
		/*
		
		*/
		this.ipcon.sendRequest(this, BrickRED.FUNCTION_PURGE_PROGRAM, [programId, cookie], 'H I', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getProgramIdentifier = function(programId, sessionId, returnCallback, errorCallback) {
		/*
		
		*/
		this.ipcon.sendRequest(this, BrickRED.FUNCTION_GET_PROGRAM_IDENTIFIER, [programId, sessionId], 'H H', 11, 'B H', returnCallback, errorCallback, false, true);
	};
	this.getProgramRootDirectory = function(programId, sessionId, returnCallback, errorCallback) {
		/*
		FIXME: root directory is absolute: <home>/programs/<identifier>
		*/
		this.ipcon.sendRequest(this, BrickRED.FUNCTION_GET_PROGRAM_ROOT_DIRECTORY, [programId, sessionId], 'H H', 11, 'B H', returnCallback, errorCallback, false, true);
	};
	this.setProgramCommand = function(programId, executableStringId, argumentsListId, environmentListId, workingDirectoryStringId, returnCallback, errorCallback) {
		/*
		FIXME: working directory is relative to <home>/programs/<identifier>/bin
		*/
		this.ipcon.sendRequest(this, BrickRED.FUNCTION_SET_PROGRAM_COMMAND, [programId, executableStringId, argumentsListId, environmentListId, workingDirectoryStringId], 'H H H H H', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getProgramCommand = function(programId, sessionId, returnCallback, errorCallback) {
		/*
		FIXME: working directory is relative to <home>/programs/<identifier>/bin
		*/
		this.ipcon.sendRequest(this, BrickRED.FUNCTION_GET_PROGRAM_COMMAND, [programId, sessionId], 'H H', 17, 'B H H H H', returnCallback, errorCallback, false, true);
	};
	this.setProgramStdioRedirection = function(programId, stdinRedirection, stdinFileNameStringId, stdoutRedirection, stdoutFileNameStringId, stderrRedirection, stderrFileNameStringId, returnCallback, errorCallback) {
		/*
		FIXME: stdio file names are relative to <home>/programs/<identifier>/bin
		*/
		this.ipcon.sendRequest(this, BrickRED.FUNCTION_SET_PROGRAM_STDIO_REDIRECTION, [programId, stdinRedirection, stdinFileNameStringId, stdoutRedirection, stdoutFileNameStringId, stderrRedirection, stderrFileNameStringId], 'H B H B H B H', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getProgramStdioRedirection = function(programId, sessionId, returnCallback, errorCallback) {
		/*
		FIXME: stdio file names are relative to <home>/programs/<identifier>/bin
		*/
		this.ipcon.sendRequest(this, BrickRED.FUNCTION_GET_PROGRAM_STDIO_REDIRECTION, [programId, sessionId], 'H H', 18, 'B B H B H B H', returnCallback, errorCallback, false, true);
	};
	this.setProgramSchedule = function(programId, startMode, continueAfterError, startInterval, startFieldsStringId, returnCallback, errorCallback) {
		/*
		
		*/
		this.ipcon.sendRequest(this, BrickRED.FUNCTION_SET_PROGRAM_SCHEDULE, [programId, startMode, continueAfterError, startInterval, startFieldsStringId], 'H B ? I H', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getProgramSchedule = function(programId, sessionId, returnCallback, errorCallback) {
		/*
		
		*/
		this.ipcon.sendRequest(this, BrickRED.FUNCTION_GET_PROGRAM_SCHEDULE, [programId, sessionId], 'H H', 17, 'B B ? I H', returnCallback, errorCallback, false, true);
	};
	this.getProgramSchedulerState = function(programId, sessionId, returnCallback, errorCallback) {
		/*
		FIXME: message is currently valid in error-occurred state only
		*/
		this.ipcon.sendRequest(this, BrickRED.FUNCTION_GET_PROGRAM_SCHEDULER_STATE, [programId, sessionId], 'H H', 20, 'B B Q H', returnCallback, errorCallback, false, true);
	};
	this.continueProgramSchedule = function(programId, returnCallback, errorCallback) {
		/*
		
		*/
		this.ipcon.sendRequest(this, BrickRED.FUNCTION_CONTINUE_PROGRAM_SCHEDULE, [programId], 'H', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.startProgram = function(programId, returnCallback, errorCallback) {
		/*
		
		*/
		this.ipcon.sendRequest(this, BrickRED.FUNCTION_START_PROGRAM, [programId], 'H', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getLastSpawnedProgramProcess = function(programId, sessionId, returnCallback, errorCallback) {
		/*
		
		*/
		this.ipcon.sendRequest(this, BrickRED.FUNCTION_GET_LAST_SPAWNED_PROGRAM_PROCESS, [programId, sessionId], 'H H', 19, 'B H Q', returnCallback, errorCallback, false, true);
	};
	this.getCustomProgramOptionNames = function(programId, sessionId, returnCallback, errorCallback) {
		/*
		
		*/
		this.ipcon.sendRequest(this, BrickRED.FUNCTION_GET_CUSTOM_PROGRAM_OPTION_NAMES, [programId, sessionId], 'H H', 11, 'B H', returnCallback, errorCallback, false, true);
	};
	this.setCustomProgramOptionValue = function(programId, nameStringId, valueStringId, returnCallback, errorCallback) {
		/*
		
		*/
		this.ipcon.sendRequest(this, BrickRED.FUNCTION_SET_CUSTOM_PROGRAM_OPTION_VALUE, [programId, nameStringId, valueStringId], 'H H H', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getCustomProgramOptionValue = function(programId, nameStringId, sessionId, returnCallback, errorCallback) {
		/*
		
		*/
		this.ipcon.sendRequest(this, BrickRED.FUNCTION_GET_CUSTOM_PROGRAM_OPTION_VALUE, [programId, nameStringId, sessionId], 'H H H', 11, 'B H', returnCallback, errorCallback, false, true);
	};
	this.removeCustomProgramOption = function(programId, nameStringId, returnCallback, errorCallback) {
		/*
		
		*/
		this.ipcon.sendRequest(this, BrickRED.FUNCTION_REMOVE_CUSTOM_PROGRAM_OPTION, [programId, nameStringId], 'H H', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Brick is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position is the position in the stack from '0' (bottom) to '8' (top).
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickRED.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickRED;

},{"./Device":279,"./IPConnection":280}],144:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickServo.DEVICE_IDENTIFIER = 14;
BrickServo.DEVICE_DISPLAY_NAME = 'Servo Brick';
BrickServo.CALLBACK_UNDER_VOLTAGE = 26;
BrickServo.CALLBACK_POSITION_REACHED = 27;
BrickServo.CALLBACK_VELOCITY_REACHED = 28;
BrickServo.FUNCTION_ENABLE = 1;
BrickServo.FUNCTION_DISABLE = 2;
BrickServo.FUNCTION_IS_ENABLED = 3;
BrickServo.FUNCTION_SET_POSITION = 4;
BrickServo.FUNCTION_GET_POSITION = 5;
BrickServo.FUNCTION_GET_CURRENT_POSITION = 6;
BrickServo.FUNCTION_SET_VELOCITY = 7;
BrickServo.FUNCTION_GET_VELOCITY = 8;
BrickServo.FUNCTION_GET_CURRENT_VELOCITY = 9;
BrickServo.FUNCTION_SET_ACCELERATION = 10;
BrickServo.FUNCTION_GET_ACCELERATION = 11;
BrickServo.FUNCTION_SET_OUTPUT_VOLTAGE = 12;
BrickServo.FUNCTION_GET_OUTPUT_VOLTAGE = 13;
BrickServo.FUNCTION_SET_PULSE_WIDTH = 14;
BrickServo.FUNCTION_GET_PULSE_WIDTH = 15;
BrickServo.FUNCTION_SET_DEGREE = 16;
BrickServo.FUNCTION_GET_DEGREE = 17;
BrickServo.FUNCTION_SET_PERIOD = 18;
BrickServo.FUNCTION_GET_PERIOD = 19;
BrickServo.FUNCTION_GET_SERVO_CURRENT = 20;
BrickServo.FUNCTION_GET_OVERALL_CURRENT = 21;
BrickServo.FUNCTION_GET_STACK_INPUT_VOLTAGE = 22;
BrickServo.FUNCTION_GET_EXTERNAL_INPUT_VOLTAGE = 23;
BrickServo.FUNCTION_SET_MINIMUM_VOLTAGE = 24;
BrickServo.FUNCTION_GET_MINIMUM_VOLTAGE = 25;
BrickServo.FUNCTION_ENABLE_POSITION_REACHED_CALLBACK = 29;
BrickServo.FUNCTION_DISABLE_POSITION_REACHED_CALLBACK = 30;
BrickServo.FUNCTION_IS_POSITION_REACHED_CALLBACK_ENABLED = 31;
BrickServo.FUNCTION_ENABLE_VELOCITY_REACHED_CALLBACK = 32;
BrickServo.FUNCTION_DISABLE_VELOCITY_REACHED_CALLBACK = 33;
BrickServo.FUNCTION_IS_VELOCITY_REACHED_CALLBACK_ENABLED = 34;
BrickServo.FUNCTION_SET_SPITFP_BAUDRATE_CONFIG = 231;
BrickServo.FUNCTION_GET_SPITFP_BAUDRATE_CONFIG = 232;
BrickServo.FUNCTION_GET_SEND_TIMEOUT_COUNT = 233;
BrickServo.FUNCTION_SET_SPITFP_BAUDRATE = 234;
BrickServo.FUNCTION_GET_SPITFP_BAUDRATE = 235;
BrickServo.FUNCTION_GET_SPITFP_ERROR_COUNT = 237;
BrickServo.FUNCTION_ENABLE_STATUS_LED = 238;
BrickServo.FUNCTION_DISABLE_STATUS_LED = 239;
BrickServo.FUNCTION_IS_STATUS_LED_ENABLED = 240;
BrickServo.FUNCTION_GET_PROTOCOL1_BRICKLET_NAME = 241;
BrickServo.FUNCTION_GET_CHIP_TEMPERATURE = 242;
BrickServo.FUNCTION_RESET = 243;
BrickServo.FUNCTION_WRITE_BRICKLET_PLUGIN = 246;
BrickServo.FUNCTION_READ_BRICKLET_PLUGIN = 247;
BrickServo.FUNCTION_GET_IDENTITY = 255;
BrickServo.COMMUNICATION_METHOD_NONE = 0;
BrickServo.COMMUNICATION_METHOD_USB = 1;
BrickServo.COMMUNICATION_METHOD_SPI_STACK = 2;
BrickServo.COMMUNICATION_METHOD_CHIBI = 3;
BrickServo.COMMUNICATION_METHOD_RS485 = 4;
BrickServo.COMMUNICATION_METHOD_WIFI = 5;
BrickServo.COMMUNICATION_METHOD_ETHERNET = 6;
BrickServo.COMMUNICATION_METHOD_WIFI_V2 = 7;

function BrickServo(uid, ipcon) {
	//Drives up to 7 RC Servos with up to 3A

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickServo.DEVICE_IDENTIFIER, BrickServo.DEVICE_DISPLAY_NAME);
	BrickServo.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 4];
	this.responseExpected[BrickServo.FUNCTION_ENABLE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickServo.FUNCTION_DISABLE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickServo.FUNCTION_IS_ENABLED] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickServo.FUNCTION_SET_POSITION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickServo.FUNCTION_GET_POSITION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickServo.FUNCTION_GET_CURRENT_POSITION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickServo.FUNCTION_SET_VELOCITY] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickServo.FUNCTION_GET_VELOCITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickServo.FUNCTION_GET_CURRENT_VELOCITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickServo.FUNCTION_SET_ACCELERATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickServo.FUNCTION_GET_ACCELERATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickServo.FUNCTION_SET_OUTPUT_VOLTAGE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickServo.FUNCTION_GET_OUTPUT_VOLTAGE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickServo.FUNCTION_SET_PULSE_WIDTH] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickServo.FUNCTION_GET_PULSE_WIDTH] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickServo.FUNCTION_SET_DEGREE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickServo.FUNCTION_GET_DEGREE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickServo.FUNCTION_SET_PERIOD] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickServo.FUNCTION_GET_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickServo.FUNCTION_GET_SERVO_CURRENT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickServo.FUNCTION_GET_OVERALL_CURRENT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickServo.FUNCTION_GET_STACK_INPUT_VOLTAGE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickServo.FUNCTION_GET_EXTERNAL_INPUT_VOLTAGE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickServo.FUNCTION_SET_MINIMUM_VOLTAGE] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickServo.FUNCTION_GET_MINIMUM_VOLTAGE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickServo.FUNCTION_ENABLE_POSITION_REACHED_CALLBACK] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickServo.FUNCTION_DISABLE_POSITION_REACHED_CALLBACK] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickServo.FUNCTION_IS_POSITION_REACHED_CALLBACK_ENABLED] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickServo.FUNCTION_ENABLE_VELOCITY_REACHED_CALLBACK] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickServo.FUNCTION_DISABLE_VELOCITY_REACHED_CALLBACK] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickServo.FUNCTION_IS_VELOCITY_REACHED_CALLBACK_ENABLED] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickServo.FUNCTION_SET_SPITFP_BAUDRATE_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickServo.FUNCTION_GET_SPITFP_BAUDRATE_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickServo.FUNCTION_GET_SEND_TIMEOUT_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickServo.FUNCTION_SET_SPITFP_BAUDRATE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickServo.FUNCTION_GET_SPITFP_BAUDRATE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickServo.FUNCTION_GET_SPITFP_ERROR_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickServo.FUNCTION_ENABLE_STATUS_LED] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickServo.FUNCTION_DISABLE_STATUS_LED] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickServo.FUNCTION_IS_STATUS_LED_ENABLED] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickServo.FUNCTION_GET_PROTOCOL1_BRICKLET_NAME] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickServo.FUNCTION_GET_CHIP_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickServo.FUNCTION_RESET] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickServo.FUNCTION_WRITE_BRICKLET_PLUGIN] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickServo.FUNCTION_READ_BRICKLET_PLUGIN] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickServo.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickServo.CALLBACK_UNDER_VOLTAGE] = [10, 'H'];
	this.callbackFormats[BrickServo.CALLBACK_POSITION_REACHED] = [11, 'B h'];
	this.callbackFormats[BrickServo.CALLBACK_VELOCITY_REACHED] = [11, 'B h'];



	this.enable = function(servoNum, returnCallback, errorCallback) {
		/*
		Enables a servo (0 to 6). If a servo is enabled, the configured position,
		velocity, acceleration, etc. are applied immediately.
		*/
		this.ipcon.sendRequest(this, BrickServo.FUNCTION_ENABLE, [servoNum], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.disable = function(servoNum, returnCallback, errorCallback) {
		/*
		Disables a servo (0 to 6). Disabled servos are not driven at all, i.e. a
		disabled servo will not hold its position if a load is applied.
		*/
		this.ipcon.sendRequest(this, BrickServo.FUNCTION_DISABLE, [servoNum], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.isEnabled = function(servoNum, returnCallback, errorCallback) {
		/*
		Returns *true* if the specified servo is enabled, *false* otherwise.
		*/
		this.ipcon.sendRequest(this, BrickServo.FUNCTION_IS_ENABLED, [servoNum], 'B', 9, '?', returnCallback, errorCallback, false, true);
	};
	this.setPosition = function(servoNum, position, returnCallback, errorCallback) {
		/*
		Sets the position for the specified servo.
		
		The default range of the position is -9000 to 9000, but it can be specified
		according to your servo with :func:`Set Degree`.
		
		If you want to control a linear servo or RC brushless motor controller or
		similar with the Servo Brick, you can also define lengths or speeds with
		:func:`Set Degree`.
		*/
		this.ipcon.sendRequest(this, BrickServo.FUNCTION_SET_POSITION, [servoNum, position], 'B h', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getPosition = function(servoNum, returnCallback, errorCallback) {
		/*
		Returns the position of the specified servo as set by :func:`Set Position`.
		*/
		this.ipcon.sendRequest(this, BrickServo.FUNCTION_GET_POSITION, [servoNum], 'B', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.getCurrentPosition = function(servoNum, returnCallback, errorCallback) {
		/*
		Returns the *current* position of the specified servo. This may not be the
		value of :func:`Set Position` if the servo is currently approaching a
		position goal.
		*/
		this.ipcon.sendRequest(this, BrickServo.FUNCTION_GET_CURRENT_POSITION, [servoNum], 'B', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.setVelocity = function(servoNum, velocity, returnCallback, errorCallback) {
		/*
		Sets the maximum velocity of the specified servo. The velocity
		is accelerated according to the value set by :func:`Set Acceleration`.
		
		The minimum velocity is 0 (no movement) and the maximum velocity is 65535.
		With a value of 65535 the position will be set immediately (no velocity).
		*/
		this.ipcon.sendRequest(this, BrickServo.FUNCTION_SET_VELOCITY, [servoNum, velocity], 'B H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getVelocity = function(servoNum, returnCallback, errorCallback) {
		/*
		Returns the velocity of the specified servo as set by :func:`Set Velocity`.
		*/
		this.ipcon.sendRequest(this, BrickServo.FUNCTION_GET_VELOCITY, [servoNum], 'B', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.getCurrentVelocity = function(servoNum, returnCallback, errorCallback) {
		/*
		Returns the *current* velocity of the specified servo. This may not be the
		value of :func:`Set Velocity` if the servo is currently approaching a
		velocity goal.
		*/
		this.ipcon.sendRequest(this, BrickServo.FUNCTION_GET_CURRENT_VELOCITY, [servoNum], 'B', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.setAcceleration = function(servoNum, acceleration, returnCallback, errorCallback) {
		/*
		Sets the acceleration of the specified servo.
		
		The minimum acceleration is 1 and the maximum acceleration is 65535.
		With a value of 65535 the velocity will be set immediately (no acceleration).
		*/
		this.ipcon.sendRequest(this, BrickServo.FUNCTION_SET_ACCELERATION, [servoNum, acceleration], 'B H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getAcceleration = function(servoNum, returnCallback, errorCallback) {
		/*
		Returns the acceleration for the specified servo as set by
		:func:`Set Acceleration`.
		*/
		this.ipcon.sendRequest(this, BrickServo.FUNCTION_GET_ACCELERATION, [servoNum], 'B', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.setOutputVoltage = function(voltage, returnCallback, errorCallback) {
		/*
		Sets the output voltages with which the servos are driven.
		
		.. note::
		 We recommend that you set this value to the maximum voltage that is
		 specified for your servo, most servos achieve their maximum force only
		 with high voltages.
		*/
		this.ipcon.sendRequest(this, BrickServo.FUNCTION_SET_OUTPUT_VOLTAGE, [voltage], 'H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getOutputVoltage = function(returnCallback, errorCallback) {
		/*
		Returns the output voltage as specified by :func:`Set Output Voltage`.
		*/
		this.ipcon.sendRequest(this, BrickServo.FUNCTION_GET_OUTPUT_VOLTAGE, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.setPulseWidth = function(servoNum, min, max, returnCallback, errorCallback) {
		/*
		Sets the minimum and maximum pulse width of the specified servo.
		
		Usually, servos are controlled with a
		`PWM <https://en.wikipedia.org/wiki/Pulse-width_modulation>`__, whereby the
		length of the pulse controls the position of the servo. Every servo has
		different minimum and maximum pulse widths, these can be specified with
		this function.
		
		If you have a datasheet for your servo that specifies the minimum and
		maximum pulse width, you should set the values accordingly. If your servo
		comes without any datasheet you have to find the values via trial and error.
		
		The minimum must be smaller than the maximum.
		*/
		this.ipcon.sendRequest(this, BrickServo.FUNCTION_SET_PULSE_WIDTH, [servoNum, min, max], 'B H H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getPulseWidth = function(servoNum, returnCallback, errorCallback) {
		/*
		Returns the minimum and maximum pulse width for the specified servo as set by
		:func:`Set Pulse Width`.
		*/
		this.ipcon.sendRequest(this, BrickServo.FUNCTION_GET_PULSE_WIDTH, [servoNum], 'B', 12, 'H H', returnCallback, errorCallback, false, true);
	};
	this.setDegree = function(servoNum, min, max, returnCallback, errorCallback) {
		/*
		Sets the minimum and maximum degree for the specified servo (by default
		given as °/100).
		
		This only specifies the abstract values between which the minimum and maximum
		pulse width is scaled. For example: If you specify a pulse width of 1000µs
		to 2000µs and a degree range of -90° to 90°, a call of :func:`Set Position`
		with 0 will result in a pulse width of 1500µs
		(-90° = 1000µs, 90° = 2000µs, etc.).
		
		Possible usage:
		
		* The datasheet of your servo specifies a range of 200° with the middle position
		  at 110°. In this case you can set the minimum to -9000 and the maximum to 11000.
		* You measure a range of 220° on your servo and you don't have or need a middle
		  position. In this case you can set the minimum to 0 and the maximum to 22000.
		* You have a linear servo with a drive length of 20cm, In this case you could
		  set the minimum to 0 and the maximum to 20000. Now you can set the Position
		  with :func:`Set Position` with a resolution of cm/100. Also the velocity will
		  have a resolution of cm/100s and the acceleration will have a resolution of
		  cm/100s².
		* You don't care about units and just want the highest possible resolution. In
		  this case you should set the minimum to -32767 and the maximum to 32767.
		* You have a brushless motor with a maximum speed of 10000 rpm and want to
		  control it with a RC brushless motor controller. In this case you can set the
		  minimum to 0 and the maximum to 10000. :func:`Set Position` now controls the rpm.
		
		The minimum must be smaller than the maximum.
		*/
		this.ipcon.sendRequest(this, BrickServo.FUNCTION_SET_DEGREE, [servoNum, min, max], 'B h h', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getDegree = function(servoNum, returnCallback, errorCallback) {
		/*
		Returns the minimum and maximum degree for the specified servo as set by
		:func:`Set Degree`.
		*/
		this.ipcon.sendRequest(this, BrickServo.FUNCTION_GET_DEGREE, [servoNum], 'B', 12, 'h h', returnCallback, errorCallback, false, true);
	};
	this.setPeriod = function(servoNum, period, returnCallback, errorCallback) {
		/*
		Sets the period of the specified servo.
		
		Usually, servos are controlled with a
		`PWM <https://en.wikipedia.org/wiki/Pulse-width_modulation>`__. Different
		servos expect PWMs with different periods. Most servos run well with a
		period of about 20ms.
		
		If your servo comes with a datasheet that specifies a period, you should
		set it accordingly. If you don't have a datasheet and you have no idea
		what the correct period is, the default value will most likely
		work fine.
		*/
		this.ipcon.sendRequest(this, BrickServo.FUNCTION_SET_PERIOD, [servoNum, period], 'B H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getPeriod = function(servoNum, returnCallback, errorCallback) {
		/*
		Returns the period for the specified servo as set by :func:`Set Period`.
		*/
		this.ipcon.sendRequest(this, BrickServo.FUNCTION_GET_PERIOD, [servoNum], 'B', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.getServoCurrent = function(servoNum, returnCallback, errorCallback) {
		/*
		Returns the current consumption of the specified servo.
		*/
		this.ipcon.sendRequest(this, BrickServo.FUNCTION_GET_SERVO_CURRENT, [servoNum], 'B', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.getOverallCurrent = function(returnCallback, errorCallback) {
		/*
		Returns the current consumption of all servos together.
		*/
		this.ipcon.sendRequest(this, BrickServo.FUNCTION_GET_OVERALL_CURRENT, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.getStackInputVoltage = function(returnCallback, errorCallback) {
		/*
		Returns the stack input voltage. The stack input voltage is the
		voltage that is supplied via the stack, i.e. it is given by a
		Step-Down or Step-Up Power Supply.
		*/
		this.ipcon.sendRequest(this, BrickServo.FUNCTION_GET_STACK_INPUT_VOLTAGE, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.getExternalInputVoltage = function(returnCallback, errorCallback) {
		/*
		Returns the external input voltage. The external input voltage is
		given via the black power input connector on the Servo Brick.
		
		If there is an external input voltage and a stack input voltage, the motors
		will be driven by the external input voltage. If there is only a stack
		voltage present, the motors will be driven by this voltage.
		
		.. warning::
		 This means, if you have a high stack voltage and a low external voltage,
		 the motors will be driven with the low external voltage. If you then remove
		 the external connection, it will immediately be driven by the high
		 stack voltage
		*/
		this.ipcon.sendRequest(this, BrickServo.FUNCTION_GET_EXTERNAL_INPUT_VOLTAGE, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.setMinimumVoltage = function(voltage, returnCallback, errorCallback) {
		/*
		Sets the minimum voltage, below which the :cb:`Under Voltage` callback
		is triggered. The minimum possible value that works with the Servo Brick is 5V.
		You can use this function to detect the discharge of a battery that is used
		to drive the stepper motor. If you have a fixed power supply, you likely do
		not need this functionality.
		*/
		this.ipcon.sendRequest(this, BrickServo.FUNCTION_SET_MINIMUM_VOLTAGE, [voltage], 'H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getMinimumVoltage = function(returnCallback, errorCallback) {
		/*
		Returns the minimum voltage as set by :func:`Set Minimum Voltage`
		*/
		this.ipcon.sendRequest(this, BrickServo.FUNCTION_GET_MINIMUM_VOLTAGE, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.enablePositionReachedCallback = function(returnCallback, errorCallback) {
		/*
		Enables the :cb:`Position Reached` callback.
		
		Default is disabled.
		
		.. versionadded:: 2.0.1$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickServo.FUNCTION_ENABLE_POSITION_REACHED_CALLBACK, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.disablePositionReachedCallback = function(returnCallback, errorCallback) {
		/*
		Disables the :cb:`Position Reached` callback.
		
		.. versionadded:: 2.0.1$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickServo.FUNCTION_DISABLE_POSITION_REACHED_CALLBACK, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.isPositionReachedCallbackEnabled = function(returnCallback, errorCallback) {
		/*
		Returns *true* if :cb:`Position Reached` callback is enabled, *false* otherwise.
		
		.. versionadded:: 2.0.1$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickServo.FUNCTION_IS_POSITION_REACHED_CALLBACK_ENABLED, [], '', 9, '?', returnCallback, errorCallback, false, true);
	};
	this.enableVelocityReachedCallback = function(returnCallback, errorCallback) {
		/*
		Enables the :cb:`Velocity Reached` callback.
		
		Default is disabled.
		
		.. versionadded:: 2.0.1$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickServo.FUNCTION_ENABLE_VELOCITY_REACHED_CALLBACK, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.disableVelocityReachedCallback = function(returnCallback, errorCallback) {
		/*
		Disables the :cb:`Velocity Reached` callback.
		
		Default is disabled.
		
		.. versionadded:: 2.0.1$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickServo.FUNCTION_DISABLE_VELOCITY_REACHED_CALLBACK, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.isVelocityReachedCallbackEnabled = function(returnCallback, errorCallback) {
		/*
		Returns *true* if :cb:`Velocity Reached` callback is enabled, *false* otherwise.
		
		.. versionadded:: 2.0.1$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickServo.FUNCTION_IS_VELOCITY_REACHED_CALLBACK_ENABLED, [], '', 9, '?', returnCallback, errorCallback, false, true);
	};
	this.setSPITFPBaudrateConfig = function(enableDynamicBaudrate, minimumDynamicBaudrate, returnCallback, errorCallback) {
		/*
		The SPITF protocol can be used with a dynamic baudrate. If the dynamic baudrate is
		enabled, the Brick will try to adapt the baudrate for the communication
		between Bricks and Bricklets according to the amount of data that is transferred.
		
		The baudrate will be increased exponentially if lots of data is sent/received and
		decreased linearly if little data is sent/received.
		
		This lowers the baudrate in applications where little data is transferred (e.g.
		a weather station) and increases the robustness. If there is lots of data to transfer
		(e.g. Thermal Imaging Bricklet) it automatically increases the baudrate as needed.
		
		In cases where some data has to transferred as fast as possible every few seconds
		(e.g. RS485 Bricklet with a high baudrate but small payload) you may want to turn
		the dynamic baudrate off to get the highest possible performance.
		
		The maximum value of the baudrate can be set per port with the function
		:func:`Set SPITFP Baudrate`. If the dynamic baudrate is disabled, the baudrate
		as set by :func:`Set SPITFP Baudrate` will be used statically.
		
		.. versionadded:: 2.3.4$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickServo.FUNCTION_SET_SPITFP_BAUDRATE_CONFIG, [enableDynamicBaudrate, minimumDynamicBaudrate], '? I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPBaudrateConfig = function(returnCallback, errorCallback) {
		/*
		Returns the baudrate config, see :func:`Set SPITFP Baudrate Config`.
		
		.. versionadded:: 2.3.4$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickServo.FUNCTION_GET_SPITFP_BAUDRATE_CONFIG, [], '', 13, '? I', returnCallback, errorCallback, false, true);
	};
	this.getSendTimeoutCount = function(communicationMethod, returnCallback, errorCallback) {
		/*
		Returns the timeout count for the different communication methods.
		
		The methods 0-2 are available for all Bricks, 3-7 only for Master Bricks.
		
		This function is mostly used for debugging during development, in normal operation
		the counters should nearly always stay at 0.
		
		.. versionadded:: 2.3.2$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickServo.FUNCTION_GET_SEND_TIMEOUT_COUNT, [communicationMethod], 'B', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setSPITFPBaudrate = function(brickletPort, baudrate, returnCallback, errorCallback) {
		/*
		Sets the baudrate for a specific Bricklet port.
		
		If you want to increase the throughput of Bricklets you can increase
		the baudrate. If you get a high error count because of high
		interference (see :func:`Get SPITFP Error Count`) you can decrease the
		baudrate.
		
		If the dynamic baudrate feature is enabled, the baudrate set by this
		function corresponds to the maximum baudrate (see :func:`Set SPITFP Baudrate Config`).
		
		Regulatory testing is done with the default baudrate. If CE compatibility
		or similar is necessary in your applications we recommend to not change
		the baudrate.
		
		.. versionadded:: 2.3.2$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickServo.FUNCTION_SET_SPITFP_BAUDRATE, [brickletPort, baudrate], 'c I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPBaudrate = function(brickletPort, returnCallback, errorCallback) {
		/*
		Returns the baudrate for a given Bricklet port, see :func:`Set SPITFP Baudrate`.
		
		.. versionadded:: 2.3.2$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickServo.FUNCTION_GET_SPITFP_BAUDRATE, [brickletPort], 'c', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPErrorCount = function(brickletPort, returnCallback, errorCallback) {
		/*
		Returns the error count for the communication between Brick and Bricklet.
		
		The errors are divided into
		
		* ACK checksum errors,
		* message checksum errors,
		* framing errors and
		* overflow errors.
		
		The errors counts are for errors that occur on the Brick side. All
		Bricklets have a similar function that returns the errors on the Bricklet side.
		
		.. versionadded:: 2.3.2$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickServo.FUNCTION_GET_SPITFP_ERROR_COUNT, [brickletPort], 'c', 24, 'I I I I', returnCallback, errorCallback, false, true);
	};
	this.enableStatusLED = function(returnCallback, errorCallback) {
		/*
		Enables the status LED.
		
		The status LED is the blue LED next to the USB connector. If enabled is is
		on and it flickers if data is transfered. If disabled it is always off.
		
		The default state is enabled.
		
		.. versionadded:: 2.3.1$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickServo.FUNCTION_ENABLE_STATUS_LED, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.disableStatusLED = function(returnCallback, errorCallback) {
		/*
		Disables the status LED.
		
		The status LED is the blue LED next to the USB connector. If enabled is is
		on and it flickers if data is transfered. If disabled it is always off.
		
		The default state is enabled.
		
		.. versionadded:: 2.3.1$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickServo.FUNCTION_DISABLE_STATUS_LED, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.isStatusLEDEnabled = function(returnCallback, errorCallback) {
		/*
		Returns *true* if the status LED is enabled, *false* otherwise.
		
		.. versionadded:: 2.3.1$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickServo.FUNCTION_IS_STATUS_LED_ENABLED, [], '', 9, '?', returnCallback, errorCallback, false, true);
	};
	this.getProtocol1BrickletName = function(port, returnCallback, errorCallback) {
		/*
		Returns the firmware and protocol version and the name of the Bricklet for a
		given port.
		
		This functions sole purpose is to allow automatic flashing of v1.x.y Bricklet
		plugins.
		*/
		this.ipcon.sendRequest(this, BrickServo.FUNCTION_GET_PROTOCOL1_BRICKLET_NAME, [port], 'c', 52, 'B B3 s40', returnCallback, errorCallback, false, true);
	};
	this.getChipTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature as measured inside the microcontroller. The
		value returned is not the ambient temperature!
		
		The temperature is only proportional to the real temperature and it has an
		accuracy of ±15%. Practically it is only useful as an indicator for
		temperature changes.
		*/
		this.ipcon.sendRequest(this, BrickServo.FUNCTION_GET_CHIP_TEMPERATURE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.reset = function(returnCallback, errorCallback) {
		/*
		Calling this function will reset the Brick. Calling this function
		on a Brick inside of a stack will reset the whole stack.
		
		After a reset you have to create new device objects,
		calling functions on the existing ones will result in
		undefined behavior!
		*/
		this.ipcon.sendRequest(this, BrickServo.FUNCTION_RESET, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeBrickletPlugin = function(port, offset, chunk, returnCallback, errorCallback) {
		/*
		Writes 32 bytes of firmware to the bricklet attached at the given port.
		The bytes are written to the position offset * 32.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickServo.FUNCTION_WRITE_BRICKLET_PLUGIN, [port, offset, chunk], 'c B B32', 0, '', returnCallback, errorCallback, false, true);
	};
	this.readBrickletPlugin = function(port, offset, returnCallback, errorCallback) {
		/*
		Reads 32 bytes of firmware from the bricklet attached at the given port.
		The bytes are read starting at the position offset * 32.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickServo.FUNCTION_READ_BRICKLET_PLUGIN, [port, offset], 'c B', 40, 'B32', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Brick is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position is the position in the stack from '0' (bottom) to '8' (top).
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickServo.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickServo;

},{"./Device":279,"./IPConnection":280}],145:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickSilentStepper.DEVICE_IDENTIFIER = 19;
BrickSilentStepper.DEVICE_DISPLAY_NAME = 'Silent Stepper Brick';
BrickSilentStepper.CALLBACK_UNDER_VOLTAGE = 40;
BrickSilentStepper.CALLBACK_POSITION_REACHED = 41;
BrickSilentStepper.CALLBACK_ALL_DATA = 47;
BrickSilentStepper.CALLBACK_NEW_STATE = 48;
BrickSilentStepper.FUNCTION_SET_MAX_VELOCITY = 1;
BrickSilentStepper.FUNCTION_GET_MAX_VELOCITY = 2;
BrickSilentStepper.FUNCTION_GET_CURRENT_VELOCITY = 3;
BrickSilentStepper.FUNCTION_SET_SPEED_RAMPING = 4;
BrickSilentStepper.FUNCTION_GET_SPEED_RAMPING = 5;
BrickSilentStepper.FUNCTION_FULL_BRAKE = 6;
BrickSilentStepper.FUNCTION_SET_CURRENT_POSITION = 7;
BrickSilentStepper.FUNCTION_GET_CURRENT_POSITION = 8;
BrickSilentStepper.FUNCTION_SET_TARGET_POSITION = 9;
BrickSilentStepper.FUNCTION_GET_TARGET_POSITION = 10;
BrickSilentStepper.FUNCTION_SET_STEPS = 11;
BrickSilentStepper.FUNCTION_GET_STEPS = 12;
BrickSilentStepper.FUNCTION_GET_REMAINING_STEPS = 13;
BrickSilentStepper.FUNCTION_SET_STEP_CONFIGURATION = 14;
BrickSilentStepper.FUNCTION_GET_STEP_CONFIGURATION = 15;
BrickSilentStepper.FUNCTION_DRIVE_FORWARD = 16;
BrickSilentStepper.FUNCTION_DRIVE_BACKWARD = 17;
BrickSilentStepper.FUNCTION_STOP = 18;
BrickSilentStepper.FUNCTION_GET_STACK_INPUT_VOLTAGE = 19;
BrickSilentStepper.FUNCTION_GET_EXTERNAL_INPUT_VOLTAGE = 20;
BrickSilentStepper.FUNCTION_SET_MOTOR_CURRENT = 22;
BrickSilentStepper.FUNCTION_GET_MOTOR_CURRENT = 23;
BrickSilentStepper.FUNCTION_ENABLE = 24;
BrickSilentStepper.FUNCTION_DISABLE = 25;
BrickSilentStepper.FUNCTION_IS_ENABLED = 26;
BrickSilentStepper.FUNCTION_SET_BASIC_CONFIGURATION = 27;
BrickSilentStepper.FUNCTION_GET_BASIC_CONFIGURATION = 28;
BrickSilentStepper.FUNCTION_SET_SPREADCYCLE_CONFIGURATION = 29;
BrickSilentStepper.FUNCTION_GET_SPREADCYCLE_CONFIGURATION = 30;
BrickSilentStepper.FUNCTION_SET_STEALTH_CONFIGURATION = 31;
BrickSilentStepper.FUNCTION_GET_STEALTH_CONFIGURATION = 32;
BrickSilentStepper.FUNCTION_SET_COOLSTEP_CONFIGURATION = 33;
BrickSilentStepper.FUNCTION_GET_COOLSTEP_CONFIGURATION = 34;
BrickSilentStepper.FUNCTION_SET_MISC_CONFIGURATION = 35;
BrickSilentStepper.FUNCTION_GET_MISC_CONFIGURATION = 36;
BrickSilentStepper.FUNCTION_GET_DRIVER_STATUS = 37;
BrickSilentStepper.FUNCTION_SET_MINIMUM_VOLTAGE = 38;
BrickSilentStepper.FUNCTION_GET_MINIMUM_VOLTAGE = 39;
BrickSilentStepper.FUNCTION_SET_TIME_BASE = 42;
BrickSilentStepper.FUNCTION_GET_TIME_BASE = 43;
BrickSilentStepper.FUNCTION_GET_ALL_DATA = 44;
BrickSilentStepper.FUNCTION_SET_ALL_DATA_PERIOD = 45;
BrickSilentStepper.FUNCTION_GET_ALL_DATA_PERIOD = 46;
BrickSilentStepper.FUNCTION_SET_SPITFP_BAUDRATE_CONFIG = 231;
BrickSilentStepper.FUNCTION_GET_SPITFP_BAUDRATE_CONFIG = 232;
BrickSilentStepper.FUNCTION_GET_SEND_TIMEOUT_COUNT = 233;
BrickSilentStepper.FUNCTION_SET_SPITFP_BAUDRATE = 234;
BrickSilentStepper.FUNCTION_GET_SPITFP_BAUDRATE = 235;
BrickSilentStepper.FUNCTION_GET_SPITFP_ERROR_COUNT = 237;
BrickSilentStepper.FUNCTION_ENABLE_STATUS_LED = 238;
BrickSilentStepper.FUNCTION_DISABLE_STATUS_LED = 239;
BrickSilentStepper.FUNCTION_IS_STATUS_LED_ENABLED = 240;
BrickSilentStepper.FUNCTION_GET_PROTOCOL1_BRICKLET_NAME = 241;
BrickSilentStepper.FUNCTION_GET_CHIP_TEMPERATURE = 242;
BrickSilentStepper.FUNCTION_RESET = 243;
BrickSilentStepper.FUNCTION_WRITE_BRICKLET_PLUGIN = 246;
BrickSilentStepper.FUNCTION_READ_BRICKLET_PLUGIN = 247;
BrickSilentStepper.FUNCTION_GET_IDENTITY = 255;
BrickSilentStepper.STEP_RESOLUTION_1 = 8;
BrickSilentStepper.STEP_RESOLUTION_2 = 7;
BrickSilentStepper.STEP_RESOLUTION_4 = 6;
BrickSilentStepper.STEP_RESOLUTION_8 = 5;
BrickSilentStepper.STEP_RESOLUTION_16 = 4;
BrickSilentStepper.STEP_RESOLUTION_32 = 3;
BrickSilentStepper.STEP_RESOLUTION_64 = 2;
BrickSilentStepper.STEP_RESOLUTION_128 = 1;
BrickSilentStepper.STEP_RESOLUTION_256 = 0;
BrickSilentStepper.CHOPPER_MODE_SPREAD_CYCLE = 0;
BrickSilentStepper.CHOPPER_MODE_FAST_DECAY = 1;
BrickSilentStepper.FREEWHEEL_MODE_NORMAL = 0;
BrickSilentStepper.FREEWHEEL_MODE_FREEWHEELING = 1;
BrickSilentStepper.FREEWHEEL_MODE_COIL_SHORT_LS = 2;
BrickSilentStepper.FREEWHEEL_MODE_COIL_SHORT_HS = 3;
BrickSilentStepper.CURRENT_UP_STEP_INCREMENT_1 = 0;
BrickSilentStepper.CURRENT_UP_STEP_INCREMENT_2 = 1;
BrickSilentStepper.CURRENT_UP_STEP_INCREMENT_4 = 2;
BrickSilentStepper.CURRENT_UP_STEP_INCREMENT_8 = 3;
BrickSilentStepper.CURRENT_DOWN_STEP_DECREMENT_1 = 0;
BrickSilentStepper.CURRENT_DOWN_STEP_DECREMENT_2 = 1;
BrickSilentStepper.CURRENT_DOWN_STEP_DECREMENT_8 = 2;
BrickSilentStepper.CURRENT_DOWN_STEP_DECREMENT_32 = 3;
BrickSilentStepper.MINIMUM_CURRENT_HALF = 0;
BrickSilentStepper.MINIMUM_CURRENT_QUARTER = 1;
BrickSilentStepper.STALLGUARD_MODE_STANDARD = 0;
BrickSilentStepper.STALLGUARD_MODE_FILTERED = 1;
BrickSilentStepper.OPEN_LOAD_NONE = 0;
BrickSilentStepper.OPEN_LOAD_PHASE_A = 1;
BrickSilentStepper.OPEN_LOAD_PHASE_B = 2;
BrickSilentStepper.OPEN_LOAD_PHASE_AB = 3;
BrickSilentStepper.SHORT_TO_GROUND_NONE = 0;
BrickSilentStepper.SHORT_TO_GROUND_PHASE_A = 1;
BrickSilentStepper.SHORT_TO_GROUND_PHASE_B = 2;
BrickSilentStepper.SHORT_TO_GROUND_PHASE_AB = 3;
BrickSilentStepper.OVER_TEMPERATURE_NONE = 0;
BrickSilentStepper.OVER_TEMPERATURE_WARNING = 1;
BrickSilentStepper.OVER_TEMPERATURE_LIMIT = 2;
BrickSilentStepper.STATE_STOP = 1;
BrickSilentStepper.STATE_ACCELERATION = 2;
BrickSilentStepper.STATE_RUN = 3;
BrickSilentStepper.STATE_DEACCELERATION = 4;
BrickSilentStepper.STATE_DIRECTION_CHANGE_TO_FORWARD = 5;
BrickSilentStepper.STATE_DIRECTION_CHANGE_TO_BACKWARD = 6;
BrickSilentStepper.COMMUNICATION_METHOD_NONE = 0;
BrickSilentStepper.COMMUNICATION_METHOD_USB = 1;
BrickSilentStepper.COMMUNICATION_METHOD_SPI_STACK = 2;
BrickSilentStepper.COMMUNICATION_METHOD_CHIBI = 3;
BrickSilentStepper.COMMUNICATION_METHOD_RS485 = 4;
BrickSilentStepper.COMMUNICATION_METHOD_WIFI = 5;
BrickSilentStepper.COMMUNICATION_METHOD_ETHERNET = 6;
BrickSilentStepper.COMMUNICATION_METHOD_WIFI_V2 = 7;

function BrickSilentStepper(uid, ipcon) {
	//Silently drives one bipolar stepper motor with up to 46V and 1.6A per phase

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickSilentStepper.DEVICE_IDENTIFIER, BrickSilentStepper.DEVICE_DISPLAY_NAME);
	BrickSilentStepper.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 1];
	this.responseExpected[BrickSilentStepper.FUNCTION_SET_MAX_VELOCITY] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickSilentStepper.FUNCTION_GET_MAX_VELOCITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickSilentStepper.FUNCTION_GET_CURRENT_VELOCITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickSilentStepper.FUNCTION_SET_SPEED_RAMPING] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickSilentStepper.FUNCTION_GET_SPEED_RAMPING] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickSilentStepper.FUNCTION_FULL_BRAKE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickSilentStepper.FUNCTION_SET_CURRENT_POSITION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickSilentStepper.FUNCTION_GET_CURRENT_POSITION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickSilentStepper.FUNCTION_SET_TARGET_POSITION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickSilentStepper.FUNCTION_GET_TARGET_POSITION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickSilentStepper.FUNCTION_SET_STEPS] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickSilentStepper.FUNCTION_GET_STEPS] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickSilentStepper.FUNCTION_GET_REMAINING_STEPS] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickSilentStepper.FUNCTION_SET_STEP_CONFIGURATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickSilentStepper.FUNCTION_GET_STEP_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickSilentStepper.FUNCTION_DRIVE_FORWARD] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickSilentStepper.FUNCTION_DRIVE_BACKWARD] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickSilentStepper.FUNCTION_STOP] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickSilentStepper.FUNCTION_GET_STACK_INPUT_VOLTAGE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickSilentStepper.FUNCTION_GET_EXTERNAL_INPUT_VOLTAGE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickSilentStepper.FUNCTION_SET_MOTOR_CURRENT] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickSilentStepper.FUNCTION_GET_MOTOR_CURRENT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickSilentStepper.FUNCTION_ENABLE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickSilentStepper.FUNCTION_DISABLE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickSilentStepper.FUNCTION_IS_ENABLED] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickSilentStepper.FUNCTION_SET_BASIC_CONFIGURATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickSilentStepper.FUNCTION_GET_BASIC_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickSilentStepper.FUNCTION_SET_SPREADCYCLE_CONFIGURATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickSilentStepper.FUNCTION_GET_SPREADCYCLE_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickSilentStepper.FUNCTION_SET_STEALTH_CONFIGURATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickSilentStepper.FUNCTION_GET_STEALTH_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickSilentStepper.FUNCTION_SET_COOLSTEP_CONFIGURATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickSilentStepper.FUNCTION_GET_COOLSTEP_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickSilentStepper.FUNCTION_SET_MISC_CONFIGURATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickSilentStepper.FUNCTION_GET_MISC_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickSilentStepper.FUNCTION_GET_DRIVER_STATUS] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickSilentStepper.FUNCTION_SET_MINIMUM_VOLTAGE] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickSilentStepper.FUNCTION_GET_MINIMUM_VOLTAGE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickSilentStepper.FUNCTION_SET_TIME_BASE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickSilentStepper.FUNCTION_GET_TIME_BASE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickSilentStepper.FUNCTION_GET_ALL_DATA] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickSilentStepper.FUNCTION_SET_ALL_DATA_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickSilentStepper.FUNCTION_GET_ALL_DATA_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickSilentStepper.FUNCTION_SET_SPITFP_BAUDRATE_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickSilentStepper.FUNCTION_GET_SPITFP_BAUDRATE_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickSilentStepper.FUNCTION_GET_SEND_TIMEOUT_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickSilentStepper.FUNCTION_SET_SPITFP_BAUDRATE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickSilentStepper.FUNCTION_GET_SPITFP_BAUDRATE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickSilentStepper.FUNCTION_GET_SPITFP_ERROR_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickSilentStepper.FUNCTION_ENABLE_STATUS_LED] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickSilentStepper.FUNCTION_DISABLE_STATUS_LED] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickSilentStepper.FUNCTION_IS_STATUS_LED_ENABLED] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickSilentStepper.FUNCTION_GET_PROTOCOL1_BRICKLET_NAME] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickSilentStepper.FUNCTION_GET_CHIP_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickSilentStepper.FUNCTION_RESET] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickSilentStepper.FUNCTION_WRITE_BRICKLET_PLUGIN] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickSilentStepper.FUNCTION_READ_BRICKLET_PLUGIN] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickSilentStepper.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickSilentStepper.CALLBACK_UNDER_VOLTAGE] = [10, 'H'];
	this.callbackFormats[BrickSilentStepper.CALLBACK_POSITION_REACHED] = [12, 'i'];
	this.callbackFormats[BrickSilentStepper.CALLBACK_ALL_DATA] = [24, 'H i i H H H'];
	this.callbackFormats[BrickSilentStepper.CALLBACK_NEW_STATE] = [10, 'B B'];



	this.setMaxVelocity = function(velocity, returnCallback, errorCallback) {
		/*
		Sets the maximum velocity of the stepper motor.
		This function does *not* start the motor, it merely sets the maximum
		velocity the stepper motor is accelerated to. To get the motor running use
		either :func:`Set Target Position`, :func:`Set Steps`, :func:`Drive Forward` or
		:func:`Drive Backward`.
		*/
		this.ipcon.sendRequest(this, BrickSilentStepper.FUNCTION_SET_MAX_VELOCITY, [velocity], 'H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getMaxVelocity = function(returnCallback, errorCallback) {
		/*
		Returns the velocity as set by :func:`Set Max Velocity`.
		*/
		this.ipcon.sendRequest(this, BrickSilentStepper.FUNCTION_GET_MAX_VELOCITY, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.getCurrentVelocity = function(returnCallback, errorCallback) {
		/*
		Returns the *current* velocity of the stepper motor.
		*/
		this.ipcon.sendRequest(this, BrickSilentStepper.FUNCTION_GET_CURRENT_VELOCITY, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.setSpeedRamping = function(acceleration, deacceleration, returnCallback, errorCallback) {
		/*
		Sets the acceleration and deacceleration of the stepper motor.
		An acceleration of 1000 means, that
		every second the velocity is increased by 1000 *steps/s*.
		
		For example: If the current velocity is 0 and you want to accelerate to a
		velocity of 8000 *steps/s* in 10 seconds, you should set an acceleration
		of 800 *steps/s²*.
		
		An acceleration/deacceleration of 0 means instantaneous
		acceleration/deacceleration (not recommended)
		*/
		this.ipcon.sendRequest(this, BrickSilentStepper.FUNCTION_SET_SPEED_RAMPING, [acceleration, deacceleration], 'H H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getSpeedRamping = function(returnCallback, errorCallback) {
		/*
		Returns the acceleration and deacceleration as set by
		:func:`Set Speed Ramping`.
		*/
		this.ipcon.sendRequest(this, BrickSilentStepper.FUNCTION_GET_SPEED_RAMPING, [], '', 12, 'H H', returnCallback, errorCallback, false, true);
	};
	this.fullBrake = function(returnCallback, errorCallback) {
		/*
		Executes an active full brake.
		
		.. warning::
		 This function is for emergency purposes,
		 where an immediate brake is necessary. Depending on the current velocity and
		 the strength of the motor, a full brake can be quite violent.
		
		Call :func:`Stop` if you just want to stop the motor.
		*/
		this.ipcon.sendRequest(this, BrickSilentStepper.FUNCTION_FULL_BRAKE, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.setCurrentPosition = function(position, returnCallback, errorCallback) {
		/*
		Sets the current steps of the internal step counter. This can be used to
		set the current position to 0 when some kind of starting position
		is reached (e.g. when a CNC machine reaches a corner).
		*/
		this.ipcon.sendRequest(this, BrickSilentStepper.FUNCTION_SET_CURRENT_POSITION, [position], 'i', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getCurrentPosition = function(returnCallback, errorCallback) {
		/*
		Returns the current position of the stepper motor in steps. On startup
		the position is 0. The steps are counted with all possible driving
		functions (:func:`Set Target Position`, :func:`Set Steps`, :func:`Drive Forward` or
		:func:`Drive Backward`). It also is possible to reset the steps to 0 or
		set them to any other desired value with :func:`Set Current Position`.
		*/
		this.ipcon.sendRequest(this, BrickSilentStepper.FUNCTION_GET_CURRENT_POSITION, [], '', 12, 'i', returnCallback, errorCallback, false, true);
	};
	this.setTargetPosition = function(position, returnCallback, errorCallback) {
		/*
		Sets the target position of the stepper motor in steps. For example,
		if the current position of the motor is 500 and :func:`Set Target Position` is
		called with 1000, the stepper motor will drive 500 steps forward. It will
		use the velocity, acceleration and deacceleration as set by
		:func:`Set Max Velocity` and :func:`Set Speed Ramping`.
		
		A call of :func:`Set Target Position` with the parameter *x* is equivalent to
		a call of :func:`Set Steps` with the parameter
		(*x* - :func:`Get Current Position`).
		*/
		this.ipcon.sendRequest(this, BrickSilentStepper.FUNCTION_SET_TARGET_POSITION, [position], 'i', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getTargetPosition = function(returnCallback, errorCallback) {
		/*
		Returns the last target position as set by :func:`Set Target Position`.
		*/
		this.ipcon.sendRequest(this, BrickSilentStepper.FUNCTION_GET_TARGET_POSITION, [], '', 12, 'i', returnCallback, errorCallback, false, true);
	};
	this.setSteps = function(steps, returnCallback, errorCallback) {
		/*
		Sets the number of steps the stepper motor should run. Positive values
		will drive the motor forward and negative values backward.
		The velocity, acceleration and deacceleration as set by
		:func:`Set Max Velocity` and :func:`Set Speed Ramping` will be used.
		*/
		this.ipcon.sendRequest(this, BrickSilentStepper.FUNCTION_SET_STEPS, [steps], 'i', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getSteps = function(returnCallback, errorCallback) {
		/*
		Returns the last steps as set by :func:`Set Steps`.
		*/
		this.ipcon.sendRequest(this, BrickSilentStepper.FUNCTION_GET_STEPS, [], '', 12, 'i', returnCallback, errorCallback, false, true);
	};
	this.getRemainingSteps = function(returnCallback, errorCallback) {
		/*
		Returns the remaining steps of the last call of :func:`Set Steps`.
		For example, if :func:`Set Steps` is called with 2000 and
		:func:`Get Remaining Steps` is called after the motor has run for 500 steps,
		it will return 1500.
		*/
		this.ipcon.sendRequest(this, BrickSilentStepper.FUNCTION_GET_REMAINING_STEPS, [], '', 12, 'i', returnCallback, errorCallback, false, true);
	};
	this.setStepConfiguration = function(stepResolution, interpolation, returnCallback, errorCallback) {
		/*
		Sets the step resolution from full-step up to 1/256-step.
		
		If interpolation is turned on, the Silent Stepper Brick will always interpolate
		your step inputs as 1/256-step. If you use full-step mode with interpolation, each
		step will generate 256 1/256 steps.
		
		For maximum torque use full-step without interpolation. For maximum resolution use
		1/256-step. Turn interpolation on to make the Stepper driving less noisy.
		
		If you often change the speed with high acceleration you should turn the
		interpolation off.
		*/
		this.ipcon.sendRequest(this, BrickSilentStepper.FUNCTION_SET_STEP_CONFIGURATION, [stepResolution, interpolation], 'B ?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getStepConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the step mode as set by :func:`Set Step Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickSilentStepper.FUNCTION_GET_STEP_CONFIGURATION, [], '', 10, 'B ?', returnCallback, errorCallback, false, true);
	};
	this.driveForward = function(returnCallback, errorCallback) {
		/*
		Drives the stepper motor forward until :func:`Drive Backward` or
		:func:`Stop` is called. The velocity, acceleration and deacceleration as
		set by :func:`Set Max Velocity` and :func:`Set Speed Ramping` will be used.
		*/
		this.ipcon.sendRequest(this, BrickSilentStepper.FUNCTION_DRIVE_FORWARD, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.driveBackward = function(returnCallback, errorCallback) {
		/*
		Drives the stepper motor backward until :func:`Drive Forward` or
		:func:`Stop` is triggered. The velocity, acceleration and deacceleration as
		set by :func:`Set Max Velocity` and :func:`Set Speed Ramping` will be used.
		*/
		this.ipcon.sendRequest(this, BrickSilentStepper.FUNCTION_DRIVE_BACKWARD, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.stop = function(returnCallback, errorCallback) {
		/*
		Stops the stepper motor with the deacceleration as set by
		:func:`Set Speed Ramping`.
		*/
		this.ipcon.sendRequest(this, BrickSilentStepper.FUNCTION_STOP, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getStackInputVoltage = function(returnCallback, errorCallback) {
		/*
		Returns the stack input voltage. The stack input voltage is the
		voltage that is supplied via the stack, i.e. it is given by a
		Step-Down or Step-Up Power Supply.
		*/
		this.ipcon.sendRequest(this, BrickSilentStepper.FUNCTION_GET_STACK_INPUT_VOLTAGE, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.getExternalInputVoltage = function(returnCallback, errorCallback) {
		/*
		Returns the external input voltage. The external input voltage is
		given via the black power input connector on the Silent Stepper Brick.
		
		If there is an external input voltage and a stack input voltage, the motor
		will be driven by the external input voltage. If there is only a stack
		voltage present, the motor will be driven by this voltage.
		
		.. warning::
		 This means, if you have a high stack voltage and a low external voltage,
		 the motor will be driven with the low external voltage. If you then remove
		 the external connection, it will immediately be driven by the high
		 stack voltage
		*/
		this.ipcon.sendRequest(this, BrickSilentStepper.FUNCTION_GET_EXTERNAL_INPUT_VOLTAGE, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.setMotorCurrent = function(current, returnCallback, errorCallback) {
		/*
		Sets the current with which the motor will be driven.
		
		.. warning::
		 Do not set this value above the specifications of your stepper motor.
		 Otherwise it may damage your motor.
		*/
		this.ipcon.sendRequest(this, BrickSilentStepper.FUNCTION_SET_MOTOR_CURRENT, [current], 'H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getMotorCurrent = function(returnCallback, errorCallback) {
		/*
		Returns the current as set by :func:`Set Motor Current`.
		*/
		this.ipcon.sendRequest(this, BrickSilentStepper.FUNCTION_GET_MOTOR_CURRENT, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.enable = function(returnCallback, errorCallback) {
		/*
		Enables the driver chip. The driver parameters can be configured (maximum velocity,
		acceleration, etc) before it is enabled.
		*/
		this.ipcon.sendRequest(this, BrickSilentStepper.FUNCTION_ENABLE, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.disable = function(returnCallback, errorCallback) {
		/*
		Disables the driver chip. The configurations are kept (maximum velocity,
		acceleration, etc) but the motor is not driven until it is enabled again.
		
		.. warning::
		 Disabling the driver chip while the motor is still turning can damage the
		 driver chip. The motor should be stopped calling :func:`Stop` function
		 before disabling the motor power. The :func:`Stop` function will **not**
		 wait until the motor is actually stopped. You have to explicitly wait for the
		 appropriate time after calling the :func:`Stop` function before calling
		 the :func:`Disable` function.
		*/
		this.ipcon.sendRequest(this, BrickSilentStepper.FUNCTION_DISABLE, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.isEnabled = function(returnCallback, errorCallback) {
		/*
		Returns *true* if the driver chip is enabled, *false* otherwise.
		*/
		this.ipcon.sendRequest(this, BrickSilentStepper.FUNCTION_IS_ENABLED, [], '', 9, '?', returnCallback, errorCallback, false, true);
	};
	this.setBasicConfiguration = function(standstillCurrent, motorRunCurrent, standstillDelayTime, powerDownTime, stealthThreshold, coolstepThreshold, classicThreshold, highVelocityChopperMode, returnCallback, errorCallback) {
		/*
		Sets the basic configuration parameters for the different modes (Stealth, Coolstep, Classic).
		
		* Standstill Current: This value can be used to lower the current during stand still. This might
		  be reasonable to reduce the heating of the motor and the Brick. When the motor is in standstill
		  the configured motor phase current will be driven until the configured
		  Power Down Time is elapsed. After that the phase current will be reduced to the standstill
		  current. The elapsed time for this reduction can be configured with the Standstill Delay Time.
		  The maximum allowed value is the configured maximum motor current
		  (see :func:`Set Motor Current`).
		
		* Motor Run Current: The value sets the motor current when the motor is running.
		  Use a value of at least one half of the global maximum motor current for a good
		  microstep performance. The maximum allowed value is the current
		  motor current. The API maps the entered value to 1/32 ... 32/32 of the maximum
		  motor current. This value should be used to change the motor current during motor movement,
		  whereas the global maximum motor current should not be changed while the motor is moving
		  (see :func:`Set Motor Current`).
		
		* Standstill Delay Time: Controls the duration for motor power down after a motion
		  as soon as standstill is detected and the Power Down Time is expired. A high Standstill Delay
		  Time results in a smooth transition that avoids motor jerk during power down.
		
		* Power Down Time: Sets the delay time after a stand still.
		
		* Stealth Threshold: Sets the upper threshold for Stealth mode.
		  If the velocity of the motor goes above this value, Stealth mode is turned
		  off. Otherwise it is turned on. In Stealth mode the torque declines with high speed.
		
		* Coolstep Threshold: Sets the lower threshold for Coolstep mode.
		  The Coolstep Threshold needs to be above the Stealth Threshold.
		
		* Classic Threshold: Sets the lower threshold for classic mode.
		  In classic mode the stepper becomes more noisy, but the torque is maximized.
		
		* High Velocity Chopper Mode: If High Velocity Chopper Mode is enabled, the stepper control
		  is optimized to run the stepper motors at high velocities.
		
		If you want to use all three thresholds make sure that
		Stealth Threshold < Coolstep Threshold < Classic Threshold.
		*/
		this.ipcon.sendRequest(this, BrickSilentStepper.FUNCTION_SET_BASIC_CONFIGURATION, [standstillCurrent, motorRunCurrent, standstillDelayTime, powerDownTime, stealthThreshold, coolstepThreshold, classicThreshold, highVelocityChopperMode], 'H H H H H H H ?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getBasicConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Basic Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickSilentStepper.FUNCTION_GET_BASIC_CONFIGURATION, [], '', 23, 'H H H H H H H ?', returnCallback, errorCallback, false, true);
	};
	this.setSpreadcycleConfiguration = function(slowDecayDuration, enableRandomSlowDecay, fastDecayDuration, hysteresisStartValue, hysteresisEndValue, sineWaveOffset, chopperMode, comparatorBlankTime, fastDecayWithoutComparator, returnCallback, errorCallback) {
		/*
		Note: If you don't know what any of this means you can very likely keep all of
		the values as default!
		
		Sets the Spreadcycle configuration parameters. Spreadcycle is a chopper algorithm which actively
		controls the motor current flow. More information can be found in the TMC2130 datasheet on page
		47 (7 spreadCycle and Classic Chopper).
		
		* Slow Decay Duration: Controls duration of off time setting of slow decay phase.
		  0 = driver disabled, all bridges off. Use 1 only with Comparator Blank time >= 2.
		
		* Enable Random Slow Decay: Set to false to fix chopper off time as set by Slow Decay Duration.
		  If you set it to true, Decay Duration is randomly modulated.
		
		* Fast Decay Duration: Sets the fast decay duration. This parameters is
		  only used if the Chopper Mode is set to Fast Decay.
		
		* Hysteresis Start Value: Sets the hysteresis start value. This parameter is
		  only used if the Chopper Mode is set to Spread Cycle.
		
		* Hysteresis End Value: Sets the hysteresis end value. This parameter is
		  only used if the Chopper Mode is set to Spread Cycle.
		
		* Sine Wave Offset: Sets the sine wave offset. This parameters is
		  only used if the Chopper Mode is set to Fast Decay. 1/512 of the value becomes added to the absolute
		  value of the sine wave.
		
		* Chopper Mode: 0 = Spread Cycle, 1 = Fast Decay.
		
		* Comparator Blank Time: Sets the blank time of the comparator. Available values are
		
		  * 0 = 16 clocks,
		  * 1 = 24 clocks,
		  * 2 = 36 clocks and
		  * 3 = 54 clocks.
		
		  A value of 1 or 2 is recommended for most applications.
		
		* Fast Decay Without Comparator: If set to true the current comparator usage for termination of the
		  fast decay cycle is disabled.
		*/
		this.ipcon.sendRequest(this, BrickSilentStepper.FUNCTION_SET_SPREADCYCLE_CONFIGURATION, [slowDecayDuration, enableRandomSlowDecay, fastDecayDuration, hysteresisStartValue, hysteresisEndValue, sineWaveOffset, chopperMode, comparatorBlankTime, fastDecayWithoutComparator], 'B ? B B b b B B ?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getSpreadcycleConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Basic Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickSilentStepper.FUNCTION_GET_SPREADCYCLE_CONFIGURATION, [], '', 17, 'B ? B B b b B B ?', returnCallback, errorCallback, false, true);
	};
	this.setStealthConfiguration = function(enableStealth, amplitude, gradient, enableAutoscale, forceSymmetric, freewheelMode, returnCallback, errorCallback) {
		/*
		Note: If you don't know what any of this means you can very likely keep all of
		the values as default!
		
		Sets the configuration relevant for Stealth mode.
		
		* Enable Stealth: If set to true the stealth mode is enabled, if set to false the
		  stealth mode is disabled, even if the speed is below the threshold set in :func:`Set Basic Configuration`.
		
		* Amplitude: If autoscale is disabled, the PWM amplitude is scaled by this value. If autoscale is enabled,
		  this value defines the maximum PWM amplitude change per half wave.
		
		* Gradient: If autoscale is disabled, the PWM gradient is scaled by this value. If autoscale is enabled,
		  this value defines the maximum PWM gradient. With autoscale a value above 64 is recommended,
		  otherwise the regulation might not be able to measure the current.
		
		* Enable Autoscale: If set to true, automatic current control is used. Otherwise the user defined
		  amplitude and gradient are used.
		
		* Force Symmetric: If true, A symmetric PWM cycle is enforced. Otherwise the PWM value may change within each
		  PWM cycle.
		
		* Freewheel Mode: The freewheel mode defines the behavior in stand still if the Standstill Current
		  (see :func:`Set Basic Configuration`) is set to 0.
		*/
		this.ipcon.sendRequest(this, BrickSilentStepper.FUNCTION_SET_STEALTH_CONFIGURATION, [enableStealth, amplitude, gradient, enableAutoscale, forceSymmetric, freewheelMode], '? B B ? ? B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getStealthConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Stealth Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickSilentStepper.FUNCTION_GET_STEALTH_CONFIGURATION, [], '', 14, '? B B ? ? B', returnCallback, errorCallback, false, true);
	};
	this.setCoolstepConfiguration = function(minimumStallguardValue, maximumStallguardValue, currentUpStepWidth, currentDownStepWidth, minimumCurrent, stallguardThresholdValue, stallguardMode, returnCallback, errorCallback) {
		/*
		Note: If you don't know what any of this means you can very likely keep all of
		the values as default!
		
		Sets the configuration relevant for Coolstep.
		
		* Minimum Stallguard Value: If the Stallguard result falls below this value*32, the motor current
		  is increased to reduce motor load angle. A value of 0 turns Coolstep off.
		
		* Maximum Stallguard Value: If the Stallguard result goes above
		  (Min Stallguard Value + Max Stallguard Value + 1) * 32, the motor current is decreased to save
		  energy.
		
		* Current Up Step Width: Sets the up step increment per Stallguard value. The value range is 0-3,
		  corresponding to the increments 1, 2, 4 and 8.
		
		* Current Down Step Width: Sets the down step decrement per Stallguard value. The value range is 0-3,
		  corresponding to the decrements 1, 2, 8 and 16.
		
		* Minimum Current: Sets the minimum current for Coolstep current control. You can choose between
		  half and quarter of the run current.
		
		* Stallguard Threshold Value: Sets the level for stall output (see :func:`Get Driver Status`).
		  A lower value gives a higher sensitivity. You have to find a suitable value for your
		  motor by trial and error, 0 works for most motors.
		
		* Stallguard Mode: Set to 0 for standard resolution or 1 for filtered mode. In filtered mode the Stallguard
		  signal will be updated every four full-steps.
		*/
		this.ipcon.sendRequest(this, BrickSilentStepper.FUNCTION_SET_COOLSTEP_CONFIGURATION, [minimumStallguardValue, maximumStallguardValue, currentUpStepWidth, currentDownStepWidth, minimumCurrent, stallguardThresholdValue, stallguardMode], 'B B B B B b B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getCoolstepConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Coolstep Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickSilentStepper.FUNCTION_GET_COOLSTEP_CONFIGURATION, [], '', 15, 'B B B B B b B', returnCallback, errorCallback, false, true);
	};
	this.setMiscConfiguration = function(disableShortToGroundProtection, synchronizePhaseFrequency, returnCallback, errorCallback) {
		/*
		Note: If you don't know what any of this means you can very likely keep all of
		the values as default!
		
		Sets miscellaneous configuration parameters.
		
		* Disable Short To Ground Protection: Set to false to enable short to ground protection, otherwise
		  it is disabled.
		
		* Synchronize Phase Frequency: With this parameter you can synchronize the chopper for both phases
		  of a two phase motor to avoid the occurrence of a beat. The value range is 0-15. If set to 0,
		  the synchronization is turned off. Otherwise the synchronization is done through the formula
		  f_sync = f_clk/(value*64). In Classic Mode the synchronization is automatically switched off.
		  f_clk is 12.8MHz.
		*/
		this.ipcon.sendRequest(this, BrickSilentStepper.FUNCTION_SET_MISC_CONFIGURATION, [disableShortToGroundProtection, synchronizePhaseFrequency], '? B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getMiscConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Misc Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickSilentStepper.FUNCTION_GET_MISC_CONFIGURATION, [], '', 10, '? B', returnCallback, errorCallback, false, true);
	};
	this.getDriverStatus = function(returnCallback, errorCallback) {
		/*
		Returns the current driver status.
		
		* Open Load: Indicates if an open load is present on phase A, B or both. This could mean that there is a problem
		  with the wiring of the motor. False detection can occur in fast motion as well as during stand still.
		
		* Short To Ground: Indicates if a short to ground is present on phase A, B or both. If this is detected the driver
		  automatically becomes disabled and stays disabled until it is enabled again manually.
		
		* Over Temperature: The over temperature indicator switches to "Warning" if the driver IC warms up. The warning flag
		  is expected during long duration stepper uses. If the temperature limit is reached the indicator switches
		  to "Limit". In this case the driver becomes disabled until it cools down again.
		
		* Motor Stalled: Is true if a motor stall was detected.
		
		* Actual Motor Current: Indicates the actual current control scaling as used in Coolstep mode.
		  It represents a multiplier of 1/32 to 32/32 of the
		  ``Motor Run Current`` as set by :func:`Set Basic Configuration`. Example: If a ``Motor Run Current``
		  of 1000mA was set and the returned value is 15, the ``Actual Motor Current`` is 16/32*1000mA = 500mA.
		
		* Stallguard Result: Indicates the load of the motor. A lower value signals a higher load. Per trial and error
		  you can find out which value corresponds to a suitable torque for the velocity used in your application.
		  After that you can use this threshold value to find out if a motor stall becomes probable and react on it (e.g.
		  decrease velocity).
		  During stand still this value can not be used for stall detection, it shows the chopper on-time for motor coil A.
		
		* Stealth Voltage Amplitude: Shows the actual PWM scaling. In Stealth mode it can be used to detect motor load and
		  stall if autoscale is enabled (see :func:`Set Stealth Configuration`).
		*/
		this.ipcon.sendRequest(this, BrickSilentStepper.FUNCTION_GET_DRIVER_STATUS, [], '', 16, 'B B B ? B ? B B', returnCallback, errorCallback, false, true);
	};
	this.setMinimumVoltage = function(voltage, returnCallback, errorCallback) {
		/*
		Sets the minimum voltage, below which the :cb:`Under Voltage` callback
		is triggered. The minimum possible value that works with the Silent Stepper
		Brick is 8V.
		You can use this function to detect the discharge of a battery that is used
		to drive the stepper motor. If you have a fixed power supply, you likely do
		not need this functionality.
		*/
		this.ipcon.sendRequest(this, BrickSilentStepper.FUNCTION_SET_MINIMUM_VOLTAGE, [voltage], 'H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getMinimumVoltage = function(returnCallback, errorCallback) {
		/*
		Returns the minimum voltage as set by :func:`Set Minimum Voltage`.
		*/
		this.ipcon.sendRequest(this, BrickSilentStepper.FUNCTION_GET_MINIMUM_VOLTAGE, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.setTimeBase = function(timeBase, returnCallback, errorCallback) {
		/*
		Sets the time base of the velocity and the acceleration of the Silent Stepper
		Brick.
		
		For example, if you want to make one step every 1.5 seconds, you can set
		the time base to 15 and the velocity to 10. Now the velocity is
		10steps/15s = 1steps/1.5s.
		*/
		this.ipcon.sendRequest(this, BrickSilentStepper.FUNCTION_SET_TIME_BASE, [timeBase], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getTimeBase = function(returnCallback, errorCallback) {
		/*
		Returns the time base as set by :func:`Set Time Base`.
		*/
		this.ipcon.sendRequest(this, BrickSilentStepper.FUNCTION_GET_TIME_BASE, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getAllData = function(returnCallback, errorCallback) {
		/*
		Returns the following parameters: The current velocity,
		the current position, the remaining steps, the stack voltage, the external
		voltage and the current consumption of the stepper motor.
		
		The current consumption is calculated by multiplying the ``Actual Motor Current``
		value (see :func:`Set Basic Configuration`) with the ``Motor Run Current``
		(see :func:`Get Driver Status`). This is an internal calculation of the
		driver, not an independent external measurement.
		
		The current consumption calculation was broken up to firmware 2.0.1, it is fixed
		since firmware 2.0.2.
		
		There is also a callback for this function, see :cb:`All Data` callback.
		*/
		this.ipcon.sendRequest(this, BrickSilentStepper.FUNCTION_GET_ALL_DATA, [], '', 24, 'H i i H H H', returnCallback, errorCallback, false, true);
	};
	this.setAllDataPeriod = function(period, returnCallback, errorCallback) {
		/*
		Sets the period with which the :cb:`All Data` callback is triggered
		periodically. A value of 0 turns the callback off.
		*/
		this.ipcon.sendRequest(this, BrickSilentStepper.FUNCTION_SET_ALL_DATA_PERIOD, [period], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getAllDataPeriod = function(returnCallback, errorCallback) {
		/*
		Returns the period as set by :func:`Set All Data Period`.
		*/
		this.ipcon.sendRequest(this, BrickSilentStepper.FUNCTION_GET_ALL_DATA_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setSPITFPBaudrateConfig = function(enableDynamicBaudrate, minimumDynamicBaudrate, returnCallback, errorCallback) {
		/*
		The SPITF protocol can be used with a dynamic baudrate. If the dynamic baudrate is
		enabled, the Brick will try to adapt the baudrate for the communication
		between Bricks and Bricklets according to the amount of data that is transferred.
		
		The baudrate will be increased exponentially if lots of data is sent/received and
		decreased linearly if little data is sent/received.
		
		This lowers the baudrate in applications where little data is transferred (e.g.
		a weather station) and increases the robustness. If there is lots of data to transfer
		(e.g. Thermal Imaging Bricklet) it automatically increases the baudrate as needed.
		
		In cases where some data has to transferred as fast as possible every few seconds
		(e.g. RS485 Bricklet with a high baudrate but small payload) you may want to turn
		the dynamic baudrate off to get the highest possible performance.
		
		The maximum value of the baudrate can be set per port with the function
		:func:`Set SPITFP Baudrate`. If the dynamic baudrate is disabled, the baudrate
		as set by :func:`Set SPITFP Baudrate` will be used statically.
		
		.. versionadded:: 2.0.4$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickSilentStepper.FUNCTION_SET_SPITFP_BAUDRATE_CONFIG, [enableDynamicBaudrate, minimumDynamicBaudrate], '? I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPBaudrateConfig = function(returnCallback, errorCallback) {
		/*
		Returns the baudrate config, see :func:`Set SPITFP Baudrate Config`.
		
		.. versionadded:: 2.0.4$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickSilentStepper.FUNCTION_GET_SPITFP_BAUDRATE_CONFIG, [], '', 13, '? I', returnCallback, errorCallback, false, true);
	};
	this.getSendTimeoutCount = function(communicationMethod, returnCallback, errorCallback) {
		/*
		Returns the timeout count for the different communication methods.
		
		The methods 0-2 are available for all Bricks, 3-7 only for Master Bricks.
		
		This function is mostly used for debugging during development, in normal operation
		the counters should nearly always stay at 0.
		*/
		this.ipcon.sendRequest(this, BrickSilentStepper.FUNCTION_GET_SEND_TIMEOUT_COUNT, [communicationMethod], 'B', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setSPITFPBaudrate = function(brickletPort, baudrate, returnCallback, errorCallback) {
		/*
		Sets the baudrate for a specific Bricklet port.
		
		If you want to increase the throughput of Bricklets you can increase
		the baudrate. If you get a high error count because of high
		interference (see :func:`Get SPITFP Error Count`) you can decrease the
		baudrate.
		
		If the dynamic baudrate feature is enabled, the baudrate set by this
		function corresponds to the maximum baudrate (see :func:`Set SPITFP Baudrate Config`).
		
		Regulatory testing is done with the default baudrate. If CE compatibility
		or similar is necessary in your applications we recommend to not change
		the baudrate.
		*/
		this.ipcon.sendRequest(this, BrickSilentStepper.FUNCTION_SET_SPITFP_BAUDRATE, [brickletPort, baudrate], 'c I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPBaudrate = function(brickletPort, returnCallback, errorCallback) {
		/*
		Returns the baudrate for a given Bricklet port, see :func:`Set SPITFP Baudrate`.
		*/
		this.ipcon.sendRequest(this, BrickSilentStepper.FUNCTION_GET_SPITFP_BAUDRATE, [brickletPort], 'c', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPErrorCount = function(brickletPort, returnCallback, errorCallback) {
		/*
		Returns the error count for the communication between Brick and Bricklet.
		
		The errors are divided into
		
		* ACK checksum errors,
		* message checksum errors,
		* framing errors and
		* overflow errors.
		
		The errors counts are for errors that occur on the Brick side. All
		Bricklets have a similar function that returns the errors on the Bricklet side.
		*/
		this.ipcon.sendRequest(this, BrickSilentStepper.FUNCTION_GET_SPITFP_ERROR_COUNT, [brickletPort], 'c', 24, 'I I I I', returnCallback, errorCallback, false, true);
	};
	this.enableStatusLED = function(returnCallback, errorCallback) {
		/*
		Enables the status LED.
		
		The status LED is the blue LED next to the USB connector. If enabled is is
		on and it flickers if data is transfered. If disabled it is always off.
		
		The default state is enabled.
		*/
		this.ipcon.sendRequest(this, BrickSilentStepper.FUNCTION_ENABLE_STATUS_LED, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.disableStatusLED = function(returnCallback, errorCallback) {
		/*
		Disables the status LED.
		
		The status LED is the blue LED next to the USB connector. If enabled is is
		on and it flickers if data is transfered. If disabled it is always off.
		
		The default state is enabled.
		*/
		this.ipcon.sendRequest(this, BrickSilentStepper.FUNCTION_DISABLE_STATUS_LED, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.isStatusLEDEnabled = function(returnCallback, errorCallback) {
		/*
		Returns *true* if the status LED is enabled, *false* otherwise.
		*/
		this.ipcon.sendRequest(this, BrickSilentStepper.FUNCTION_IS_STATUS_LED_ENABLED, [], '', 9, '?', returnCallback, errorCallback, false, true);
	};
	this.getProtocol1BrickletName = function(port, returnCallback, errorCallback) {
		/*
		Returns the firmware and protocol version and the name of the Bricklet for a
		given port.
		
		This functions sole purpose is to allow automatic flashing of v1.x.y Bricklet
		plugins.
		*/
		this.ipcon.sendRequest(this, BrickSilentStepper.FUNCTION_GET_PROTOCOL1_BRICKLET_NAME, [port], 'c', 52, 'B B3 s40', returnCallback, errorCallback, false, true);
	};
	this.getChipTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature as measured inside the microcontroller. The
		value returned is not the ambient temperature!
		
		The temperature is only proportional to the real temperature and it has an
		accuracy of ±15%. Practically it is only useful as an indicator for
		temperature changes.
		*/
		this.ipcon.sendRequest(this, BrickSilentStepper.FUNCTION_GET_CHIP_TEMPERATURE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.reset = function(returnCallback, errorCallback) {
		/*
		Calling this function will reset the Brick. Calling this function
		on a Brick inside of a stack will reset the whole stack.
		
		After a reset you have to create new device objects,
		calling functions on the existing ones will result in
		undefined behavior!
		*/
		this.ipcon.sendRequest(this, BrickSilentStepper.FUNCTION_RESET, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeBrickletPlugin = function(port, offset, chunk, returnCallback, errorCallback) {
		/*
		Writes 32 bytes of firmware to the bricklet attached at the given port.
		The bytes are written to the position offset * 32.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickSilentStepper.FUNCTION_WRITE_BRICKLET_PLUGIN, [port, offset, chunk], 'c B B32', 0, '', returnCallback, errorCallback, false, true);
	};
	this.readBrickletPlugin = function(port, offset, returnCallback, errorCallback) {
		/*
		Reads 32 bytes of firmware from the bricklet attached at the given port.
		The bytes are read starting at the position offset * 32.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickSilentStepper.FUNCTION_READ_BRICKLET_PLUGIN, [port, offset], 'c B', 40, 'B32', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Brick is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position is the position in the stack from '0' (bottom) to '8' (top).
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickSilentStepper.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickSilentStepper;

},{"./Device":279,"./IPConnection":280}],146:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickStepper.DEVICE_IDENTIFIER = 15;
BrickStepper.DEVICE_DISPLAY_NAME = 'Stepper Brick';
BrickStepper.CALLBACK_UNDER_VOLTAGE = 31;
BrickStepper.CALLBACK_POSITION_REACHED = 32;
BrickStepper.CALLBACK_ALL_DATA = 40;
BrickStepper.CALLBACK_NEW_STATE = 41;
BrickStepper.FUNCTION_SET_MAX_VELOCITY = 1;
BrickStepper.FUNCTION_GET_MAX_VELOCITY = 2;
BrickStepper.FUNCTION_GET_CURRENT_VELOCITY = 3;
BrickStepper.FUNCTION_SET_SPEED_RAMPING = 4;
BrickStepper.FUNCTION_GET_SPEED_RAMPING = 5;
BrickStepper.FUNCTION_FULL_BRAKE = 6;
BrickStepper.FUNCTION_SET_CURRENT_POSITION = 7;
BrickStepper.FUNCTION_GET_CURRENT_POSITION = 8;
BrickStepper.FUNCTION_SET_TARGET_POSITION = 9;
BrickStepper.FUNCTION_GET_TARGET_POSITION = 10;
BrickStepper.FUNCTION_SET_STEPS = 11;
BrickStepper.FUNCTION_GET_STEPS = 12;
BrickStepper.FUNCTION_GET_REMAINING_STEPS = 13;
BrickStepper.FUNCTION_SET_STEP_MODE = 14;
BrickStepper.FUNCTION_GET_STEP_MODE = 15;
BrickStepper.FUNCTION_DRIVE_FORWARD = 16;
BrickStepper.FUNCTION_DRIVE_BACKWARD = 17;
BrickStepper.FUNCTION_STOP = 18;
BrickStepper.FUNCTION_GET_STACK_INPUT_VOLTAGE = 19;
BrickStepper.FUNCTION_GET_EXTERNAL_INPUT_VOLTAGE = 20;
BrickStepper.FUNCTION_GET_CURRENT_CONSUMPTION = 21;
BrickStepper.FUNCTION_SET_MOTOR_CURRENT = 22;
BrickStepper.FUNCTION_GET_MOTOR_CURRENT = 23;
BrickStepper.FUNCTION_ENABLE = 24;
BrickStepper.FUNCTION_DISABLE = 25;
BrickStepper.FUNCTION_IS_ENABLED = 26;
BrickStepper.FUNCTION_SET_DECAY = 27;
BrickStepper.FUNCTION_GET_DECAY = 28;
BrickStepper.FUNCTION_SET_MINIMUM_VOLTAGE = 29;
BrickStepper.FUNCTION_GET_MINIMUM_VOLTAGE = 30;
BrickStepper.FUNCTION_SET_SYNC_RECT = 33;
BrickStepper.FUNCTION_IS_SYNC_RECT = 34;
BrickStepper.FUNCTION_SET_TIME_BASE = 35;
BrickStepper.FUNCTION_GET_TIME_BASE = 36;
BrickStepper.FUNCTION_GET_ALL_DATA = 37;
BrickStepper.FUNCTION_SET_ALL_DATA_PERIOD = 38;
BrickStepper.FUNCTION_GET_ALL_DATA_PERIOD = 39;
BrickStepper.FUNCTION_SET_SPITFP_BAUDRATE_CONFIG = 231;
BrickStepper.FUNCTION_GET_SPITFP_BAUDRATE_CONFIG = 232;
BrickStepper.FUNCTION_GET_SEND_TIMEOUT_COUNT = 233;
BrickStepper.FUNCTION_SET_SPITFP_BAUDRATE = 234;
BrickStepper.FUNCTION_GET_SPITFP_BAUDRATE = 235;
BrickStepper.FUNCTION_GET_SPITFP_ERROR_COUNT = 237;
BrickStepper.FUNCTION_ENABLE_STATUS_LED = 238;
BrickStepper.FUNCTION_DISABLE_STATUS_LED = 239;
BrickStepper.FUNCTION_IS_STATUS_LED_ENABLED = 240;
BrickStepper.FUNCTION_GET_PROTOCOL1_BRICKLET_NAME = 241;
BrickStepper.FUNCTION_GET_CHIP_TEMPERATURE = 242;
BrickStepper.FUNCTION_RESET = 243;
BrickStepper.FUNCTION_WRITE_BRICKLET_PLUGIN = 246;
BrickStepper.FUNCTION_READ_BRICKLET_PLUGIN = 247;
BrickStepper.FUNCTION_GET_IDENTITY = 255;
BrickStepper.STEP_MODE_FULL_STEP = 1;
BrickStepper.STEP_MODE_HALF_STEP = 2;
BrickStepper.STEP_MODE_QUARTER_STEP = 4;
BrickStepper.STEP_MODE_EIGHTH_STEP = 8;
BrickStepper.STATE_STOP = 1;
BrickStepper.STATE_ACCELERATION = 2;
BrickStepper.STATE_RUN = 3;
BrickStepper.STATE_DEACCELERATION = 4;
BrickStepper.STATE_DIRECTION_CHANGE_TO_FORWARD = 5;
BrickStepper.STATE_DIRECTION_CHANGE_TO_BACKWARD = 6;
BrickStepper.COMMUNICATION_METHOD_NONE = 0;
BrickStepper.COMMUNICATION_METHOD_USB = 1;
BrickStepper.COMMUNICATION_METHOD_SPI_STACK = 2;
BrickStepper.COMMUNICATION_METHOD_CHIBI = 3;
BrickStepper.COMMUNICATION_METHOD_RS485 = 4;
BrickStepper.COMMUNICATION_METHOD_WIFI = 5;
BrickStepper.COMMUNICATION_METHOD_ETHERNET = 6;
BrickStepper.COMMUNICATION_METHOD_WIFI_V2 = 7;

function BrickStepper(uid, ipcon) {
	//Drives one bipolar stepper motor with up to 38V and 2.5A per phase

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickStepper.DEVICE_IDENTIFIER, BrickStepper.DEVICE_DISPLAY_NAME);
	BrickStepper.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 4];
	this.responseExpected[BrickStepper.FUNCTION_SET_MAX_VELOCITY] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickStepper.FUNCTION_GET_MAX_VELOCITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickStepper.FUNCTION_GET_CURRENT_VELOCITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickStepper.FUNCTION_SET_SPEED_RAMPING] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickStepper.FUNCTION_GET_SPEED_RAMPING] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickStepper.FUNCTION_FULL_BRAKE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickStepper.FUNCTION_SET_CURRENT_POSITION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickStepper.FUNCTION_GET_CURRENT_POSITION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickStepper.FUNCTION_SET_TARGET_POSITION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickStepper.FUNCTION_GET_TARGET_POSITION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickStepper.FUNCTION_SET_STEPS] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickStepper.FUNCTION_GET_STEPS] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickStepper.FUNCTION_GET_REMAINING_STEPS] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickStepper.FUNCTION_SET_STEP_MODE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickStepper.FUNCTION_GET_STEP_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickStepper.FUNCTION_DRIVE_FORWARD] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickStepper.FUNCTION_DRIVE_BACKWARD] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickStepper.FUNCTION_STOP] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickStepper.FUNCTION_GET_STACK_INPUT_VOLTAGE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickStepper.FUNCTION_GET_EXTERNAL_INPUT_VOLTAGE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickStepper.FUNCTION_GET_CURRENT_CONSUMPTION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickStepper.FUNCTION_SET_MOTOR_CURRENT] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickStepper.FUNCTION_GET_MOTOR_CURRENT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickStepper.FUNCTION_ENABLE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickStepper.FUNCTION_DISABLE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickStepper.FUNCTION_IS_ENABLED] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickStepper.FUNCTION_SET_DECAY] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickStepper.FUNCTION_GET_DECAY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickStepper.FUNCTION_SET_MINIMUM_VOLTAGE] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickStepper.FUNCTION_GET_MINIMUM_VOLTAGE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickStepper.FUNCTION_SET_SYNC_RECT] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickStepper.FUNCTION_IS_SYNC_RECT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickStepper.FUNCTION_SET_TIME_BASE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickStepper.FUNCTION_GET_TIME_BASE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickStepper.FUNCTION_GET_ALL_DATA] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickStepper.FUNCTION_SET_ALL_DATA_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickStepper.FUNCTION_GET_ALL_DATA_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickStepper.FUNCTION_SET_SPITFP_BAUDRATE_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickStepper.FUNCTION_GET_SPITFP_BAUDRATE_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickStepper.FUNCTION_GET_SEND_TIMEOUT_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickStepper.FUNCTION_SET_SPITFP_BAUDRATE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickStepper.FUNCTION_GET_SPITFP_BAUDRATE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickStepper.FUNCTION_GET_SPITFP_ERROR_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickStepper.FUNCTION_ENABLE_STATUS_LED] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickStepper.FUNCTION_DISABLE_STATUS_LED] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickStepper.FUNCTION_IS_STATUS_LED_ENABLED] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickStepper.FUNCTION_GET_PROTOCOL1_BRICKLET_NAME] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickStepper.FUNCTION_GET_CHIP_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickStepper.FUNCTION_RESET] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickStepper.FUNCTION_WRITE_BRICKLET_PLUGIN] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickStepper.FUNCTION_READ_BRICKLET_PLUGIN] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickStepper.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickStepper.CALLBACK_UNDER_VOLTAGE] = [10, 'H'];
	this.callbackFormats[BrickStepper.CALLBACK_POSITION_REACHED] = [12, 'i'];
	this.callbackFormats[BrickStepper.CALLBACK_ALL_DATA] = [24, 'H i i H H H'];
	this.callbackFormats[BrickStepper.CALLBACK_NEW_STATE] = [10, 'B B'];



	this.setMaxVelocity = function(velocity, returnCallback, errorCallback) {
		/*
		Sets the maximum velocity of the stepper motor.
		This function does *not* start the motor, it merely sets the maximum
		velocity the stepper motor is accelerated to. To get the motor running use
		either :func:`Set Target Position`, :func:`Set Steps`, :func:`Drive Forward` or
		:func:`Drive Backward`.
		*/
		this.ipcon.sendRequest(this, BrickStepper.FUNCTION_SET_MAX_VELOCITY, [velocity], 'H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getMaxVelocity = function(returnCallback, errorCallback) {
		/*
		Returns the velocity as set by :func:`Set Max Velocity`.
		*/
		this.ipcon.sendRequest(this, BrickStepper.FUNCTION_GET_MAX_VELOCITY, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.getCurrentVelocity = function(returnCallback, errorCallback) {
		/*
		Returns the *current* velocity of the stepper motor.
		*/
		this.ipcon.sendRequest(this, BrickStepper.FUNCTION_GET_CURRENT_VELOCITY, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.setSpeedRamping = function(acceleration, deacceleration, returnCallback, errorCallback) {
		/*
		Sets the acceleration and deacceleration of the stepper motor.
		An acceleration of 1000 means, that
		every second the velocity is increased by 1000 *steps/s*.
		
		For example: If the current velocity is 0 and you want to accelerate to a
		velocity of 8000 *steps/s* in 10 seconds, you should set an acceleration
		of 800 *steps/s²*.
		
		An acceleration/deacceleration of 0 means instantaneous
		acceleration/deacceleration (not recommended)
		*/
		this.ipcon.sendRequest(this, BrickStepper.FUNCTION_SET_SPEED_RAMPING, [acceleration, deacceleration], 'H H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getSpeedRamping = function(returnCallback, errorCallback) {
		/*
		Returns the acceleration and deacceleration as set by
		:func:`Set Speed Ramping`.
		*/
		this.ipcon.sendRequest(this, BrickStepper.FUNCTION_GET_SPEED_RAMPING, [], '', 12, 'H H', returnCallback, errorCallback, false, true);
	};
	this.fullBrake = function(returnCallback, errorCallback) {
		/*
		Executes an active full brake.
		
		.. warning::
		 This function is for emergency purposes,
		 where an immediate brake is necessary. Depending on the current velocity and
		 the strength of the motor, a full brake can be quite violent.
		
		Call :func:`Stop` if you just want to stop the motor.
		*/
		this.ipcon.sendRequest(this, BrickStepper.FUNCTION_FULL_BRAKE, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.setCurrentPosition = function(position, returnCallback, errorCallback) {
		/*
		Sets the current steps of the internal step counter. This can be used to
		set the current position to 0 when some kind of starting position
		is reached (e.g. when a CNC machine reaches a corner).
		*/
		this.ipcon.sendRequest(this, BrickStepper.FUNCTION_SET_CURRENT_POSITION, [position], 'i', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getCurrentPosition = function(returnCallback, errorCallback) {
		/*
		Returns the current position of the stepper motor in steps. On startup
		the position is 0. The steps are counted with all possible driving
		functions (:func:`Set Target Position`, :func:`Set Steps`, :func:`Drive Forward` or
		:func:`Drive Backward`). It also is possible to reset the steps to 0 or
		set them to any other desired value with :func:`Set Current Position`.
		*/
		this.ipcon.sendRequest(this, BrickStepper.FUNCTION_GET_CURRENT_POSITION, [], '', 12, 'i', returnCallback, errorCallback, false, true);
	};
	this.setTargetPosition = function(position, returnCallback, errorCallback) {
		/*
		Sets the target position of the stepper motor in steps. For example,
		if the current position of the motor is 500 and :func:`Set Target Position` is
		called with 1000, the stepper motor will drive 500 steps forward. It will
		use the velocity, acceleration and deacceleration as set by
		:func:`Set Max Velocity` and :func:`Set Speed Ramping`.
		
		A call of :func:`Set Target Position` with the parameter *x* is equivalent to
		a call of :func:`Set Steps` with the parameter
		(*x* - :func:`Get Current Position`).
		*/
		this.ipcon.sendRequest(this, BrickStepper.FUNCTION_SET_TARGET_POSITION, [position], 'i', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getTargetPosition = function(returnCallback, errorCallback) {
		/*
		Returns the last target position as set by :func:`Set Target Position`.
		*/
		this.ipcon.sendRequest(this, BrickStepper.FUNCTION_GET_TARGET_POSITION, [], '', 12, 'i', returnCallback, errorCallback, false, true);
	};
	this.setSteps = function(steps, returnCallback, errorCallback) {
		/*
		Sets the number of steps the stepper motor should run. Positive values
		will drive the motor forward and negative values backward.
		The velocity, acceleration and deacceleration as set by
		:func:`Set Max Velocity` and :func:`Set Speed Ramping` will be used.
		*/
		this.ipcon.sendRequest(this, BrickStepper.FUNCTION_SET_STEPS, [steps], 'i', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getSteps = function(returnCallback, errorCallback) {
		/*
		Returns the last steps as set by :func:`Set Steps`.
		*/
		this.ipcon.sendRequest(this, BrickStepper.FUNCTION_GET_STEPS, [], '', 12, 'i', returnCallback, errorCallback, false, true);
	};
	this.getRemainingSteps = function(returnCallback, errorCallback) {
		/*
		Returns the remaining steps of the last call of :func:`Set Steps`.
		For example, if :func:`Set Steps` is called with 2000 and
		:func:`Get Remaining Steps` is called after the motor has run for 500 steps,
		it will return 1500.
		*/
		this.ipcon.sendRequest(this, BrickStepper.FUNCTION_GET_REMAINING_STEPS, [], '', 12, 'i', returnCallback, errorCallback, false, true);
	};
	this.setStepMode = function(mode, returnCallback, errorCallback) {
		/*
		Sets the step mode of the stepper motor. Possible values are:
		
		* Full Step = 1
		* Half Step = 2
		* Quarter Step = 4
		* Eighth Step = 8
		
		A higher value will increase the resolution and
		decrease the torque of the stepper motor.
		*/
		this.ipcon.sendRequest(this, BrickStepper.FUNCTION_SET_STEP_MODE, [mode], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getStepMode = function(returnCallback, errorCallback) {
		/*
		Returns the step mode as set by :func:`Set Step Mode`.
		*/
		this.ipcon.sendRequest(this, BrickStepper.FUNCTION_GET_STEP_MODE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.driveForward = function(returnCallback, errorCallback) {
		/*
		Drives the stepper motor forward until :func:`Drive Backward` or
		:func:`Stop` is called. The velocity, acceleration and deacceleration as
		set by :func:`Set Max Velocity` and :func:`Set Speed Ramping` will be used.
		*/
		this.ipcon.sendRequest(this, BrickStepper.FUNCTION_DRIVE_FORWARD, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.driveBackward = function(returnCallback, errorCallback) {
		/*
		Drives the stepper motor backward until :func:`Drive Forward` or
		:func:`Stop` is triggered. The velocity, acceleration and deacceleration as
		set by :func:`Set Max Velocity` and :func:`Set Speed Ramping` will be used.
		*/
		this.ipcon.sendRequest(this, BrickStepper.FUNCTION_DRIVE_BACKWARD, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.stop = function(returnCallback, errorCallback) {
		/*
		Stops the stepper motor with the deacceleration as set by
		:func:`Set Speed Ramping`.
		*/
		this.ipcon.sendRequest(this, BrickStepper.FUNCTION_STOP, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getStackInputVoltage = function(returnCallback, errorCallback) {
		/*
		Returns the stack input voltage. The stack input voltage is the
		voltage that is supplied via the stack, i.e. it is given by a
		Step-Down or Step-Up Power Supply.
		*/
		this.ipcon.sendRequest(this, BrickStepper.FUNCTION_GET_STACK_INPUT_VOLTAGE, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.getExternalInputVoltage = function(returnCallback, errorCallback) {
		/*
		Returns the external input voltage. The external input voltage is
		given via the black power input connector on the Stepper Brick.
		
		If there is an external input voltage and a stack input voltage, the motor
		will be driven by the external input voltage. If there is only a stack
		voltage present, the motor will be driven by this voltage.
		
		.. warning::
		 This means, if you have a high stack voltage and a low external voltage,
		 the motor will be driven with the low external voltage. If you then remove
		 the external connection, it will immediately be driven by the high
		 stack voltage
		*/
		this.ipcon.sendRequest(this, BrickStepper.FUNCTION_GET_EXTERNAL_INPUT_VOLTAGE, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.getCurrentConsumption = function(returnCallback, errorCallback) {
		/*
		Returns the current consumption of the motor.
		*/
		this.ipcon.sendRequest(this, BrickStepper.FUNCTION_GET_CURRENT_CONSUMPTION, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.setMotorCurrent = function(current, returnCallback, errorCallback) {
		/*
		Sets the current with which the motor will be driven.
		
		.. warning::
		 Do not set this value above the specifications of your stepper motor.
		 Otherwise it may damage your motor.
		*/
		this.ipcon.sendRequest(this, BrickStepper.FUNCTION_SET_MOTOR_CURRENT, [current], 'H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getMotorCurrent = function(returnCallback, errorCallback) {
		/*
		Returns the current as set by :func:`Set Motor Current`.
		*/
		this.ipcon.sendRequest(this, BrickStepper.FUNCTION_GET_MOTOR_CURRENT, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.enable = function(returnCallback, errorCallback) {
		/*
		Enables the driver chip. The driver parameters can be configured (maximum velocity,
		acceleration, etc) before it is enabled.
		*/
		this.ipcon.sendRequest(this, BrickStepper.FUNCTION_ENABLE, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.disable = function(returnCallback, errorCallback) {
		/*
		Disables the driver chip. The configurations are kept (maximum velocity,
		acceleration, etc) but the motor is not driven until it is enabled again.
		
		.. warning::
		 Disabling the driver chip while the motor is still turning can damage the
		 driver chip. The motor should be stopped calling :func:`Stop` function
		 before disabling the motor power. The :func:`Stop` function will **not**
		 wait until the motor is actually stopped. You have to explicitly wait for the
		 appropriate time after calling the :func:`Stop` function before calling
		 the :func:`Disable` function.
		*/
		this.ipcon.sendRequest(this, BrickStepper.FUNCTION_DISABLE, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.isEnabled = function(returnCallback, errorCallback) {
		/*
		Returns *true* if the driver chip is enabled, *false* otherwise.
		*/
		this.ipcon.sendRequest(this, BrickStepper.FUNCTION_IS_ENABLED, [], '', 9, '?', returnCallback, errorCallback, false, true);
	};
	this.setDecay = function(decay, returnCallback, errorCallback) {
		/*
		Sets the decay mode of the stepper motor.
		A value of 0 sets the fast decay mode, a value of
		65535 sets the slow decay mode and a value in between sets the mixed
		decay mode.
		
		Changing the decay mode is only possible if synchronous rectification
		is enabled (see :func:`Set Sync Rect`).
		
		For a good explanation of the different decay modes see
		`this <https://ebldc.com/?p=86/>`__ blog post by Avayan.
		
		A good decay mode is unfortunately different for every motor. The best
		way to work out a good decay mode for your stepper motor, if you can't
		measure the current with an oscilloscope, is to listen to the sound of
		the motor. If the value is too low, you often hear a high pitched
		sound and if it is too high you can often hear a humming sound.
		
		Generally, fast decay mode (small value) will be noisier but also
		allow higher motor speeds.
		
		.. note::
		 There is unfortunately no formula to calculate a perfect decay
		 mode for a given stepper motor. If you have problems with loud noises
		 or the maximum motor speed is too slow, you should try to tinker with
		 the decay value
		*/
		this.ipcon.sendRequest(this, BrickStepper.FUNCTION_SET_DECAY, [decay], 'H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getDecay = function(returnCallback, errorCallback) {
		/*
		Returns the decay mode as set by :func:`Set Decay`.
		*/
		this.ipcon.sendRequest(this, BrickStepper.FUNCTION_GET_DECAY, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.setMinimumVoltage = function(voltage, returnCallback, errorCallback) {
		/*
		Sets the minimum voltage, below which the :cb:`Under Voltage` callback
		is triggered. The minimum possible value that works with the Stepper Brick is 8V.
		You can use this function to detect the discharge of a battery that is used
		to drive the stepper motor. If you have a fixed power supply, you likely do
		not need this functionality.
		*/
		this.ipcon.sendRequest(this, BrickStepper.FUNCTION_SET_MINIMUM_VOLTAGE, [voltage], 'H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getMinimumVoltage = function(returnCallback, errorCallback) {
		/*
		Returns the minimum voltage as set by :func:`Set Minimum Voltage`.
		*/
		this.ipcon.sendRequest(this, BrickStepper.FUNCTION_GET_MINIMUM_VOLTAGE, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.setSyncRect = function(syncRect, returnCallback, errorCallback) {
		/*
		Turns synchronous rectification on or off (*true* or *false*).
		
		With synchronous rectification on, the decay can be changed
		(see :func:`Set Decay`). Without synchronous rectification fast
		decay is used.
		
		For an explanation of synchronous rectification see
		`here <https://en.wikipedia.org/wiki/Active_rectification>`__.
		
		.. warning::
		 If you want to use high speeds (> 10000 steps/s) for a large
		 stepper motor with a large inductivity we strongly
		 suggest that you disable synchronous rectification. Otherwise the
		 Brick may not be able to cope with the load and overheat.
		*/
		this.ipcon.sendRequest(this, BrickStepper.FUNCTION_SET_SYNC_RECT, [syncRect], '?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.isSyncRect = function(returnCallback, errorCallback) {
		/*
		Returns *true* if synchronous rectification is enabled, *false* otherwise.
		*/
		this.ipcon.sendRequest(this, BrickStepper.FUNCTION_IS_SYNC_RECT, [], '', 9, '?', returnCallback, errorCallback, false, true);
	};
	this.setTimeBase = function(timeBase, returnCallback, errorCallback) {
		/*
		Sets the time base of the velocity and the acceleration of the stepper brick.
		
		For example, if you want to make one step every 1.5 seconds, you can set
		the time base to 15 and the velocity to 10. Now the velocity is
		10steps/15s = 1steps/1.5s.
		*/
		this.ipcon.sendRequest(this, BrickStepper.FUNCTION_SET_TIME_BASE, [timeBase], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getTimeBase = function(returnCallback, errorCallback) {
		/*
		Returns the time base as set by :func:`Set Time Base`.
		*/
		this.ipcon.sendRequest(this, BrickStepper.FUNCTION_GET_TIME_BASE, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getAllData = function(returnCallback, errorCallback) {
		/*
		Returns the following parameters: The current velocity,
		the current position, the remaining steps, the stack voltage, the external
		voltage and the current consumption of the stepper motor.
		
		There is also a callback for this function, see :cb:`All Data` callback.
		*/
		this.ipcon.sendRequest(this, BrickStepper.FUNCTION_GET_ALL_DATA, [], '', 24, 'H i i H H H', returnCallback, errorCallback, false, true);
	};
	this.setAllDataPeriod = function(period, returnCallback, errorCallback) {
		/*
		Sets the period with which the :cb:`All Data` callback is triggered
		periodically. A value of 0 turns the callback off.
		*/
		this.ipcon.sendRequest(this, BrickStepper.FUNCTION_SET_ALL_DATA_PERIOD, [period], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getAllDataPeriod = function(returnCallback, errorCallback) {
		/*
		Returns the period as set by :func:`Set All Data Period`.
		*/
		this.ipcon.sendRequest(this, BrickStepper.FUNCTION_GET_ALL_DATA_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setSPITFPBaudrateConfig = function(enableDynamicBaudrate, minimumDynamicBaudrate, returnCallback, errorCallback) {
		/*
		The SPITF protocol can be used with a dynamic baudrate. If the dynamic baudrate is
		enabled, the Brick will try to adapt the baudrate for the communication
		between Bricks and Bricklets according to the amount of data that is transferred.
		
		The baudrate will be increased exponentially if lots of data is sent/received and
		decreased linearly if little data is sent/received.
		
		This lowers the baudrate in applications where little data is transferred (e.g.
		a weather station) and increases the robustness. If there is lots of data to transfer
		(e.g. Thermal Imaging Bricklet) it automatically increases the baudrate as needed.
		
		In cases where some data has to transferred as fast as possible every few seconds
		(e.g. RS485 Bricklet with a high baudrate but small payload) you may want to turn
		the dynamic baudrate off to get the highest possible performance.
		
		The maximum value of the baudrate can be set per port with the function
		:func:`Set SPITFP Baudrate`. If the dynamic baudrate is disabled, the baudrate
		as set by :func:`Set SPITFP Baudrate` will be used statically.
		
		.. versionadded:: 2.3.6$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickStepper.FUNCTION_SET_SPITFP_BAUDRATE_CONFIG, [enableDynamicBaudrate, minimumDynamicBaudrate], '? I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPBaudrateConfig = function(returnCallback, errorCallback) {
		/*
		Returns the baudrate config, see :func:`Set SPITFP Baudrate Config`.
		
		.. versionadded:: 2.3.6$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickStepper.FUNCTION_GET_SPITFP_BAUDRATE_CONFIG, [], '', 13, '? I', returnCallback, errorCallback, false, true);
	};
	this.getSendTimeoutCount = function(communicationMethod, returnCallback, errorCallback) {
		/*
		Returns the timeout count for the different communication methods.
		
		The methods 0-2 are available for all Bricks, 3-7 only for Master Bricks.
		
		This function is mostly used for debugging during development, in normal operation
		the counters should nearly always stay at 0.
		
		.. versionadded:: 2.3.4$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickStepper.FUNCTION_GET_SEND_TIMEOUT_COUNT, [communicationMethod], 'B', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setSPITFPBaudrate = function(brickletPort, baudrate, returnCallback, errorCallback) {
		/*
		Sets the baudrate for a specific Bricklet port.
		
		If you want to increase the throughput of Bricklets you can increase
		the baudrate. If you get a high error count because of high
		interference (see :func:`Get SPITFP Error Count`) you can decrease the
		baudrate.
		
		If the dynamic baudrate feature is enabled, the baudrate set by this
		function corresponds to the maximum baudrate (see :func:`Set SPITFP Baudrate Config`).
		
		Regulatory testing is done with the default baudrate. If CE compatibility
		or similar is necessary in your applications we recommend to not change
		the baudrate.
		
		.. versionadded:: 2.3.3$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickStepper.FUNCTION_SET_SPITFP_BAUDRATE, [brickletPort, baudrate], 'c I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPBaudrate = function(brickletPort, returnCallback, errorCallback) {
		/*
		Returns the baudrate for a given Bricklet port, see :func:`Set SPITFP Baudrate`.
		
		.. versionadded:: 2.3.3$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickStepper.FUNCTION_GET_SPITFP_BAUDRATE, [brickletPort], 'c', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPErrorCount = function(brickletPort, returnCallback, errorCallback) {
		/*
		Returns the error count for the communication between Brick and Bricklet.
		
		The errors are divided into
		
		* ACK checksum errors,
		* message checksum errors,
		* framing errors and
		* overflow errors.
		
		The errors counts are for errors that occur on the Brick side. All
		Bricklets have a similar function that returns the errors on the Bricklet side.
		
		.. versionadded:: 2.3.3$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickStepper.FUNCTION_GET_SPITFP_ERROR_COUNT, [brickletPort], 'c', 24, 'I I I I', returnCallback, errorCallback, false, true);
	};
	this.enableStatusLED = function(returnCallback, errorCallback) {
		/*
		Enables the status LED.
		
		The status LED is the blue LED next to the USB connector. If enabled is is
		on and it flickers if data is transfered. If disabled it is always off.
		
		The default state is enabled.
		
		.. versionadded:: 2.3.1$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickStepper.FUNCTION_ENABLE_STATUS_LED, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.disableStatusLED = function(returnCallback, errorCallback) {
		/*
		Disables the status LED.
		
		The status LED is the blue LED next to the USB connector. If enabled is is
		on and it flickers if data is transfered. If disabled it is always off.
		
		The default state is enabled.
		
		.. versionadded:: 2.3.1$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickStepper.FUNCTION_DISABLE_STATUS_LED, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.isStatusLEDEnabled = function(returnCallback, errorCallback) {
		/*
		Returns *true* if the status LED is enabled, *false* otherwise.
		
		.. versionadded:: 2.3.1$nbsp;(Firmware)
		*/
		this.ipcon.sendRequest(this, BrickStepper.FUNCTION_IS_STATUS_LED_ENABLED, [], '', 9, '?', returnCallback, errorCallback, false, true);
	};
	this.getProtocol1BrickletName = function(port, returnCallback, errorCallback) {
		/*
		Returns the firmware and protocol version and the name of the Bricklet for a
		given port.
		
		This functions sole purpose is to allow automatic flashing of v1.x.y Bricklet
		plugins.
		*/
		this.ipcon.sendRequest(this, BrickStepper.FUNCTION_GET_PROTOCOL1_BRICKLET_NAME, [port], 'c', 52, 'B B3 s40', returnCallback, errorCallback, false, true);
	};
	this.getChipTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature as measured inside the microcontroller. The
		value returned is not the ambient temperature!
		
		The temperature is only proportional to the real temperature and it has an
		accuracy of ±15%. Practically it is only useful as an indicator for
		temperature changes.
		*/
		this.ipcon.sendRequest(this, BrickStepper.FUNCTION_GET_CHIP_TEMPERATURE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.reset = function(returnCallback, errorCallback) {
		/*
		Calling this function will reset the Brick. Calling this function
		on a Brick inside of a stack will reset the whole stack.
		
		After a reset you have to create new device objects,
		calling functions on the existing ones will result in
		undefined behavior!
		*/
		this.ipcon.sendRequest(this, BrickStepper.FUNCTION_RESET, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeBrickletPlugin = function(port, offset, chunk, returnCallback, errorCallback) {
		/*
		Writes 32 bytes of firmware to the bricklet attached at the given port.
		The bytes are written to the position offset * 32.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickStepper.FUNCTION_WRITE_BRICKLET_PLUGIN, [port, offset, chunk], 'c B B32', 0, '', returnCallback, errorCallback, false, true);
	};
	this.readBrickletPlugin = function(port, offset, returnCallback, errorCallback) {
		/*
		Reads 32 bytes of firmware from the bricklet attached at the given port.
		The bytes are read starting at the position offset * 32.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickStepper.FUNCTION_READ_BRICKLET_PLUGIN, [port, offset], 'c B', 40, 'B32', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Brick is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position is the position in the stack from '0' (bottom) to '8' (top).
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickStepper.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickStepper;

},{"./Device":279,"./IPConnection":280}],147:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletAccelerometer.DEVICE_IDENTIFIER = 250;
BrickletAccelerometer.DEVICE_DISPLAY_NAME = 'Accelerometer Bricklet';
BrickletAccelerometer.CALLBACK_ACCELERATION = 14;
BrickletAccelerometer.CALLBACK_ACCELERATION_REACHED = 15;
BrickletAccelerometer.FUNCTION_GET_ACCELERATION = 1;
BrickletAccelerometer.FUNCTION_SET_ACCELERATION_CALLBACK_PERIOD = 2;
BrickletAccelerometer.FUNCTION_GET_ACCELERATION_CALLBACK_PERIOD = 3;
BrickletAccelerometer.FUNCTION_SET_ACCELERATION_CALLBACK_THRESHOLD = 4;
BrickletAccelerometer.FUNCTION_GET_ACCELERATION_CALLBACK_THRESHOLD = 5;
BrickletAccelerometer.FUNCTION_SET_DEBOUNCE_PERIOD = 6;
BrickletAccelerometer.FUNCTION_GET_DEBOUNCE_PERIOD = 7;
BrickletAccelerometer.FUNCTION_GET_TEMPERATURE = 8;
BrickletAccelerometer.FUNCTION_SET_CONFIGURATION = 9;
BrickletAccelerometer.FUNCTION_GET_CONFIGURATION = 10;
BrickletAccelerometer.FUNCTION_LED_ON = 11;
BrickletAccelerometer.FUNCTION_LED_OFF = 12;
BrickletAccelerometer.FUNCTION_IS_LED_ON = 13;
BrickletAccelerometer.FUNCTION_GET_IDENTITY = 255;
BrickletAccelerometer.THRESHOLD_OPTION_OFF = 'x';
BrickletAccelerometer.THRESHOLD_OPTION_OUTSIDE = 'o';
BrickletAccelerometer.THRESHOLD_OPTION_INSIDE = 'i';
BrickletAccelerometer.THRESHOLD_OPTION_SMALLER = '<';
BrickletAccelerometer.THRESHOLD_OPTION_GREATER = '>';
BrickletAccelerometer.DATA_RATE_OFF = 0;
BrickletAccelerometer.DATA_RATE_3HZ = 1;
BrickletAccelerometer.DATA_RATE_6HZ = 2;
BrickletAccelerometer.DATA_RATE_12HZ = 3;
BrickletAccelerometer.DATA_RATE_25HZ = 4;
BrickletAccelerometer.DATA_RATE_50HZ = 5;
BrickletAccelerometer.DATA_RATE_100HZ = 6;
BrickletAccelerometer.DATA_RATE_400HZ = 7;
BrickletAccelerometer.DATA_RATE_800HZ = 8;
BrickletAccelerometer.DATA_RATE_1600HZ = 9;
BrickletAccelerometer.FULL_SCALE_2G = 0;
BrickletAccelerometer.FULL_SCALE_4G = 1;
BrickletAccelerometer.FULL_SCALE_6G = 2;
BrickletAccelerometer.FULL_SCALE_8G = 3;
BrickletAccelerometer.FULL_SCALE_16G = 4;
BrickletAccelerometer.FILTER_BANDWIDTH_800HZ = 0;
BrickletAccelerometer.FILTER_BANDWIDTH_400HZ = 1;
BrickletAccelerometer.FILTER_BANDWIDTH_200HZ = 2;
BrickletAccelerometer.FILTER_BANDWIDTH_50HZ = 3;

function BrickletAccelerometer(uid, ipcon) {
	//Measures acceleration in three axis

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletAccelerometer.DEVICE_IDENTIFIER, BrickletAccelerometer.DEVICE_DISPLAY_NAME);
	BrickletAccelerometer.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 1];
	this.responseExpected[BrickletAccelerometer.FUNCTION_GET_ACCELERATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAccelerometer.FUNCTION_SET_ACCELERATION_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletAccelerometer.FUNCTION_GET_ACCELERATION_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAccelerometer.FUNCTION_SET_ACCELERATION_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletAccelerometer.FUNCTION_GET_ACCELERATION_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAccelerometer.FUNCTION_SET_DEBOUNCE_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletAccelerometer.FUNCTION_GET_DEBOUNCE_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAccelerometer.FUNCTION_GET_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAccelerometer.FUNCTION_SET_CONFIGURATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletAccelerometer.FUNCTION_GET_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAccelerometer.FUNCTION_LED_ON] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletAccelerometer.FUNCTION_LED_OFF] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletAccelerometer.FUNCTION_IS_LED_ON] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAccelerometer.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletAccelerometer.CALLBACK_ACCELERATION] = [14, 'h h h'];
	this.callbackFormats[BrickletAccelerometer.CALLBACK_ACCELERATION_REACHED] = [14, 'h h h'];



	this.getAcceleration = function(returnCallback, errorCallback) {
		/*
		Returns the acceleration in x, y and z direction. The values
		are given in gₙ/1000 (1gₙ = 9.80665m/s²). The range is
		configured with :func:`Set Configuration`.
		
		If you want to get the acceleration periodically, it is recommended
		to use the :cb:`Acceleration` callback and set the period with
		:func:`Set Acceleration Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletAccelerometer.FUNCTION_GET_ACCELERATION, [], '', 14, 'h h h', returnCallback, errorCallback, false, true);
	};
	this.setAccelerationCallbackPeriod = function(period, returnCallback, errorCallback) {
		/*
		Sets the period with which the :cb:`Acceleration` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		The :cb:`Acceleration` callback is only triggered if the acceleration has
		changed since the last triggering.
		*/
		this.ipcon.sendRequest(this, BrickletAccelerometer.FUNCTION_SET_ACCELERATION_CALLBACK_PERIOD, [period], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getAccelerationCallbackPeriod = function(returnCallback, errorCallback) {
		/*
		Returns the period as set by :func:`Set Acceleration Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletAccelerometer.FUNCTION_GET_ACCELERATION_CALLBACK_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setAccelerationCallbackThreshold = function(option, minX, maxX, minY, maxY, minZ, maxZ, returnCallback, errorCallback) {
		/*
		Sets the thresholds for the :cb:`Acceleration Reached` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Callback is turned off"
		 "'o'",    "Callback is triggered when the acceleration is *outside* the min and max values"
		 "'i'",    "Callback is triggered when the acceleration is *inside* the min and max values"
		 "'<'",    "Callback is triggered when the acceleration is smaller than the min value (max is ignored)"
		 "'>'",    "Callback is triggered when the acceleration is greater than the min value (max is ignored)"
		*/
		this.ipcon.sendRequest(this, BrickletAccelerometer.FUNCTION_SET_ACCELERATION_CALLBACK_THRESHOLD, [option, minX, maxX, minY, maxY, minZ, maxZ], 'c h h h h h h', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getAccelerationCallbackThreshold = function(returnCallback, errorCallback) {
		/*
		Returns the threshold as set by :func:`Set Acceleration Callback Threshold`.
		*/
		this.ipcon.sendRequest(this, BrickletAccelerometer.FUNCTION_GET_ACCELERATION_CALLBACK_THRESHOLD, [], '', 21, 'c h h h h h h', returnCallback, errorCallback, false, true);
	};
	this.setDebouncePeriod = function(debounce, returnCallback, errorCallback) {
		/*
		Sets the period with which the threshold callback
		
		* :cb:`Acceleration Reached`
		
		is triggered, if the threshold
		
		* :func:`Set Acceleration Callback Threshold`
		
		keeps being reached.
		*/
		this.ipcon.sendRequest(this, BrickletAccelerometer.FUNCTION_SET_DEBOUNCE_PERIOD, [debounce], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getDebouncePeriod = function(returnCallback, errorCallback) {
		/*
		Returns the debounce period as set by :func:`Set Debounce Period`.
		*/
		this.ipcon.sendRequest(this, BrickletAccelerometer.FUNCTION_GET_DEBOUNCE_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature of the accelerometer.
		*/
		this.ipcon.sendRequest(this, BrickletAccelerometer.FUNCTION_GET_TEMPERATURE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.setConfiguration = function(dataRate, fullScale, filterBandwidth, returnCallback, errorCallback) {
		/*
		Configures the data rate, full scale range and filter bandwidth.
		Possible values are:
		
		* Data rate of 0Hz to 1600Hz.
		* Full scale range of ±2gₙ up to ±16gₙ.
		* Filter bandwidth between 50Hz and 800Hz.
		
		Decreasing data rate or full scale range will also decrease the noise on
		the data.
		*/
		this.ipcon.sendRequest(this, BrickletAccelerometer.FUNCTION_SET_CONFIGURATION, [dataRate, fullScale, filterBandwidth], 'B B B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletAccelerometer.FUNCTION_GET_CONFIGURATION, [], '', 11, 'B B B', returnCallback, errorCallback, false, true);
	};
	this.ledOn = function(returnCallback, errorCallback) {
		/*
		Enables the LED on the Bricklet.
		*/
		this.ipcon.sendRequest(this, BrickletAccelerometer.FUNCTION_LED_ON, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.ledOff = function(returnCallback, errorCallback) {
		/*
		Disables the LED on the Bricklet.
		*/
		this.ipcon.sendRequest(this, BrickletAccelerometer.FUNCTION_LED_OFF, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.isLEDOn = function(returnCallback, errorCallback) {
		/*
		Returns *true* if the LED is enabled, *false* otherwise.
		*/
		this.ipcon.sendRequest(this, BrickletAccelerometer.FUNCTION_IS_LED_ON, [], '', 9, '?', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletAccelerometer.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletAccelerometer;

},{"./Device":279,"./IPConnection":280}],148:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletAccelerometerV2.DEVICE_IDENTIFIER = 2130;
BrickletAccelerometerV2.DEVICE_DISPLAY_NAME = 'Accelerometer Bricklet 2.0';
BrickletAccelerometerV2.CALLBACK_ACCELERATION = 8;
BrickletAccelerometerV2.CALLBACK_CONTINUOUS_ACCELERATION_16_BIT = 11;
BrickletAccelerometerV2.CALLBACK_CONTINUOUS_ACCELERATION_8_BIT = 12;
BrickletAccelerometerV2.FUNCTION_GET_ACCELERATION = 1;
BrickletAccelerometerV2.FUNCTION_SET_CONFIGURATION = 2;
BrickletAccelerometerV2.FUNCTION_GET_CONFIGURATION = 3;
BrickletAccelerometerV2.FUNCTION_SET_ACCELERATION_CALLBACK_CONFIGURATION = 4;
BrickletAccelerometerV2.FUNCTION_GET_ACCELERATION_CALLBACK_CONFIGURATION = 5;
BrickletAccelerometerV2.FUNCTION_SET_INFO_LED_CONFIG = 6;
BrickletAccelerometerV2.FUNCTION_GET_INFO_LED_CONFIG = 7;
BrickletAccelerometerV2.FUNCTION_SET_CONTINUOUS_ACCELERATION_CONFIGURATION = 9;
BrickletAccelerometerV2.FUNCTION_GET_CONTINUOUS_ACCELERATION_CONFIGURATION = 10;
BrickletAccelerometerV2.FUNCTION_SET_FILTER_CONFIGURATION = 13;
BrickletAccelerometerV2.FUNCTION_GET_FILTER_CONFIGURATION = 14;
BrickletAccelerometerV2.FUNCTION_GET_SPITFP_ERROR_COUNT = 234;
BrickletAccelerometerV2.FUNCTION_SET_BOOTLOADER_MODE = 235;
BrickletAccelerometerV2.FUNCTION_GET_BOOTLOADER_MODE = 236;
BrickletAccelerometerV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER = 237;
BrickletAccelerometerV2.FUNCTION_WRITE_FIRMWARE = 238;
BrickletAccelerometerV2.FUNCTION_SET_STATUS_LED_CONFIG = 239;
BrickletAccelerometerV2.FUNCTION_GET_STATUS_LED_CONFIG = 240;
BrickletAccelerometerV2.FUNCTION_GET_CHIP_TEMPERATURE = 242;
BrickletAccelerometerV2.FUNCTION_RESET = 243;
BrickletAccelerometerV2.FUNCTION_WRITE_UID = 248;
BrickletAccelerometerV2.FUNCTION_READ_UID = 249;
BrickletAccelerometerV2.FUNCTION_GET_IDENTITY = 255;
BrickletAccelerometerV2.DATA_RATE_0_781HZ = 0;
BrickletAccelerometerV2.DATA_RATE_1_563HZ = 1;
BrickletAccelerometerV2.DATA_RATE_3_125HZ = 2;
BrickletAccelerometerV2.DATA_RATE_6_2512HZ = 3;
BrickletAccelerometerV2.DATA_RATE_12_5HZ = 4;
BrickletAccelerometerV2.DATA_RATE_25HZ = 5;
BrickletAccelerometerV2.DATA_RATE_50HZ = 6;
BrickletAccelerometerV2.DATA_RATE_100HZ = 7;
BrickletAccelerometerV2.DATA_RATE_200HZ = 8;
BrickletAccelerometerV2.DATA_RATE_400HZ = 9;
BrickletAccelerometerV2.DATA_RATE_800HZ = 10;
BrickletAccelerometerV2.DATA_RATE_1600HZ = 11;
BrickletAccelerometerV2.DATA_RATE_3200HZ = 12;
BrickletAccelerometerV2.DATA_RATE_6400HZ = 13;
BrickletAccelerometerV2.DATA_RATE_12800HZ = 14;
BrickletAccelerometerV2.DATA_RATE_25600HZ = 15;
BrickletAccelerometerV2.FULL_SCALE_2G = 0;
BrickletAccelerometerV2.FULL_SCALE_4G = 1;
BrickletAccelerometerV2.FULL_SCALE_8G = 2;
BrickletAccelerometerV2.INFO_LED_CONFIG_OFF = 0;
BrickletAccelerometerV2.INFO_LED_CONFIG_ON = 1;
BrickletAccelerometerV2.INFO_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletAccelerometerV2.RESOLUTION_8BIT = 0;
BrickletAccelerometerV2.RESOLUTION_16BIT = 1;
BrickletAccelerometerV2.IIR_BYPASS_APPLIED = 0;
BrickletAccelerometerV2.IIR_BYPASS_BYPASSED = 1;
BrickletAccelerometerV2.LOW_PASS_FILTER_NINTH = 0;
BrickletAccelerometerV2.LOW_PASS_FILTER_HALF = 1;
BrickletAccelerometerV2.BOOTLOADER_MODE_BOOTLOADER = 0;
BrickletAccelerometerV2.BOOTLOADER_MODE_FIRMWARE = 1;
BrickletAccelerometerV2.BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT = 2;
BrickletAccelerometerV2.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT = 3;
BrickletAccelerometerV2.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT = 4;
BrickletAccelerometerV2.BOOTLOADER_STATUS_OK = 0;
BrickletAccelerometerV2.BOOTLOADER_STATUS_INVALID_MODE = 1;
BrickletAccelerometerV2.BOOTLOADER_STATUS_NO_CHANGE = 2;
BrickletAccelerometerV2.BOOTLOADER_STATUS_ENTRY_FUNCTION_NOT_PRESENT = 3;
BrickletAccelerometerV2.BOOTLOADER_STATUS_DEVICE_IDENTIFIER_INCORRECT = 4;
BrickletAccelerometerV2.BOOTLOADER_STATUS_CRC_MISMATCH = 5;
BrickletAccelerometerV2.STATUS_LED_CONFIG_OFF = 0;
BrickletAccelerometerV2.STATUS_LED_CONFIG_ON = 1;
BrickletAccelerometerV2.STATUS_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletAccelerometerV2.STATUS_LED_CONFIG_SHOW_STATUS = 3;

function BrickletAccelerometerV2(uid, ipcon) {
	//Measures acceleration in three axis

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletAccelerometerV2.DEVICE_IDENTIFIER, BrickletAccelerometerV2.DEVICE_DISPLAY_NAME);
	BrickletAccelerometerV2.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 1];
	this.responseExpected[BrickletAccelerometerV2.FUNCTION_GET_ACCELERATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAccelerometerV2.FUNCTION_SET_CONFIGURATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletAccelerometerV2.FUNCTION_GET_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAccelerometerV2.FUNCTION_SET_ACCELERATION_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletAccelerometerV2.FUNCTION_GET_ACCELERATION_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAccelerometerV2.FUNCTION_SET_INFO_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletAccelerometerV2.FUNCTION_GET_INFO_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAccelerometerV2.FUNCTION_SET_CONTINUOUS_ACCELERATION_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletAccelerometerV2.FUNCTION_GET_CONTINUOUS_ACCELERATION_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAccelerometerV2.FUNCTION_SET_FILTER_CONFIGURATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletAccelerometerV2.FUNCTION_GET_FILTER_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAccelerometerV2.FUNCTION_GET_SPITFP_ERROR_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAccelerometerV2.FUNCTION_SET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAccelerometerV2.FUNCTION_GET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAccelerometerV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletAccelerometerV2.FUNCTION_WRITE_FIRMWARE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAccelerometerV2.FUNCTION_SET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletAccelerometerV2.FUNCTION_GET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAccelerometerV2.FUNCTION_GET_CHIP_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAccelerometerV2.FUNCTION_RESET] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletAccelerometerV2.FUNCTION_WRITE_UID] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletAccelerometerV2.FUNCTION_READ_UID] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAccelerometerV2.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletAccelerometerV2.CALLBACK_ACCELERATION] = [20, 'i i i'];
	this.callbackFormats[BrickletAccelerometerV2.CALLBACK_CONTINUOUS_ACCELERATION_16_BIT] = [68, 'h30'];
	this.callbackFormats[BrickletAccelerometerV2.CALLBACK_CONTINUOUS_ACCELERATION_8_BIT] = [68, 'b60'];



	this.getAcceleration = function(returnCallback, errorCallback) {
		/*
		Returns the acceleration in x, y and z direction. The values
		are given in gₙ/10000 (1gₙ = 9.80665m/s²). The range is
		configured with :func:`Set Configuration`.
		
		If you want to get the acceleration periodically, it is recommended
		to use the :cb:`Acceleration` callback and set the period with
		:func:`Set Acceleration Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletAccelerometerV2.FUNCTION_GET_ACCELERATION, [], '', 20, 'i i i', returnCallback, errorCallback, false, true);
	};
	this.setConfiguration = function(dataRate, fullScale, returnCallback, errorCallback) {
		/*
		Configures the data rate and full scale range.
		Possible values are:
		
		* Data rate of 0.781Hz to 25600Hz.
		* Full scale range of ±2g up to ±8g.
		
		Decreasing data rate or full scale range will also decrease the noise on
		the data.
		*/
		this.ipcon.sendRequest(this, BrickletAccelerometerV2.FUNCTION_SET_CONFIGURATION, [dataRate, fullScale], 'B B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletAccelerometerV2.FUNCTION_GET_CONFIGURATION, [], '', 10, 'B B', returnCallback, errorCallback, false, true);
	};
	this.setAccelerationCallbackConfiguration = function(period, valueHasToChange, returnCallback, errorCallback) {
		/*
		The period is the period with which the :cb:`Acceleration`
		callback is triggered periodically. A value of 0 turns the callback off.
		
		If the `value has to change`-parameter is set to true, the callback is only
		triggered after the value has changed. If the value didn't change within the
		period, the callback is triggered immediately on change.
		
		If it is set to false, the callback is continuously triggered with the period,
		independent of the value.
		
		If this callback is enabled, the :cb:`Continuous Acceleration 16 Bit` callback
		and :cb:`Continuous Acceleration 8 Bit` callback will automatically be disabled.
		*/
		this.ipcon.sendRequest(this, BrickletAccelerometerV2.FUNCTION_SET_ACCELERATION_CALLBACK_CONFIGURATION, [period, valueHasToChange], 'I ?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getAccelerationCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the callback configuration as set by
		:func:`Set Acceleration Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletAccelerometerV2.FUNCTION_GET_ACCELERATION_CALLBACK_CONFIGURATION, [], '', 13, 'I ?', returnCallback, errorCallback, false, true);
	};
	this.setInfoLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Configures the info LED (marked as "Force" on the Bricklet) to be either turned off,
		turned on, or blink in heartbeat mode.
		*/
		this.ipcon.sendRequest(this, BrickletAccelerometerV2.FUNCTION_SET_INFO_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getInfoLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the LED configuration as set by :func:`Set Info LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletAccelerometerV2.FUNCTION_GET_INFO_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setContinuousAccelerationConfiguration = function(enableX, enableY, enableZ, resolution, returnCallback, errorCallback) {
		/*
		For high throughput of acceleration data (> 1000Hz) you have to use the
		:cb:`Continuous Acceleration 16 Bit` or :cb:`Continuous Acceleration 8 Bit`
		callbacks.
		
		You can enable the callback for each axis (x, y, z) individually and choose a
		resolution of 8 bit or 16 bit.
		
		If at least one of the axis is enabled and the resolution is set to 8 bit,
		the :cb:`Continuous Acceleration 8 Bit` callback is activated. If at least
		one of the axis is enabled and the resolution is set to 16 bit,
		the :cb:`Continuous Acceleration 16 Bit` callback is activated.
		
		The returned values are raw ADC data. If you want to put this data into
		a FFT to determine the occurrences of specific frequencies we recommend
		that you use the data as is. It has all of the ADC noise in it. This noise
		looks like pure noise at first glance, but it might still have some frequnecy
		information in it that can be utilized by the FFT.
		
		Otherwise you have to use the following formulas that depend on the configured
		resolution (8/16 bit) and the full scale range (see :func:`Set Configuration`) to calculate
		the data in gₙ/10000 (same unit that is returned by :func:`Get Acceleration`):
		
		* 16 bit, full scale 2g: acceleration = value * 625 / 1024
		* 16 bit, full scale 4g: acceleration = value * 1250 / 1024
		* 16 bit, full scale 8g: acceleration = value * 2500 / 1024
		
		If a resolution of 8 bit is used, only the 8 most significant bits will be
		transferred, so you can use the following formulas:
		
		* 8 bit, full scale 2g: acceleration = value * 256 * 625 / 1024
		* 8 bit, full scale 4g: acceleration = value * 256 * 1250 / 1024
		* 8 bit, full scale 8g: acceleration = value * 256 * 2500 / 1024
		
		If no axis is enabled, both callbacks are disabled. If one of the continuous
		callbacks is enabled, the :cb:`Acceleration` callback is disabled.
		
		The maximum throughput depends on the exact configuration:
		
		.. csv-table::
		 :header: "Number of axis enabled", "Throughput 8 bit", "Throughout 16 bit"
		 :widths: 20, 20, 20
		
		 "1", "25600Hz", "25600Hz"
		 "2", "25600Hz", "15000Hz"
		 "3", "20000Hz", "10000Hz"
		*/
		this.ipcon.sendRequest(this, BrickletAccelerometerV2.FUNCTION_SET_CONTINUOUS_ACCELERATION_CONFIGURATION, [enableX, enableY, enableZ, resolution], '? ? ? B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getContinuousAccelerationConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the continuous acceleration configuration as set by
		:func:`Set Continuous Acceleration Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletAccelerometerV2.FUNCTION_GET_CONTINUOUS_ACCELERATION_CONFIGURATION, [], '', 12, '? ? ? B', returnCallback, errorCallback, false, true);
	};
	this.setFilterConfiguration = function(iirBypass, lowPassFilter, returnCallback, errorCallback) {
		/*
		Configures IIR Bypass filter mode and low pass filter roll off corner frequency.
		
		The filter can be applied or bypassed and the corner frequency can be
		half or a ninth of the output data rate.
		
		.. image:: /Images/Bricklets/bricklet_accelerometer_v2_filter.png
		   :scale: 100 %
		   :alt: Accelerometer filter
		   :align: center
		   :target: ../../_images/Bricklets/bricklet_accelerometer_v2_filter.png
		
		.. versionadded:: 2.0.2$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletAccelerometerV2.FUNCTION_SET_FILTER_CONFIGURATION, [iirBypass, lowPassFilter], 'B B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getFilterConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Filter Configuration`.
		
		.. versionadded:: 2.0.2$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletAccelerometerV2.FUNCTION_GET_FILTER_CONFIGURATION, [], '', 10, 'B B', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPErrorCount = function(returnCallback, errorCallback) {
		/*
		Returns the error count for the communication between Brick and Bricklet.
		
		The errors are divided into
		
		* ACK checksum errors,
		* message checksum errors,
		* framing errors and
		* overflow errors.
		
		The errors counts are for errors that occur on the Bricklet side. All
		Bricks have a similar function that returns the errors on the Brick side.
		*/
		this.ipcon.sendRequest(this, BrickletAccelerometerV2.FUNCTION_GET_SPITFP_ERROR_COUNT, [], '', 24, 'I I I I', returnCallback, errorCallback, false, true);
	};
	this.setBootloaderMode = function(mode, returnCallback, errorCallback) {
		/*
		Sets the bootloader mode and returns the status after the requested
		mode change was instigated.
		
		You can change from bootloader mode to firmware mode and vice versa. A change
		from bootloader mode to firmware mode will only take place if the entry function,
		device identifier and CRC are present and correct.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletAccelerometerV2.FUNCTION_SET_BOOTLOADER_MODE, [mode], 'B', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getBootloaderMode = function(returnCallback, errorCallback) {
		/*
		Returns the current bootloader mode, see :func:`Set Bootloader Mode`.
		*/
		this.ipcon.sendRequest(this, BrickletAccelerometerV2.FUNCTION_GET_BOOTLOADER_MODE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setWriteFirmwarePointer = function(pointer, returnCallback, errorCallback) {
		/*
		Sets the firmware pointer for :func:`Write Firmware`. The pointer has
		to be increased by chunks of size 64. The data is written to flash
		every 4 chunks (which equals to one page of size 256).
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletAccelerometerV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER, [pointer], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeFirmware = function(data, returnCallback, errorCallback) {
		/*
		Writes 64 Bytes of firmware at the position as written by
		:func:`Set Write Firmware Pointer` before. The firmware is written
		to flash every 4 chunks.
		
		You can only write firmware in bootloader mode.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletAccelerometerV2.FUNCTION_WRITE_FIRMWARE, [data], 'B64', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setStatusLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Sets the status LED configuration. By default the LED shows
		communication traffic between Brick and Bricklet, it flickers once
		for every 10 received data packets.
		
		You can also turn the LED permanently on/off or show a heartbeat.
		
		If the Bricklet is in bootloader mode, the LED is will show heartbeat by default.
		*/
		this.ipcon.sendRequest(this, BrickletAccelerometerV2.FUNCTION_SET_STATUS_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getStatusLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Status LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletAccelerometerV2.FUNCTION_GET_STATUS_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getChipTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature as measured inside the microcontroller. The
		value returned is not the ambient temperature!
		
		The temperature is only proportional to the real temperature and it has bad
		accuracy. Practically it is only useful as an indicator for
		temperature changes.
		*/
		this.ipcon.sendRequest(this, BrickletAccelerometerV2.FUNCTION_GET_CHIP_TEMPERATURE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.reset = function(returnCallback, errorCallback) {
		/*
		Calling this function will reset the Bricklet. All configurations
		will be lost.
		
		After a reset you have to create new device objects,
		calling functions on the existing ones will result in
		undefined behavior!
		*/
		this.ipcon.sendRequest(this, BrickletAccelerometerV2.FUNCTION_RESET, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeUID = function(uid, returnCallback, errorCallback) {
		/*
		Writes a new UID into flash. If you want to set a new UID
		you have to decode the Base58 encoded UID string into an
		integer first.
		
		We recommend that you use Brick Viewer to change the UID.
		*/
		this.ipcon.sendRequest(this, BrickletAccelerometerV2.FUNCTION_WRITE_UID, [uid], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.readUID = function(returnCallback, errorCallback) {
		/*
		Returns the current UID as an integer. Encode as
		Base58 to get the usual string version.
		*/
		this.ipcon.sendRequest(this, BrickletAccelerometerV2.FUNCTION_READ_UID, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletAccelerometerV2.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletAccelerometerV2;

},{"./Device":279,"./IPConnection":280}],149:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletAirQuality.DEVICE_IDENTIFIER = 297;
BrickletAirQuality.DEVICE_DISPLAY_NAME = 'Air Quality Bricklet';
BrickletAirQuality.CALLBACK_ALL_VALUES = 6;
BrickletAirQuality.CALLBACK_IAQ_INDEX = 10;
BrickletAirQuality.CALLBACK_TEMPERATURE = 14;
BrickletAirQuality.CALLBACK_HUMIDITY = 18;
BrickletAirQuality.CALLBACK_AIR_PRESSURE = 22;
BrickletAirQuality.FUNCTION_GET_ALL_VALUES = 1;
BrickletAirQuality.FUNCTION_SET_TEMPERATURE_OFFSET = 2;
BrickletAirQuality.FUNCTION_GET_TEMPERATURE_OFFSET = 3;
BrickletAirQuality.FUNCTION_SET_ALL_VALUES_CALLBACK_CONFIGURATION = 4;
BrickletAirQuality.FUNCTION_GET_ALL_VALUES_CALLBACK_CONFIGURATION = 5;
BrickletAirQuality.FUNCTION_GET_IAQ_INDEX = 7;
BrickletAirQuality.FUNCTION_SET_IAQ_INDEX_CALLBACK_CONFIGURATION = 8;
BrickletAirQuality.FUNCTION_GET_IAQ_INDEX_CALLBACK_CONFIGURATION = 9;
BrickletAirQuality.FUNCTION_GET_TEMPERATURE = 11;
BrickletAirQuality.FUNCTION_SET_TEMPERATURE_CALLBACK_CONFIGURATION = 12;
BrickletAirQuality.FUNCTION_GET_TEMPERATURE_CALLBACK_CONFIGURATION = 13;
BrickletAirQuality.FUNCTION_GET_HUMIDITY = 15;
BrickletAirQuality.FUNCTION_SET_HUMIDITY_CALLBACK_CONFIGURATION = 16;
BrickletAirQuality.FUNCTION_GET_HUMIDITY_CALLBACK_CONFIGURATION = 17;
BrickletAirQuality.FUNCTION_GET_AIR_PRESSURE = 19;
BrickletAirQuality.FUNCTION_SET_AIR_PRESSURE_CALLBACK_CONFIGURATION = 20;
BrickletAirQuality.FUNCTION_GET_AIR_PRESSURE_CALLBACK_CONFIGURATION = 21;
BrickletAirQuality.FUNCTION_REMOVE_CALIBRATION = 23;
BrickletAirQuality.FUNCTION_SET_BACKGROUND_CALIBRATION_DURATION = 24;
BrickletAirQuality.FUNCTION_GET_BACKGROUND_CALIBRATION_DURATION = 25;
BrickletAirQuality.FUNCTION_GET_SPITFP_ERROR_COUNT = 234;
BrickletAirQuality.FUNCTION_SET_BOOTLOADER_MODE = 235;
BrickletAirQuality.FUNCTION_GET_BOOTLOADER_MODE = 236;
BrickletAirQuality.FUNCTION_SET_WRITE_FIRMWARE_POINTER = 237;
BrickletAirQuality.FUNCTION_WRITE_FIRMWARE = 238;
BrickletAirQuality.FUNCTION_SET_STATUS_LED_CONFIG = 239;
BrickletAirQuality.FUNCTION_GET_STATUS_LED_CONFIG = 240;
BrickletAirQuality.FUNCTION_GET_CHIP_TEMPERATURE = 242;
BrickletAirQuality.FUNCTION_RESET = 243;
BrickletAirQuality.FUNCTION_WRITE_UID = 248;
BrickletAirQuality.FUNCTION_READ_UID = 249;
BrickletAirQuality.FUNCTION_GET_IDENTITY = 255;
BrickletAirQuality.ACCURACY_UNRELIABLE = 0;
BrickletAirQuality.ACCURACY_LOW = 1;
BrickletAirQuality.ACCURACY_MEDIUM = 2;
BrickletAirQuality.ACCURACY_HIGH = 3;
BrickletAirQuality.THRESHOLD_OPTION_OFF = 'x';
BrickletAirQuality.THRESHOLD_OPTION_OUTSIDE = 'o';
BrickletAirQuality.THRESHOLD_OPTION_INSIDE = 'i';
BrickletAirQuality.THRESHOLD_OPTION_SMALLER = '<';
BrickletAirQuality.THRESHOLD_OPTION_GREATER = '>';
BrickletAirQuality.DURATION_4_DAYS = 0;
BrickletAirQuality.DURATION_28_DAYS = 1;
BrickletAirQuality.BOOTLOADER_MODE_BOOTLOADER = 0;
BrickletAirQuality.BOOTLOADER_MODE_FIRMWARE = 1;
BrickletAirQuality.BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT = 2;
BrickletAirQuality.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT = 3;
BrickletAirQuality.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT = 4;
BrickletAirQuality.BOOTLOADER_STATUS_OK = 0;
BrickletAirQuality.BOOTLOADER_STATUS_INVALID_MODE = 1;
BrickletAirQuality.BOOTLOADER_STATUS_NO_CHANGE = 2;
BrickletAirQuality.BOOTLOADER_STATUS_ENTRY_FUNCTION_NOT_PRESENT = 3;
BrickletAirQuality.BOOTLOADER_STATUS_DEVICE_IDENTIFIER_INCORRECT = 4;
BrickletAirQuality.BOOTLOADER_STATUS_CRC_MISMATCH = 5;
BrickletAirQuality.STATUS_LED_CONFIG_OFF = 0;
BrickletAirQuality.STATUS_LED_CONFIG_ON = 1;
BrickletAirQuality.STATUS_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletAirQuality.STATUS_LED_CONFIG_SHOW_STATUS = 3;

function BrickletAirQuality(uid, ipcon) {
	//Measures IAQ index, temperature, humidity and air pressure

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletAirQuality.DEVICE_IDENTIFIER, BrickletAirQuality.DEVICE_DISPLAY_NAME);
	BrickletAirQuality.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 1];
	this.responseExpected[BrickletAirQuality.FUNCTION_GET_ALL_VALUES] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAirQuality.FUNCTION_SET_TEMPERATURE_OFFSET] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletAirQuality.FUNCTION_GET_TEMPERATURE_OFFSET] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAirQuality.FUNCTION_SET_ALL_VALUES_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletAirQuality.FUNCTION_GET_ALL_VALUES_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAirQuality.FUNCTION_GET_IAQ_INDEX] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAirQuality.FUNCTION_SET_IAQ_INDEX_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletAirQuality.FUNCTION_GET_IAQ_INDEX_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAirQuality.FUNCTION_GET_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAirQuality.FUNCTION_SET_TEMPERATURE_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletAirQuality.FUNCTION_GET_TEMPERATURE_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAirQuality.FUNCTION_GET_HUMIDITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAirQuality.FUNCTION_SET_HUMIDITY_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletAirQuality.FUNCTION_GET_HUMIDITY_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAirQuality.FUNCTION_GET_AIR_PRESSURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAirQuality.FUNCTION_SET_AIR_PRESSURE_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletAirQuality.FUNCTION_GET_AIR_PRESSURE_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAirQuality.FUNCTION_REMOVE_CALIBRATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletAirQuality.FUNCTION_SET_BACKGROUND_CALIBRATION_DURATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletAirQuality.FUNCTION_GET_BACKGROUND_CALIBRATION_DURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAirQuality.FUNCTION_GET_SPITFP_ERROR_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAirQuality.FUNCTION_SET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAirQuality.FUNCTION_GET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAirQuality.FUNCTION_SET_WRITE_FIRMWARE_POINTER] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletAirQuality.FUNCTION_WRITE_FIRMWARE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAirQuality.FUNCTION_SET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletAirQuality.FUNCTION_GET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAirQuality.FUNCTION_GET_CHIP_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAirQuality.FUNCTION_RESET] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletAirQuality.FUNCTION_WRITE_UID] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletAirQuality.FUNCTION_READ_UID] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAirQuality.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletAirQuality.CALLBACK_ALL_VALUES] = [25, 'i B i i i'];
	this.callbackFormats[BrickletAirQuality.CALLBACK_IAQ_INDEX] = [13, 'i B'];
	this.callbackFormats[BrickletAirQuality.CALLBACK_TEMPERATURE] = [12, 'i'];
	this.callbackFormats[BrickletAirQuality.CALLBACK_HUMIDITY] = [12, 'i'];
	this.callbackFormats[BrickletAirQuality.CALLBACK_AIR_PRESSURE] = [12, 'i'];



	this.getAllValues = function(returnCallback, errorCallback) {
		/*
		Returns all values measured by the Air Quality Bricklet. The values are
		IAQ (Indoor Air Quality) Index (higher value means greater level of air pollution), IAQ Index Accuracy, Temperature, Humidity and
		Air Pressure.
		
		.. image:: /Images/Misc/bricklet_air_quality_iaq_index.png
		   :scale: 100 %
		   :alt: Air Quality Index description
		   :align: center
		   :target: ../../_images/Misc/bricklet_air_quality_iaq_index.png
		*/
		this.ipcon.sendRequest(this, BrickletAirQuality.FUNCTION_GET_ALL_VALUES, [], '', 25, 'i B i i i', returnCallback, errorCallback, false, true);
	};
	this.setTemperatureOffset = function(offset, returnCallback, errorCallback) {
		/*
		Sets a temperature offset. A offset of 10 will decrease the measured temperature by 0.1 °C.
		
		If you install this Bricklet into an enclosure and you want to measure the ambient
		temperature, you may have to decrease the measured temperature by some value to
		compensate for the error because of the heating inside of the enclosure.
		
		We recommend that you leave the parts in the enclosure running for at least
		24 hours such that a temperature equilibrium can be reached. After that you can measure
		the temperature directly outside of enclosure and set the difference as offset.
		
		This temperature offset is used to calculate the relative humidity and
		IAQ index measurements. In case the Bricklet is installed in an enclosure, we
		recommend to measure and set the temperature offset to improve the accuracy of
		the measurements.
		*/
		this.ipcon.sendRequest(this, BrickletAirQuality.FUNCTION_SET_TEMPERATURE_OFFSET, [offset], 'i', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getTemperatureOffset = function(returnCallback, errorCallback) {
		/*
		Returns the temperature offset as set by
		:func:`Set Temperature Offset`.
		*/
		this.ipcon.sendRequest(this, BrickletAirQuality.FUNCTION_GET_TEMPERATURE_OFFSET, [], '', 12, 'i', returnCallback, errorCallback, false, true);
	};
	this.setAllValuesCallbackConfiguration = function(period, valueHasToChange, returnCallback, errorCallback) {
		/*
		The period is the period with which the :cb:`All Values`
		callback is triggered periodically. A value of 0 turns the callback off.
		
		If the `value has to change`-parameter is set to true, the callback is only
		triggered after at least one of the values has changed. If the values didn't
		change within the period, the callback is triggered immediately on change.
		
		If it is set to false, the callback is continuously triggered with the period,
		independent of the value.
		*/
		this.ipcon.sendRequest(this, BrickletAirQuality.FUNCTION_SET_ALL_VALUES_CALLBACK_CONFIGURATION, [period, valueHasToChange], 'I ?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getAllValuesCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the callback configuration as set by
		:func:`Set All Values Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletAirQuality.FUNCTION_GET_ALL_VALUES_CALLBACK_CONFIGURATION, [], '', 13, 'I ?', returnCallback, errorCallback, false, true);
	};
	this.getIAQIndex = function(returnCallback, errorCallback) {
		/*
		Returns the IAQ index and accuracy. The higher the IAQ index, the greater the level of air pollution.
		
		.. image:: /Images/Misc/bricklet_air_quality_iaq_index.png
		   :scale: 100 %
		   :alt: IAQ index description
		   :align: center
		   :target: ../../_images/Misc/bricklet_air_quality_iaq_index.png
		
		If you want to get the value periodically, it is recommended to use the
		:cb:`IAQ Index` callback. You can set the callback configuration
		with :func:`Set IAQ Index Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletAirQuality.FUNCTION_GET_IAQ_INDEX, [], '', 13, 'i B', returnCallback, errorCallback, false, true);
	};
	this.setIAQIndexCallbackConfiguration = function(period, valueHasToChange, returnCallback, errorCallback) {
		/*
		The period is the period with which the :cb:`IAQ Index`
		callback is triggered periodically. A value of 0 turns the callback off.
		
		If the `value has to change`-parameter is set to true, the callback is only
		triggered after at least one of the values has changed. If the values didn't
		change within the period, the callback is triggered immediately on change.
		
		If it is set to false, the callback is continuously triggered with the period,
		independent of the value.
		*/
		this.ipcon.sendRequest(this, BrickletAirQuality.FUNCTION_SET_IAQ_INDEX_CALLBACK_CONFIGURATION, [period, valueHasToChange], 'I ?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getIAQIndexCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the callback configuration as set by
		:func:`Set IAQ Index Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletAirQuality.FUNCTION_GET_IAQ_INDEX_CALLBACK_CONFIGURATION, [], '', 13, 'I ?', returnCallback, errorCallback, false, true);
	};
	this.getTemperature = function(returnCallback, errorCallback) {
		/*
		Returns temperature.
		
		
		If you want to get the value periodically, it is recommended to use the
		:cb:`Temperature` callback. You can set the callback configuration
		with :func:`Set Temperature Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletAirQuality.FUNCTION_GET_TEMPERATURE, [], '', 12, 'i', returnCallback, errorCallback, false, true);
	};
	this.setTemperatureCallbackConfiguration = function(period, valueHasToChange, option, min, max, returnCallback, errorCallback) {
		/*
		The period is the period with which the :cb:`Temperature` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		If the `value has to change`-parameter is set to true, the callback is only
		triggered after the value has changed. If the value didn't change
		within the period, the callback is triggered immediately on change.
		
		If it is set to false, the callback is continuously triggered with the period,
		independent of the value.
		
		It is furthermore possible to constrain the callback with thresholds.
		
		The `option`-parameter together with min/max sets a threshold for the :cb:`Temperature` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Threshold is turned off"
		 "'o'",    "Threshold is triggered when the value is *outside* the min and max values"
		 "'i'",    "Threshold is triggered when the value is *inside* or equal to the min and max values"
		 "'<'",    "Threshold is triggered when the value is smaller than the min value (max is ignored)"
		 "'>'",    "Threshold is triggered when the value is greater than the min value (max is ignored)"
		
		If the option is set to 'x' (threshold turned off) the callback is triggered with the fixed period.
		*/
		this.ipcon.sendRequest(this, BrickletAirQuality.FUNCTION_SET_TEMPERATURE_CALLBACK_CONFIGURATION, [period, valueHasToChange, option, min, max], 'I ? c i i', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getTemperatureCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the callback configuration as set by :func:`Set Temperature Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletAirQuality.FUNCTION_GET_TEMPERATURE_CALLBACK_CONFIGURATION, [], '', 22, 'I ? c i i', returnCallback, errorCallback, false, true);
	};
	this.getHumidity = function(returnCallback, errorCallback) {
		/*
		Returns relative humidity.
		
		
		If you want to get the value periodically, it is recommended to use the
		:cb:`Humidity` callback. You can set the callback configuration
		with :func:`Set Humidity Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletAirQuality.FUNCTION_GET_HUMIDITY, [], '', 12, 'i', returnCallback, errorCallback, false, true);
	};
	this.setHumidityCallbackConfiguration = function(period, valueHasToChange, option, min, max, returnCallback, errorCallback) {
		/*
		The period is the period with which the :cb:`Humidity` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		If the `value has to change`-parameter is set to true, the callback is only
		triggered after the value has changed. If the value didn't change
		within the period, the callback is triggered immediately on change.
		
		If it is set to false, the callback is continuously triggered with the period,
		independent of the value.
		
		It is furthermore possible to constrain the callback with thresholds.
		
		The `option`-parameter together with min/max sets a threshold for the :cb:`Humidity` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Threshold is turned off"
		 "'o'",    "Threshold is triggered when the value is *outside* the min and max values"
		 "'i'",    "Threshold is triggered when the value is *inside* or equal to the min and max values"
		 "'<'",    "Threshold is triggered when the value is smaller than the min value (max is ignored)"
		 "'>'",    "Threshold is triggered when the value is greater than the min value (max is ignored)"
		
		If the option is set to 'x' (threshold turned off) the callback is triggered with the fixed period.
		*/
		this.ipcon.sendRequest(this, BrickletAirQuality.FUNCTION_SET_HUMIDITY_CALLBACK_CONFIGURATION, [period, valueHasToChange, option, min, max], 'I ? c i i', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getHumidityCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the callback configuration as set by :func:`Set Humidity Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletAirQuality.FUNCTION_GET_HUMIDITY_CALLBACK_CONFIGURATION, [], '', 22, 'I ? c i i', returnCallback, errorCallback, false, true);
	};
	this.getAirPressure = function(returnCallback, errorCallback) {
		/*
		Returns air pressure.
		
		
		If you want to get the value periodically, it is recommended to use the
		:cb:`Air Pressure` callback. You can set the callback configuration
		with :func:`Set Air Pressure Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletAirQuality.FUNCTION_GET_AIR_PRESSURE, [], '', 12, 'i', returnCallback, errorCallback, false, true);
	};
	this.setAirPressureCallbackConfiguration = function(period, valueHasToChange, option, min, max, returnCallback, errorCallback) {
		/*
		The period is the period with which the :cb:`Air Pressure` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		If the `value has to change`-parameter is set to true, the callback is only
		triggered after the value has changed. If the value didn't change
		within the period, the callback is triggered immediately on change.
		
		If it is set to false, the callback is continuously triggered with the period,
		independent of the value.
		
		It is furthermore possible to constrain the callback with thresholds.
		
		The `option`-parameter together with min/max sets a threshold for the :cb:`Air Pressure` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Threshold is turned off"
		 "'o'",    "Threshold is triggered when the value is *outside* the min and max values"
		 "'i'",    "Threshold is triggered when the value is *inside* or equal to the min and max values"
		 "'<'",    "Threshold is triggered when the value is smaller than the min value (max is ignored)"
		 "'>'",    "Threshold is triggered when the value is greater than the min value (max is ignored)"
		
		If the option is set to 'x' (threshold turned off) the callback is triggered with the fixed period.
		*/
		this.ipcon.sendRequest(this, BrickletAirQuality.FUNCTION_SET_AIR_PRESSURE_CALLBACK_CONFIGURATION, [period, valueHasToChange, option, min, max], 'I ? c i i', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getAirPressureCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the callback configuration as set by :func:`Set Air Pressure Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletAirQuality.FUNCTION_GET_AIR_PRESSURE_CALLBACK_CONFIGURATION, [], '', 22, 'I ? c i i', returnCallback, errorCallback, false, true);
	};
	this.removeCalibration = function(returnCallback, errorCallback) {
		/*
		Deletes the calibration from flash. After you call this function,
		you need to power cycle the Air Quality Bricklet.
		
		On the next power up the Bricklet will start a new calibration, as
		if it was started for the very first time.
		
		The calibration is based on the data of the last four days, so it takes
		four days until a full calibration is re-established.
		
		.. versionadded:: 2.0.3$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletAirQuality.FUNCTION_REMOVE_CALIBRATION, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.setBackgroundCalibrationDuration = function(duration, returnCallback, errorCallback) {
		/*
		The Air Quality Bricklet uses an automatic background calibration mechanism to
		calculate the IAQ Index. This calibration mechanism considers a history of
		measured data. The duration of this history can be configured to either be
		4 days or 28 days.
		
		If you keep the Bricklet mostly at one place and it does not get moved around
		to different environments, we recommend that you use a duration of 28 days.
		
		If you change the duration, the current calibration will be discarded and
		the calibration will start from beginning again. The configuration of the
		duration is saved in flash, so you should only have to call this function
		once in the lifetime of the Bricklet.
		
		The Bricklet has to be power cycled after this function is called
		for a duration change to take effect.
		
		Before firmware version 2.0.3 this was not configurable and the duration was
		4 days.
		
		The default value (since firmware version 2.0.3) is 28 days.
		
		.. versionadded:: 2.0.3$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletAirQuality.FUNCTION_SET_BACKGROUND_CALIBRATION_DURATION, [duration], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getBackgroundCalibrationDuration = function(returnCallback, errorCallback) {
		/*
		Returns the background calibration duration as set by
		:func:`Set Background Calibration Duration`.
		
		.. versionadded:: 2.0.3$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletAirQuality.FUNCTION_GET_BACKGROUND_CALIBRATION_DURATION, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPErrorCount = function(returnCallback, errorCallback) {
		/*
		Returns the error count for the communication between Brick and Bricklet.
		
		The errors are divided into
		
		* ACK checksum errors,
		* message checksum errors,
		* framing errors and
		* overflow errors.
		
		The errors counts are for errors that occur on the Bricklet side. All
		Bricks have a similar function that returns the errors on the Brick side.
		*/
		this.ipcon.sendRequest(this, BrickletAirQuality.FUNCTION_GET_SPITFP_ERROR_COUNT, [], '', 24, 'I I I I', returnCallback, errorCallback, false, true);
	};
	this.setBootloaderMode = function(mode, returnCallback, errorCallback) {
		/*
		Sets the bootloader mode and returns the status after the requested
		mode change was instigated.
		
		You can change from bootloader mode to firmware mode and vice versa. A change
		from bootloader mode to firmware mode will only take place if the entry function,
		device identifier and CRC are present and correct.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletAirQuality.FUNCTION_SET_BOOTLOADER_MODE, [mode], 'B', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getBootloaderMode = function(returnCallback, errorCallback) {
		/*
		Returns the current bootloader mode, see :func:`Set Bootloader Mode`.
		*/
		this.ipcon.sendRequest(this, BrickletAirQuality.FUNCTION_GET_BOOTLOADER_MODE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setWriteFirmwarePointer = function(pointer, returnCallback, errorCallback) {
		/*
		Sets the firmware pointer for :func:`Write Firmware`. The pointer has
		to be increased by chunks of size 64. The data is written to flash
		every 4 chunks (which equals to one page of size 256).
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletAirQuality.FUNCTION_SET_WRITE_FIRMWARE_POINTER, [pointer], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeFirmware = function(data, returnCallback, errorCallback) {
		/*
		Writes 64 Bytes of firmware at the position as written by
		:func:`Set Write Firmware Pointer` before. The firmware is written
		to flash every 4 chunks.
		
		You can only write firmware in bootloader mode.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletAirQuality.FUNCTION_WRITE_FIRMWARE, [data], 'B64', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setStatusLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Sets the status LED configuration. By default the LED shows
		communication traffic between Brick and Bricklet, it flickers once
		for every 10 received data packets.
		
		You can also turn the LED permanently on/off or show a heartbeat.
		
		If the Bricklet is in bootloader mode, the LED is will show heartbeat by default.
		*/
		this.ipcon.sendRequest(this, BrickletAirQuality.FUNCTION_SET_STATUS_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getStatusLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Status LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletAirQuality.FUNCTION_GET_STATUS_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getChipTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature as measured inside the microcontroller. The
		value returned is not the ambient temperature!
		
		The temperature is only proportional to the real temperature and it has bad
		accuracy. Practically it is only useful as an indicator for
		temperature changes.
		*/
		this.ipcon.sendRequest(this, BrickletAirQuality.FUNCTION_GET_CHIP_TEMPERATURE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.reset = function(returnCallback, errorCallback) {
		/*
		Calling this function will reset the Bricklet. All configurations
		will be lost.
		
		After a reset you have to create new device objects,
		calling functions on the existing ones will result in
		undefined behavior!
		*/
		this.ipcon.sendRequest(this, BrickletAirQuality.FUNCTION_RESET, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeUID = function(uid, returnCallback, errorCallback) {
		/*
		Writes a new UID into flash. If you want to set a new UID
		you have to decode the Base58 encoded UID string into an
		integer first.
		
		We recommend that you use Brick Viewer to change the UID.
		*/
		this.ipcon.sendRequest(this, BrickletAirQuality.FUNCTION_WRITE_UID, [uid], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.readUID = function(returnCallback, errorCallback) {
		/*
		Returns the current UID as an integer. Encode as
		Base58 to get the usual string version.
		*/
		this.ipcon.sendRequest(this, BrickletAirQuality.FUNCTION_READ_UID, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletAirQuality.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletAirQuality;

},{"./Device":279,"./IPConnection":280}],150:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletAmbientLight.DEVICE_IDENTIFIER = 21;
BrickletAmbientLight.DEVICE_DISPLAY_NAME = 'Ambient Light Bricklet';
BrickletAmbientLight.CALLBACK_ILLUMINANCE = 13;
BrickletAmbientLight.CALLBACK_ANALOG_VALUE = 14;
BrickletAmbientLight.CALLBACK_ILLUMINANCE_REACHED = 15;
BrickletAmbientLight.CALLBACK_ANALOG_VALUE_REACHED = 16;
BrickletAmbientLight.FUNCTION_GET_ILLUMINANCE = 1;
BrickletAmbientLight.FUNCTION_GET_ANALOG_VALUE = 2;
BrickletAmbientLight.FUNCTION_SET_ILLUMINANCE_CALLBACK_PERIOD = 3;
BrickletAmbientLight.FUNCTION_GET_ILLUMINANCE_CALLBACK_PERIOD = 4;
BrickletAmbientLight.FUNCTION_SET_ANALOG_VALUE_CALLBACK_PERIOD = 5;
BrickletAmbientLight.FUNCTION_GET_ANALOG_VALUE_CALLBACK_PERIOD = 6;
BrickletAmbientLight.FUNCTION_SET_ILLUMINANCE_CALLBACK_THRESHOLD = 7;
BrickletAmbientLight.FUNCTION_GET_ILLUMINANCE_CALLBACK_THRESHOLD = 8;
BrickletAmbientLight.FUNCTION_SET_ANALOG_VALUE_CALLBACK_THRESHOLD = 9;
BrickletAmbientLight.FUNCTION_GET_ANALOG_VALUE_CALLBACK_THRESHOLD = 10;
BrickletAmbientLight.FUNCTION_SET_DEBOUNCE_PERIOD = 11;
BrickletAmbientLight.FUNCTION_GET_DEBOUNCE_PERIOD = 12;
BrickletAmbientLight.FUNCTION_GET_IDENTITY = 255;
BrickletAmbientLight.THRESHOLD_OPTION_OFF = 'x';
BrickletAmbientLight.THRESHOLD_OPTION_OUTSIDE = 'o';
BrickletAmbientLight.THRESHOLD_OPTION_INSIDE = 'i';
BrickletAmbientLight.THRESHOLD_OPTION_SMALLER = '<';
BrickletAmbientLight.THRESHOLD_OPTION_GREATER = '>';

function BrickletAmbientLight(uid, ipcon) {
	//Measures ambient light up to 900lux

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletAmbientLight.DEVICE_IDENTIFIER, BrickletAmbientLight.DEVICE_DISPLAY_NAME);
	BrickletAmbientLight.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 1];
	this.responseExpected[BrickletAmbientLight.FUNCTION_GET_ILLUMINANCE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAmbientLight.FUNCTION_GET_ANALOG_VALUE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAmbientLight.FUNCTION_SET_ILLUMINANCE_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletAmbientLight.FUNCTION_GET_ILLUMINANCE_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAmbientLight.FUNCTION_SET_ANALOG_VALUE_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletAmbientLight.FUNCTION_GET_ANALOG_VALUE_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAmbientLight.FUNCTION_SET_ILLUMINANCE_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletAmbientLight.FUNCTION_GET_ILLUMINANCE_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAmbientLight.FUNCTION_SET_ANALOG_VALUE_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletAmbientLight.FUNCTION_GET_ANALOG_VALUE_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAmbientLight.FUNCTION_SET_DEBOUNCE_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletAmbientLight.FUNCTION_GET_DEBOUNCE_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAmbientLight.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletAmbientLight.CALLBACK_ILLUMINANCE] = [10, 'H'];
	this.callbackFormats[BrickletAmbientLight.CALLBACK_ANALOG_VALUE] = [10, 'H'];
	this.callbackFormats[BrickletAmbientLight.CALLBACK_ILLUMINANCE_REACHED] = [10, 'H'];
	this.callbackFormats[BrickletAmbientLight.CALLBACK_ANALOG_VALUE_REACHED] = [10, 'H'];



	this.getIlluminance = function(returnCallback, errorCallback) {
		/*
		Returns the illuminance of the ambient light sensor.
		
		If you want to get the illuminance periodically, it is recommended to use the
		:cb:`Illuminance` callback and set the period with
		:func:`Set Illuminance Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletAmbientLight.FUNCTION_GET_ILLUMINANCE, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.getAnalogValue = function(returnCallback, errorCallback) {
		/*
		Returns the value as read by a 12-bit analog-to-digital converter.
		
		.. note::
		 The value returned by :func:`Get Illuminance` is averaged over several samples
		 to yield less noise, while :func:`Get Analog Value` gives back raw
		 unfiltered analog values. The only reason to use :func:`Get Analog Value` is,
		 if you need the full resolution of the analog-to-digital converter.
		
		 Also, the analog-to-digital converter covers three different ranges that are
		 set dynamically depending on the light intensity. It is impossible to
		 distinguish between these ranges with the analog value.
		
		If you want the analog value periodically, it is recommended to use the
		:cb:`Analog Value` callback and set the period with
		:func:`Set Analog Value Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletAmbientLight.FUNCTION_GET_ANALOG_VALUE, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.setIlluminanceCallbackPeriod = function(period, returnCallback, errorCallback) {
		/*
		Sets the period with which the :cb:`Illuminance` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		The :cb:`Illuminance` callback is only triggered if the illuminance has changed
		since the last triggering.
		*/
		this.ipcon.sendRequest(this, BrickletAmbientLight.FUNCTION_SET_ILLUMINANCE_CALLBACK_PERIOD, [period], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getIlluminanceCallbackPeriod = function(returnCallback, errorCallback) {
		/*
		Returns the period as set by :func:`Set Illuminance Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletAmbientLight.FUNCTION_GET_ILLUMINANCE_CALLBACK_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setAnalogValueCallbackPeriod = function(period, returnCallback, errorCallback) {
		/*
		Sets the period with which the :cb:`Analog Value` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		The :cb:`Analog Value` callback is only triggered if the analog value has
		changed since the last triggering.
		*/
		this.ipcon.sendRequest(this, BrickletAmbientLight.FUNCTION_SET_ANALOG_VALUE_CALLBACK_PERIOD, [period], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getAnalogValueCallbackPeriod = function(returnCallback, errorCallback) {
		/*
		Returns the period as set by :func:`Set Analog Value Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletAmbientLight.FUNCTION_GET_ANALOG_VALUE_CALLBACK_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setIlluminanceCallbackThreshold = function(option, min, max, returnCallback, errorCallback) {
		/*
		Sets the thresholds for the :cb:`Illuminance Reached` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Callback is turned off"
		 "'o'",    "Callback is triggered when the illuminance is *outside* the min and max values"
		 "'i'",    "Callback is triggered when the illuminance is *inside* the min and max values"
		 "'<'",    "Callback is triggered when the illuminance is smaller than the min value (max is ignored)"
		 "'>'",    "Callback is triggered when the illuminance is greater than the min value (max is ignored)"
		*/
		this.ipcon.sendRequest(this, BrickletAmbientLight.FUNCTION_SET_ILLUMINANCE_CALLBACK_THRESHOLD, [option, min, max], 'c H H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getIlluminanceCallbackThreshold = function(returnCallback, errorCallback) {
		/*
		Returns the threshold as set by :func:`Set Illuminance Callback Threshold`.
		*/
		this.ipcon.sendRequest(this, BrickletAmbientLight.FUNCTION_GET_ILLUMINANCE_CALLBACK_THRESHOLD, [], '', 13, 'c H H', returnCallback, errorCallback, false, true);
	};
	this.setAnalogValueCallbackThreshold = function(option, min, max, returnCallback, errorCallback) {
		/*
		Sets the thresholds for the :cb:`Analog Value Reached` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Callback is turned off"
		 "'o'",    "Callback is triggered when the analog value is *outside* the min and max values"
		 "'i'",    "Callback is triggered when the analog value is *inside* the min and max values"
		 "'<'",    "Callback is triggered when the analog value is smaller than the min value (max is ignored)"
		 "'>'",    "Callback is triggered when the analog value is greater than the min value (max is ignored)"
		*/
		this.ipcon.sendRequest(this, BrickletAmbientLight.FUNCTION_SET_ANALOG_VALUE_CALLBACK_THRESHOLD, [option, min, max], 'c H H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getAnalogValueCallbackThreshold = function(returnCallback, errorCallback) {
		/*
		Returns the threshold as set by :func:`Set Analog Value Callback Threshold`.
		*/
		this.ipcon.sendRequest(this, BrickletAmbientLight.FUNCTION_GET_ANALOG_VALUE_CALLBACK_THRESHOLD, [], '', 13, 'c H H', returnCallback, errorCallback, false, true);
	};
	this.setDebouncePeriod = function(debounce, returnCallback, errorCallback) {
		/*
		Sets the period with which the threshold callbacks
		
		* :cb:`Illuminance Reached`,
		* :cb:`Analog Value Reached`
		
		are triggered, if the thresholds
		
		* :func:`Set Illuminance Callback Threshold`,
		* :func:`Set Analog Value Callback Threshold`
		
		keep being reached.
		*/
		this.ipcon.sendRequest(this, BrickletAmbientLight.FUNCTION_SET_DEBOUNCE_PERIOD, [debounce], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getDebouncePeriod = function(returnCallback, errorCallback) {
		/*
		Returns the debounce period as set by :func:`Set Debounce Period`.
		*/
		this.ipcon.sendRequest(this, BrickletAmbientLight.FUNCTION_GET_DEBOUNCE_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletAmbientLight.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletAmbientLight;

},{"./Device":279,"./IPConnection":280}],151:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletAmbientLightV2.DEVICE_IDENTIFIER = 259;
BrickletAmbientLightV2.DEVICE_DISPLAY_NAME = 'Ambient Light Bricklet 2.0';
BrickletAmbientLightV2.CALLBACK_ILLUMINANCE = 10;
BrickletAmbientLightV2.CALLBACK_ILLUMINANCE_REACHED = 11;
BrickletAmbientLightV2.FUNCTION_GET_ILLUMINANCE = 1;
BrickletAmbientLightV2.FUNCTION_SET_ILLUMINANCE_CALLBACK_PERIOD = 2;
BrickletAmbientLightV2.FUNCTION_GET_ILLUMINANCE_CALLBACK_PERIOD = 3;
BrickletAmbientLightV2.FUNCTION_SET_ILLUMINANCE_CALLBACK_THRESHOLD = 4;
BrickletAmbientLightV2.FUNCTION_GET_ILLUMINANCE_CALLBACK_THRESHOLD = 5;
BrickletAmbientLightV2.FUNCTION_SET_DEBOUNCE_PERIOD = 6;
BrickletAmbientLightV2.FUNCTION_GET_DEBOUNCE_PERIOD = 7;
BrickletAmbientLightV2.FUNCTION_SET_CONFIGURATION = 8;
BrickletAmbientLightV2.FUNCTION_GET_CONFIGURATION = 9;
BrickletAmbientLightV2.FUNCTION_GET_IDENTITY = 255;
BrickletAmbientLightV2.THRESHOLD_OPTION_OFF = 'x';
BrickletAmbientLightV2.THRESHOLD_OPTION_OUTSIDE = 'o';
BrickletAmbientLightV2.THRESHOLD_OPTION_INSIDE = 'i';
BrickletAmbientLightV2.THRESHOLD_OPTION_SMALLER = '<';
BrickletAmbientLightV2.THRESHOLD_OPTION_GREATER = '>';
BrickletAmbientLightV2.ILLUMINANCE_RANGE_UNLIMITED = 6;
BrickletAmbientLightV2.ILLUMINANCE_RANGE_64000LUX = 0;
BrickletAmbientLightV2.ILLUMINANCE_RANGE_32000LUX = 1;
BrickletAmbientLightV2.ILLUMINANCE_RANGE_16000LUX = 2;
BrickletAmbientLightV2.ILLUMINANCE_RANGE_8000LUX = 3;
BrickletAmbientLightV2.ILLUMINANCE_RANGE_1300LUX = 4;
BrickletAmbientLightV2.ILLUMINANCE_RANGE_600LUX = 5;
BrickletAmbientLightV2.INTEGRATION_TIME_50MS = 0;
BrickletAmbientLightV2.INTEGRATION_TIME_100MS = 1;
BrickletAmbientLightV2.INTEGRATION_TIME_150MS = 2;
BrickletAmbientLightV2.INTEGRATION_TIME_200MS = 3;
BrickletAmbientLightV2.INTEGRATION_TIME_250MS = 4;
BrickletAmbientLightV2.INTEGRATION_TIME_300MS = 5;
BrickletAmbientLightV2.INTEGRATION_TIME_350MS = 6;
BrickletAmbientLightV2.INTEGRATION_TIME_400MS = 7;

function BrickletAmbientLightV2(uid, ipcon) {
	//Measures ambient light up to 64000lux

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletAmbientLightV2.DEVICE_IDENTIFIER, BrickletAmbientLightV2.DEVICE_DISPLAY_NAME);
	BrickletAmbientLightV2.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 1];
	this.responseExpected[BrickletAmbientLightV2.FUNCTION_GET_ILLUMINANCE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAmbientLightV2.FUNCTION_SET_ILLUMINANCE_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletAmbientLightV2.FUNCTION_GET_ILLUMINANCE_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAmbientLightV2.FUNCTION_SET_ILLUMINANCE_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletAmbientLightV2.FUNCTION_GET_ILLUMINANCE_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAmbientLightV2.FUNCTION_SET_DEBOUNCE_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletAmbientLightV2.FUNCTION_GET_DEBOUNCE_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAmbientLightV2.FUNCTION_SET_CONFIGURATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletAmbientLightV2.FUNCTION_GET_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAmbientLightV2.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletAmbientLightV2.CALLBACK_ILLUMINANCE] = [12, 'I'];
	this.callbackFormats[BrickletAmbientLightV2.CALLBACK_ILLUMINANCE_REACHED] = [12, 'I'];



	this.getIlluminance = function(returnCallback, errorCallback) {
		/*
		Returns the illuminance of the ambient light sensor. The measurement range goes
		up to about 100000lux, but above 64000lux the precision starts to drop.
		
		.. versionchanged:: 2.0.2$nbsp;(Plugin)
		  An illuminance of 0lux indicates an error condition where the sensor cannot
		  perform a reasonable measurement. This can happen with very dim or very bright
		  light conditions. In bright light conditions this might indicate that the sensor
		  is saturated and the configuration should be modified (:func:`Set Configuration`)
		  to better match the light conditions.
		
		If you want to get the illuminance periodically, it is recommended to use the
		:cb:`Illuminance` callback and set the period with
		:func:`Set Illuminance Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletAmbientLightV2.FUNCTION_GET_ILLUMINANCE, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setIlluminanceCallbackPeriod = function(period, returnCallback, errorCallback) {
		/*
		Sets the period with which the :cb:`Illuminance` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		The :cb:`Illuminance` callback is only triggered if the illuminance has changed
		since the last triggering.
		*/
		this.ipcon.sendRequest(this, BrickletAmbientLightV2.FUNCTION_SET_ILLUMINANCE_CALLBACK_PERIOD, [period], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getIlluminanceCallbackPeriod = function(returnCallback, errorCallback) {
		/*
		Returns the period as set by :func:`Set Illuminance Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletAmbientLightV2.FUNCTION_GET_ILLUMINANCE_CALLBACK_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setIlluminanceCallbackThreshold = function(option, min, max, returnCallback, errorCallback) {
		/*
		Sets the thresholds for the :cb:`Illuminance Reached` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Callback is turned off"
		 "'o'",    "Callback is triggered when the illuminance is *outside* the min and max values"
		 "'i'",    "Callback is triggered when the illuminance is *inside* the min and max values"
		 "'<'",    "Callback is triggered when the illuminance is smaller than the min value (max is ignored)"
		 "'>'",    "Callback is triggered when the illuminance is greater than the min value (max is ignored)"
		*/
		this.ipcon.sendRequest(this, BrickletAmbientLightV2.FUNCTION_SET_ILLUMINANCE_CALLBACK_THRESHOLD, [option, min, max], 'c I I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getIlluminanceCallbackThreshold = function(returnCallback, errorCallback) {
		/*
		Returns the threshold as set by :func:`Set Illuminance Callback Threshold`.
		*/
		this.ipcon.sendRequest(this, BrickletAmbientLightV2.FUNCTION_GET_ILLUMINANCE_CALLBACK_THRESHOLD, [], '', 17, 'c I I', returnCallback, errorCallback, false, true);
	};
	this.setDebouncePeriod = function(debounce, returnCallback, errorCallback) {
		/*
		Sets the period with which the threshold callbacks
		
		* :cb:`Illuminance Reached`,
		
		are triggered, if the thresholds
		
		* :func:`Set Illuminance Callback Threshold`,
		
		keep being reached.
		*/
		this.ipcon.sendRequest(this, BrickletAmbientLightV2.FUNCTION_SET_DEBOUNCE_PERIOD, [debounce], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getDebouncePeriod = function(returnCallback, errorCallback) {
		/*
		Returns the debounce period as set by :func:`Set Debounce Period`.
		*/
		this.ipcon.sendRequest(this, BrickletAmbientLightV2.FUNCTION_GET_DEBOUNCE_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setConfiguration = function(illuminanceRange, integrationTime, returnCallback, errorCallback) {
		/*
		Sets the configuration. It is possible to configure an illuminance range
		between 0-600lux and 0-64000lux and an integration time between 50ms and 400ms.
		
		.. versionadded:: 2.0.2$nbsp;(Plugin)
		  The unlimited illuminance range allows to measure up to about 100000lux, but
		  above 64000lux the precision starts to drop.
		
		A smaller illuminance range increases the resolution of the data. A longer
		integration time will result in less noise on the data.
		
		.. versionchanged:: 2.0.2$nbsp;(Plugin)
		  If the actual measure illuminance is out-of-range then the current illuminance
		  range maximum +0.01lux is reported by :func:`Get Illuminance` and the
		  :cb:`Illuminance` callback. For example, 800001 for the 0-8000lux range.
		
		.. versionchanged:: 2.0.2$nbsp;(Plugin)
		  With a long integration time the sensor might be saturated before the measured
		  value reaches the maximum of the selected illuminance range. In this case 0lux
		  is reported by :func:`Get Illuminance` and the :cb:`Illuminance` callback.
		
		If the measurement is out-of-range or the sensor is saturated then you should
		configure the next higher illuminance range. If the highest range is already
		in use, then start to reduce the integration time.
		*/
		this.ipcon.sendRequest(this, BrickletAmbientLightV2.FUNCTION_SET_CONFIGURATION, [illuminanceRange, integrationTime], 'B B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletAmbientLightV2.FUNCTION_GET_CONFIGURATION, [], '', 10, 'B B', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletAmbientLightV2.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletAmbientLightV2;

},{"./Device":279,"./IPConnection":280}],152:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletAmbientLightV3.DEVICE_IDENTIFIER = 2131;
BrickletAmbientLightV3.DEVICE_DISPLAY_NAME = 'Ambient Light Bricklet 3.0';
BrickletAmbientLightV3.CALLBACK_ILLUMINANCE = 4;
BrickletAmbientLightV3.FUNCTION_GET_ILLUMINANCE = 1;
BrickletAmbientLightV3.FUNCTION_SET_ILLUMINANCE_CALLBACK_CONFIGURATION = 2;
BrickletAmbientLightV3.FUNCTION_GET_ILLUMINANCE_CALLBACK_CONFIGURATION = 3;
BrickletAmbientLightV3.FUNCTION_SET_CONFIGURATION = 5;
BrickletAmbientLightV3.FUNCTION_GET_CONFIGURATION = 6;
BrickletAmbientLightV3.FUNCTION_GET_SPITFP_ERROR_COUNT = 234;
BrickletAmbientLightV3.FUNCTION_SET_BOOTLOADER_MODE = 235;
BrickletAmbientLightV3.FUNCTION_GET_BOOTLOADER_MODE = 236;
BrickletAmbientLightV3.FUNCTION_SET_WRITE_FIRMWARE_POINTER = 237;
BrickletAmbientLightV3.FUNCTION_WRITE_FIRMWARE = 238;
BrickletAmbientLightV3.FUNCTION_SET_STATUS_LED_CONFIG = 239;
BrickletAmbientLightV3.FUNCTION_GET_STATUS_LED_CONFIG = 240;
BrickletAmbientLightV3.FUNCTION_GET_CHIP_TEMPERATURE = 242;
BrickletAmbientLightV3.FUNCTION_RESET = 243;
BrickletAmbientLightV3.FUNCTION_WRITE_UID = 248;
BrickletAmbientLightV3.FUNCTION_READ_UID = 249;
BrickletAmbientLightV3.FUNCTION_GET_IDENTITY = 255;
BrickletAmbientLightV3.THRESHOLD_OPTION_OFF = 'x';
BrickletAmbientLightV3.THRESHOLD_OPTION_OUTSIDE = 'o';
BrickletAmbientLightV3.THRESHOLD_OPTION_INSIDE = 'i';
BrickletAmbientLightV3.THRESHOLD_OPTION_SMALLER = '<';
BrickletAmbientLightV3.THRESHOLD_OPTION_GREATER = '>';
BrickletAmbientLightV3.ILLUMINANCE_RANGE_UNLIMITED = 6;
BrickletAmbientLightV3.ILLUMINANCE_RANGE_64000LUX = 0;
BrickletAmbientLightV3.ILLUMINANCE_RANGE_32000LUX = 1;
BrickletAmbientLightV3.ILLUMINANCE_RANGE_16000LUX = 2;
BrickletAmbientLightV3.ILLUMINANCE_RANGE_8000LUX = 3;
BrickletAmbientLightV3.ILLUMINANCE_RANGE_1300LUX = 4;
BrickletAmbientLightV3.ILLUMINANCE_RANGE_600LUX = 5;
BrickletAmbientLightV3.INTEGRATION_TIME_50MS = 0;
BrickletAmbientLightV3.INTEGRATION_TIME_100MS = 1;
BrickletAmbientLightV3.INTEGRATION_TIME_150MS = 2;
BrickletAmbientLightV3.INTEGRATION_TIME_200MS = 3;
BrickletAmbientLightV3.INTEGRATION_TIME_250MS = 4;
BrickletAmbientLightV3.INTEGRATION_TIME_300MS = 5;
BrickletAmbientLightV3.INTEGRATION_TIME_350MS = 6;
BrickletAmbientLightV3.INTEGRATION_TIME_400MS = 7;
BrickletAmbientLightV3.BOOTLOADER_MODE_BOOTLOADER = 0;
BrickletAmbientLightV3.BOOTLOADER_MODE_FIRMWARE = 1;
BrickletAmbientLightV3.BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT = 2;
BrickletAmbientLightV3.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT = 3;
BrickletAmbientLightV3.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT = 4;
BrickletAmbientLightV3.BOOTLOADER_STATUS_OK = 0;
BrickletAmbientLightV3.BOOTLOADER_STATUS_INVALID_MODE = 1;
BrickletAmbientLightV3.BOOTLOADER_STATUS_NO_CHANGE = 2;
BrickletAmbientLightV3.BOOTLOADER_STATUS_ENTRY_FUNCTION_NOT_PRESENT = 3;
BrickletAmbientLightV3.BOOTLOADER_STATUS_DEVICE_IDENTIFIER_INCORRECT = 4;
BrickletAmbientLightV3.BOOTLOADER_STATUS_CRC_MISMATCH = 5;
BrickletAmbientLightV3.STATUS_LED_CONFIG_OFF = 0;
BrickletAmbientLightV3.STATUS_LED_CONFIG_ON = 1;
BrickletAmbientLightV3.STATUS_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletAmbientLightV3.STATUS_LED_CONFIG_SHOW_STATUS = 3;

function BrickletAmbientLightV3(uid, ipcon) {
	//Measures ambient light up to 64000lux

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletAmbientLightV3.DEVICE_IDENTIFIER, BrickletAmbientLightV3.DEVICE_DISPLAY_NAME);
	BrickletAmbientLightV3.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickletAmbientLightV3.FUNCTION_GET_ILLUMINANCE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAmbientLightV3.FUNCTION_SET_ILLUMINANCE_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletAmbientLightV3.FUNCTION_GET_ILLUMINANCE_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAmbientLightV3.FUNCTION_SET_CONFIGURATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletAmbientLightV3.FUNCTION_GET_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAmbientLightV3.FUNCTION_GET_SPITFP_ERROR_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAmbientLightV3.FUNCTION_SET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAmbientLightV3.FUNCTION_GET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAmbientLightV3.FUNCTION_SET_WRITE_FIRMWARE_POINTER] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletAmbientLightV3.FUNCTION_WRITE_FIRMWARE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAmbientLightV3.FUNCTION_SET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletAmbientLightV3.FUNCTION_GET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAmbientLightV3.FUNCTION_GET_CHIP_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAmbientLightV3.FUNCTION_RESET] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletAmbientLightV3.FUNCTION_WRITE_UID] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletAmbientLightV3.FUNCTION_READ_UID] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAmbientLightV3.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletAmbientLightV3.CALLBACK_ILLUMINANCE] = [12, 'I'];



	this.getIlluminance = function(returnCallback, errorCallback) {
		/*
		Returns the illuminance of the ambient light sensor. The measurement range goes
		up to about 100000lux, but above 64000lux the precision starts to drop.
		The illuminance is given in lux/100, i.e. a value of 450000 means that an
		illuminance of 4500lux is measured.
		
		An illuminance of 0lux indicates an error condition where the sensor cannot
		perform a reasonable measurement. This can happen with very dim or very bright
		light conditions. In bright light conditions this might indicate that the sensor
		is saturated and the configuration should be modified (:func:`Set Configuration`)
		to better match the conditions.
		
		
		If you want to get the value periodically, it is recommended to use the
		:cb:`Illuminance` callback. You can set the callback configuration
		with :func:`Set Illuminance Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletAmbientLightV3.FUNCTION_GET_ILLUMINANCE, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setIlluminanceCallbackConfiguration = function(period, valueHasToChange, option, min, max, returnCallback, errorCallback) {
		/*
		The period is the period with which the :cb:`Illuminance` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		If the `value has to change`-parameter is set to true, the callback is only
		triggered after the value has changed. If the value didn't change
		within the period, the callback is triggered immediately on change.
		
		If it is set to false, the callback is continuously triggered with the period,
		independent of the value.
		
		It is furthermore possible to constrain the callback with thresholds.
		
		The `option`-parameter together with min/max sets a threshold for the :cb:`Illuminance` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Threshold is turned off"
		 "'o'",    "Threshold is triggered when the value is *outside* the min and max values"
		 "'i'",    "Threshold is triggered when the value is *inside* or equal to the min and max values"
		 "'<'",    "Threshold is triggered when the value is smaller than the min value (max is ignored)"
		 "'>'",    "Threshold is triggered when the value is greater than the min value (max is ignored)"
		
		If the option is set to 'x' (threshold turned off) the callback is triggered with the fixed period.
		*/
		this.ipcon.sendRequest(this, BrickletAmbientLightV3.FUNCTION_SET_ILLUMINANCE_CALLBACK_CONFIGURATION, [period, valueHasToChange, option, min, max], 'I ? c I I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getIlluminanceCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the callback configuration as set by :func:`Set Illuminance Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletAmbientLightV3.FUNCTION_GET_ILLUMINANCE_CALLBACK_CONFIGURATION, [], '', 22, 'I ? c I I', returnCallback, errorCallback, false, true);
	};
	this.setConfiguration = function(illuminanceRange, integrationTime, returnCallback, errorCallback) {
		/*
		Sets the configuration. It is possible to configure an illuminance range
		between 0-600lux and 0-64000lux and an integration time between 50ms and 400ms.
		
		The unlimited illuminance range allows to measure up to about 100000lux, but
		above 64000lux the precision starts to drop.
		
		A smaller illuminance range increases the resolution of the data. A longer
		integration time will result in less noise on the data.
		
		If the actual measure illuminance is out-of-range then the current illuminance
		range maximum +0.01lux is reported by :func:`Get Illuminance` and the
		:cb:`Illuminance` callback. For example, 800001 for the 0-8000lux range.
		
		With a long integration time the sensor might be saturated before the measured
		value reaches the maximum of the selected illuminance range. In this case 0lux
		is reported by :func:`Get Illuminance` and the :cb:`Illuminance` callback.
		
		If the measurement is out-of-range or the sensor is saturated then you should
		configure the next higher illuminance range. If the highest range is already
		in use, then start to reduce the integration time.
		*/
		this.ipcon.sendRequest(this, BrickletAmbientLightV3.FUNCTION_SET_CONFIGURATION, [illuminanceRange, integrationTime], 'B B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletAmbientLightV3.FUNCTION_GET_CONFIGURATION, [], '', 10, 'B B', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPErrorCount = function(returnCallback, errorCallback) {
		/*
		Returns the error count for the communication between Brick and Bricklet.
		
		The errors are divided into
		
		* ACK checksum errors,
		* message checksum errors,
		* framing errors and
		* overflow errors.
		
		The errors counts are for errors that occur on the Bricklet side. All
		Bricks have a similar function that returns the errors on the Brick side.
		*/
		this.ipcon.sendRequest(this, BrickletAmbientLightV3.FUNCTION_GET_SPITFP_ERROR_COUNT, [], '', 24, 'I I I I', returnCallback, errorCallback, false, true);
	};
	this.setBootloaderMode = function(mode, returnCallback, errorCallback) {
		/*
		Sets the bootloader mode and returns the status after the requested
		mode change was instigated.
		
		You can change from bootloader mode to firmware mode and vice versa. A change
		from bootloader mode to firmware mode will only take place if the entry function,
		device identifier and CRC are present and correct.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletAmbientLightV3.FUNCTION_SET_BOOTLOADER_MODE, [mode], 'B', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getBootloaderMode = function(returnCallback, errorCallback) {
		/*
		Returns the current bootloader mode, see :func:`Set Bootloader Mode`.
		*/
		this.ipcon.sendRequest(this, BrickletAmbientLightV3.FUNCTION_GET_BOOTLOADER_MODE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setWriteFirmwarePointer = function(pointer, returnCallback, errorCallback) {
		/*
		Sets the firmware pointer for :func:`Write Firmware`. The pointer has
		to be increased by chunks of size 64. The data is written to flash
		every 4 chunks (which equals to one page of size 256).
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletAmbientLightV3.FUNCTION_SET_WRITE_FIRMWARE_POINTER, [pointer], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeFirmware = function(data, returnCallback, errorCallback) {
		/*
		Writes 64 Bytes of firmware at the position as written by
		:func:`Set Write Firmware Pointer` before. The firmware is written
		to flash every 4 chunks.
		
		You can only write firmware in bootloader mode.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletAmbientLightV3.FUNCTION_WRITE_FIRMWARE, [data], 'B64', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setStatusLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Sets the status LED configuration. By default the LED shows
		communication traffic between Brick and Bricklet, it flickers once
		for every 10 received data packets.
		
		You can also turn the LED permanently on/off or show a heartbeat.
		
		If the Bricklet is in bootloader mode, the LED is will show heartbeat by default.
		*/
		this.ipcon.sendRequest(this, BrickletAmbientLightV3.FUNCTION_SET_STATUS_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getStatusLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Status LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletAmbientLightV3.FUNCTION_GET_STATUS_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getChipTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature as measured inside the microcontroller. The
		value returned is not the ambient temperature!
		
		The temperature is only proportional to the real temperature and it has bad
		accuracy. Practically it is only useful as an indicator for
		temperature changes.
		*/
		this.ipcon.sendRequest(this, BrickletAmbientLightV3.FUNCTION_GET_CHIP_TEMPERATURE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.reset = function(returnCallback, errorCallback) {
		/*
		Calling this function will reset the Bricklet. All configurations
		will be lost.
		
		After a reset you have to create new device objects,
		calling functions on the existing ones will result in
		undefined behavior!
		*/
		this.ipcon.sendRequest(this, BrickletAmbientLightV3.FUNCTION_RESET, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeUID = function(uid, returnCallback, errorCallback) {
		/*
		Writes a new UID into flash. If you want to set a new UID
		you have to decode the Base58 encoded UID string into an
		integer first.
		
		We recommend that you use Brick Viewer to change the UID.
		*/
		this.ipcon.sendRequest(this, BrickletAmbientLightV3.FUNCTION_WRITE_UID, [uid], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.readUID = function(returnCallback, errorCallback) {
		/*
		Returns the current UID as an integer. Encode as
		Base58 to get the usual string version.
		*/
		this.ipcon.sendRequest(this, BrickletAmbientLightV3.FUNCTION_READ_UID, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletAmbientLightV3.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletAmbientLightV3;

},{"./Device":279,"./IPConnection":280}],153:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletAnalogIn.DEVICE_IDENTIFIER = 219;
BrickletAnalogIn.DEVICE_DISPLAY_NAME = 'Analog In Bricklet';
BrickletAnalogIn.CALLBACK_VOLTAGE = 13;
BrickletAnalogIn.CALLBACK_ANALOG_VALUE = 14;
BrickletAnalogIn.CALLBACK_VOLTAGE_REACHED = 15;
BrickletAnalogIn.CALLBACK_ANALOG_VALUE_REACHED = 16;
BrickletAnalogIn.FUNCTION_GET_VOLTAGE = 1;
BrickletAnalogIn.FUNCTION_GET_ANALOG_VALUE = 2;
BrickletAnalogIn.FUNCTION_SET_VOLTAGE_CALLBACK_PERIOD = 3;
BrickletAnalogIn.FUNCTION_GET_VOLTAGE_CALLBACK_PERIOD = 4;
BrickletAnalogIn.FUNCTION_SET_ANALOG_VALUE_CALLBACK_PERIOD = 5;
BrickletAnalogIn.FUNCTION_GET_ANALOG_VALUE_CALLBACK_PERIOD = 6;
BrickletAnalogIn.FUNCTION_SET_VOLTAGE_CALLBACK_THRESHOLD = 7;
BrickletAnalogIn.FUNCTION_GET_VOLTAGE_CALLBACK_THRESHOLD = 8;
BrickletAnalogIn.FUNCTION_SET_ANALOG_VALUE_CALLBACK_THRESHOLD = 9;
BrickletAnalogIn.FUNCTION_GET_ANALOG_VALUE_CALLBACK_THRESHOLD = 10;
BrickletAnalogIn.FUNCTION_SET_DEBOUNCE_PERIOD = 11;
BrickletAnalogIn.FUNCTION_GET_DEBOUNCE_PERIOD = 12;
BrickletAnalogIn.FUNCTION_SET_RANGE = 17;
BrickletAnalogIn.FUNCTION_GET_RANGE = 18;
BrickletAnalogIn.FUNCTION_SET_AVERAGING = 19;
BrickletAnalogIn.FUNCTION_GET_AVERAGING = 20;
BrickletAnalogIn.FUNCTION_GET_IDENTITY = 255;
BrickletAnalogIn.THRESHOLD_OPTION_OFF = 'x';
BrickletAnalogIn.THRESHOLD_OPTION_OUTSIDE = 'o';
BrickletAnalogIn.THRESHOLD_OPTION_INSIDE = 'i';
BrickletAnalogIn.THRESHOLD_OPTION_SMALLER = '<';
BrickletAnalogIn.THRESHOLD_OPTION_GREATER = '>';
BrickletAnalogIn.RANGE_AUTOMATIC = 0;
BrickletAnalogIn.RANGE_UP_TO_6V = 1;
BrickletAnalogIn.RANGE_UP_TO_10V = 2;
BrickletAnalogIn.RANGE_UP_TO_36V = 3;
BrickletAnalogIn.RANGE_UP_TO_45V = 4;
BrickletAnalogIn.RANGE_UP_TO_3V = 5;

function BrickletAnalogIn(uid, ipcon) {
	//Measures DC voltage between 0V and 45V

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletAnalogIn.DEVICE_IDENTIFIER, BrickletAnalogIn.DEVICE_DISPLAY_NAME);
	BrickletAnalogIn.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 3];
	this.responseExpected[BrickletAnalogIn.FUNCTION_GET_VOLTAGE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAnalogIn.FUNCTION_GET_ANALOG_VALUE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAnalogIn.FUNCTION_SET_VOLTAGE_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletAnalogIn.FUNCTION_GET_VOLTAGE_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAnalogIn.FUNCTION_SET_ANALOG_VALUE_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletAnalogIn.FUNCTION_GET_ANALOG_VALUE_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAnalogIn.FUNCTION_SET_VOLTAGE_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletAnalogIn.FUNCTION_GET_VOLTAGE_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAnalogIn.FUNCTION_SET_ANALOG_VALUE_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletAnalogIn.FUNCTION_GET_ANALOG_VALUE_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAnalogIn.FUNCTION_SET_DEBOUNCE_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletAnalogIn.FUNCTION_GET_DEBOUNCE_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAnalogIn.FUNCTION_SET_RANGE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletAnalogIn.FUNCTION_GET_RANGE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAnalogIn.FUNCTION_SET_AVERAGING] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletAnalogIn.FUNCTION_GET_AVERAGING] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAnalogIn.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletAnalogIn.CALLBACK_VOLTAGE] = [10, 'H'];
	this.callbackFormats[BrickletAnalogIn.CALLBACK_ANALOG_VALUE] = [10, 'H'];
	this.callbackFormats[BrickletAnalogIn.CALLBACK_VOLTAGE_REACHED] = [10, 'H'];
	this.callbackFormats[BrickletAnalogIn.CALLBACK_ANALOG_VALUE_REACHED] = [10, 'H'];



	this.getVoltage = function(returnCallback, errorCallback) {
		/*
		Returns the voltage of the sensor. The resolution between 0 and 6V is about 2mV.
		Between 6 and 45V the resolution is about 10mV.
		
		If you want to get the voltage periodically, it is recommended to use the
		:cb:`Voltage` callback and set the period with
		:func:`Set Voltage Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletAnalogIn.FUNCTION_GET_VOLTAGE, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.getAnalogValue = function(returnCallback, errorCallback) {
		/*
		Returns the value as read by a 12-bit analog-to-digital converter.
		
		.. note::
		 The value returned by :func:`Get Voltage` is averaged over several samples
		 to yield less noise, while :func:`Get Analog Value` gives back raw
		 unfiltered analog values. The only reason to use :func:`Get Analog Value` is,
		 if you need the full resolution of the analog-to-digital converter.
		
		If you want the analog value periodically, it is recommended to use the
		:cb:`Analog Value` callback and set the period with
		:func:`Set Analog Value Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletAnalogIn.FUNCTION_GET_ANALOG_VALUE, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.setVoltageCallbackPeriod = function(period, returnCallback, errorCallback) {
		/*
		Sets the period with which the :cb:`Voltage` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		The :cb:`Voltage` callback is only triggered if the voltage has changed since
		the last triggering.
		*/
		this.ipcon.sendRequest(this, BrickletAnalogIn.FUNCTION_SET_VOLTAGE_CALLBACK_PERIOD, [period], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getVoltageCallbackPeriod = function(returnCallback, errorCallback) {
		/*
		Returns the period as set by :func:`Set Voltage Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletAnalogIn.FUNCTION_GET_VOLTAGE_CALLBACK_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setAnalogValueCallbackPeriod = function(period, returnCallback, errorCallback) {
		/*
		Sets the period with which the :cb:`Analog Value` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		The :cb:`Analog Value` callback is only triggered if the analog value has
		changed since the last triggering.
		*/
		this.ipcon.sendRequest(this, BrickletAnalogIn.FUNCTION_SET_ANALOG_VALUE_CALLBACK_PERIOD, [period], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getAnalogValueCallbackPeriod = function(returnCallback, errorCallback) {
		/*
		Returns the period as set by :func:`Set Analog Value Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletAnalogIn.FUNCTION_GET_ANALOG_VALUE_CALLBACK_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setVoltageCallbackThreshold = function(option, min, max, returnCallback, errorCallback) {
		/*
		Sets the thresholds for the :cb:`Voltage Reached` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Callback is turned off"
		 "'o'",    "Callback is triggered when the voltage is *outside* the min and max values"
		 "'i'",    "Callback is triggered when the voltage is *inside* the min and max values"
		 "'<'",    "Callback is triggered when the voltage is smaller than the min value (max is ignored)"
		 "'>'",    "Callback is triggered when the voltage is greater than the min value (max is ignored)"
		*/
		this.ipcon.sendRequest(this, BrickletAnalogIn.FUNCTION_SET_VOLTAGE_CALLBACK_THRESHOLD, [option, min, max], 'c H H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getVoltageCallbackThreshold = function(returnCallback, errorCallback) {
		/*
		Returns the threshold as set by :func:`Set Voltage Callback Threshold`.
		*/
		this.ipcon.sendRequest(this, BrickletAnalogIn.FUNCTION_GET_VOLTAGE_CALLBACK_THRESHOLD, [], '', 13, 'c H H', returnCallback, errorCallback, false, true);
	};
	this.setAnalogValueCallbackThreshold = function(option, min, max, returnCallback, errorCallback) {
		/*
		Sets the thresholds for the :cb:`Analog Value Reached` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Callback is turned off"
		 "'o'",    "Callback is triggered when the analog value is *outside* the min and max values"
		 "'i'",    "Callback is triggered when the analog value is *inside* the min and max values"
		 "'<'",    "Callback is triggered when the analog value is smaller than the min value (max is ignored)"
		 "'>'",    "Callback is triggered when the analog value is greater than the min value (max is ignored)"
		*/
		this.ipcon.sendRequest(this, BrickletAnalogIn.FUNCTION_SET_ANALOG_VALUE_CALLBACK_THRESHOLD, [option, min, max], 'c H H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getAnalogValueCallbackThreshold = function(returnCallback, errorCallback) {
		/*
		Returns the threshold as set by :func:`Set Analog Value Callback Threshold`.
		*/
		this.ipcon.sendRequest(this, BrickletAnalogIn.FUNCTION_GET_ANALOG_VALUE_CALLBACK_THRESHOLD, [], '', 13, 'c H H', returnCallback, errorCallback, false, true);
	};
	this.setDebouncePeriod = function(debounce, returnCallback, errorCallback) {
		/*
		Sets the period with which the threshold callbacks
		
		* :cb:`Voltage Reached`,
		* :cb:`Analog Value Reached`
		
		are triggered, if the thresholds
		
		* :func:`Set Voltage Callback Threshold`,
		* :func:`Set Analog Value Callback Threshold`
		
		keep being reached.
		*/
		this.ipcon.sendRequest(this, BrickletAnalogIn.FUNCTION_SET_DEBOUNCE_PERIOD, [debounce], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getDebouncePeriod = function(returnCallback, errorCallback) {
		/*
		Returns the debounce period as set by :func:`Set Debounce Period`.
		*/
		this.ipcon.sendRequest(this, BrickletAnalogIn.FUNCTION_GET_DEBOUNCE_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setRange = function(range, returnCallback, errorCallback) {
		/*
		Sets the measurement range. Possible ranges:
		
		* 0: Automatically switched
		* 1: 0V - 6.05V, ~1.48mV resolution
		* 2: 0V - 10.32V, ~2.52mV resolution
		* 3: 0V - 36.30V, ~8.86mV resolution
		* 4: 0V - 45.00V, ~11.25mV resolution
		* 5: 0V - 3.3V, ~0.81mV resolution, new in version 2.0.3$nbsp;(Plugin)
		
		.. versionadded:: 2.0.1$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletAnalogIn.FUNCTION_SET_RANGE, [range], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getRange = function(returnCallback, errorCallback) {
		/*
		Returns the measurement range as set by :func:`Set Range`.
		
		.. versionadded:: 2.0.1$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletAnalogIn.FUNCTION_GET_RANGE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setAveraging = function(average, returnCallback, errorCallback) {
		/*
		Set the length of a averaging for the voltage value.
		
		Setting the length to 0 will turn the averaging completely off. If the
		averaging is off, there is more noise on the data, but the data is without
		delay.
		
		.. versionadded:: 2.0.3$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletAnalogIn.FUNCTION_SET_AVERAGING, [average], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getAveraging = function(returnCallback, errorCallback) {
		/*
		Returns the averaging configuration as set by :func:`Set Averaging`.
		
		.. versionadded:: 2.0.3$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletAnalogIn.FUNCTION_GET_AVERAGING, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletAnalogIn.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletAnalogIn;

},{"./Device":279,"./IPConnection":280}],154:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletAnalogInV2.DEVICE_IDENTIFIER = 251;
BrickletAnalogInV2.DEVICE_DISPLAY_NAME = 'Analog In Bricklet 2.0';
BrickletAnalogInV2.CALLBACK_VOLTAGE = 15;
BrickletAnalogInV2.CALLBACK_ANALOG_VALUE = 16;
BrickletAnalogInV2.CALLBACK_VOLTAGE_REACHED = 17;
BrickletAnalogInV2.CALLBACK_ANALOG_VALUE_REACHED = 18;
BrickletAnalogInV2.FUNCTION_GET_VOLTAGE = 1;
BrickletAnalogInV2.FUNCTION_GET_ANALOG_VALUE = 2;
BrickletAnalogInV2.FUNCTION_SET_VOLTAGE_CALLBACK_PERIOD = 3;
BrickletAnalogInV2.FUNCTION_GET_VOLTAGE_CALLBACK_PERIOD = 4;
BrickletAnalogInV2.FUNCTION_SET_ANALOG_VALUE_CALLBACK_PERIOD = 5;
BrickletAnalogInV2.FUNCTION_GET_ANALOG_VALUE_CALLBACK_PERIOD = 6;
BrickletAnalogInV2.FUNCTION_SET_VOLTAGE_CALLBACK_THRESHOLD = 7;
BrickletAnalogInV2.FUNCTION_GET_VOLTAGE_CALLBACK_THRESHOLD = 8;
BrickletAnalogInV2.FUNCTION_SET_ANALOG_VALUE_CALLBACK_THRESHOLD = 9;
BrickletAnalogInV2.FUNCTION_GET_ANALOG_VALUE_CALLBACK_THRESHOLD = 10;
BrickletAnalogInV2.FUNCTION_SET_DEBOUNCE_PERIOD = 11;
BrickletAnalogInV2.FUNCTION_GET_DEBOUNCE_PERIOD = 12;
BrickletAnalogInV2.FUNCTION_SET_MOVING_AVERAGE = 13;
BrickletAnalogInV2.FUNCTION_GET_MOVING_AVERAGE = 14;
BrickletAnalogInV2.FUNCTION_GET_IDENTITY = 255;
BrickletAnalogInV2.THRESHOLD_OPTION_OFF = 'x';
BrickletAnalogInV2.THRESHOLD_OPTION_OUTSIDE = 'o';
BrickletAnalogInV2.THRESHOLD_OPTION_INSIDE = 'i';
BrickletAnalogInV2.THRESHOLD_OPTION_SMALLER = '<';
BrickletAnalogInV2.THRESHOLD_OPTION_GREATER = '>';

function BrickletAnalogInV2(uid, ipcon) {
	//Measures DC voltage between 0V and 42V

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletAnalogInV2.DEVICE_IDENTIFIER, BrickletAnalogInV2.DEVICE_DISPLAY_NAME);
	BrickletAnalogInV2.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 1];
	this.responseExpected[BrickletAnalogInV2.FUNCTION_GET_VOLTAGE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAnalogInV2.FUNCTION_GET_ANALOG_VALUE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAnalogInV2.FUNCTION_SET_VOLTAGE_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletAnalogInV2.FUNCTION_GET_VOLTAGE_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAnalogInV2.FUNCTION_SET_ANALOG_VALUE_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletAnalogInV2.FUNCTION_GET_ANALOG_VALUE_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAnalogInV2.FUNCTION_SET_VOLTAGE_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletAnalogInV2.FUNCTION_GET_VOLTAGE_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAnalogInV2.FUNCTION_SET_ANALOG_VALUE_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletAnalogInV2.FUNCTION_GET_ANALOG_VALUE_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAnalogInV2.FUNCTION_SET_DEBOUNCE_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletAnalogInV2.FUNCTION_GET_DEBOUNCE_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAnalogInV2.FUNCTION_SET_MOVING_AVERAGE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletAnalogInV2.FUNCTION_GET_MOVING_AVERAGE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAnalogInV2.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletAnalogInV2.CALLBACK_VOLTAGE] = [10, 'H'];
	this.callbackFormats[BrickletAnalogInV2.CALLBACK_ANALOG_VALUE] = [10, 'H'];
	this.callbackFormats[BrickletAnalogInV2.CALLBACK_VOLTAGE_REACHED] = [10, 'H'];
	this.callbackFormats[BrickletAnalogInV2.CALLBACK_ANALOG_VALUE_REACHED] = [10, 'H'];



	this.getVoltage = function(returnCallback, errorCallback) {
		/*
		Returns the measured voltage. The resolution is approximately 10mV.
		
		If you want to get the voltage periodically, it is recommended to use the
		:cb:`Voltage` callback and set the period with
		:func:`Set Voltage Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletAnalogInV2.FUNCTION_GET_VOLTAGE, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.getAnalogValue = function(returnCallback, errorCallback) {
		/*
		Returns the value as read by a 12-bit analog-to-digital converter.
		
		If you want the analog value periodically, it is recommended to use the
		:cb:`Analog Value` callback and set the period with
		:func:`Set Analog Value Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletAnalogInV2.FUNCTION_GET_ANALOG_VALUE, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.setVoltageCallbackPeriod = function(period, returnCallback, errorCallback) {
		/*
		Sets the period with which the :cb:`Voltage` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		The :cb:`Voltage` callback is only triggered if the voltage has changed since
		the last triggering.
		*/
		this.ipcon.sendRequest(this, BrickletAnalogInV2.FUNCTION_SET_VOLTAGE_CALLBACK_PERIOD, [period], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getVoltageCallbackPeriod = function(returnCallback, errorCallback) {
		/*
		Returns the period as set by :func:`Set Voltage Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletAnalogInV2.FUNCTION_GET_VOLTAGE_CALLBACK_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setAnalogValueCallbackPeriod = function(period, returnCallback, errorCallback) {
		/*
		Sets the period with which the :cb:`Analog Value` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		The :cb:`Analog Value` callback is only triggered if the analog value has
		changed since the last triggering.
		*/
		this.ipcon.sendRequest(this, BrickletAnalogInV2.FUNCTION_SET_ANALOG_VALUE_CALLBACK_PERIOD, [period], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getAnalogValueCallbackPeriod = function(returnCallback, errorCallback) {
		/*
		Returns the period as set by :func:`Set Analog Value Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletAnalogInV2.FUNCTION_GET_ANALOG_VALUE_CALLBACK_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setVoltageCallbackThreshold = function(option, min, max, returnCallback, errorCallback) {
		/*
		Sets the thresholds for the :cb:`Voltage Reached` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Callback is turned off"
		 "'o'",    "Callback is triggered when the voltage is *outside* the min and max values"
		 "'i'",    "Callback is triggered when the voltage is *inside* the min and max values"
		 "'<'",    "Callback is triggered when the voltage is smaller than the min value (max is ignored)"
		 "'>'",    "Callback is triggered when the voltage is greater than the min value (max is ignored)"
		*/
		this.ipcon.sendRequest(this, BrickletAnalogInV2.FUNCTION_SET_VOLTAGE_CALLBACK_THRESHOLD, [option, min, max], 'c H H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getVoltageCallbackThreshold = function(returnCallback, errorCallback) {
		/*
		Returns the threshold as set by :func:`Set Voltage Callback Threshold`.
		*/
		this.ipcon.sendRequest(this, BrickletAnalogInV2.FUNCTION_GET_VOLTAGE_CALLBACK_THRESHOLD, [], '', 13, 'c H H', returnCallback, errorCallback, false, true);
	};
	this.setAnalogValueCallbackThreshold = function(option, min, max, returnCallback, errorCallback) {
		/*
		Sets the thresholds for the :cb:`Analog Value Reached` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Callback is turned off"
		 "'o'",    "Callback is triggered when the analog value is *outside* the min and max values"
		 "'i'",    "Callback is triggered when the analog value is *inside* the min and max values"
		 "'<'",    "Callback is triggered when the analog value is smaller than the min value (max is ignored)"
		 "'>'",    "Callback is triggered when the analog value is greater than the min value (max is ignored)"
		*/
		this.ipcon.sendRequest(this, BrickletAnalogInV2.FUNCTION_SET_ANALOG_VALUE_CALLBACK_THRESHOLD, [option, min, max], 'c H H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getAnalogValueCallbackThreshold = function(returnCallback, errorCallback) {
		/*
		Returns the threshold as set by :func:`Set Analog Value Callback Threshold`.
		*/
		this.ipcon.sendRequest(this, BrickletAnalogInV2.FUNCTION_GET_ANALOG_VALUE_CALLBACK_THRESHOLD, [], '', 13, 'c H H', returnCallback, errorCallback, false, true);
	};
	this.setDebouncePeriod = function(debounce, returnCallback, errorCallback) {
		/*
		Sets the period with which the threshold callbacks
		
		* :cb:`Voltage Reached`,
		* :cb:`Analog Value Reached`
		
		are triggered, if the thresholds
		
		* :func:`Set Voltage Callback Threshold`,
		* :func:`Set Analog Value Callback Threshold`
		
		keep being reached.
		*/
		this.ipcon.sendRequest(this, BrickletAnalogInV2.FUNCTION_SET_DEBOUNCE_PERIOD, [debounce], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getDebouncePeriod = function(returnCallback, errorCallback) {
		/*
		Returns the debounce period as set by :func:`Set Debounce Period`.
		*/
		this.ipcon.sendRequest(this, BrickletAnalogInV2.FUNCTION_GET_DEBOUNCE_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setMovingAverage = function(average, returnCallback, errorCallback) {
		/*
		Sets the length of a `moving averaging <https://en.wikipedia.org/wiki/Moving_average>`__
		for the voltage.
		
		Setting the length to 1 will turn the averaging off. With less
		averaging, there is more noise on the data.
		*/
		this.ipcon.sendRequest(this, BrickletAnalogInV2.FUNCTION_SET_MOVING_AVERAGE, [average], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getMovingAverage = function(returnCallback, errorCallback) {
		/*
		Returns the length of the moving average as set by :func:`Set Moving Average`.
		*/
		this.ipcon.sendRequest(this, BrickletAnalogInV2.FUNCTION_GET_MOVING_AVERAGE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletAnalogInV2.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletAnalogInV2;

},{"./Device":279,"./IPConnection":280}],155:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletAnalogInV3.DEVICE_IDENTIFIER = 295;
BrickletAnalogInV3.DEVICE_DISPLAY_NAME = 'Analog In Bricklet 3.0';
BrickletAnalogInV3.CALLBACK_VOLTAGE = 4;
BrickletAnalogInV3.FUNCTION_GET_VOLTAGE = 1;
BrickletAnalogInV3.FUNCTION_SET_VOLTAGE_CALLBACK_CONFIGURATION = 2;
BrickletAnalogInV3.FUNCTION_GET_VOLTAGE_CALLBACK_CONFIGURATION = 3;
BrickletAnalogInV3.FUNCTION_SET_OVERSAMPLING = 5;
BrickletAnalogInV3.FUNCTION_GET_OVERSAMPLING = 6;
BrickletAnalogInV3.FUNCTION_SET_CALIBRATION = 7;
BrickletAnalogInV3.FUNCTION_GET_CALIBRATION = 8;
BrickletAnalogInV3.FUNCTION_GET_SPITFP_ERROR_COUNT = 234;
BrickletAnalogInV3.FUNCTION_SET_BOOTLOADER_MODE = 235;
BrickletAnalogInV3.FUNCTION_GET_BOOTLOADER_MODE = 236;
BrickletAnalogInV3.FUNCTION_SET_WRITE_FIRMWARE_POINTER = 237;
BrickletAnalogInV3.FUNCTION_WRITE_FIRMWARE = 238;
BrickletAnalogInV3.FUNCTION_SET_STATUS_LED_CONFIG = 239;
BrickletAnalogInV3.FUNCTION_GET_STATUS_LED_CONFIG = 240;
BrickletAnalogInV3.FUNCTION_GET_CHIP_TEMPERATURE = 242;
BrickletAnalogInV3.FUNCTION_RESET = 243;
BrickletAnalogInV3.FUNCTION_WRITE_UID = 248;
BrickletAnalogInV3.FUNCTION_READ_UID = 249;
BrickletAnalogInV3.FUNCTION_GET_IDENTITY = 255;
BrickletAnalogInV3.THRESHOLD_OPTION_OFF = 'x';
BrickletAnalogInV3.THRESHOLD_OPTION_OUTSIDE = 'o';
BrickletAnalogInV3.THRESHOLD_OPTION_INSIDE = 'i';
BrickletAnalogInV3.THRESHOLD_OPTION_SMALLER = '<';
BrickletAnalogInV3.THRESHOLD_OPTION_GREATER = '>';
BrickletAnalogInV3.OVERSAMPLING_32 = 0;
BrickletAnalogInV3.OVERSAMPLING_64 = 1;
BrickletAnalogInV3.OVERSAMPLING_128 = 2;
BrickletAnalogInV3.OVERSAMPLING_256 = 3;
BrickletAnalogInV3.OVERSAMPLING_512 = 4;
BrickletAnalogInV3.OVERSAMPLING_1024 = 5;
BrickletAnalogInV3.OVERSAMPLING_2048 = 6;
BrickletAnalogInV3.OVERSAMPLING_4096 = 7;
BrickletAnalogInV3.OVERSAMPLING_8192 = 8;
BrickletAnalogInV3.OVERSAMPLING_16384 = 9;
BrickletAnalogInV3.BOOTLOADER_MODE_BOOTLOADER = 0;
BrickletAnalogInV3.BOOTLOADER_MODE_FIRMWARE = 1;
BrickletAnalogInV3.BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT = 2;
BrickletAnalogInV3.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT = 3;
BrickletAnalogInV3.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT = 4;
BrickletAnalogInV3.BOOTLOADER_STATUS_OK = 0;
BrickletAnalogInV3.BOOTLOADER_STATUS_INVALID_MODE = 1;
BrickletAnalogInV3.BOOTLOADER_STATUS_NO_CHANGE = 2;
BrickletAnalogInV3.BOOTLOADER_STATUS_ENTRY_FUNCTION_NOT_PRESENT = 3;
BrickletAnalogInV3.BOOTLOADER_STATUS_DEVICE_IDENTIFIER_INCORRECT = 4;
BrickletAnalogInV3.BOOTLOADER_STATUS_CRC_MISMATCH = 5;
BrickletAnalogInV3.STATUS_LED_CONFIG_OFF = 0;
BrickletAnalogInV3.STATUS_LED_CONFIG_ON = 1;
BrickletAnalogInV3.STATUS_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletAnalogInV3.STATUS_LED_CONFIG_SHOW_STATUS = 3;

function BrickletAnalogInV3(uid, ipcon) {
	//Measures DC voltage between 0V and 42V

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletAnalogInV3.DEVICE_IDENTIFIER, BrickletAnalogInV3.DEVICE_DISPLAY_NAME);
	BrickletAnalogInV3.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickletAnalogInV3.FUNCTION_GET_VOLTAGE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAnalogInV3.FUNCTION_SET_VOLTAGE_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletAnalogInV3.FUNCTION_GET_VOLTAGE_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAnalogInV3.FUNCTION_SET_OVERSAMPLING] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletAnalogInV3.FUNCTION_GET_OVERSAMPLING] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAnalogInV3.FUNCTION_SET_CALIBRATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletAnalogInV3.FUNCTION_GET_CALIBRATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAnalogInV3.FUNCTION_GET_SPITFP_ERROR_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAnalogInV3.FUNCTION_SET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAnalogInV3.FUNCTION_GET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAnalogInV3.FUNCTION_SET_WRITE_FIRMWARE_POINTER] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletAnalogInV3.FUNCTION_WRITE_FIRMWARE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAnalogInV3.FUNCTION_SET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletAnalogInV3.FUNCTION_GET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAnalogInV3.FUNCTION_GET_CHIP_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAnalogInV3.FUNCTION_RESET] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletAnalogInV3.FUNCTION_WRITE_UID] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletAnalogInV3.FUNCTION_READ_UID] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAnalogInV3.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletAnalogInV3.CALLBACK_VOLTAGE] = [10, 'H'];



	this.getVoltage = function(returnCallback, errorCallback) {
		/*
		Returns the measured voltage. The resolution is approximately 10mV to 1mV
		depending on the oversampling configuration (:func:`Set Oversampling`).
		
		
		If you want to get the value periodically, it is recommended to use the
		:cb:`Voltage` callback. You can set the callback configuration
		with :func:`Set Voltage Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletAnalogInV3.FUNCTION_GET_VOLTAGE, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.setVoltageCallbackConfiguration = function(period, valueHasToChange, option, min, max, returnCallback, errorCallback) {
		/*
		The period is the period with which the :cb:`Voltage` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		If the `value has to change`-parameter is set to true, the callback is only
		triggered after the value has changed. If the value didn't change
		within the period, the callback is triggered immediately on change.
		
		If it is set to false, the callback is continuously triggered with the period,
		independent of the value.
		
		It is furthermore possible to constrain the callback with thresholds.
		
		The `option`-parameter together with min/max sets a threshold for the :cb:`Voltage` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Threshold is turned off"
		 "'o'",    "Threshold is triggered when the value is *outside* the min and max values"
		 "'i'",    "Threshold is triggered when the value is *inside* or equal to the min and max values"
		 "'<'",    "Threshold is triggered when the value is smaller than the min value (max is ignored)"
		 "'>'",    "Threshold is triggered when the value is greater than the min value (max is ignored)"
		
		If the option is set to 'x' (threshold turned off) the callback is triggered with the fixed period.
		*/
		this.ipcon.sendRequest(this, BrickletAnalogInV3.FUNCTION_SET_VOLTAGE_CALLBACK_CONFIGURATION, [period, valueHasToChange, option, min, max], 'I ? c H H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getVoltageCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the callback configuration as set by :func:`Set Voltage Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletAnalogInV3.FUNCTION_GET_VOLTAGE_CALLBACK_CONFIGURATION, [], '', 18, 'I ? c H H', returnCallback, errorCallback, false, true);
	};
	this.setOversampling = function(oversampling, returnCallback, errorCallback) {
		/*
		Sets the oversampling between 32x and 16384x. The Bricklet
		takes one 12bit sample every 17.5µs. Thus an oversampling
		of 32x is equivalent to an integration time of 0.56ms and
		a oversampling of 16384x is equivalent to an integration
		time of 286ms.
		
		The oversampling uses the moving average principle. A
		new value is always calculated once per millisecond.
		
		With increased oversampling the noise decreases. With decreased
		oversampling the reaction time increases (changes in voltage will be
		measured faster).
		*/
		this.ipcon.sendRequest(this, BrickletAnalogInV3.FUNCTION_SET_OVERSAMPLING, [oversampling], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getOversampling = function(returnCallback, errorCallback) {
		/*
		Returns the oversampling value as set by :func:`Set Oversampling`.
		*/
		this.ipcon.sendRequest(this, BrickletAnalogInV3.FUNCTION_GET_OVERSAMPLING, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setCalibration = function(offset, multiplier, divisor, returnCallback, errorCallback) {
		/*
		Sets a calibration for the measured voltage value.
		The formula for the calibration is as follows::
		
		 Calibrated Value = (Value + Offset) * Multiplier / Divisor
		
		We recommend that you use the Brick Viewer to calibrate
		the Bricklet. The calibration will be saved internally and only
		has to be done once.
		*/
		this.ipcon.sendRequest(this, BrickletAnalogInV3.FUNCTION_SET_CALIBRATION, [offset, multiplier, divisor], 'h H H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getCalibration = function(returnCallback, errorCallback) {
		/*
		Returns the calibration as set by :func:`Set Calibration`.
		*/
		this.ipcon.sendRequest(this, BrickletAnalogInV3.FUNCTION_GET_CALIBRATION, [], '', 14, 'h H H', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPErrorCount = function(returnCallback, errorCallback) {
		/*
		Returns the error count for the communication between Brick and Bricklet.
		
		The errors are divided into
		
		* ACK checksum errors,
		* message checksum errors,
		* framing errors and
		* overflow errors.
		
		The errors counts are for errors that occur on the Bricklet side. All
		Bricks have a similar function that returns the errors on the Brick side.
		*/
		this.ipcon.sendRequest(this, BrickletAnalogInV3.FUNCTION_GET_SPITFP_ERROR_COUNT, [], '', 24, 'I I I I', returnCallback, errorCallback, false, true);
	};
	this.setBootloaderMode = function(mode, returnCallback, errorCallback) {
		/*
		Sets the bootloader mode and returns the status after the requested
		mode change was instigated.
		
		You can change from bootloader mode to firmware mode and vice versa. A change
		from bootloader mode to firmware mode will only take place if the entry function,
		device identifier and CRC are present and correct.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletAnalogInV3.FUNCTION_SET_BOOTLOADER_MODE, [mode], 'B', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getBootloaderMode = function(returnCallback, errorCallback) {
		/*
		Returns the current bootloader mode, see :func:`Set Bootloader Mode`.
		*/
		this.ipcon.sendRequest(this, BrickletAnalogInV3.FUNCTION_GET_BOOTLOADER_MODE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setWriteFirmwarePointer = function(pointer, returnCallback, errorCallback) {
		/*
		Sets the firmware pointer for :func:`Write Firmware`. The pointer has
		to be increased by chunks of size 64. The data is written to flash
		every 4 chunks (which equals to one page of size 256).
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletAnalogInV3.FUNCTION_SET_WRITE_FIRMWARE_POINTER, [pointer], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeFirmware = function(data, returnCallback, errorCallback) {
		/*
		Writes 64 Bytes of firmware at the position as written by
		:func:`Set Write Firmware Pointer` before. The firmware is written
		to flash every 4 chunks.
		
		You can only write firmware in bootloader mode.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletAnalogInV3.FUNCTION_WRITE_FIRMWARE, [data], 'B64', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setStatusLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Sets the status LED configuration. By default the LED shows
		communication traffic between Brick and Bricklet, it flickers once
		for every 10 received data packets.
		
		You can also turn the LED permanently on/off or show a heartbeat.
		
		If the Bricklet is in bootloader mode, the LED is will show heartbeat by default.
		*/
		this.ipcon.sendRequest(this, BrickletAnalogInV3.FUNCTION_SET_STATUS_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getStatusLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Status LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletAnalogInV3.FUNCTION_GET_STATUS_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getChipTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature as measured inside the microcontroller. The
		value returned is not the ambient temperature!
		
		The temperature is only proportional to the real temperature and it has bad
		accuracy. Practically it is only useful as an indicator for
		temperature changes.
		*/
		this.ipcon.sendRequest(this, BrickletAnalogInV3.FUNCTION_GET_CHIP_TEMPERATURE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.reset = function(returnCallback, errorCallback) {
		/*
		Calling this function will reset the Bricklet. All configurations
		will be lost.
		
		After a reset you have to create new device objects,
		calling functions on the existing ones will result in
		undefined behavior!
		*/
		this.ipcon.sendRequest(this, BrickletAnalogInV3.FUNCTION_RESET, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeUID = function(uid, returnCallback, errorCallback) {
		/*
		Writes a new UID into flash. If you want to set a new UID
		you have to decode the Base58 encoded UID string into an
		integer first.
		
		We recommend that you use Brick Viewer to change the UID.
		*/
		this.ipcon.sendRequest(this, BrickletAnalogInV3.FUNCTION_WRITE_UID, [uid], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.readUID = function(returnCallback, errorCallback) {
		/*
		Returns the current UID as an integer. Encode as
		Base58 to get the usual string version.
		*/
		this.ipcon.sendRequest(this, BrickletAnalogInV3.FUNCTION_READ_UID, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletAnalogInV3.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletAnalogInV3;

},{"./Device":279,"./IPConnection":280}],156:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletAnalogOut.DEVICE_IDENTIFIER = 220;
BrickletAnalogOut.DEVICE_DISPLAY_NAME = 'Analog Out Bricklet';
BrickletAnalogOut.FUNCTION_SET_VOLTAGE = 1;
BrickletAnalogOut.FUNCTION_GET_VOLTAGE = 2;
BrickletAnalogOut.FUNCTION_SET_MODE = 3;
BrickletAnalogOut.FUNCTION_GET_MODE = 4;
BrickletAnalogOut.FUNCTION_GET_IDENTITY = 255;
BrickletAnalogOut.MODE_ANALOG_VALUE = 0;
BrickletAnalogOut.MODE_1K_TO_GROUND = 1;
BrickletAnalogOut.MODE_100K_TO_GROUND = 2;
BrickletAnalogOut.MODE_500K_TO_GROUND = 3;

function BrickletAnalogOut(uid, ipcon) {
	//Generates configurable DC voltage between 0V and 5V

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletAnalogOut.DEVICE_IDENTIFIER, BrickletAnalogOut.DEVICE_DISPLAY_NAME);
	BrickletAnalogOut.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickletAnalogOut.FUNCTION_SET_VOLTAGE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletAnalogOut.FUNCTION_GET_VOLTAGE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAnalogOut.FUNCTION_SET_MODE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletAnalogOut.FUNCTION_GET_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAnalogOut.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;



	this.setVoltage = function(voltage, returnCallback, errorCallback) {
		/*
		Sets the voltage. Calling this function will set
		the mode to 0 (see :func:`Set Mode`).
		*/
		this.ipcon.sendRequest(this, BrickletAnalogOut.FUNCTION_SET_VOLTAGE, [voltage], 'H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getVoltage = function(returnCallback, errorCallback) {
		/*
		Returns the voltage as set by :func:`Set Voltage`.
		*/
		this.ipcon.sendRequest(this, BrickletAnalogOut.FUNCTION_GET_VOLTAGE, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.setMode = function(mode, returnCallback, errorCallback) {
		/*
		Sets the mode of the analog value. Possible modes:
		
		* 0: Normal Mode (Analog value as set by :func:`Set Voltage` is applied)
		* 1: 1k Ohm resistor to ground
		* 2: 100k Ohm resistor to ground
		* 3: 500k Ohm resistor to ground
		
		Setting the mode to 0 will result in an output voltage of 0 V. You can jump
		to a higher output voltage directly by calling :func:`Set Voltage`.
		*/
		this.ipcon.sendRequest(this, BrickletAnalogOut.FUNCTION_SET_MODE, [mode], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getMode = function(returnCallback, errorCallback) {
		/*
		Returns the mode as set by :func:`Set Mode`.
		*/
		this.ipcon.sendRequest(this, BrickletAnalogOut.FUNCTION_GET_MODE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletAnalogOut.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletAnalogOut;

},{"./Device":279,"./IPConnection":280}],157:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletAnalogOutV2.DEVICE_IDENTIFIER = 256;
BrickletAnalogOutV2.DEVICE_DISPLAY_NAME = 'Analog Out Bricklet 2.0';
BrickletAnalogOutV2.FUNCTION_SET_OUTPUT_VOLTAGE = 1;
BrickletAnalogOutV2.FUNCTION_GET_OUTPUT_VOLTAGE = 2;
BrickletAnalogOutV2.FUNCTION_GET_INPUT_VOLTAGE = 3;
BrickletAnalogOutV2.FUNCTION_GET_IDENTITY = 255;

function BrickletAnalogOutV2(uid, ipcon) {
	//Generates configurable DC voltage between 0V and 12V

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletAnalogOutV2.DEVICE_IDENTIFIER, BrickletAnalogOutV2.DEVICE_DISPLAY_NAME);
	BrickletAnalogOutV2.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickletAnalogOutV2.FUNCTION_SET_OUTPUT_VOLTAGE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletAnalogOutV2.FUNCTION_GET_OUTPUT_VOLTAGE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAnalogOutV2.FUNCTION_GET_INPUT_VOLTAGE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAnalogOutV2.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;



	this.setOutputVoltage = function(voltage, returnCallback, errorCallback) {
		/*
		Sets the voltage.
		*/
		this.ipcon.sendRequest(this, BrickletAnalogOutV2.FUNCTION_SET_OUTPUT_VOLTAGE, [voltage], 'H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getOutputVoltage = function(returnCallback, errorCallback) {
		/*
		Returns the voltage as set by :func:`Set Output Voltage`.
		*/
		this.ipcon.sendRequest(this, BrickletAnalogOutV2.FUNCTION_GET_OUTPUT_VOLTAGE, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.getInputVoltage = function(returnCallback, errorCallback) {
		/*
		Returns the input voltage.
		*/
		this.ipcon.sendRequest(this, BrickletAnalogOutV2.FUNCTION_GET_INPUT_VOLTAGE, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletAnalogOutV2.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletAnalogOutV2;

},{"./Device":279,"./IPConnection":280}],158:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletAnalogOutV3.DEVICE_IDENTIFIER = 2115;
BrickletAnalogOutV3.DEVICE_DISPLAY_NAME = 'Analog Out Bricklet 3.0';
BrickletAnalogOutV3.FUNCTION_SET_OUTPUT_VOLTAGE = 1;
BrickletAnalogOutV3.FUNCTION_GET_OUTPUT_VOLTAGE = 2;
BrickletAnalogOutV3.FUNCTION_GET_INPUT_VOLTAGE = 3;
BrickletAnalogOutV3.FUNCTION_GET_SPITFP_ERROR_COUNT = 234;
BrickletAnalogOutV3.FUNCTION_SET_BOOTLOADER_MODE = 235;
BrickletAnalogOutV3.FUNCTION_GET_BOOTLOADER_MODE = 236;
BrickletAnalogOutV3.FUNCTION_SET_WRITE_FIRMWARE_POINTER = 237;
BrickletAnalogOutV3.FUNCTION_WRITE_FIRMWARE = 238;
BrickletAnalogOutV3.FUNCTION_SET_STATUS_LED_CONFIG = 239;
BrickletAnalogOutV3.FUNCTION_GET_STATUS_LED_CONFIG = 240;
BrickletAnalogOutV3.FUNCTION_GET_CHIP_TEMPERATURE = 242;
BrickletAnalogOutV3.FUNCTION_RESET = 243;
BrickletAnalogOutV3.FUNCTION_WRITE_UID = 248;
BrickletAnalogOutV3.FUNCTION_READ_UID = 249;
BrickletAnalogOutV3.FUNCTION_GET_IDENTITY = 255;
BrickletAnalogOutV3.BOOTLOADER_MODE_BOOTLOADER = 0;
BrickletAnalogOutV3.BOOTLOADER_MODE_FIRMWARE = 1;
BrickletAnalogOutV3.BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT = 2;
BrickletAnalogOutV3.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT = 3;
BrickletAnalogOutV3.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT = 4;
BrickletAnalogOutV3.BOOTLOADER_STATUS_OK = 0;
BrickletAnalogOutV3.BOOTLOADER_STATUS_INVALID_MODE = 1;
BrickletAnalogOutV3.BOOTLOADER_STATUS_NO_CHANGE = 2;
BrickletAnalogOutV3.BOOTLOADER_STATUS_ENTRY_FUNCTION_NOT_PRESENT = 3;
BrickletAnalogOutV3.BOOTLOADER_STATUS_DEVICE_IDENTIFIER_INCORRECT = 4;
BrickletAnalogOutV3.BOOTLOADER_STATUS_CRC_MISMATCH = 5;
BrickletAnalogOutV3.STATUS_LED_CONFIG_OFF = 0;
BrickletAnalogOutV3.STATUS_LED_CONFIG_ON = 1;
BrickletAnalogOutV3.STATUS_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletAnalogOutV3.STATUS_LED_CONFIG_SHOW_STATUS = 3;

function BrickletAnalogOutV3(uid, ipcon) {
	//Generates configurable DC voltage between 0V and 12V

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletAnalogOutV3.DEVICE_IDENTIFIER, BrickletAnalogOutV3.DEVICE_DISPLAY_NAME);
	BrickletAnalogOutV3.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickletAnalogOutV3.FUNCTION_SET_OUTPUT_VOLTAGE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletAnalogOutV3.FUNCTION_GET_OUTPUT_VOLTAGE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAnalogOutV3.FUNCTION_GET_INPUT_VOLTAGE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAnalogOutV3.FUNCTION_GET_SPITFP_ERROR_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAnalogOutV3.FUNCTION_SET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAnalogOutV3.FUNCTION_GET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAnalogOutV3.FUNCTION_SET_WRITE_FIRMWARE_POINTER] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletAnalogOutV3.FUNCTION_WRITE_FIRMWARE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAnalogOutV3.FUNCTION_SET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletAnalogOutV3.FUNCTION_GET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAnalogOutV3.FUNCTION_GET_CHIP_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAnalogOutV3.FUNCTION_RESET] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletAnalogOutV3.FUNCTION_WRITE_UID] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletAnalogOutV3.FUNCTION_READ_UID] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletAnalogOutV3.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;



	this.setOutputVoltage = function(voltage, returnCallback, errorCallback) {
		/*
		Sets the voltage.
		*/
		this.ipcon.sendRequest(this, BrickletAnalogOutV3.FUNCTION_SET_OUTPUT_VOLTAGE, [voltage], 'H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getOutputVoltage = function(returnCallback, errorCallback) {
		/*
		Returns the voltage as set by :func:`Set Output Voltage`.
		*/
		this.ipcon.sendRequest(this, BrickletAnalogOutV3.FUNCTION_GET_OUTPUT_VOLTAGE, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.getInputVoltage = function(returnCallback, errorCallback) {
		/*
		Returns the input voltage.
		*/
		this.ipcon.sendRequest(this, BrickletAnalogOutV3.FUNCTION_GET_INPUT_VOLTAGE, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPErrorCount = function(returnCallback, errorCallback) {
		/*
		Returns the error count for the communication between Brick and Bricklet.
		
		The errors are divided into
		
		* ACK checksum errors,
		* message checksum errors,
		* framing errors and
		* overflow errors.
		
		The errors counts are for errors that occur on the Bricklet side. All
		Bricks have a similar function that returns the errors on the Brick side.
		*/
		this.ipcon.sendRequest(this, BrickletAnalogOutV3.FUNCTION_GET_SPITFP_ERROR_COUNT, [], '', 24, 'I I I I', returnCallback, errorCallback, false, true);
	};
	this.setBootloaderMode = function(mode, returnCallback, errorCallback) {
		/*
		Sets the bootloader mode and returns the status after the requested
		mode change was instigated.
		
		You can change from bootloader mode to firmware mode and vice versa. A change
		from bootloader mode to firmware mode will only take place if the entry function,
		device identifier and CRC are present and correct.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletAnalogOutV3.FUNCTION_SET_BOOTLOADER_MODE, [mode], 'B', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getBootloaderMode = function(returnCallback, errorCallback) {
		/*
		Returns the current bootloader mode, see :func:`Set Bootloader Mode`.
		*/
		this.ipcon.sendRequest(this, BrickletAnalogOutV3.FUNCTION_GET_BOOTLOADER_MODE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setWriteFirmwarePointer = function(pointer, returnCallback, errorCallback) {
		/*
		Sets the firmware pointer for :func:`Write Firmware`. The pointer has
		to be increased by chunks of size 64. The data is written to flash
		every 4 chunks (which equals to one page of size 256).
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletAnalogOutV3.FUNCTION_SET_WRITE_FIRMWARE_POINTER, [pointer], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeFirmware = function(data, returnCallback, errorCallback) {
		/*
		Writes 64 Bytes of firmware at the position as written by
		:func:`Set Write Firmware Pointer` before. The firmware is written
		to flash every 4 chunks.
		
		You can only write firmware in bootloader mode.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletAnalogOutV3.FUNCTION_WRITE_FIRMWARE, [data], 'B64', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setStatusLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Sets the status LED configuration. By default the LED shows
		communication traffic between Brick and Bricklet, it flickers once
		for every 10 received data packets.
		
		You can also turn the LED permanently on/off or show a heartbeat.
		
		If the Bricklet is in bootloader mode, the LED is will show heartbeat by default.
		*/
		this.ipcon.sendRequest(this, BrickletAnalogOutV3.FUNCTION_SET_STATUS_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getStatusLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Status LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletAnalogOutV3.FUNCTION_GET_STATUS_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getChipTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature as measured inside the microcontroller. The
		value returned is not the ambient temperature!
		
		The temperature is only proportional to the real temperature and it has bad
		accuracy. Practically it is only useful as an indicator for
		temperature changes.
		*/
		this.ipcon.sendRequest(this, BrickletAnalogOutV3.FUNCTION_GET_CHIP_TEMPERATURE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.reset = function(returnCallback, errorCallback) {
		/*
		Calling this function will reset the Bricklet. All configurations
		will be lost.
		
		After a reset you have to create new device objects,
		calling functions on the existing ones will result in
		undefined behavior!
		*/
		this.ipcon.sendRequest(this, BrickletAnalogOutV3.FUNCTION_RESET, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeUID = function(uid, returnCallback, errorCallback) {
		/*
		Writes a new UID into flash. If you want to set a new UID
		you have to decode the Base58 encoded UID string into an
		integer first.
		
		We recommend that you use Brick Viewer to change the UID.
		*/
		this.ipcon.sendRequest(this, BrickletAnalogOutV3.FUNCTION_WRITE_UID, [uid], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.readUID = function(returnCallback, errorCallback) {
		/*
		Returns the current UID as an integer. Encode as
		Base58 to get the usual string version.
		*/
		this.ipcon.sendRequest(this, BrickletAnalogOutV3.FUNCTION_READ_UID, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletAnalogOutV3.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletAnalogOutV3;

},{"./Device":279,"./IPConnection":280}],159:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletBarometer.DEVICE_IDENTIFIER = 221;
BrickletBarometer.DEVICE_DISPLAY_NAME = 'Barometer Bricklet';
BrickletBarometer.CALLBACK_AIR_PRESSURE = 15;
BrickletBarometer.CALLBACK_ALTITUDE = 16;
BrickletBarometer.CALLBACK_AIR_PRESSURE_REACHED = 17;
BrickletBarometer.CALLBACK_ALTITUDE_REACHED = 18;
BrickletBarometer.FUNCTION_GET_AIR_PRESSURE = 1;
BrickletBarometer.FUNCTION_GET_ALTITUDE = 2;
BrickletBarometer.FUNCTION_SET_AIR_PRESSURE_CALLBACK_PERIOD = 3;
BrickletBarometer.FUNCTION_GET_AIR_PRESSURE_CALLBACK_PERIOD = 4;
BrickletBarometer.FUNCTION_SET_ALTITUDE_CALLBACK_PERIOD = 5;
BrickletBarometer.FUNCTION_GET_ALTITUDE_CALLBACK_PERIOD = 6;
BrickletBarometer.FUNCTION_SET_AIR_PRESSURE_CALLBACK_THRESHOLD = 7;
BrickletBarometer.FUNCTION_GET_AIR_PRESSURE_CALLBACK_THRESHOLD = 8;
BrickletBarometer.FUNCTION_SET_ALTITUDE_CALLBACK_THRESHOLD = 9;
BrickletBarometer.FUNCTION_GET_ALTITUDE_CALLBACK_THRESHOLD = 10;
BrickletBarometer.FUNCTION_SET_DEBOUNCE_PERIOD = 11;
BrickletBarometer.FUNCTION_GET_DEBOUNCE_PERIOD = 12;
BrickletBarometer.FUNCTION_SET_REFERENCE_AIR_PRESSURE = 13;
BrickletBarometer.FUNCTION_GET_CHIP_TEMPERATURE = 14;
BrickletBarometer.FUNCTION_GET_REFERENCE_AIR_PRESSURE = 19;
BrickletBarometer.FUNCTION_SET_AVERAGING = 20;
BrickletBarometer.FUNCTION_GET_AVERAGING = 21;
BrickletBarometer.FUNCTION_SET_I2C_MODE = 22;
BrickletBarometer.FUNCTION_GET_I2C_MODE = 23;
BrickletBarometer.FUNCTION_GET_IDENTITY = 255;
BrickletBarometer.THRESHOLD_OPTION_OFF = 'x';
BrickletBarometer.THRESHOLD_OPTION_OUTSIDE = 'o';
BrickletBarometer.THRESHOLD_OPTION_INSIDE = 'i';
BrickletBarometer.THRESHOLD_OPTION_SMALLER = '<';
BrickletBarometer.THRESHOLD_OPTION_GREATER = '>';
BrickletBarometer.I2C_MODE_FAST = 0;
BrickletBarometer.I2C_MODE_SLOW = 1;

function BrickletBarometer(uid, ipcon) {
	//Measures air pressure and altitude changes

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletBarometer.DEVICE_IDENTIFIER, BrickletBarometer.DEVICE_DISPLAY_NAME);
	BrickletBarometer.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 2];
	this.responseExpected[BrickletBarometer.FUNCTION_GET_AIR_PRESSURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletBarometer.FUNCTION_GET_ALTITUDE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletBarometer.FUNCTION_SET_AIR_PRESSURE_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletBarometer.FUNCTION_GET_AIR_PRESSURE_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletBarometer.FUNCTION_SET_ALTITUDE_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletBarometer.FUNCTION_GET_ALTITUDE_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletBarometer.FUNCTION_SET_AIR_PRESSURE_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletBarometer.FUNCTION_GET_AIR_PRESSURE_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletBarometer.FUNCTION_SET_ALTITUDE_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletBarometer.FUNCTION_GET_ALTITUDE_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletBarometer.FUNCTION_SET_DEBOUNCE_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletBarometer.FUNCTION_GET_DEBOUNCE_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletBarometer.FUNCTION_SET_REFERENCE_AIR_PRESSURE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletBarometer.FUNCTION_GET_CHIP_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletBarometer.FUNCTION_GET_REFERENCE_AIR_PRESSURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletBarometer.FUNCTION_SET_AVERAGING] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletBarometer.FUNCTION_GET_AVERAGING] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletBarometer.FUNCTION_SET_I2C_MODE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletBarometer.FUNCTION_GET_I2C_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletBarometer.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletBarometer.CALLBACK_AIR_PRESSURE] = [12, 'i'];
	this.callbackFormats[BrickletBarometer.CALLBACK_ALTITUDE] = [12, 'i'];
	this.callbackFormats[BrickletBarometer.CALLBACK_AIR_PRESSURE_REACHED] = [12, 'i'];
	this.callbackFormats[BrickletBarometer.CALLBACK_ALTITUDE_REACHED] = [12, 'i'];



	this.getAirPressure = function(returnCallback, errorCallback) {
		/*
		Returns the air pressure of the air pressure sensor.
		
		If you want to get the air pressure periodically, it is recommended to use the
		:cb:`Air Pressure` callback and set the period with
		:func:`Set Air Pressure Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletBarometer.FUNCTION_GET_AIR_PRESSURE, [], '', 12, 'i', returnCallback, errorCallback, false, true);
	};
	this.getAltitude = function(returnCallback, errorCallback) {
		/*
		Returns the relative altitude of the air pressure sensor. The value is
		calculated based on the difference between the current air pressure
		and the reference air pressure that can be set with :func:`Set Reference Air Pressure`.
		
		If you want to get the altitude periodically, it is recommended to use the
		:cb:`Altitude` callback and set the period with
		:func:`Set Altitude Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletBarometer.FUNCTION_GET_ALTITUDE, [], '', 12, 'i', returnCallback, errorCallback, false, true);
	};
	this.setAirPressureCallbackPeriod = function(period, returnCallback, errorCallback) {
		/*
		Sets the period with which the :cb:`Air Pressure` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		The :cb:`Air Pressure` callback is only triggered if the air pressure has
		changed since the last triggering.
		*/
		this.ipcon.sendRequest(this, BrickletBarometer.FUNCTION_SET_AIR_PRESSURE_CALLBACK_PERIOD, [period], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getAirPressureCallbackPeriod = function(returnCallback, errorCallback) {
		/*
		Returns the period as set by :func:`Set Air Pressure Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletBarometer.FUNCTION_GET_AIR_PRESSURE_CALLBACK_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setAltitudeCallbackPeriod = function(period, returnCallback, errorCallback) {
		/*
		Sets the period with which the :cb:`Altitude` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		The :cb:`Altitude` callback is only triggered if the altitude has changed since
		the last triggering.
		*/
		this.ipcon.sendRequest(this, BrickletBarometer.FUNCTION_SET_ALTITUDE_CALLBACK_PERIOD, [period], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getAltitudeCallbackPeriod = function(returnCallback, errorCallback) {
		/*
		Returns the period as set by :func:`Set Altitude Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletBarometer.FUNCTION_GET_ALTITUDE_CALLBACK_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setAirPressureCallbackThreshold = function(option, min, max, returnCallback, errorCallback) {
		/*
		Sets the thresholds for the :cb:`Air Pressure Reached` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Callback is turned off"
		 "'o'",    "Callback is triggered when the air pressure is *outside* the min and max values"
		 "'i'",    "Callback is triggered when the air pressure is *inside* the min and max values"
		 "'<'",    "Callback is triggered when the air pressure is smaller than the min value (max is ignored)"
		 "'>'",    "Callback is triggered when the air pressure is greater than the min value (max is ignored)"
		*/
		this.ipcon.sendRequest(this, BrickletBarometer.FUNCTION_SET_AIR_PRESSURE_CALLBACK_THRESHOLD, [option, min, max], 'c i i', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getAirPressureCallbackThreshold = function(returnCallback, errorCallback) {
		/*
		Returns the threshold as set by :func:`Set Air Pressure Callback Threshold`.
		*/
		this.ipcon.sendRequest(this, BrickletBarometer.FUNCTION_GET_AIR_PRESSURE_CALLBACK_THRESHOLD, [], '', 17, 'c i i', returnCallback, errorCallback, false, true);
	};
	this.setAltitudeCallbackThreshold = function(option, min, max, returnCallback, errorCallback) {
		/*
		Sets the thresholds for the :cb:`Altitude Reached` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Callback is turned off"
		 "'o'",    "Callback is triggered when the altitude is *outside* the min and max values"
		 "'i'",    "Callback is triggered when the altitude is *inside* the min and max values"
		 "'<'",    "Callback is triggered when the altitude is smaller than the min value (max is ignored)"
		 "'>'",    "Callback is triggered when the altitude is greater than the min value (max is ignored)"
		*/
		this.ipcon.sendRequest(this, BrickletBarometer.FUNCTION_SET_ALTITUDE_CALLBACK_THRESHOLD, [option, min, max], 'c i i', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getAltitudeCallbackThreshold = function(returnCallback, errorCallback) {
		/*
		Returns the threshold as set by :func:`Set Altitude Callback Threshold`.
		*/
		this.ipcon.sendRequest(this, BrickletBarometer.FUNCTION_GET_ALTITUDE_CALLBACK_THRESHOLD, [], '', 17, 'c i i', returnCallback, errorCallback, false, true);
	};
	this.setDebouncePeriod = function(debounce, returnCallback, errorCallback) {
		/*
		Sets the period with which the threshold callbacks
		
		* :cb:`Air Pressure Reached`,
		* :cb:`Altitude Reached`
		
		are triggered, if the thresholds
		
		* :func:`Set Air Pressure Callback Threshold`,
		* :func:`Set Altitude Callback Threshold`
		
		keep being reached.
		*/
		this.ipcon.sendRequest(this, BrickletBarometer.FUNCTION_SET_DEBOUNCE_PERIOD, [debounce], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getDebouncePeriod = function(returnCallback, errorCallback) {
		/*
		Returns the debounce period as set by :func:`Set Debounce Period`.
		*/
		this.ipcon.sendRequest(this, BrickletBarometer.FUNCTION_GET_DEBOUNCE_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setReferenceAirPressure = function(airPressure, returnCallback, errorCallback) {
		/*
		Sets the reference air pressure for the altitude calculation.
		Setting the reference to the current air pressure results in a calculated
		altitude of 0cm. Passing 0 is a shortcut for passing the current air pressure as
		reference.
		
		Well known reference values are the Q codes
		`QNH <https://en.wikipedia.org/wiki/QNH>`__ and
		`QFE <https://en.wikipedia.org/wiki/Mean_sea_level_pressure#Mean_sea_level_pressure>`__
		used in aviation.
		*/
		this.ipcon.sendRequest(this, BrickletBarometer.FUNCTION_SET_REFERENCE_AIR_PRESSURE, [airPressure], 'i', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getChipTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature of the air pressure sensor.
		
		This temperature is used internally for temperature compensation of the air
		pressure measurement. It is not as accurate as the temperature measured by the
		:ref:`temperature_bricklet` or the :ref:`temperature_ir_bricklet`.
		*/
		this.ipcon.sendRequest(this, BrickletBarometer.FUNCTION_GET_CHIP_TEMPERATURE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.getReferenceAirPressure = function(returnCallback, errorCallback) {
		/*
		Returns the reference air pressure as set by :func:`Set Reference Air Pressure`.
		*/
		this.ipcon.sendRequest(this, BrickletBarometer.FUNCTION_GET_REFERENCE_AIR_PRESSURE, [], '', 12, 'i', returnCallback, errorCallback, false, true);
	};
	this.setAveraging = function(movingAveragePressure, averagePressure, averageTemperature, returnCallback, errorCallback) {
		/*
		Sets the different averaging parameters. It is possible to set
		the length of a normal averaging for the temperature and pressure,
		as well as an additional length of a
		`moving average <https://en.wikipedia.org/wiki/Moving_average>`__
		for the pressure. The moving average is calculated from the normal
		averages.  There is no moving average for the temperature.
		
		Setting the all three parameters to 0 will turn the averaging
		completely off. If the averaging is off, there is lots of noise
		on the data, but the data is without delay. Thus we recommend
		to turn the averaging off if the Barometer Bricklet data is
		to be used for sensor fusion with other sensors.
		
		.. versionadded:: 2.0.1$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletBarometer.FUNCTION_SET_AVERAGING, [movingAveragePressure, averagePressure, averageTemperature], 'B B B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getAveraging = function(returnCallback, errorCallback) {
		/*
		Returns the averaging configuration as set by :func:`Set Averaging`.
		
		.. versionadded:: 2.0.1$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletBarometer.FUNCTION_GET_AVERAGING, [], '', 11, 'B B B', returnCallback, errorCallback, false, true);
	};
	this.setI2CMode = function(mode, returnCallback, errorCallback) {
		/*
		Sets the I2C mode. Possible modes are:
		
		* 0: Fast (400kHz)
		* 1: Slow (100kHz)
		
		If you have problems with obvious outliers in the
		Barometer Bricklet measurements, they may be caused by EMI issues.
		In this case it may be helpful to lower the I2C speed.
		
		It is however not recommended to lower the I2C speed in applications where
		a high throughput needs to be achieved.
		
		.. versionadded:: 2.0.3$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletBarometer.FUNCTION_SET_I2C_MODE, [mode], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getI2CMode = function(returnCallback, errorCallback) {
		/*
		Returns the I2C mode as set by :func:`Set I2C Mode`.
		
		.. versionadded:: 2.0.3$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletBarometer.FUNCTION_GET_I2C_MODE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletBarometer.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletBarometer;

},{"./Device":279,"./IPConnection":280}],160:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletBarometerV2.DEVICE_IDENTIFIER = 2117;
BrickletBarometerV2.DEVICE_DISPLAY_NAME = 'Barometer Bricklet 2.0';
BrickletBarometerV2.CALLBACK_AIR_PRESSURE = 4;
BrickletBarometerV2.CALLBACK_ALTITUDE = 8;
BrickletBarometerV2.CALLBACK_TEMPERATURE = 12;
BrickletBarometerV2.FUNCTION_GET_AIR_PRESSURE = 1;
BrickletBarometerV2.FUNCTION_SET_AIR_PRESSURE_CALLBACK_CONFIGURATION = 2;
BrickletBarometerV2.FUNCTION_GET_AIR_PRESSURE_CALLBACK_CONFIGURATION = 3;
BrickletBarometerV2.FUNCTION_GET_ALTITUDE = 5;
BrickletBarometerV2.FUNCTION_SET_ALTITUDE_CALLBACK_CONFIGURATION = 6;
BrickletBarometerV2.FUNCTION_GET_ALTITUDE_CALLBACK_CONFIGURATION = 7;
BrickletBarometerV2.FUNCTION_GET_TEMPERATURE = 9;
BrickletBarometerV2.FUNCTION_SET_TEMPERATURE_CALLBACK_CONFIGURATION = 10;
BrickletBarometerV2.FUNCTION_GET_TEMPERATURE_CALLBACK_CONFIGURATION = 11;
BrickletBarometerV2.FUNCTION_SET_MOVING_AVERAGE_CONFIGURATION = 13;
BrickletBarometerV2.FUNCTION_GET_MOVING_AVERAGE_CONFIGURATION = 14;
BrickletBarometerV2.FUNCTION_SET_REFERENCE_AIR_PRESSURE = 15;
BrickletBarometerV2.FUNCTION_GET_REFERENCE_AIR_PRESSURE = 16;
BrickletBarometerV2.FUNCTION_SET_CALIBRATION = 17;
BrickletBarometerV2.FUNCTION_GET_CALIBRATION = 18;
BrickletBarometerV2.FUNCTION_SET_SENSOR_CONFIGURATION = 19;
BrickletBarometerV2.FUNCTION_GET_SENSOR_CONFIGURATION = 20;
BrickletBarometerV2.FUNCTION_GET_SPITFP_ERROR_COUNT = 234;
BrickletBarometerV2.FUNCTION_SET_BOOTLOADER_MODE = 235;
BrickletBarometerV2.FUNCTION_GET_BOOTLOADER_MODE = 236;
BrickletBarometerV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER = 237;
BrickletBarometerV2.FUNCTION_WRITE_FIRMWARE = 238;
BrickletBarometerV2.FUNCTION_SET_STATUS_LED_CONFIG = 239;
BrickletBarometerV2.FUNCTION_GET_STATUS_LED_CONFIG = 240;
BrickletBarometerV2.FUNCTION_GET_CHIP_TEMPERATURE = 242;
BrickletBarometerV2.FUNCTION_RESET = 243;
BrickletBarometerV2.FUNCTION_WRITE_UID = 248;
BrickletBarometerV2.FUNCTION_READ_UID = 249;
BrickletBarometerV2.FUNCTION_GET_IDENTITY = 255;
BrickletBarometerV2.THRESHOLD_OPTION_OFF = 'x';
BrickletBarometerV2.THRESHOLD_OPTION_OUTSIDE = 'o';
BrickletBarometerV2.THRESHOLD_OPTION_INSIDE = 'i';
BrickletBarometerV2.THRESHOLD_OPTION_SMALLER = '<';
BrickletBarometerV2.THRESHOLD_OPTION_GREATER = '>';
BrickletBarometerV2.DATA_RATE_OFF = 0;
BrickletBarometerV2.DATA_RATE_1HZ = 1;
BrickletBarometerV2.DATA_RATE_10HZ = 2;
BrickletBarometerV2.DATA_RATE_25HZ = 3;
BrickletBarometerV2.DATA_RATE_50HZ = 4;
BrickletBarometerV2.DATA_RATE_75HZ = 5;
BrickletBarometerV2.LOW_PASS_FILTER_OFF = 0;
BrickletBarometerV2.LOW_PASS_FILTER_1_9TH = 1;
BrickletBarometerV2.LOW_PASS_FILTER_1_20TH = 2;
BrickletBarometerV2.BOOTLOADER_MODE_BOOTLOADER = 0;
BrickletBarometerV2.BOOTLOADER_MODE_FIRMWARE = 1;
BrickletBarometerV2.BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT = 2;
BrickletBarometerV2.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT = 3;
BrickletBarometerV2.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT = 4;
BrickletBarometerV2.BOOTLOADER_STATUS_OK = 0;
BrickletBarometerV2.BOOTLOADER_STATUS_INVALID_MODE = 1;
BrickletBarometerV2.BOOTLOADER_STATUS_NO_CHANGE = 2;
BrickletBarometerV2.BOOTLOADER_STATUS_ENTRY_FUNCTION_NOT_PRESENT = 3;
BrickletBarometerV2.BOOTLOADER_STATUS_DEVICE_IDENTIFIER_INCORRECT = 4;
BrickletBarometerV2.BOOTLOADER_STATUS_CRC_MISMATCH = 5;
BrickletBarometerV2.STATUS_LED_CONFIG_OFF = 0;
BrickletBarometerV2.STATUS_LED_CONFIG_ON = 1;
BrickletBarometerV2.STATUS_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletBarometerV2.STATUS_LED_CONFIG_SHOW_STATUS = 3;

function BrickletBarometerV2(uid, ipcon) {
	//Measures air pressure and altitude changes

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletBarometerV2.DEVICE_IDENTIFIER, BrickletBarometerV2.DEVICE_DISPLAY_NAME);
	BrickletBarometerV2.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickletBarometerV2.FUNCTION_GET_AIR_PRESSURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletBarometerV2.FUNCTION_SET_AIR_PRESSURE_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletBarometerV2.FUNCTION_GET_AIR_PRESSURE_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletBarometerV2.FUNCTION_GET_ALTITUDE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletBarometerV2.FUNCTION_SET_ALTITUDE_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletBarometerV2.FUNCTION_GET_ALTITUDE_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletBarometerV2.FUNCTION_GET_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletBarometerV2.FUNCTION_SET_TEMPERATURE_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletBarometerV2.FUNCTION_GET_TEMPERATURE_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletBarometerV2.FUNCTION_SET_MOVING_AVERAGE_CONFIGURATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletBarometerV2.FUNCTION_GET_MOVING_AVERAGE_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletBarometerV2.FUNCTION_SET_REFERENCE_AIR_PRESSURE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletBarometerV2.FUNCTION_GET_REFERENCE_AIR_PRESSURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletBarometerV2.FUNCTION_SET_CALIBRATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletBarometerV2.FUNCTION_GET_CALIBRATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletBarometerV2.FUNCTION_SET_SENSOR_CONFIGURATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletBarometerV2.FUNCTION_GET_SENSOR_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletBarometerV2.FUNCTION_GET_SPITFP_ERROR_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletBarometerV2.FUNCTION_SET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletBarometerV2.FUNCTION_GET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletBarometerV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletBarometerV2.FUNCTION_WRITE_FIRMWARE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletBarometerV2.FUNCTION_SET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletBarometerV2.FUNCTION_GET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletBarometerV2.FUNCTION_GET_CHIP_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletBarometerV2.FUNCTION_RESET] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletBarometerV2.FUNCTION_WRITE_UID] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletBarometerV2.FUNCTION_READ_UID] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletBarometerV2.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletBarometerV2.CALLBACK_AIR_PRESSURE] = [12, 'i'];
	this.callbackFormats[BrickletBarometerV2.CALLBACK_ALTITUDE] = [12, 'i'];
	this.callbackFormats[BrickletBarometerV2.CALLBACK_TEMPERATURE] = [12, 'i'];



	this.getAirPressure = function(returnCallback, errorCallback) {
		/*
		Returns the measured air pressure.
		
		
		If you want to get the value periodically, it is recommended to use the
		:cb:`Air Pressure` callback. You can set the callback configuration
		with :func:`Set Air Pressure Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletBarometerV2.FUNCTION_GET_AIR_PRESSURE, [], '', 12, 'i', returnCallback, errorCallback, false, true);
	};
	this.setAirPressureCallbackConfiguration = function(period, valueHasToChange, option, min, max, returnCallback, errorCallback) {
		/*
		The period is the period with which the :cb:`Air Pressure` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		If the `value has to change`-parameter is set to true, the callback is only
		triggered after the value has changed. If the value didn't change
		within the period, the callback is triggered immediately on change.
		
		If it is set to false, the callback is continuously triggered with the period,
		independent of the value.
		
		It is furthermore possible to constrain the callback with thresholds.
		
		The `option`-parameter together with min/max sets a threshold for the :cb:`Air Pressure` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Threshold is turned off"
		 "'o'",    "Threshold is triggered when the value is *outside* the min and max values"
		 "'i'",    "Threshold is triggered when the value is *inside* or equal to the min and max values"
		 "'<'",    "Threshold is triggered when the value is smaller than the min value (max is ignored)"
		 "'>'",    "Threshold is triggered when the value is greater than the min value (max is ignored)"
		
		If the option is set to 'x' (threshold turned off) the callback is triggered with the fixed period.
		*/
		this.ipcon.sendRequest(this, BrickletBarometerV2.FUNCTION_SET_AIR_PRESSURE_CALLBACK_CONFIGURATION, [period, valueHasToChange, option, min, max], 'I ? c i i', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getAirPressureCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the callback configuration as set by :func:`Set Air Pressure Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletBarometerV2.FUNCTION_GET_AIR_PRESSURE_CALLBACK_CONFIGURATION, [], '', 22, 'I ? c i i', returnCallback, errorCallback, false, true);
	};
	this.getAltitude = function(returnCallback, errorCallback) {
		/*
		Returns the relative altitude of the air pressure sensor. The value
		is calculated based on the difference between the
		current air pressure and the reference air pressure that can be set
		with :func:`Set Reference Air Pressure`.
		
		
		If you want to get the value periodically, it is recommended to use the
		:cb:`Altitude` callback. You can set the callback configuration
		with :func:`Set Altitude Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletBarometerV2.FUNCTION_GET_ALTITUDE, [], '', 12, 'i', returnCallback, errorCallback, false, true);
	};
	this.setAltitudeCallbackConfiguration = function(period, valueHasToChange, option, min, max, returnCallback, errorCallback) {
		/*
		The period is the period with which the :cb:`Altitude` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		If the `value has to change`-parameter is set to true, the callback is only
		triggered after the value has changed. If the value didn't change
		within the period, the callback is triggered immediately on change.
		
		If it is set to false, the callback is continuously triggered with the period,
		independent of the value.
		
		It is furthermore possible to constrain the callback with thresholds.
		
		The `option`-parameter together with min/max sets a threshold for the :cb:`Altitude` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Threshold is turned off"
		 "'o'",    "Threshold is triggered when the value is *outside* the min and max values"
		 "'i'",    "Threshold is triggered when the value is *inside* or equal to the min and max values"
		 "'<'",    "Threshold is triggered when the value is smaller than the min value (max is ignored)"
		 "'>'",    "Threshold is triggered when the value is greater than the min value (max is ignored)"
		
		If the option is set to 'x' (threshold turned off) the callback is triggered with the fixed period.
		*/
		this.ipcon.sendRequest(this, BrickletBarometerV2.FUNCTION_SET_ALTITUDE_CALLBACK_CONFIGURATION, [period, valueHasToChange, option, min, max], 'I ? c i i', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getAltitudeCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the callback configuration as set by :func:`Set Altitude Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletBarometerV2.FUNCTION_GET_ALTITUDE_CALLBACK_CONFIGURATION, [], '', 22, 'I ? c i i', returnCallback, errorCallback, false, true);
	};
	this.getTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature of the air pressure sensor.
		
		This temperature is used internally for temperature compensation
		of the air pressure measurement. It is not as accurate as the
		temperature measured by the :ref:`temperature_v2_bricklet` or the
		:ref:`temperature_ir_v2_bricklet`.
		
		
		If you want to get the value periodically, it is recommended to use the
		:cb:`Temperature` callback. You can set the callback configuration
		with :func:`Set Temperature Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletBarometerV2.FUNCTION_GET_TEMPERATURE, [], '', 12, 'i', returnCallback, errorCallback, false, true);
	};
	this.setTemperatureCallbackConfiguration = function(period, valueHasToChange, option, min, max, returnCallback, errorCallback) {
		/*
		The period is the period with which the :cb:`Temperature` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		If the `value has to change`-parameter is set to true, the callback is only
		triggered after the value has changed. If the value didn't change
		within the period, the callback is triggered immediately on change.
		
		If it is set to false, the callback is continuously triggered with the period,
		independent of the value.
		
		It is furthermore possible to constrain the callback with thresholds.
		
		The `option`-parameter together with min/max sets a threshold for the :cb:`Temperature` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Threshold is turned off"
		 "'o'",    "Threshold is triggered when the value is *outside* the min and max values"
		 "'i'",    "Threshold is triggered when the value is *inside* or equal to the min and max values"
		 "'<'",    "Threshold is triggered when the value is smaller than the min value (max is ignored)"
		 "'>'",    "Threshold is triggered when the value is greater than the min value (max is ignored)"
		
		If the option is set to 'x' (threshold turned off) the callback is triggered with the fixed period.
		*/
		this.ipcon.sendRequest(this, BrickletBarometerV2.FUNCTION_SET_TEMPERATURE_CALLBACK_CONFIGURATION, [period, valueHasToChange, option, min, max], 'I ? c i i', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getTemperatureCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the callback configuration as set by :func:`Set Temperature Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletBarometerV2.FUNCTION_GET_TEMPERATURE_CALLBACK_CONFIGURATION, [], '', 22, 'I ? c i i', returnCallback, errorCallback, false, true);
	};
	this.setMovingAverageConfiguration = function(movingAverageLengthAirPressure, movingAverageLengthTemperature, returnCallback, errorCallback) {
		/*
		Sets the length of a `moving averaging <https://en.wikipedia.org/wiki/Moving_average>`__
		for the air pressure and temperature measurements.
		
		Setting the length to 1 will turn the averaging off. With less
		averaging, there is more noise on the data.
		
		If you want to do long term measurements the longest moving average will give
		the cleanest results.
		*/
		this.ipcon.sendRequest(this, BrickletBarometerV2.FUNCTION_SET_MOVING_AVERAGE_CONFIGURATION, [movingAverageLengthAirPressure, movingAverageLengthTemperature], 'H H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getMovingAverageConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the moving average configuration as set by
		:func:`Set Moving Average Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletBarometerV2.FUNCTION_GET_MOVING_AVERAGE_CONFIGURATION, [], '', 12, 'H H', returnCallback, errorCallback, false, true);
	};
	this.setReferenceAirPressure = function(airPressure, returnCallback, errorCallback) {
		/*
		Sets the reference air pressure for the altitude calculation.
		Setting the reference to the
		current air pressure results in a calculated altitude of 0mm. Passing 0 is
		a shortcut for passing the current air pressure as reference.
		
		Well known reference values are the Q codes
		`QNH <https://en.wikipedia.org/wiki/QNH>`__ and
		`QFE <https://en.wikipedia.org/wiki/Mean_sea_level_pressure#Mean_sea_level_pressure>`__
		used in aviation.
		*/
		this.ipcon.sendRequest(this, BrickletBarometerV2.FUNCTION_SET_REFERENCE_AIR_PRESSURE, [airPressure], 'i', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getReferenceAirPressure = function(returnCallback, errorCallback) {
		/*
		Returns the reference air pressure as set by :func:`Set Reference Air Pressure`.
		*/
		this.ipcon.sendRequest(this, BrickletBarometerV2.FUNCTION_GET_REFERENCE_AIR_PRESSURE, [], '', 12, 'i', returnCallback, errorCallback, false, true);
	};
	this.setCalibration = function(measuredAirPressure, actualAirPressure, returnCallback, errorCallback) {
		/*
		Sets the one point calibration (OPC) values for the air pressure measurement.
		
		Before the Bricklet can be calibrated any previous calibration has to be removed
		by setting ``measured air pressure`` and ``actual air pressure`` to 0.
		
		Then the current air pressure has to be measured using the Bricklet
		(``measured air pressure``) and with an accurate reference barometer
		(``actual air pressure``) at the same time and passed to this function.
		
		After proper calibration the air pressure measurement can achieve an accuracy
		up to 0.2 hPa.
		
		The calibration is saved in the EEPROM of the Bricklet and only needs to be
		configured once.
		*/
		this.ipcon.sendRequest(this, BrickletBarometerV2.FUNCTION_SET_CALIBRATION, [measuredAirPressure, actualAirPressure], 'i i', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getCalibration = function(returnCallback, errorCallback) {
		/*
		Returns the air pressure one point calibration values as set by
		:func:`Set Calibration`.
		*/
		this.ipcon.sendRequest(this, BrickletBarometerV2.FUNCTION_GET_CALIBRATION, [], '', 16, 'i i', returnCallback, errorCallback, false, true);
	};
	this.setSensorConfiguration = function(dataRate, airPressureLowPassFilter, returnCallback, errorCallback) {
		/*
		Configures the data rate and air pressure low pass filter. The low pass filter
		cut-off frequency (if enabled) can be set to 1/9th or 1/20th of the configure
		data rate to decrease the noise on the air pressure data.
		
		The low pass filter configuration only applies to the air pressure measurement.
		There is no low pass filter for the temperature measurement.
		
		A higher data rate will result in a less precise temperature because of
		self-heating of the sensor. If the accuracy of the temperature reading is
		important to you, we would recommend the 1Hz data rate.
		*/
		this.ipcon.sendRequest(this, BrickletBarometerV2.FUNCTION_SET_SENSOR_CONFIGURATION, [dataRate, airPressureLowPassFilter], 'B B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getSensorConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the sensor configuration as set by :func:`Set Sensor Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletBarometerV2.FUNCTION_GET_SENSOR_CONFIGURATION, [], '', 10, 'B B', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPErrorCount = function(returnCallback, errorCallback) {
		/*
		Returns the error count for the communication between Brick and Bricklet.
		
		The errors are divided into
		
		* ACK checksum errors,
		* message checksum errors,
		* framing errors and
		* overflow errors.
		
		The errors counts are for errors that occur on the Bricklet side. All
		Bricks have a similar function that returns the errors on the Brick side.
		*/
		this.ipcon.sendRequest(this, BrickletBarometerV2.FUNCTION_GET_SPITFP_ERROR_COUNT, [], '', 24, 'I I I I', returnCallback, errorCallback, false, true);
	};
	this.setBootloaderMode = function(mode, returnCallback, errorCallback) {
		/*
		Sets the bootloader mode and returns the status after the requested
		mode change was instigated.
		
		You can change from bootloader mode to firmware mode and vice versa. A change
		from bootloader mode to firmware mode will only take place if the entry function,
		device identifier and CRC are present and correct.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletBarometerV2.FUNCTION_SET_BOOTLOADER_MODE, [mode], 'B', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getBootloaderMode = function(returnCallback, errorCallback) {
		/*
		Returns the current bootloader mode, see :func:`Set Bootloader Mode`.
		*/
		this.ipcon.sendRequest(this, BrickletBarometerV2.FUNCTION_GET_BOOTLOADER_MODE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setWriteFirmwarePointer = function(pointer, returnCallback, errorCallback) {
		/*
		Sets the firmware pointer for :func:`Write Firmware`. The pointer has
		to be increased by chunks of size 64. The data is written to flash
		every 4 chunks (which equals to one page of size 256).
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletBarometerV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER, [pointer], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeFirmware = function(data, returnCallback, errorCallback) {
		/*
		Writes 64 Bytes of firmware at the position as written by
		:func:`Set Write Firmware Pointer` before. The firmware is written
		to flash every 4 chunks.
		
		You can only write firmware in bootloader mode.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletBarometerV2.FUNCTION_WRITE_FIRMWARE, [data], 'B64', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setStatusLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Sets the status LED configuration. By default the LED shows
		communication traffic between Brick and Bricklet, it flickers once
		for every 10 received data packets.
		
		You can also turn the LED permanently on/off or show a heartbeat.
		
		If the Bricklet is in bootloader mode, the LED is will show heartbeat by default.
		*/
		this.ipcon.sendRequest(this, BrickletBarometerV2.FUNCTION_SET_STATUS_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getStatusLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Status LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletBarometerV2.FUNCTION_GET_STATUS_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getChipTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature as measured inside the microcontroller. The
		value returned is not the ambient temperature!
		
		The temperature is only proportional to the real temperature and it has bad
		accuracy. Practically it is only useful as an indicator for
		temperature changes.
		*/
		this.ipcon.sendRequest(this, BrickletBarometerV2.FUNCTION_GET_CHIP_TEMPERATURE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.reset = function(returnCallback, errorCallback) {
		/*
		Calling this function will reset the Bricklet. All configurations
		will be lost.
		
		After a reset you have to create new device objects,
		calling functions on the existing ones will result in
		undefined behavior!
		*/
		this.ipcon.sendRequest(this, BrickletBarometerV2.FUNCTION_RESET, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeUID = function(uid, returnCallback, errorCallback) {
		/*
		Writes a new UID into flash. If you want to set a new UID
		you have to decode the Base58 encoded UID string into an
		integer first.
		
		We recommend that you use Brick Viewer to change the UID.
		*/
		this.ipcon.sendRequest(this, BrickletBarometerV2.FUNCTION_WRITE_UID, [uid], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.readUID = function(returnCallback, errorCallback) {
		/*
		Returns the current UID as an integer. Encode as
		Base58 to get the usual string version.
		*/
		this.ipcon.sendRequest(this, BrickletBarometerV2.FUNCTION_READ_UID, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletBarometerV2.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletBarometerV2;

},{"./Device":279,"./IPConnection":280}],161:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletCAN.DEVICE_IDENTIFIER = 270;
BrickletCAN.DEVICE_DISPLAY_NAME = 'CAN Bricklet';
BrickletCAN.CALLBACK_FRAME_READ = 11;
BrickletCAN.CALLBACK_FRAME_READABLE = 14;
BrickletCAN.FUNCTION_WRITE_FRAME = 1;
BrickletCAN.FUNCTION_READ_FRAME = 2;
BrickletCAN.FUNCTION_ENABLE_FRAME_READ_CALLBACK = 3;
BrickletCAN.FUNCTION_DISABLE_FRAME_READ_CALLBACK = 4;
BrickletCAN.FUNCTION_IS_FRAME_READ_CALLBACK_ENABLED = 5;
BrickletCAN.FUNCTION_SET_CONFIGURATION = 6;
BrickletCAN.FUNCTION_GET_CONFIGURATION = 7;
BrickletCAN.FUNCTION_SET_READ_FILTER = 8;
BrickletCAN.FUNCTION_GET_READ_FILTER = 9;
BrickletCAN.FUNCTION_GET_ERROR_LOG = 10;
BrickletCAN.FUNCTION_SET_FRAME_READABLE_CALLBACK_CONFIGURATION = 12;
BrickletCAN.FUNCTION_GET_FRAME_READABLE_CALLBACK_CONFIGURATION = 13;
BrickletCAN.FUNCTION_GET_IDENTITY = 255;
BrickletCAN.FRAME_TYPE_STANDARD_DATA = 0;
BrickletCAN.FRAME_TYPE_STANDARD_REMOTE = 1;
BrickletCAN.FRAME_TYPE_EXTENDED_DATA = 2;
BrickletCAN.FRAME_TYPE_EXTENDED_REMOTE = 3;
BrickletCAN.BAUD_RATE_10KBPS = 0;
BrickletCAN.BAUD_RATE_20KBPS = 1;
BrickletCAN.BAUD_RATE_50KBPS = 2;
BrickletCAN.BAUD_RATE_125KBPS = 3;
BrickletCAN.BAUD_RATE_250KBPS = 4;
BrickletCAN.BAUD_RATE_500KBPS = 5;
BrickletCAN.BAUD_RATE_800KBPS = 6;
BrickletCAN.BAUD_RATE_1000KBPS = 7;
BrickletCAN.TRANSCEIVER_MODE_NORMAL = 0;
BrickletCAN.TRANSCEIVER_MODE_LOOPBACK = 1;
BrickletCAN.TRANSCEIVER_MODE_READ_ONLY = 2;
BrickletCAN.FILTER_MODE_DISABLED = 0;
BrickletCAN.FILTER_MODE_ACCEPT_ALL = 1;
BrickletCAN.FILTER_MODE_MATCH_STANDARD = 2;
BrickletCAN.FILTER_MODE_MATCH_STANDARD_AND_DATA = 3;
BrickletCAN.FILTER_MODE_MATCH_EXTENDED = 4;

function BrickletCAN(uid, ipcon) {
	//Communicates with CAN bus devices

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletCAN.DEVICE_IDENTIFIER, BrickletCAN.DEVICE_DISPLAY_NAME);
	BrickletCAN.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 1];
	this.responseExpected[BrickletCAN.FUNCTION_WRITE_FRAME] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletCAN.FUNCTION_READ_FRAME] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletCAN.FUNCTION_ENABLE_FRAME_READ_CALLBACK] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletCAN.FUNCTION_DISABLE_FRAME_READ_CALLBACK] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletCAN.FUNCTION_IS_FRAME_READ_CALLBACK_ENABLED] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletCAN.FUNCTION_SET_CONFIGURATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletCAN.FUNCTION_GET_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletCAN.FUNCTION_SET_READ_FILTER] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletCAN.FUNCTION_GET_READ_FILTER] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletCAN.FUNCTION_GET_ERROR_LOG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletCAN.FUNCTION_SET_FRAME_READABLE_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletCAN.FUNCTION_GET_FRAME_READABLE_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletCAN.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletCAN.CALLBACK_FRAME_READ] = [22, 'B I B8 B'];
	this.callbackFormats[BrickletCAN.CALLBACK_FRAME_READABLE] = [8, ''];



	this.writeFrame = function(frameType, identifier, data, length, returnCallback, errorCallback) {
		/*
		Writes a data or remote frame to the write buffer to be transmitted over the
		CAN transceiver.
		
		The Bricklet supports the standard 11-bit (CAN 2.0A) and the additional extended
		18-bit (CAN 2.0B) identifiers. For standard frames the Bricklet uses bit 0 to 10
		from the ``identifier`` parameter as standard 11-bit identifier. For extended
		frames the Bricklet additionally uses bit 11 to 28 from the ``identifier``
		parameter as extended 18-bit identifier.
		
		For remote frames the ``data`` parameter is ignored.
		
		Returns *true* if the frame was successfully added to the write buffer. Returns
		*false* if the frame could not be added because write buffer is already full.
		
		The write buffer can overflow if frames are written to it at a higher rate
		than the Bricklet can transmitted them over the CAN transceiver. This may
		happen if the CAN transceiver is configured as read-only or is using a low baud
		rate (see :func:`Set Configuration`). It can also happen if the CAN bus is
		congested and the frame cannot be transmitted because it constantly loses
		arbitration or because the CAN transceiver is currently disabled due to a high
		write error level (see :func:`Get Error Log`).
		*/
		this.ipcon.sendRequest(this, BrickletCAN.FUNCTION_WRITE_FRAME, [frameType, identifier, data, length], 'B I B8 B', 9, '?', returnCallback, errorCallback, false, true);
	};
	this.readFrame = function(returnCallback, errorCallback) {
		/*
		Tries to read the next data or remote frame from the read buffer and return it.
		If a frame was successfully read, then the ``success`` return value is set to
		*true* and the other return values contain the frame. If the read buffer is
		empty and no frame could be read, then the ``success`` return value is set to
		*false* and the other return values contain invalid data.
		
		The ``identifier`` return value follows the identifier format described for
		:func:`Write Frame`.
		
		For remote frames the ``data`` return value always contains invalid data.
		
		A configurable read filter can be used to define which frames should be
		received by the CAN transceiver and put into the read buffer (see
		:func:`Set Read Filter`).
		
		Instead of polling with this function, you can also use callbacks. See the
		:func:`Enable Frame Read Callback` function and the :cb:`Frame Read` callback.
		*/
		this.ipcon.sendRequest(this, BrickletCAN.FUNCTION_READ_FRAME, [], '', 23, '? B I B8 B', returnCallback, errorCallback, false, true);
	};
	this.enableFrameReadCallback = function(returnCallback, errorCallback) {
		/*
		Enables the :cb:`Frame Read` callback.
		
		By default the callback is disabled. Enabling this callback will disable the :cb:`Frame Readable` callback.
		*/
		this.ipcon.sendRequest(this, BrickletCAN.FUNCTION_ENABLE_FRAME_READ_CALLBACK, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.disableFrameReadCallback = function(returnCallback, errorCallback) {
		/*
		Disables the :cb:`Frame Read` callback.
		
		By default the callback is disabled.
		*/
		this.ipcon.sendRequest(this, BrickletCAN.FUNCTION_DISABLE_FRAME_READ_CALLBACK, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.isFrameReadCallbackEnabled = function(returnCallback, errorCallback) {
		/*
		Returns *true* if the :cb:`Frame Read` callback is enabled, *false* otherwise.
		*/
		this.ipcon.sendRequest(this, BrickletCAN.FUNCTION_IS_FRAME_READ_CALLBACK_ENABLED, [], '', 9, '?', returnCallback, errorCallback, false, true);
	};
	this.setConfiguration = function(baudRate, transceiverMode, writeTimeout, returnCallback, errorCallback) {
		/*
		Sets the configuration for the CAN bus communication.
		
		The baud rate can be configured in steps between 10 and 1000 kbit/s.
		
		The CAN transceiver has three different modes:
		
		* Normal: Reads from and writes to the CAN bus and performs active bus
		  error detection and acknowledgement.
		* Loopback: All reads and writes are performed internally. The transceiver
		  is disconnected from the actual CAN bus.
		* Read-Only: Only reads from the CAN bus, but does neither active bus error
		  detection nor acknowledgement. Only the receiving part of the transceiver
		  is connected to the CAN bus.
		
		The write timeout has three different modes that define how a failed frame
		transmission should be handled:
		
		* One-Shot (= -1): Only one transmission attempt will be made. If the
		  transmission fails then the frame is discarded.
		* Infinite (= 0): Infinite transmission attempts will be made. The frame will
		  never be discarded.
		* Milliseconds (> 0): A limited number of transmission attempts will be made.
		  If the frame could not be transmitted successfully after the configured
		  number of milliseconds then the frame is discarded.
		*/
		this.ipcon.sendRequest(this, BrickletCAN.FUNCTION_SET_CONFIGURATION, [baudRate, transceiverMode, writeTimeout], 'B B i', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletCAN.FUNCTION_GET_CONFIGURATION, [], '', 14, 'B B i', returnCallback, errorCallback, false, true);
	};
	this.setReadFilter = function(mode, mask, filter1, filter2, returnCallback, errorCallback) {
		/*
		Set the read filter configuration. This can be used to define which frames
		should be received by the CAN transceiver and put into the read buffer.
		
		The read filter has five different modes that define if and how the mask and
		the two filters are applied:
		
		* Disabled: No filtering is applied at all. All frames are received even
		  incomplete and defective frames. This mode should be used for debugging only.
		* Accept-All: All complete and error-free frames are received.
		* Match-Standard: Only standard frames with a matching identifier are received.
		* Match-Standard-and-Data: Only standard frames with matching identifier and
		  data bytes are received.
		* Match-Extended: Only extended frames with a matching identifier are received.
		
		The mask and filters are used as bit masks. Their usage depends on the mode:
		
		* Disabled: Mask and filters are ignored.
		* Accept-All: Mask and filters are ignored.
		* Match-Standard: Bit 0 to 10 (11 bits) of mask and filters are used to match
		  the 11-bit identifier of standard frames.
		* Match-Standard-and-Data: Bit 0 to 10 (11 bits) of mask and filters are used
		  to match the 11-bit identifier of standard frames. Bit 11 to 18 (8 bits) and
		  bit 19 to 26 (8 bits) of mask and filters are used to match the first and
		  second data byte (if present) of standard frames.
		* Match-Extended: Bit 0 to 10 (11 bits) of mask and filters are used
		  to match the standard 11-bit identifier part of extended frames. Bit 11 to 28
		  (18 bits) of mask and filters are used to match the extended 18-bit identifier
		  part of extended frames.
		
		The mask and filters are applied in this way: The mask is used to select the
		identifier and data bits that should be compared to the corresponding filter
		bits. All unselected bits are automatically accepted. All selected bits have
		to match one of the filters to be accepted. If all bits for the selected mode
		are accepted then the frame is accepted and is added to the read buffer.
		
		.. csv-table::
		 :header: "Mask Bit", "Filter Bit", "Identifier/Data Bit", "Result"
		 :widths: 10, 10, 10, 10
		
		 0, X, X, Accept
		 1, 0, 0, Accept
		 1, 0, 1, Reject
		 1, 1, 0, Reject
		 1, 1, 1, Accept
		
		For example, to receive standard frames with identifier 0x123 only the mode can
		be set to Match-Standard with 0x7FF as mask and 0x123 as filter 1 and filter 2.
		The mask of 0x7FF selects all 11 identifier bits for matching so that the
		identifier has to be exactly 0x123 to be accepted.
		
		To accept identifier 0x123 and identifier 0x456 at the same time, just set
		filter 2 to 0x456 and keep mask and filter 1 unchanged.
		*/
		this.ipcon.sendRequest(this, BrickletCAN.FUNCTION_SET_READ_FILTER, [mode, mask, filter1, filter2], 'B I I I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getReadFilter = function(returnCallback, errorCallback) {
		/*
		Returns the read filter as set by :func:`Set Read Filter`.
		*/
		this.ipcon.sendRequest(this, BrickletCAN.FUNCTION_GET_READ_FILTER, [], '', 21, 'B I I I', returnCallback, errorCallback, false, true);
	};
	this.getErrorLog = function(returnCallback, errorCallback) {
		/*
		Returns information about different kinds of errors.
		
		The write and read error levels indicate the current level of checksum,
		acknowledgement, form, bit and stuffing errors during CAN bus write and read
		operations.
		
		When the write error level exceeds 255 then the CAN transceiver gets disabled
		and no frames can be transmitted or received anymore. The CAN transceiver will
		automatically be activated again after the CAN bus is idle for a while.
		
		The write and read error levels are not available in read-only transceiver mode
		(see :func:`Set Configuration`) and are reset to 0 as a side effect of changing
		the configuration or the read filter.
		
		The write timeout, read register and buffer overflow counts represents the
		number of these errors:
		
		* A write timeout occurs if a frame could not be transmitted before the
		  configured write timeout expired (see :func:`Set Configuration`).
		* A read register overflow occurs if the read register of the CAN transceiver
		  still contains the last received frame when the next frame arrives. In this
		  case the newly arrived frame is lost. This happens if the CAN transceiver
		  receives more frames than the Bricklet can handle. Using the read filter
		  (see :func:`Set Read Filter`) can help to reduce the amount of received frames.
		  This count is not exact, but a lower bound, because the Bricklet might not
		  able detect all overflows if they occur in rapid succession.
		* A read buffer overflow occurs if the read buffer of the Bricklet is already
		  full when the next frame should be read from the read register of the CAN
		  transceiver. In this case the frame in the read register is lost. This
		  happens if the CAN transceiver receives more frames to be added to the read
		  buffer than are removed from the read buffer using the :func:`Read Frame`
		  function. Using the :cb:`Frame Read` callback ensures that the read buffer
		  can not overflow.
		*/
		this.ipcon.sendRequest(this, BrickletCAN.FUNCTION_GET_ERROR_LOG, [], '', 23, 'B B ? I I I', returnCallback, errorCallback, false, true);
	};
	this.setFrameReadableCallbackConfiguration = function(enabled, returnCallback, errorCallback) {
		/*
		Enables/disables the :cb:`Frame Readable` callback.
		
		By default the callback is disabled. Enabling this callback will disable the :cb:`Frame Read` callback.
		
		.. versionadded:: 2.0.1$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletCAN.FUNCTION_SET_FRAME_READABLE_CALLBACK_CONFIGURATION, [enabled], '?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getFrameReadableCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns *true* if the :cb:`Frame Readable` callback is enabled, *false* otherwise.
		
		.. versionadded:: 2.0.1$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletCAN.FUNCTION_GET_FRAME_READABLE_CALLBACK_CONFIGURATION, [], '', 9, '?', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletCAN.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletCAN;

},{"./Device":279,"./IPConnection":280}],162:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletCANV2.DEVICE_IDENTIFIER = 2107;
BrickletCANV2.DEVICE_DISPLAY_NAME = 'CAN Bricklet 2.0';
BrickletCANV2.CALLBACK_FRAME_READ_LOW_LEVEL = 16;
BrickletCANV2.CALLBACK_FRAME_READABLE = 19;
BrickletCANV2.CALLBACK_ERROR_OCCURRED = 22;
BrickletCANV2.CALLBACK_FRAME_READ = -16;
BrickletCANV2.FUNCTION_WRITE_FRAME_LOW_LEVEL = 1;
BrickletCANV2.FUNCTION_READ_FRAME_LOW_LEVEL = 2;
BrickletCANV2.FUNCTION_SET_FRAME_READ_CALLBACK_CONFIGURATION = 3;
BrickletCANV2.FUNCTION_GET_FRAME_READ_CALLBACK_CONFIGURATION = 4;
BrickletCANV2.FUNCTION_SET_TRANSCEIVER_CONFIGURATION = 5;
BrickletCANV2.FUNCTION_GET_TRANSCEIVER_CONFIGURATION = 6;
BrickletCANV2.FUNCTION_SET_QUEUE_CONFIGURATION_LOW_LEVEL = 7;
BrickletCANV2.FUNCTION_GET_QUEUE_CONFIGURATION_LOW_LEVEL = 8;
BrickletCANV2.FUNCTION_SET_READ_FILTER_CONFIGURATION = 9;
BrickletCANV2.FUNCTION_GET_READ_FILTER_CONFIGURATION = 10;
BrickletCANV2.FUNCTION_GET_ERROR_LOG_LOW_LEVEL = 11;
BrickletCANV2.FUNCTION_SET_COMMUNICATION_LED_CONFIG = 12;
BrickletCANV2.FUNCTION_GET_COMMUNICATION_LED_CONFIG = 13;
BrickletCANV2.FUNCTION_SET_ERROR_LED_CONFIG = 14;
BrickletCANV2.FUNCTION_GET_ERROR_LED_CONFIG = 15;
BrickletCANV2.FUNCTION_SET_FRAME_READABLE_CALLBACK_CONFIGURATION = 17;
BrickletCANV2.FUNCTION_GET_FRAME_READABLE_CALLBACK_CONFIGURATION = 18;
BrickletCANV2.FUNCTION_SET_ERROR_OCCURRED_CALLBACK_CONFIGURATION = 20;
BrickletCANV2.FUNCTION_GET_ERROR_OCCURRED_CALLBACK_CONFIGURATION = 21;
BrickletCANV2.FUNCTION_GET_SPITFP_ERROR_COUNT = 234;
BrickletCANV2.FUNCTION_SET_BOOTLOADER_MODE = 235;
BrickletCANV2.FUNCTION_GET_BOOTLOADER_MODE = 236;
BrickletCANV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER = 237;
BrickletCANV2.FUNCTION_WRITE_FIRMWARE = 238;
BrickletCANV2.FUNCTION_SET_STATUS_LED_CONFIG = 239;
BrickletCANV2.FUNCTION_GET_STATUS_LED_CONFIG = 240;
BrickletCANV2.FUNCTION_GET_CHIP_TEMPERATURE = 242;
BrickletCANV2.FUNCTION_RESET = 243;
BrickletCANV2.FUNCTION_WRITE_UID = 248;
BrickletCANV2.FUNCTION_READ_UID = 249;
BrickletCANV2.FUNCTION_GET_IDENTITY = 255;
BrickletCANV2.FRAME_TYPE_STANDARD_DATA = 0;
BrickletCANV2.FRAME_TYPE_STANDARD_REMOTE = 1;
BrickletCANV2.FRAME_TYPE_EXTENDED_DATA = 2;
BrickletCANV2.FRAME_TYPE_EXTENDED_REMOTE = 3;
BrickletCANV2.TRANSCEIVER_MODE_NORMAL = 0;
BrickletCANV2.TRANSCEIVER_MODE_LOOPBACK = 1;
BrickletCANV2.TRANSCEIVER_MODE_READ_ONLY = 2;
BrickletCANV2.FILTER_MODE_ACCEPT_ALL = 0;
BrickletCANV2.FILTER_MODE_MATCH_STANDARD_ONLY = 1;
BrickletCANV2.FILTER_MODE_MATCH_EXTENDED_ONLY = 2;
BrickletCANV2.FILTER_MODE_MATCH_STANDARD_AND_EXTENDED = 3;
BrickletCANV2.TRANSCEIVER_STATE_ACTIVE = 0;
BrickletCANV2.TRANSCEIVER_STATE_PASSIVE = 1;
BrickletCANV2.TRANSCEIVER_STATE_DISABLED = 2;
BrickletCANV2.COMMUNICATION_LED_CONFIG_OFF = 0;
BrickletCANV2.COMMUNICATION_LED_CONFIG_ON = 1;
BrickletCANV2.COMMUNICATION_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletCANV2.COMMUNICATION_LED_CONFIG_SHOW_COMMUNICATION = 3;
BrickletCANV2.ERROR_LED_CONFIG_OFF = 0;
BrickletCANV2.ERROR_LED_CONFIG_ON = 1;
BrickletCANV2.ERROR_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletCANV2.ERROR_LED_CONFIG_SHOW_TRANSCEIVER_STATE = 3;
BrickletCANV2.ERROR_LED_CONFIG_SHOW_ERROR = 4;
BrickletCANV2.BOOTLOADER_MODE_BOOTLOADER = 0;
BrickletCANV2.BOOTLOADER_MODE_FIRMWARE = 1;
BrickletCANV2.BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT = 2;
BrickletCANV2.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT = 3;
BrickletCANV2.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT = 4;
BrickletCANV2.BOOTLOADER_STATUS_OK = 0;
BrickletCANV2.BOOTLOADER_STATUS_INVALID_MODE = 1;
BrickletCANV2.BOOTLOADER_STATUS_NO_CHANGE = 2;
BrickletCANV2.BOOTLOADER_STATUS_ENTRY_FUNCTION_NOT_PRESENT = 3;
BrickletCANV2.BOOTLOADER_STATUS_DEVICE_IDENTIFIER_INCORRECT = 4;
BrickletCANV2.BOOTLOADER_STATUS_CRC_MISMATCH = 5;
BrickletCANV2.STATUS_LED_CONFIG_OFF = 0;
BrickletCANV2.STATUS_LED_CONFIG_ON = 1;
BrickletCANV2.STATUS_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletCANV2.STATUS_LED_CONFIG_SHOW_STATUS = 3;

function BrickletCANV2(uid, ipcon) {
	//Communicates with CAN bus devices

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletCANV2.DEVICE_IDENTIFIER, BrickletCANV2.DEVICE_DISPLAY_NAME);
	BrickletCANV2.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 1];
	this.responseExpected[BrickletCANV2.FUNCTION_WRITE_FRAME_LOW_LEVEL] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletCANV2.FUNCTION_READ_FRAME_LOW_LEVEL] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletCANV2.FUNCTION_SET_FRAME_READ_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletCANV2.FUNCTION_GET_FRAME_READ_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletCANV2.FUNCTION_SET_TRANSCEIVER_CONFIGURATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletCANV2.FUNCTION_GET_TRANSCEIVER_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletCANV2.FUNCTION_SET_QUEUE_CONFIGURATION_LOW_LEVEL] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletCANV2.FUNCTION_GET_QUEUE_CONFIGURATION_LOW_LEVEL] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletCANV2.FUNCTION_SET_READ_FILTER_CONFIGURATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletCANV2.FUNCTION_GET_READ_FILTER_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletCANV2.FUNCTION_GET_ERROR_LOG_LOW_LEVEL] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletCANV2.FUNCTION_SET_COMMUNICATION_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletCANV2.FUNCTION_GET_COMMUNICATION_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletCANV2.FUNCTION_SET_ERROR_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletCANV2.FUNCTION_GET_ERROR_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletCANV2.FUNCTION_SET_FRAME_READABLE_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletCANV2.FUNCTION_GET_FRAME_READABLE_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletCANV2.FUNCTION_SET_ERROR_OCCURRED_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletCANV2.FUNCTION_GET_ERROR_OCCURRED_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletCANV2.FUNCTION_GET_SPITFP_ERROR_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletCANV2.FUNCTION_SET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletCANV2.FUNCTION_GET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletCANV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletCANV2.FUNCTION_WRITE_FIRMWARE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletCANV2.FUNCTION_SET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletCANV2.FUNCTION_GET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletCANV2.FUNCTION_GET_CHIP_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletCANV2.FUNCTION_RESET] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletCANV2.FUNCTION_WRITE_UID] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletCANV2.FUNCTION_READ_UID] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletCANV2.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletCANV2.CALLBACK_FRAME_READ_LOW_LEVEL] = [29, 'B I B B15'];
	this.callbackFormats[BrickletCANV2.CALLBACK_FRAME_READABLE] = [8, ''];
	this.callbackFormats[BrickletCANV2.CALLBACK_ERROR_OCCURRED] = [8, ''];

	this.highLevelCallbacks[BrickletCANV2.CALLBACK_FRAME_READ] = [[null, null, 'streamLength', 'streamChunkData'], {'fixedLength': null, 'singleChunk': true}, null];

	this.streamStateObjects[BrickletCANV2.FUNCTION_WRITE_FRAME_LOW_LEVEL] = {
		'dataMapping': [null],
		'dataMappingStreamIn': [null, null, 'streamLength', 'streamChunkData'],
		'streamProperties': {
			'fixedLength': null,
			'singleChunk': true,
			'shortWrite': false
		},
		'responseProperties': {
			'running': false,
			'runningSubcall': false,
			'runningSubcallOOS': false,
			'waitingFirstChunk': true,
			'timeout': null,
			'data': [],
			'streamInChunkOffset': 0,
			'streamInChunkLength': 0,
			'streamInResponseEmpty': false,
			'streamInWritten': 0,
			'streamInLLParams': null,
			'responseHandler': null,
			'packFormatString': 'B I B B15',
			'unpackFormatString': '?',
			'returnCB': null,
			'errorCB': null,
			'callQueue': []
		}
	};
	this.streamStateObjects[BrickletCANV2.FUNCTION_READ_FRAME_LOW_LEVEL] = {
		'dataMapping': [null, null, null, 'streamLength', 'streamChunkData'],
		'dataMappingStreamIn': [],
		'streamProperties': {
			'fixedLength': null,
			'singleChunk': true,
			'shortWrite': false
		},
		'responseProperties': {
			'running': false,
			'runningSubcall': false,
			'runningSubcallOOS': false,
			'waitingFirstChunk': true,
			'timeout': null,
			'data': [],
			'streamInChunkOffset': 0,
			'streamInChunkLength': 0,
			'streamInResponseEmpty': true,
			'streamInWritten': 0,
			'streamInLLParams': null,
			'responseHandler': null,
			'packFormatString': '',
			'unpackFormatString': '? B I B B15',
			'returnCB': null,
			'errorCB': null,
			'callQueue': []
		}
	};
	this.streamStateObjects[BrickletCANV2.FUNCTION_SET_QUEUE_CONFIGURATION_LOW_LEVEL] = {
		'dataMapping': [],
		'dataMappingStreamIn': [null, null, null, 'streamLength', 'streamChunkData', null],
		'streamProperties': {
			'fixedLength': null,
			'singleChunk': true,
			'shortWrite': false
		},
		'responseProperties': {
			'running': false,
			'runningSubcall': false,
			'runningSubcallOOS': false,
			'waitingFirstChunk': true,
			'timeout': null,
			'data': [],
			'streamInChunkOffset': 0,
			'streamInChunkLength': 0,
			'streamInResponseEmpty': true,
			'streamInWritten': 0,
			'streamInLLParams': null,
			'responseHandler': null,
			'packFormatString': 'B i H B b32 H',
			'unpackFormatString': '',
			'returnCB': null,
			'errorCB': null,
			'callQueue': []
		}
	};
	this.streamStateObjects[BrickletCANV2.FUNCTION_GET_QUEUE_CONFIGURATION_LOW_LEVEL] = {
		'dataMapping': [null, null, null, 'streamLength', 'streamChunkData', null],
		'dataMappingStreamIn': [],
		'streamProperties': {
			'fixedLength': null,
			'singleChunk': true,
			'shortWrite': false
		},
		'responseProperties': {
			'running': false,
			'runningSubcall': false,
			'runningSubcallOOS': false,
			'waitingFirstChunk': true,
			'timeout': null,
			'data': [],
			'streamInChunkOffset': 0,
			'streamInChunkLength': 0,
			'streamInResponseEmpty': true,
			'streamInWritten': 0,
			'streamInLLParams': null,
			'responseHandler': null,
			'packFormatString': '',
			'unpackFormatString': 'B i H B b32 H',
			'returnCB': null,
			'errorCB': null,
			'callQueue': []
		}
	};
	this.streamStateObjects[BrickletCANV2.FUNCTION_GET_ERROR_LOG_LOW_LEVEL] = {
		'dataMapping': [null, null, null, null, null, null, null, null, null, null, null, 'streamLength', 'streamChunkData', null],
		'dataMappingStreamIn': [],
		'streamProperties': {
			'fixedLength': null,
			'singleChunk': true,
			'shortWrite': false
		},
		'responseProperties': {
			'running': false,
			'runningSubcall': false,
			'runningSubcallOOS': false,
			'waitingFirstChunk': true,
			'timeout': null,
			'data': [],
			'streamInChunkOffset': 0,
			'streamInChunkLength': 0,
			'streamInResponseEmpty': true,
			'streamInWritten': 0,
			'streamInLLParams': null,
			'responseHandler': null,
			'packFormatString': '',
			'unpackFormatString': 'B B B I I I I I I I I B ?32 I',
			'returnCB': null,
			'errorCB': null,
			'callQueue': []
		}
	};

	this.writeFrameLowLevel = function(frameType, identifier, dataLength, dataData, returnCallback, errorCallback) {
		/*
		Writes a data or remote frame to the write queue to be transmitted over the
		CAN transceiver.
		
		The Bricklet supports the standard 11-bit (CAN 2.0A) and the additional extended
		29-bit (CAN 2.0B) identifiers. For standard frames the Bricklet uses bit 0 to 10
		from the ``identifier`` parameter as standard 11-bit identifier. For extended
		frames the Bricklet uses bit 0 to 28 from the ``identifier`` parameter as
		extended 29-bit identifier.
		
		The ``data`` parameter can be up to 15 bytes long. For data frames up to 8 bytes
		will be used as the actual data. The length (DLC) field in the data or remote
		frame will be set to the actual length of the ``data`` parameter. This allows
		to transmit data and remote frames with excess length. For remote frames only
		the length of the ``data`` parameter is used. The actual ``data`` bytes are
		ignored.
		
		Returns *true* if the frame was successfully added to the write queue. Returns
		*false* if the frame could not be added because write queue is already full or
		because the write buffer or the write backlog are configured with a size of
		zero (see :func:`Set Queue Configuration`).
		
		The write queue can overflow if frames are written to it at a higher rate
		than the Bricklet can transmitted them over the CAN transceiver. This may
		happen if the CAN transceiver is configured as read-only or is using a low baud
		rate (see :func:`Set Transceiver Configuration`). It can also happen if the CAN
		bus is congested and the frame cannot be transmitted because it constantly loses
		arbitration or because the CAN transceiver is currently disabled due to a high
		write error level (see :func:`Get Error Log`).
		*/
		this.ipcon.sendRequest(this, BrickletCANV2.FUNCTION_WRITE_FRAME_LOW_LEVEL, [frameType, identifier, dataLength, dataData], 'B I B B15', 9, '?', returnCallback, errorCallback, false, true);
	};
	this.readFrameLowLevel = function(returnCallback, errorCallback) {
		/*
		Tries to read the next data or remote frame from the read queue and returns it.
		If a frame was successfully read, then the ``success`` return value is set to
		*true* and the other return values contain the frame. If the read queue is
		empty and no frame could be read, then the ``success`` return value is set to
		*false* and the other return values contain invalid data.
		
		The ``identifier`` return value follows the identifier format described for
		:func:`Write Frame`.
		
		The ``data`` return value can be up to 15 bytes long. For data frames up to the
		first 8 bytes are the actual received data. All bytes after the 8th byte are
		always zero and only there to indicate the length of a data or remote frame
		with excess length. For remote frames the length of the ``data`` return value
		represents the requested length. The actual ``data`` bytes are always zero.
		
		A configurable read filter can be used to define which frames should be
		received by the CAN transceiver and put into the read queue (see
		:func:`Set Read Filter Configuration`).
		
		Instead of polling with this function, you can also use callbacks. See the
		:func:`Set Frame Read Callback Configuration` function and the :cb:`Frame Read`
		callback.
		*/
		this.ipcon.sendRequest(this, BrickletCANV2.FUNCTION_READ_FRAME_LOW_LEVEL, [], '', 30, '? B I B B15', returnCallback, errorCallback, false, true);
	};
	this.setFrameReadCallbackConfiguration = function(enabled, returnCallback, errorCallback) {
		/*
		Enables and disables the :cb:`Frame Read` callback.
		
		By default the callback is disabled. Enabling this callback will disable the :cb:`Frame Readable` callback.
		*/
		this.ipcon.sendRequest(this, BrickletCANV2.FUNCTION_SET_FRAME_READ_CALLBACK_CONFIGURATION, [enabled], '?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getFrameReadCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns *true* if the :cb:`Frame Read` callback is enabled, *false* otherwise.
		*/
		this.ipcon.sendRequest(this, BrickletCANV2.FUNCTION_GET_FRAME_READ_CALLBACK_CONFIGURATION, [], '', 9, '?', returnCallback, errorCallback, false, true);
	};
	this.setTransceiverConfiguration = function(baudRate, samplePoint, transceiverMode, returnCallback, errorCallback) {
		/*
		Sets the transceiver configuration for the CAN bus communication.
		
		The CAN transceiver has three different modes:
		
		* Normal: Reads from and writes to the CAN bus and performs active bus
		  error detection and acknowledgement.
		* Loopback: All reads and writes are performed internally. The transceiver
		  is disconnected from the actual CAN bus.
		* Read-Only: Only reads from the CAN bus, but does neither active bus error
		  detection nor acknowledgement. Only the receiving part of the transceiver
		  is connected to the CAN bus.
		*/
		this.ipcon.sendRequest(this, BrickletCANV2.FUNCTION_SET_TRANSCEIVER_CONFIGURATION, [baudRate, samplePoint, transceiverMode], 'I H B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getTransceiverConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Transceiver Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletCANV2.FUNCTION_GET_TRANSCEIVER_CONFIGURATION, [], '', 15, 'I H B', returnCallback, errorCallback, false, true);
	};
	this.setQueueConfigurationLowLevel = function(writeBufferSize, writeBufferTimeout, writeBacklogSize, readBufferSizesLength, readBufferSizesData, readBacklogSize, returnCallback, errorCallback) {
		/*
		Sets the write and read queue configuration.
		
		The CAN transceiver has 32 buffers in total in hardware for transmitting and
		receiving frames. Additionally, the Bricklet has a backlog for 768 frames in
		total in software. The buffers and the backlog can be freely assigned to the
		write and read queues.
		
		:func:`Write Frame` writes a frame into the write backlog. The Bricklet moves
		the frame from the backlog into a free write buffer. The CAN transceiver then
		transmits the frame from the write buffer to the CAN bus. If there are no
		write buffers (``write_buffer_size`` is zero) or there is no write backlog
		(``write_backlog_size`` is zero) then no frames can be transmitted and
		:func:`Write Frame` returns always *false*.
		
		The CAN transceiver receives a frame from the CAN bus and stores it into a
		free read buffer. The Bricklet moves the frame from the read buffer into the
		read backlog. :func:`Read Frame` reads the frame from the read backlog and
		returns it. If there are no read buffers (``read_buffer_sizes`` is empty) or
		there is no read backlog (``read_backlog_size`` is zero) then no frames can be
		received and :func:`Read Frame` returns always *false*.
		
		There can be multiple read buffers, because the CAN transceiver cannot receive
		data and remote frames into the same read buffer. A positive read buffer size
		represents a data frame read buffer and a negative read buffer size represents
		a remote frame read buffer. A read buffer size of zero is not allowed. By
		default the first read buffer is configured for data frames and the second read
		buffer is configured for remote frame. There can be up to 32 different read
		buffers, assuming that no write buffer is used. Each read buffer has its own
		filter configuration (see :func:`Set Read Filter Configuration`).
		
		A valid queue configuration fulfills these conditions::
		
		 write_buffer_size + abs(read_buffer_size_0) + abs(read_buffer_size_1) + ... + abs(read_buffer_size_31) <= 32
		 write_backlog_size + read_backlog_size <= 768
		
		The write buffer timeout has three different modes that define how a failed
		frame transmission should be handled:
		
		* Single-Shot (< 0): Only one transmission attempt will be made. If the
		  transmission fails then the frame is discarded.
		* Infinite (= 0): Infinite transmission attempts will be made. The frame will
		  never be discarded.
		* Milliseconds (> 0): A limited number of transmission attempts will be made.
		  If the frame could not be transmitted successfully after the configured
		  number of milliseconds then the frame is discarded.
		
		The current content of the queues is lost when this function is called.
		*/
		this.ipcon.sendRequest(this, BrickletCANV2.FUNCTION_SET_QUEUE_CONFIGURATION_LOW_LEVEL, [writeBufferSize, writeBufferTimeout, writeBacklogSize, readBufferSizesLength, readBufferSizesData, readBacklogSize], 'B i H B b32 H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getQueueConfigurationLowLevel = function(returnCallback, errorCallback) {
		/*
		Returns the queue configuration as set by :func:`Set Queue Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletCANV2.FUNCTION_GET_QUEUE_CONFIGURATION_LOW_LEVEL, [], '', 50, 'B i H B b32 H', returnCallback, errorCallback, false, true);
	};
	this.setReadFilterConfiguration = function(bufferIndex, filterMode, filterMask, filterIdentifier, returnCallback, errorCallback) {
		/*
		Set the read filter configuration for the given read buffer index. This can be
		used to define which frames should be received by the CAN transceiver and put
		into the read buffer.
		
		The read filter has four different modes that define if and how the filter mask
		and the filter identifier are applied:
		
		* Accept-All: All frames are received.
		* Match-Standard-Only: Only standard frames with a matching identifier are
		  received.
		* Match-Extended-Only: Only extended frames with a matching identifier are
		  received.
		* Match-Standard-And-Extended: Standard and extended frames with a matching
		  identifier are received.
		
		The filter mask and filter identifier are used as bit masks. Their usage
		depends on the mode:
		
		* Accept-All: Mask and identifier are ignored.
		* Match-Standard-Only: Bit 0 to 10 (11 bits) of filter mask and filter
		  identifier are used to match the 11-bit identifier of standard frames.
		* Match-Extended-Only: Bit 0 to 28 (29 bits) of filter mask and filter
		  identifier are used to match the 29-bit identifier of extended frames.
		* Match-Standard-And-Extended: Bit 18 to 28 (11 bits) of filter mask and filter
		  identifier are used to match the 11-bit identifier of standard frames, bit 0
		  to 17 (18 bits) are ignored in this case. Bit 0 to 28 (29 bits) of filter
		  mask and filter identifier are used to match the 29-bit identifier of extended
		  frames.
		
		The filter mask and filter identifier are applied in this way: The filter mask
		is used to select the frame identifier bits that should be compared to the
		corresponding filter identifier bits. All unselected bits are automatically
		accepted. All selected bits have to match the filter identifier to be accepted.
		If all bits for the selected mode are accepted then the frame is accepted and
		is added to the read buffer.
		
		.. csv-table::
		 :header: "Filter Mask Bit", "Filter Identifier Bit", "Frame Identifier Bit", "Result"
		 :widths: 10, 10, 10, 10
		
		 0, X, X, Accept
		 1, 0, 0, Accept
		 1, 0, 1, Reject
		 1, 1, 0, Reject
		 1, 1, 1, Accept
		
		For example, to receive standard frames with identifier 0x123 only, the mode
		can be set to Match-Standard-Only with 0x7FF as mask and 0x123 as identifier.
		The mask of 0x7FF selects all 11 identifier bits for matching so that the
		identifier has to be exactly 0x123 to be accepted.
		
		To accept identifier 0x123 and identifier 0x456 at the same time, just set
		filter 2 to 0x456 and keep mask and filter 1 unchanged.
		
		There can be up to 32 different read filters configured at the same time,
		because there can be up to 32 read buffer (see :func:`Set Queue Configuration`).
		
		The default mode is accept-all for all read buffers.
		*/
		this.ipcon.sendRequest(this, BrickletCANV2.FUNCTION_SET_READ_FILTER_CONFIGURATION, [bufferIndex, filterMode, filterMask, filterIdentifier], 'B B I I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getReadFilterConfiguration = function(bufferIndex, returnCallback, errorCallback) {
		/*
		Returns the read filter configuration as set by :func:`Set Read Filter Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletCANV2.FUNCTION_GET_READ_FILTER_CONFIGURATION, [bufferIndex], 'B', 17, 'B I I', returnCallback, errorCallback, false, true);
	};
	this.getErrorLogLowLevel = function(returnCallback, errorCallback) {
		/*
		Returns information about different kinds of errors.
		
		The write and read error levels indicate the current level of stuffing, form,
		acknowledgement, bit and checksum errors during CAN bus write and read
		operations. For each of this error kinds there is also an individual counter.
		
		When the write error level extends 255 then the CAN transceiver gets disabled
		and no frames can be transmitted or received anymore. The CAN transceiver will
		automatically be activated again after the CAN bus is idle for a while.
		
		The write buffer timeout, read buffer and backlog overflow counts represents the
		number of these errors:
		
		* A write buffer timeout occurs if a frame could not be transmitted before the
		  configured write buffer timeout expired (see :func:`Set Queue Configuration`).
		* A read buffer overflow occurs if a read buffer of the CAN transceiver
		  still contains the last received frame when the next frame arrives. In this
		  case the last received frame is lost. This happens if the CAN transceiver
		  receives more frames than the Bricklet can handle. Using the read filter
		  (see :func:`Set Read Filter Configuration`) can help to reduce the amount of
		  received frames. This count is not exact, but a lower bound, because the
		  Bricklet might not able detect all overflows if they occur in rapid succession.
		* A read backlog overflow occurs if the read backlog of the Bricklet is already
		  full when the next frame should be read from a read buffer of the CAN
		  transceiver. In this case the frame in the read buffer is lost. This
		  happens if the CAN transceiver receives more frames to be added to the read
		  backlog than are removed from the read backlog using the :func:`Read Frame`
		  function. Using the :cb:`Frame Read` callback ensures that the read backlog
		  can not overflow.
		
		The read buffer overflow counter counts the overflows of all configured read
		buffers. Which read buffer exactly suffered from an overflow can be figured
		out from the read buffer overflow occurrence list
		(``read_buffer_overflow_error_occurred``). Reading the error log clears the
		occurence list.
		*/
		this.ipcon.sendRequest(this, BrickletCANV2.FUNCTION_GET_ERROR_LOG_LOW_LEVEL, [], '', 52, 'B B B I I I I I I I I B ?32 I', returnCallback, errorCallback, false, true);
	};
	this.setCommunicationLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Sets the communication LED configuration. By default the LED shows
		CAN-Bus traffic, it flickers once for every 40 transmitted or received frames.
		
		You can also turn the LED permanently on/off or show a heartbeat.
		
		If the Bricklet is in bootloader mode, the LED is off.
		*/
		this.ipcon.sendRequest(this, BrickletCANV2.FUNCTION_SET_COMMUNICATION_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getCommunicationLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Communication LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletCANV2.FUNCTION_GET_COMMUNICATION_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setErrorLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Sets the error LED configuration.
		
		By default (show-transceiver-state) the error LED turns on if the CAN
		transceiver is passive or disabled state (see :func:`Get Error Log`). If
		the CAN transceiver is in active state the LED turns off.
		
		If the LED is configured as show-error then the error LED turns on if any error
		occurs. If you call this function with the show-error option again, the LED will
		turn off until the next error occurs.
		
		You can also turn the LED permanently on/off or show a heartbeat.
		
		If the Bricklet is in bootloader mode, the LED is off.
		*/
		this.ipcon.sendRequest(this, BrickletCANV2.FUNCTION_SET_ERROR_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getErrorLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Error LED Config`.
		*/
		this.ipcon.sendRequest(this, BrickletCANV2.FUNCTION_GET_ERROR_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setFrameReadableCallbackConfiguration = function(enabled, returnCallback, errorCallback) {
		/*
		Enables and disables the :cb:`Frame Readable` callback.
		
		By default the callback is disabled. Enabling this callback will disable the :cb:`Frame Read` callback.
		
		.. versionadded:: 2.0.3$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletCANV2.FUNCTION_SET_FRAME_READABLE_CALLBACK_CONFIGURATION, [enabled], '?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getFrameReadableCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns *true* if the :cb:`Frame Readable` callback is enabled, *false* otherwise.
		
		.. versionadded:: 2.0.3$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletCANV2.FUNCTION_GET_FRAME_READABLE_CALLBACK_CONFIGURATION, [], '', 9, '?', returnCallback, errorCallback, false, true);
	};
	this.setErrorOccurredCallbackConfiguration = function(enabled, returnCallback, errorCallback) {
		/*
		Enables and disables the :cb:`Error Occurred` callback.
		
		By default the callback is disabled.
		
		.. versionadded:: 2.0.3$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletCANV2.FUNCTION_SET_ERROR_OCCURRED_CALLBACK_CONFIGURATION, [enabled], '?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getErrorOccurredCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns *true* if the :cb:`Error Occurred` callback is enabled, *false* otherwise.
		
		.. versionadded:: 2.0.3$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletCANV2.FUNCTION_GET_ERROR_OCCURRED_CALLBACK_CONFIGURATION, [], '', 9, '?', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPErrorCount = function(returnCallback, errorCallback) {
		/*
		Returns the error count for the communication between Brick and Bricklet.
		
		The errors are divided into
		
		* ACK checksum errors,
		* message checksum errors,
		* framing errors and
		* overflow errors.
		
		The errors counts are for errors that occur on the Bricklet side. All
		Bricks have a similar function that returns the errors on the Brick side.
		*/
		this.ipcon.sendRequest(this, BrickletCANV2.FUNCTION_GET_SPITFP_ERROR_COUNT, [], '', 24, 'I I I I', returnCallback, errorCallback, false, true);
	};
	this.setBootloaderMode = function(mode, returnCallback, errorCallback) {
		/*
		Sets the bootloader mode and returns the status after the requested
		mode change was instigated.
		
		You can change from bootloader mode to firmware mode and vice versa. A change
		from bootloader mode to firmware mode will only take place if the entry function,
		device identifier and CRC are present and correct.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletCANV2.FUNCTION_SET_BOOTLOADER_MODE, [mode], 'B', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getBootloaderMode = function(returnCallback, errorCallback) {
		/*
		Returns the current bootloader mode, see :func:`Set Bootloader Mode`.
		*/
		this.ipcon.sendRequest(this, BrickletCANV2.FUNCTION_GET_BOOTLOADER_MODE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setWriteFirmwarePointer = function(pointer, returnCallback, errorCallback) {
		/*
		Sets the firmware pointer for :func:`Write Firmware`. The pointer has
		to be increased by chunks of size 64. The data is written to flash
		every 4 chunks (which equals to one page of size 256).
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletCANV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER, [pointer], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeFirmware = function(data, returnCallback, errorCallback) {
		/*
		Writes 64 Bytes of firmware at the position as written by
		:func:`Set Write Firmware Pointer` before. The firmware is written
		to flash every 4 chunks.
		
		You can only write firmware in bootloader mode.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletCANV2.FUNCTION_WRITE_FIRMWARE, [data], 'B64', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setStatusLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Sets the status LED configuration. By default the LED shows
		communication traffic between Brick and Bricklet, it flickers once
		for every 10 received data packets.
		
		You can also turn the LED permanently on/off or show a heartbeat.
		
		If the Bricklet is in bootloader mode, the LED is will show heartbeat by default.
		*/
		this.ipcon.sendRequest(this, BrickletCANV2.FUNCTION_SET_STATUS_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getStatusLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Status LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletCANV2.FUNCTION_GET_STATUS_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getChipTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature as measured inside the microcontroller. The
		value returned is not the ambient temperature!
		
		The temperature is only proportional to the real temperature and it has bad
		accuracy. Practically it is only useful as an indicator for
		temperature changes.
		*/
		this.ipcon.sendRequest(this, BrickletCANV2.FUNCTION_GET_CHIP_TEMPERATURE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.reset = function(returnCallback, errorCallback) {
		/*
		Calling this function will reset the Bricklet. All configurations
		will be lost.
		
		After a reset you have to create new device objects,
		calling functions on the existing ones will result in
		undefined behavior!
		*/
		this.ipcon.sendRequest(this, BrickletCANV2.FUNCTION_RESET, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeUID = function(uid, returnCallback, errorCallback) {
		/*
		Writes a new UID into flash. If you want to set a new UID
		you have to decode the Base58 encoded UID string into an
		integer first.
		
		We recommend that you use Brick Viewer to change the UID.
		*/
		this.ipcon.sendRequest(this, BrickletCANV2.FUNCTION_WRITE_UID, [uid], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.readUID = function(returnCallback, errorCallback) {
		/*
		Returns the current UID as an integer. Encode as
		Base58 to get the usual string version.
		*/
		this.ipcon.sendRequest(this, BrickletCANV2.FUNCTION_READ_UID, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletCANV2.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};
	this.writeFrame = function(frameType, identifier, data, returnCallback, errorCallback) {
		/*
		Writes a data or remote frame to the write queue to be transmitted over the
		CAN transceiver.
		
		The Bricklet supports the standard 11-bit (CAN 2.0A) and the additional extended
		29-bit (CAN 2.0B) identifiers. For standard frames the Bricklet uses bit 0 to 10
		from the ``identifier`` parameter as standard 11-bit identifier. For extended
		frames the Bricklet uses bit 0 to 28 from the ``identifier`` parameter as
		extended 29-bit identifier.
		
		The ``data`` parameter can be up to 15 bytes long. For data frames up to 8 bytes
		will be used as the actual data. The length (DLC) field in the data or remote
		frame will be set to the actual length of the ``data`` parameter. This allows
		to transmit data and remote frames with excess length. For remote frames only
		the length of the ``data`` parameter is used. The actual ``data`` bytes are
		ignored.
		
		Returns *true* if the frame was successfully added to the write queue. Returns
		*false* if the frame could not be added because write queue is already full or
		because the write buffer or the write backlog are configured with a size of
		zero (see :func:`Set Queue Configuration`).
		
		The write queue can overflow if frames are written to it at a higher rate
		than the Bricklet can transmitted them over the CAN transceiver. This may
		happen if the CAN transceiver is configured as read-only or is using a low baud
		rate (see :func:`Set Transceiver Configuration`). It can also happen if the CAN
		bus is congested and the frame cannot be transmitted because it constantly loses
		arbitration or because the CAN transceiver is currently disabled due to a high
		write error level (see :func:`Get Error Log`).
		*/

		var dataLength = 0;
		var dataData = [];
		var None = 0;
		var streamStateObject = this.streamStateObjects[1];

		if (data.length > 15) {
			if (errorCallback !== null){
				errorCallback(IPConnection.ERROR_INVALID_PARAMETER);
			}

			this.resetStreamStateObject(streamStateObject);

			if (streamStateObject['responseProperties']['callQueue'].length > 0) {
				streamStateObject['responseProperties']['callQueue'].shift()(device);
			}

			return;
		}

		if (!this.getResponseExpected(1)) {
			if (streamStateObject['streamProperties']['fixedLength']) {
				dataLength = streamStateObject['streamProperties']['fixedLength'];
			}
			else {
				dataLength = data.length;
			}

			if (streamStateObject['streamProperties']['singleChunk']) {
				dataData =
					this.ipcon.createChunkData(data, 0, 15, '\0');

				this.ipcon.sendRequest(this,
				                       BrickletCANV2.FUNCTION_WRITE_FRAME_LOW_LEVEL,
				                       [frameType, identifier, dataLength, dataData],
				                       'B I B B15',
				                       9,
				                       '?',
				                       returnCallback,
				                       errorCallback,
				                       false,
				                       true);
			}
			else {
				while (None < data.length) {
					dataData =
						this.ipcon.createChunkData(data, None, 15, '\0');

					this.ipcon.sendRequest(this,
					                       BrickletCANV2.FUNCTION_WRITE_FRAME_LOW_LEVEL,
					                       [frameType, identifier, dataLength, dataData],
					                       'B I B B15',
					                       9,
					                       '?',
					                       returnCallback,
					                       errorCallback,
					                       false,
					                       true);

					None += 15;
				}
			}

			if (returnCallback) {
				returnCallback();
			}
		}
		else {
			var responseHandler = null;
			var functionToQueue = null;

			if (streamStateObject['responseProperties']['responseHandler'] === null) {
				responseHandler = function (device, fid, packetResponse) {
					var result = [];
					var payload = null;
					var llvalues = null;
					var packetErrorFlag = 0;
					var rolesMappedData = [];
					var shortWriteWritten = -1;
					var streamStateObject = device.streamStateObjects[fid];
					var responseEmpty = streamStateObject['responseProperties']['streamInResponseEmpty'];
					var dataLength = 0;
					var dataData = [];
					var None = 0;

					function doNextLLCall() {
						dataLength = streamStateObject['responseProperties']['data'].length;
						dataData =
							device.ipcon.createChunkData(streamStateObject['responseProperties']['data'],
							                             streamStateObject['responseProperties']['streamInChunkOffset'],
							                             streamStateObject['responseProperties']['streamInChunkLength'],
							                             '\0');
						None = streamStateObject['responseProperties']['streamInChunkOffset'];

						for (var i = 0; i < streamStateObject['dataMappingStreamIn'].length; i++) {
							if (streamStateObject['dataMappingStreamIn'][i] === null) {
								continue;
							}

							if (streamStateObject['dataMappingStreamIn'][i].endsWith('Length')) {
								streamStateObject['responseProperties']['streamInLLParams'][i] = dataLength;
							}
							else if (streamStateObject['dataMappingStreamIn'][i].endsWith('Offset')) {
								streamStateObject['responseProperties']['streamInLLParams'][i] = None;
							}
							else if (streamStateObject['dataMappingStreamIn'][i].endsWith('Data')) {
								streamStateObject['responseProperties']['streamInLLParams'][i] = dataData;
							}
						}

						device.ipcon.sendRequest(device,
						                         BrickletCANV2.FUNCTION_WRITE_FRAME_LOW_LEVEL,
						                         streamStateObject['responseProperties']['streamInLLParams'],
						                         'B I B B15',
						                         9,
						                         '?',
						                         returnCallback,
						                         errorCallback,
						                         true,
						                         true);

						streamStateObject['responseProperties']['streamInChunkOffset'] += 15;
					}

					function handleStreamInDone() {
						if (streamStateObject['responseProperties']['returnCB']) {
							if (streamStateObject['streamProperties']['shortWrite']) {
								for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
									if (streamStateObject['dataMapping'][i].endsWith('Written')) {
										result[i] = streamStateObject['responseProperties']['streamInWritten'];
										break;
									}
								}
							}

							if (!responseEmpty) {
								streamStateObject['responseProperties']['returnCB'].apply(device, result);
							}
							else {
								streamStateObject['responseProperties']['returnCB'].apply(device);
							}
						}

						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}
					}

					if (!streamStateObject) {
						return;
					}

					packetErrorFlag = device.ipcon.getEFromPacket(packetResponse);

					if (packetErrorFlag !== 0) {
						if (streamStateObject['responseProperties']['errorCB'] !== undefined) {
							if (packetErrorFlag === 1) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_INVALID_PARAMETER);
							}
							else if (packetErrorFlag === 2) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_FUNCTION_NOT_SUPPORTED);
							}
							else {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_UNKNOWN_ERROR);
							}
						}

						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}

						return;
					}

					if (responseEmpty) {
						if (streamStateObject['streamProperties']['singleChunk']) {
							handleStreamInDone();

							return;
						}

						if (streamStateObject['responseProperties']['streamInChunkOffset'] < streamStateObject['responseProperties']['data'].length) {
							doNextLLCall();
						}
						else {
							handleStreamInDone();
						}
					}
					else {
						payload = device.ipcon.getPayloadFromPacket(packetResponse);
						llvalues = device.ipcon.unpack(payload,
						                               streamStateObject['responseProperties']['unpackFormatString']);

						if (!payload || !llvalues) {
							device.resetStreamStateObject(streamStateObject);

							if (streamStateObject['responseProperties']['callQueue'].length > 0) {
								streamStateObject['responseProperties']['callQueue'].shift()(device);
							}

							return;
						}

						for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
							result.push(llvalues[i]);
						}

						if (streamStateObject['streamProperties']['singleChunk']) {
							if (streamStateObject['responseProperties']['returnCB']) {
								streamStateObject['responseProperties']['returnCB'].apply(device, result);
							}

							device.resetStreamStateObject(streamStateObject);

							if (streamStateObject['responseProperties']['callQueue'].length > 0) {
								streamStateObject['responseProperties']['callQueue'].shift()(device);
							}

							return;
						}

						if (streamStateObject['streamProperties']['shortWrite']) {
							for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
								if (streamStateObject['dataMapping'][i].endsWith('Written')) {
									shortWriteWritten = llvalues[i];
									streamStateObject['responseProperties']['streamInWritten'] += shortWriteWritten;
									break;
								}
							}
							if ((shortWriteWritten !== -1) && (shortWriteWritten < 15)) {
								// Either last chunk or short write
								handleStreamInDone();
								return;
							}
						}

						if (streamStateObject['responseProperties']['streamInChunkOffset'] < streamStateObject['responseProperties']['data'].length) {
							doNextLLCall();
						}
						else {
							handleStreamInDone();
						}
					}
				};

				streamStateObject['responseProperties']['responseHandler'] = responseHandler;
			}

			if (!streamStateObject['responseProperties']['running']) {
				streamStateObject['responseProperties']['running'] = true;
				streamStateObject['responseProperties']['returnCB'] = returnCallback;
				streamStateObject['responseProperties']['errorCB'] = errorCallback;
				streamStateObject['responseProperties']['data'].length = 0;
				streamStateObject['responseProperties']['data'].push.apply(streamStateObject['responseProperties']['data'],
				                                                           data);

				if (streamStateObject['streamProperties']['fixedLength']) {
					dataLength = streamStateObject['streamProperties']['fixedLength'];
				}
				else {
					dataLength = data.length;
				}

				None = 0;
				dataData =
					this.ipcon.createChunkData(data, 0, 15, '\0');

				streamStateObject['responseProperties']['streamInChunkOffset'] = 15;
				streamStateObject['responseProperties']['streamInChunkLength'] = 15;
				streamStateObject['responseProperties']['streamInLLParams'] = [frameType, identifier, dataLength, dataData];

				this.ipcon.sendRequest(this,
				                       BrickletCANV2.FUNCTION_WRITE_FRAME_LOW_LEVEL,
				                       [frameType, identifier, dataLength, dataData],
				                       'B I B B15',
				                       9,
				                       '?',
				                       returnCallback,
				                       errorCallback,
				                       true,
				                       true);
			}
			else {
				functionToQueue = function (device) {
					device.writeFrame.call(device, frameType, identifier, data, returnCallback, errorCallback);
				}

				streamStateObject['responseProperties']['callQueue'].push(functionToQueue);
			}
		}
	};

	this.readFrame = function(returnCallback, errorCallback) {
		/*
		Tries to read the next data or remote frame from the read queue and returns it.
		If a frame was successfully read, then the ``success`` return value is set to
		*true* and the other return values contain the frame. If the read queue is
		empty and no frame could be read, then the ``success`` return value is set to
		*false* and the other return values contain invalid data.
		
		The ``identifier`` return value follows the identifier format described for
		:func:`Write Frame`.
		
		The ``data`` return value can be up to 15 bytes long. For data frames up to the
		first 8 bytes are the actual received data. All bytes after the 8th byte are
		always zero and only there to indicate the length of a data or remote frame
		with excess length. For remote frames the length of the ``data`` return value
		represents the requested length. The actual ``data`` bytes are always zero.
		
		A configurable read filter can be used to define which frames should be
		received by the CAN transceiver and put into the read queue (see
		:func:`Set Read Filter Configuration`).
		
		Instead of polling with this function, you can also use callbacks. See the
		:func:`Set Frame Read Callback Configuration` function and the :cb:`Frame Read`
		callback.
		*/
		var responseHandler = null;
		var functionToQueue = null;
		var streamStateObject = this.streamStateObjects[2];
		if (streamStateObject['responseProperties']['responseHandler'] === null) {
			responseHandler = 
				function (device, fid, packetResponse) {
					var result = [];
					var llvalues = null;
					var packetErrorFlag = 0;
					var rolesMappedData = [];
					var dataLength = null;
					var dataChunkData = null;
					var dataOutOfSync = false;
					var streamStateObject = device.streamStateObjects[fid];
					var dataChunkOffset = null;
					var payload = device.ipcon.getPayloadFromPacket(packetResponse);

					packetErrorFlag = device.ipcon.getEFromPacket(packetResponse);

					if (packetErrorFlag !== 0) {
						if (streamStateObject['responseProperties']['errorCB'] !== undefined) {
							if (packetErrorFlag === 1) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_INVALID_PARAMETER);
							}
							else if (packetErrorFlag === 2) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_FUNCTION_NOT_SUPPORTED);
							}
							else {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_UNKNOWN_ERROR);
							}
						}

						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}

						return;
					}

					if (payload.length === 0) {
						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}

						return;
					}

					llvalues = device.ipcon.unpack(payload,
					                               streamStateObject['responseProperties']['unpackFormatString']);

					for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
						if (streamStateObject['dataMapping'][i] === 'streamChunkData') {
							dataChunkData = llvalues[i];
						}
						else if (streamStateObject['dataMapping'][i] === 'streamChunkOffset') {
							dataChunkOffset = llvalues[i];
						}
					}

					for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
						if (streamStateObject['dataMapping'][i] === 'streamLength') {
							dataLength = llvalues[i];
							break;
						}
					}

					dataChunkOffset = 0;

					if (streamStateObject['responseProperties']['returnCB']) {
						for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
							rolesMappedData.push({'role': streamStateObject['dataMapping'][i], 'llvalue': llvalues[i]});
						}

						for (var i = 0; i < rolesMappedData.length; i++) {
							if (rolesMappedData[i]['role'] === 'streamChunkData') {
								result.push(dataChunkData.splice(0, dataLength));
							}
							else if (rolesMappedData[i]['role'] === null) {
								result.push(rolesMappedData[i]['llvalue']);
							}
						}

						streamStateObject['responseProperties']['returnCB'].apply(device, result);
					}

					device.resetStreamStateObject(streamStateObject);

					if (streamStateObject['responseProperties']['callQueue'].length > 0) {
						streamStateObject['responseProperties']['callQueue'].shift()(device);
					}
				};

			streamStateObject['responseProperties']['responseHandler'] = responseHandler;
		}
		if (!streamStateObject['responseProperties']['running']) {
			streamStateObject['responseProperties']['running'] = true;
			streamStateObject['responseProperties']['returnCB'] = returnCallback;
			streamStateObject['responseProperties']['errorCB'] = errorCallback;
			this.ipcon.sendRequest(this,
			                       BrickletCANV2.FUNCTION_READ_FRAME_LOW_LEVEL,
			                       [],
			                       '',
			                       30,
			                       '? B I B B15',
			                       returnCallback,
			                       errorCallback,
			                       true,
			                       true);
		}
		else {
			functionToQueue = function (device) {
				device.readFrame.call(device, returnCallback, errorCallback);
			}
			streamStateObject['responseProperties']['callQueue'].push(functionToQueue);
		}
	};
	this.setQueueConfiguration = function(writeBufferSize, writeBufferTimeout, writeBacklogSize, readBufferSizes, readBacklogSize, returnCallback, errorCallback) {
		/*
		Sets the write and read queue configuration.
		
		The CAN transceiver has 32 buffers in total in hardware for transmitting and
		receiving frames. Additionally, the Bricklet has a backlog for 768 frames in
		total in software. The buffers and the backlog can be freely assigned to the
		write and read queues.
		
		:func:`Write Frame` writes a frame into the write backlog. The Bricklet moves
		the frame from the backlog into a free write buffer. The CAN transceiver then
		transmits the frame from the write buffer to the CAN bus. If there are no
		write buffers (``write_buffer_size`` is zero) or there is no write backlog
		(``write_backlog_size`` is zero) then no frames can be transmitted and
		:func:`Write Frame` returns always *false*.
		
		The CAN transceiver receives a frame from the CAN bus and stores it into a
		free read buffer. The Bricklet moves the frame from the read buffer into the
		read backlog. :func:`Read Frame` reads the frame from the read backlog and
		returns it. If there are no read buffers (``read_buffer_sizes`` is empty) or
		there is no read backlog (``read_backlog_size`` is zero) then no frames can be
		received and :func:`Read Frame` returns always *false*.
		
		There can be multiple read buffers, because the CAN transceiver cannot receive
		data and remote frames into the same read buffer. A positive read buffer size
		represents a data frame read buffer and a negative read buffer size represents
		a remote frame read buffer. A read buffer size of zero is not allowed. By
		default the first read buffer is configured for data frames and the second read
		buffer is configured for remote frame. There can be up to 32 different read
		buffers, assuming that no write buffer is used. Each read buffer has its own
		filter configuration (see :func:`Set Read Filter Configuration`).
		
		A valid queue configuration fulfills these conditions::
		
		 write_buffer_size + abs(read_buffer_size_0) + abs(read_buffer_size_1) + ... + abs(read_buffer_size_31) <= 32
		 write_backlog_size + read_backlog_size <= 768
		
		The write buffer timeout has three different modes that define how a failed
		frame transmission should be handled:
		
		* Single-Shot (< 0): Only one transmission attempt will be made. If the
		  transmission fails then the frame is discarded.
		* Infinite (= 0): Infinite transmission attempts will be made. The frame will
		  never be discarded.
		* Milliseconds (> 0): A limited number of transmission attempts will be made.
		  If the frame could not be transmitted successfully after the configured
		  number of milliseconds then the frame is discarded.
		
		The current content of the queues is lost when this function is called.
		*/

		var readBufferSizesLength = 0;
		var readBufferSizesData = [];
		var None = 0;
		var streamStateObject = this.streamStateObjects[7];

		if (readBufferSizes.length > 32) {
			if (errorCallback !== null){
				errorCallback(IPConnection.ERROR_INVALID_PARAMETER);
			}

			this.resetStreamStateObject(streamStateObject);

			if (streamStateObject['responseProperties']['callQueue'].length > 0) {
				streamStateObject['responseProperties']['callQueue'].shift()(device);
			}

			return;
		}

		if (!this.getResponseExpected(7)) {
			if (streamStateObject['streamProperties']['fixedLength']) {
				readBufferSizesLength = streamStateObject['streamProperties']['fixedLength'];
			}
			else {
				readBufferSizesLength = readBufferSizes.length;
			}

			if (streamStateObject['streamProperties']['singleChunk']) {
				readBufferSizesData =
					this.ipcon.createChunkData(readBufferSizes, 0, 32, '\0');

				this.ipcon.sendRequest(this,
				                       BrickletCANV2.FUNCTION_SET_QUEUE_CONFIGURATION_LOW_LEVEL,
				                       [writeBufferSize, writeBufferTimeout, writeBacklogSize, readBufferSizesLength, readBufferSizesData, readBacklogSize],
				                       'B i H B b32 H',
				                       0,
				                       '',
				                       returnCallback,
				                       errorCallback,
				                       false,
				                       true);
			}
			else {
				while (None < readBufferSizes.length) {
					readBufferSizesData =
						this.ipcon.createChunkData(readBufferSizes, None, 32, '\0');

					this.ipcon.sendRequest(this,
					                       BrickletCANV2.FUNCTION_SET_QUEUE_CONFIGURATION_LOW_LEVEL,
					                       [writeBufferSize, writeBufferTimeout, writeBacklogSize, readBufferSizesLength, readBufferSizesData, readBacklogSize],
					                       'B i H B b32 H',
					                       0,
					                       '',
					                       returnCallback,
					                       errorCallback,
					                       false,
					                       true);

					None += 32;
				}
			}

			if (returnCallback) {
				returnCallback();
			}
		}
		else {
			var responseHandler = null;
			var functionToQueue = null;

			if (streamStateObject['responseProperties']['responseHandler'] === null) {
				responseHandler = function (device, fid, packetResponse) {
					var result = [];
					var payload = null;
					var llvalues = null;
					var packetErrorFlag = 0;
					var rolesMappedData = [];
					var shortWriteWritten = -1;
					var streamStateObject = device.streamStateObjects[fid];
					var responseEmpty = streamStateObject['responseProperties']['streamInResponseEmpty'];
					var readBufferSizesLength = 0;
					var readBufferSizesData = [];
					var None = 0;

					function doNextLLCall() {
						readBufferSizesLength = streamStateObject['responseProperties']['data'].length;
						readBufferSizesData =
							device.ipcon.createChunkData(streamStateObject['responseProperties']['data'],
							                             streamStateObject['responseProperties']['streamInChunkOffset'],
							                             streamStateObject['responseProperties']['streamInChunkLength'],
							                             '\0');
						None = streamStateObject['responseProperties']['streamInChunkOffset'];

						for (var i = 0; i < streamStateObject['dataMappingStreamIn'].length; i++) {
							if (streamStateObject['dataMappingStreamIn'][i] === null) {
								continue;
							}

							if (streamStateObject['dataMappingStreamIn'][i].endsWith('Length')) {
								streamStateObject['responseProperties']['streamInLLParams'][i] = readBufferSizesLength;
							}
							else if (streamStateObject['dataMappingStreamIn'][i].endsWith('Offset')) {
								streamStateObject['responseProperties']['streamInLLParams'][i] = None;
							}
							else if (streamStateObject['dataMappingStreamIn'][i].endsWith('Data')) {
								streamStateObject['responseProperties']['streamInLLParams'][i] = readBufferSizesData;
							}
						}

						device.ipcon.sendRequest(device,
						                         BrickletCANV2.FUNCTION_SET_QUEUE_CONFIGURATION_LOW_LEVEL,
						                         streamStateObject['responseProperties']['streamInLLParams'],
						                         'B i H B b32 H',
						                         0,
						                         '',
						                         returnCallback,
						                         errorCallback,
						                         true,
						                         true);

						streamStateObject['responseProperties']['streamInChunkOffset'] += 32;
					}

					function handleStreamInDone() {
						if (streamStateObject['responseProperties']['returnCB']) {
							if (streamStateObject['streamProperties']['shortWrite']) {
								for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
									if (streamStateObject['dataMapping'][i].endsWith('Written')) {
										result[i] = streamStateObject['responseProperties']['streamInWritten'];
										break;
									}
								}
							}

							if (!responseEmpty) {
								streamStateObject['responseProperties']['returnCB'].apply(device, result);
							}
							else {
								streamStateObject['responseProperties']['returnCB'].apply(device);
							}
						}

						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}
					}

					if (!streamStateObject) {
						return;
					}

					packetErrorFlag = device.ipcon.getEFromPacket(packetResponse);

					if (packetErrorFlag !== 0) {
						if (streamStateObject['responseProperties']['errorCB'] !== undefined) {
							if (packetErrorFlag === 1) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_INVALID_PARAMETER);
							}
							else if (packetErrorFlag === 2) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_FUNCTION_NOT_SUPPORTED);
							}
							else {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_UNKNOWN_ERROR);
							}
						}

						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}

						return;
					}

					if (responseEmpty) {
						if (streamStateObject['streamProperties']['singleChunk']) {
							handleStreamInDone();

							return;
						}

						if (streamStateObject['responseProperties']['streamInChunkOffset'] < streamStateObject['responseProperties']['data'].length) {
							doNextLLCall();
						}
						else {
							handleStreamInDone();
						}
					}
					else {
						payload = device.ipcon.getPayloadFromPacket(packetResponse);
						llvalues = device.ipcon.unpack(payload,
						                               streamStateObject['responseProperties']['unpackFormatString']);

						if (!payload || !llvalues) {
							device.resetStreamStateObject(streamStateObject);

							if (streamStateObject['responseProperties']['callQueue'].length > 0) {
								streamStateObject['responseProperties']['callQueue'].shift()(device);
							}

							return;
						}

						for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
							result.push(llvalues[i]);
						}

						if (streamStateObject['streamProperties']['singleChunk']) {
							if (streamStateObject['responseProperties']['returnCB']) {
								streamStateObject['responseProperties']['returnCB'].apply(device, result);
							}

							device.resetStreamStateObject(streamStateObject);

							if (streamStateObject['responseProperties']['callQueue'].length > 0) {
								streamStateObject['responseProperties']['callQueue'].shift()(device);
							}

							return;
						}

						if (streamStateObject['streamProperties']['shortWrite']) {
							for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
								if (streamStateObject['dataMapping'][i].endsWith('Written')) {
									shortWriteWritten = llvalues[i];
									streamStateObject['responseProperties']['streamInWritten'] += shortWriteWritten;
									break;
								}
							}
							if ((shortWriteWritten !== -1) && (shortWriteWritten < 32)) {
								// Either last chunk or short write
								handleStreamInDone();
								return;
							}
						}

						if (streamStateObject['responseProperties']['streamInChunkOffset'] < streamStateObject['responseProperties']['data'].length) {
							doNextLLCall();
						}
						else {
							handleStreamInDone();
						}
					}
				};

				streamStateObject['responseProperties']['responseHandler'] = responseHandler;
			}

			if (!streamStateObject['responseProperties']['running']) {
				streamStateObject['responseProperties']['running'] = true;
				streamStateObject['responseProperties']['returnCB'] = returnCallback;
				streamStateObject['responseProperties']['errorCB'] = errorCallback;
				streamStateObject['responseProperties']['data'].length = 0;
				streamStateObject['responseProperties']['data'].push.apply(streamStateObject['responseProperties']['data'],
				                                                           readBufferSizes);

				if (streamStateObject['streamProperties']['fixedLength']) {
					readBufferSizesLength = streamStateObject['streamProperties']['fixedLength'];
				}
				else {
					readBufferSizesLength = readBufferSizes.length;
				}

				None = 0;
				readBufferSizesData =
					this.ipcon.createChunkData(readBufferSizes, 0, 32, '\0');

				streamStateObject['responseProperties']['streamInChunkOffset'] = 32;
				streamStateObject['responseProperties']['streamInChunkLength'] = 32;
				streamStateObject['responseProperties']['streamInLLParams'] = [writeBufferSize, writeBufferTimeout, writeBacklogSize, readBufferSizesLength, readBufferSizesData, readBacklogSize];

				this.ipcon.sendRequest(this,
				                       BrickletCANV2.FUNCTION_SET_QUEUE_CONFIGURATION_LOW_LEVEL,
				                       [writeBufferSize, writeBufferTimeout, writeBacklogSize, readBufferSizesLength, readBufferSizesData, readBacklogSize],
				                       'B i H B b32 H',
				                       0,
				                       '',
				                       returnCallback,
				                       errorCallback,
				                       true,
				                       true);
			}
			else {
				functionToQueue = function (device) {
					device.setQueueConfiguration.call(device, writeBufferSize, writeBufferTimeout, writeBacklogSize, readBufferSizes, readBacklogSize, returnCallback, errorCallback);
				}

				streamStateObject['responseProperties']['callQueue'].push(functionToQueue);
			}
		}
	};

	this.getQueueConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the queue configuration as set by :func:`Set Queue Configuration`.
		*/
		var responseHandler = null;
		var functionToQueue = null;
		var streamStateObject = this.streamStateObjects[8];
		if (streamStateObject['responseProperties']['responseHandler'] === null) {
			responseHandler = 
				function (device, fid, packetResponse) {
					var result = [];
					var llvalues = null;
					var packetErrorFlag = 0;
					var rolesMappedData = [];
					var readBufferSizesLength = null;
					var readBufferSizesChunkData = null;
					var readBufferSizesOutOfSync = false;
					var streamStateObject = device.streamStateObjects[fid];
					var readBufferSizesChunkOffset = null;
					var payload = device.ipcon.getPayloadFromPacket(packetResponse);

					packetErrorFlag = device.ipcon.getEFromPacket(packetResponse);

					if (packetErrorFlag !== 0) {
						if (streamStateObject['responseProperties']['errorCB'] !== undefined) {
							if (packetErrorFlag === 1) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_INVALID_PARAMETER);
							}
							else if (packetErrorFlag === 2) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_FUNCTION_NOT_SUPPORTED);
							}
							else {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_UNKNOWN_ERROR);
							}
						}

						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}

						return;
					}

					if (payload.length === 0) {
						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}

						return;
					}

					llvalues = device.ipcon.unpack(payload,
					                               streamStateObject['responseProperties']['unpackFormatString']);

					for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
						if (streamStateObject['dataMapping'][i] === 'streamChunkData') {
							readBufferSizesChunkData = llvalues[i];
						}
						else if (streamStateObject['dataMapping'][i] === 'streamChunkOffset') {
							readBufferSizesChunkOffset = llvalues[i];
						}
					}

					for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
						if (streamStateObject['dataMapping'][i] === 'streamLength') {
							readBufferSizesLength = llvalues[i];
							break;
						}
					}

					readBufferSizesChunkOffset = 0;

					if (streamStateObject['responseProperties']['returnCB']) {
						for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
							rolesMappedData.push({'role': streamStateObject['dataMapping'][i], 'llvalue': llvalues[i]});
						}

						for (var i = 0; i < rolesMappedData.length; i++) {
							if (rolesMappedData[i]['role'] === 'streamChunkData') {
								result.push(readBufferSizesChunkData.splice(0, readBufferSizesLength));
							}
							else if (rolesMappedData[i]['role'] === null) {
								result.push(rolesMappedData[i]['llvalue']);
							}
						}

						streamStateObject['responseProperties']['returnCB'].apply(device, result);
					}

					device.resetStreamStateObject(streamStateObject);

					if (streamStateObject['responseProperties']['callQueue'].length > 0) {
						streamStateObject['responseProperties']['callQueue'].shift()(device);
					}
				};

			streamStateObject['responseProperties']['responseHandler'] = responseHandler;
		}
		if (!streamStateObject['responseProperties']['running']) {
			streamStateObject['responseProperties']['running'] = true;
			streamStateObject['responseProperties']['returnCB'] = returnCallback;
			streamStateObject['responseProperties']['errorCB'] = errorCallback;
			this.ipcon.sendRequest(this,
			                       BrickletCANV2.FUNCTION_GET_QUEUE_CONFIGURATION_LOW_LEVEL,
			                       [],
			                       '',
			                       50,
			                       'B i H B b32 H',
			                       returnCallback,
			                       errorCallback,
			                       true,
			                       true);
		}
		else {
			functionToQueue = function (device) {
				device.getQueueConfiguration.call(device, returnCallback, errorCallback);
			}
			streamStateObject['responseProperties']['callQueue'].push(functionToQueue);
		}
	};

	this.getErrorLog = function(returnCallback, errorCallback) {
		/*
		Returns information about different kinds of errors.
		
		The write and read error levels indicate the current level of stuffing, form,
		acknowledgement, bit and checksum errors during CAN bus write and read
		operations. For each of this error kinds there is also an individual counter.
		
		When the write error level extends 255 then the CAN transceiver gets disabled
		and no frames can be transmitted or received anymore. The CAN transceiver will
		automatically be activated again after the CAN bus is idle for a while.
		
		The write buffer timeout, read buffer and backlog overflow counts represents the
		number of these errors:
		
		* A write buffer timeout occurs if a frame could not be transmitted before the
		  configured write buffer timeout expired (see :func:`Set Queue Configuration`).
		* A read buffer overflow occurs if a read buffer of the CAN transceiver
		  still contains the last received frame when the next frame arrives. In this
		  case the last received frame is lost. This happens if the CAN transceiver
		  receives more frames than the Bricklet can handle. Using the read filter
		  (see :func:`Set Read Filter Configuration`) can help to reduce the amount of
		  received frames. This count is not exact, but a lower bound, because the
		  Bricklet might not able detect all overflows if they occur in rapid succession.
		* A read backlog overflow occurs if the read backlog of the Bricklet is already
		  full when the next frame should be read from a read buffer of the CAN
		  transceiver. In this case the frame in the read buffer is lost. This
		  happens if the CAN transceiver receives more frames to be added to the read
		  backlog than are removed from the read backlog using the :func:`Read Frame`
		  function. Using the :cb:`Frame Read` callback ensures that the read backlog
		  can not overflow.
		
		The read buffer overflow counter counts the overflows of all configured read
		buffers. Which read buffer exactly suffered from an overflow can be figured
		out from the read buffer overflow occurrence list
		(``read_buffer_overflow_error_occurred``). Reading the error log clears the
		occurence list.
		*/
		var responseHandler = null;
		var functionToQueue = null;
		var streamStateObject = this.streamStateObjects[11];
		if (streamStateObject['responseProperties']['responseHandler'] === null) {
			responseHandler = 
				function (device, fid, packetResponse) {
					var result = [];
					var llvalues = null;
					var packetErrorFlag = 0;
					var rolesMappedData = [];
					var readBufferOverflowErrorOccurredLength = null;
					var readBufferOverflowErrorOccurredChunkData = null;
					var readBufferOverflowErrorOccurredOutOfSync = false;
					var streamStateObject = device.streamStateObjects[fid];
					var readBufferOverflowErrorOccurredChunkOffset = null;
					var payload = device.ipcon.getPayloadFromPacket(packetResponse);

					packetErrorFlag = device.ipcon.getEFromPacket(packetResponse);

					if (packetErrorFlag !== 0) {
						if (streamStateObject['responseProperties']['errorCB'] !== undefined) {
							if (packetErrorFlag === 1) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_INVALID_PARAMETER);
							}
							else if (packetErrorFlag === 2) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_FUNCTION_NOT_SUPPORTED);
							}
							else {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_UNKNOWN_ERROR);
							}
						}

						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}

						return;
					}

					if (payload.length === 0) {
						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}

						return;
					}

					llvalues = device.ipcon.unpack(payload,
					                               streamStateObject['responseProperties']['unpackFormatString']);

					for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
						if (streamStateObject['dataMapping'][i] === 'streamChunkData') {
							readBufferOverflowErrorOccurredChunkData = llvalues[i];
						}
						else if (streamStateObject['dataMapping'][i] === 'streamChunkOffset') {
							readBufferOverflowErrorOccurredChunkOffset = llvalues[i];
						}
					}

					for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
						if (streamStateObject['dataMapping'][i] === 'streamLength') {
							readBufferOverflowErrorOccurredLength = llvalues[i];
							break;
						}
					}

					readBufferOverflowErrorOccurredChunkOffset = 0;

					if (streamStateObject['responseProperties']['returnCB']) {
						for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
							rolesMappedData.push({'role': streamStateObject['dataMapping'][i], 'llvalue': llvalues[i]});
						}

						for (var i = 0; i < rolesMappedData.length; i++) {
							if (rolesMappedData[i]['role'] === 'streamChunkData') {
								result.push(readBufferOverflowErrorOccurredChunkData.splice(0, readBufferOverflowErrorOccurredLength));
							}
							else if (rolesMappedData[i]['role'] === null) {
								result.push(rolesMappedData[i]['llvalue']);
							}
						}

						streamStateObject['responseProperties']['returnCB'].apply(device, result);
					}

					device.resetStreamStateObject(streamStateObject);

					if (streamStateObject['responseProperties']['callQueue'].length > 0) {
						streamStateObject['responseProperties']['callQueue'].shift()(device);
					}
				};

			streamStateObject['responseProperties']['responseHandler'] = responseHandler;
		}
		if (!streamStateObject['responseProperties']['running']) {
			streamStateObject['responseProperties']['running'] = true;
			streamStateObject['responseProperties']['returnCB'] = returnCallback;
			streamStateObject['responseProperties']['errorCB'] = errorCallback;
			this.ipcon.sendRequest(this,
			                       BrickletCANV2.FUNCTION_GET_ERROR_LOG_LOW_LEVEL,
			                       [],
			                       '',
			                       52,
			                       'B B B I I I I I I I I B ?32 I',
			                       returnCallback,
			                       errorCallback,
			                       true,
			                       true);
		}
		else {
			functionToQueue = function (device) {
				device.getErrorLog.call(device, returnCallback, errorCallback);
			}
			streamStateObject['responseProperties']['callQueue'].push(functionToQueue);
		}
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletCANV2;

},{"./Device":279,"./IPConnection":280}],163:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletCO2.DEVICE_IDENTIFIER = 262;
BrickletCO2.DEVICE_DISPLAY_NAME = 'CO2 Bricklet';
BrickletCO2.CALLBACK_CO2_CONCENTRATION = 8;
BrickletCO2.CALLBACK_CO2_CONCENTRATION_REACHED = 9;
BrickletCO2.FUNCTION_GET_CO2_CONCENTRATION = 1;
BrickletCO2.FUNCTION_SET_CO2_CONCENTRATION_CALLBACK_PERIOD = 2;
BrickletCO2.FUNCTION_GET_CO2_CONCENTRATION_CALLBACK_PERIOD = 3;
BrickletCO2.FUNCTION_SET_CO2_CONCENTRATION_CALLBACK_THRESHOLD = 4;
BrickletCO2.FUNCTION_GET_CO2_CONCENTRATION_CALLBACK_THRESHOLD = 5;
BrickletCO2.FUNCTION_SET_DEBOUNCE_PERIOD = 6;
BrickletCO2.FUNCTION_GET_DEBOUNCE_PERIOD = 7;
BrickletCO2.FUNCTION_GET_IDENTITY = 255;
BrickletCO2.THRESHOLD_OPTION_OFF = 'x';
BrickletCO2.THRESHOLD_OPTION_OUTSIDE = 'o';
BrickletCO2.THRESHOLD_OPTION_INSIDE = 'i';
BrickletCO2.THRESHOLD_OPTION_SMALLER = '<';
BrickletCO2.THRESHOLD_OPTION_GREATER = '>';

function BrickletCO2(uid, ipcon) {
	//Measures CO2 concentration in ppm

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletCO2.DEVICE_IDENTIFIER, BrickletCO2.DEVICE_DISPLAY_NAME);
	BrickletCO2.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickletCO2.FUNCTION_GET_CO2_CONCENTRATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletCO2.FUNCTION_SET_CO2_CONCENTRATION_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletCO2.FUNCTION_GET_CO2_CONCENTRATION_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletCO2.FUNCTION_SET_CO2_CONCENTRATION_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletCO2.FUNCTION_GET_CO2_CONCENTRATION_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletCO2.FUNCTION_SET_DEBOUNCE_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletCO2.FUNCTION_GET_DEBOUNCE_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletCO2.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletCO2.CALLBACK_CO2_CONCENTRATION] = [10, 'H'];
	this.callbackFormats[BrickletCO2.CALLBACK_CO2_CONCENTRATION_REACHED] = [10, 'H'];



	this.getCO2Concentration = function(returnCallback, errorCallback) {
		/*
		Returns the measured CO2 concentration.
		
		If you want to get the CO2 concentration periodically, it is recommended to use
		the :cb:`CO2 Concentration` callback and set the period with
		:func:`Set CO2 Concentration Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletCO2.FUNCTION_GET_CO2_CONCENTRATION, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.setCO2ConcentrationCallbackPeriod = function(period, returnCallback, errorCallback) {
		/*
		Sets the period with which the :cb:`CO2 Concentration` callback is
		triggered periodically. A value of 0 turns the callback off.
		
		The :cb:`CO2 Concentration` callback is only triggered if the CO2 concentration
		has changed since the last triggering.
		*/
		this.ipcon.sendRequest(this, BrickletCO2.FUNCTION_SET_CO2_CONCENTRATION_CALLBACK_PERIOD, [period], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getCO2ConcentrationCallbackPeriod = function(returnCallback, errorCallback) {
		/*
		Returns the period as set by :func:`Set CO2 Concentration Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletCO2.FUNCTION_GET_CO2_CONCENTRATION_CALLBACK_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setCO2ConcentrationCallbackThreshold = function(option, min, max, returnCallback, errorCallback) {
		/*
		Sets the thresholds for the :cb:`CO2 Concentration Reached` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Callback is turned off"
		 "'o'",    "Callback is triggered when the CO2 concentration is *outside* the min and max values"
		 "'i'",    "Callback is triggered when the CO2 concentration is *inside* the min and max values"
		 "'<'",    "Callback is triggered when the CO2 concentration is smaller than the min value (max is ignored)"
		 "'>'",    "Callback is triggered when the CO2 concentration is greater than the min value (max is ignored)"
		*/
		this.ipcon.sendRequest(this, BrickletCO2.FUNCTION_SET_CO2_CONCENTRATION_CALLBACK_THRESHOLD, [option, min, max], 'c H H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getCO2ConcentrationCallbackThreshold = function(returnCallback, errorCallback) {
		/*
		Returns the threshold as set by :func:`Set CO2 Concentration Callback Threshold`.
		*/
		this.ipcon.sendRequest(this, BrickletCO2.FUNCTION_GET_CO2_CONCENTRATION_CALLBACK_THRESHOLD, [], '', 13, 'c H H', returnCallback, errorCallback, false, true);
	};
	this.setDebouncePeriod = function(debounce, returnCallback, errorCallback) {
		/*
		Sets the period with which the threshold callbacks
		
		* :cb:`CO2 Concentration Reached`,
		
		are triggered, if the thresholds
		
		* :func:`Set CO2 Concentration Callback Threshold`,
		
		keep being reached.
		*/
		this.ipcon.sendRequest(this, BrickletCO2.FUNCTION_SET_DEBOUNCE_PERIOD, [debounce], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getDebouncePeriod = function(returnCallback, errorCallback) {
		/*
		Returns the debounce period as set by :func:`Set Debounce Period`.
		*/
		this.ipcon.sendRequest(this, BrickletCO2.FUNCTION_GET_DEBOUNCE_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletCO2.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletCO2;

},{"./Device":279,"./IPConnection":280}],164:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletCO2V2.DEVICE_IDENTIFIER = 2147;
BrickletCO2V2.DEVICE_DISPLAY_NAME = 'CO2 Bricklet 2.0';
BrickletCO2V2.CALLBACK_ALL_VALUES = 8;
BrickletCO2V2.CALLBACK_CO2_CONCENTRATION = 12;
BrickletCO2V2.CALLBACK_TEMPERATURE = 16;
BrickletCO2V2.CALLBACK_HUMIDITY = 20;
BrickletCO2V2.FUNCTION_GET_ALL_VALUES = 1;
BrickletCO2V2.FUNCTION_SET_AIR_PRESSURE = 2;
BrickletCO2V2.FUNCTION_GET_AIR_PRESSURE = 3;
BrickletCO2V2.FUNCTION_SET_TEMPERATURE_OFFSET = 4;
BrickletCO2V2.FUNCTION_GET_TEMPERATURE_OFFSET = 5;
BrickletCO2V2.FUNCTION_SET_ALL_VALUES_CALLBACK_CONFIGURATION = 6;
BrickletCO2V2.FUNCTION_GET_ALL_VALUES_CALLBACK_CONFIGURATION = 7;
BrickletCO2V2.FUNCTION_GET_CO2_CONCENTRATION = 9;
BrickletCO2V2.FUNCTION_SET_CO2_CONCENTRATION_CALLBACK_CONFIGURATION = 10;
BrickletCO2V2.FUNCTION_GET_CO2_CONCENTRATION_CALLBACK_CONFIGURATION = 11;
BrickletCO2V2.FUNCTION_GET_TEMPERATURE = 13;
BrickletCO2V2.FUNCTION_SET_TEMPERATURE_CALLBACK_CONFIGURATION = 14;
BrickletCO2V2.FUNCTION_GET_TEMPERATURE_CALLBACK_CONFIGURATION = 15;
BrickletCO2V2.FUNCTION_GET_HUMIDITY = 17;
BrickletCO2V2.FUNCTION_SET_HUMIDITY_CALLBACK_CONFIGURATION = 18;
BrickletCO2V2.FUNCTION_GET_HUMIDITY_CALLBACK_CONFIGURATION = 19;
BrickletCO2V2.FUNCTION_GET_SPITFP_ERROR_COUNT = 234;
BrickletCO2V2.FUNCTION_SET_BOOTLOADER_MODE = 235;
BrickletCO2V2.FUNCTION_GET_BOOTLOADER_MODE = 236;
BrickletCO2V2.FUNCTION_SET_WRITE_FIRMWARE_POINTER = 237;
BrickletCO2V2.FUNCTION_WRITE_FIRMWARE = 238;
BrickletCO2V2.FUNCTION_SET_STATUS_LED_CONFIG = 239;
BrickletCO2V2.FUNCTION_GET_STATUS_LED_CONFIG = 240;
BrickletCO2V2.FUNCTION_GET_CHIP_TEMPERATURE = 242;
BrickletCO2V2.FUNCTION_RESET = 243;
BrickletCO2V2.FUNCTION_WRITE_UID = 248;
BrickletCO2V2.FUNCTION_READ_UID = 249;
BrickletCO2V2.FUNCTION_GET_IDENTITY = 255;
BrickletCO2V2.THRESHOLD_OPTION_OFF = 'x';
BrickletCO2V2.THRESHOLD_OPTION_OUTSIDE = 'o';
BrickletCO2V2.THRESHOLD_OPTION_INSIDE = 'i';
BrickletCO2V2.THRESHOLD_OPTION_SMALLER = '<';
BrickletCO2V2.THRESHOLD_OPTION_GREATER = '>';
BrickletCO2V2.BOOTLOADER_MODE_BOOTLOADER = 0;
BrickletCO2V2.BOOTLOADER_MODE_FIRMWARE = 1;
BrickletCO2V2.BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT = 2;
BrickletCO2V2.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT = 3;
BrickletCO2V2.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT = 4;
BrickletCO2V2.BOOTLOADER_STATUS_OK = 0;
BrickletCO2V2.BOOTLOADER_STATUS_INVALID_MODE = 1;
BrickletCO2V2.BOOTLOADER_STATUS_NO_CHANGE = 2;
BrickletCO2V2.BOOTLOADER_STATUS_ENTRY_FUNCTION_NOT_PRESENT = 3;
BrickletCO2V2.BOOTLOADER_STATUS_DEVICE_IDENTIFIER_INCORRECT = 4;
BrickletCO2V2.BOOTLOADER_STATUS_CRC_MISMATCH = 5;
BrickletCO2V2.STATUS_LED_CONFIG_OFF = 0;
BrickletCO2V2.STATUS_LED_CONFIG_ON = 1;
BrickletCO2V2.STATUS_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletCO2V2.STATUS_LED_CONFIG_SHOW_STATUS = 3;

function BrickletCO2V2(uid, ipcon) {
	//Measures CO2 concentration, temperature and humidity

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletCO2V2.DEVICE_IDENTIFIER, BrickletCO2V2.DEVICE_DISPLAY_NAME);
	BrickletCO2V2.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickletCO2V2.FUNCTION_GET_ALL_VALUES] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletCO2V2.FUNCTION_SET_AIR_PRESSURE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletCO2V2.FUNCTION_GET_AIR_PRESSURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletCO2V2.FUNCTION_SET_TEMPERATURE_OFFSET] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletCO2V2.FUNCTION_GET_TEMPERATURE_OFFSET] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletCO2V2.FUNCTION_SET_ALL_VALUES_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletCO2V2.FUNCTION_GET_ALL_VALUES_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletCO2V2.FUNCTION_GET_CO2_CONCENTRATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletCO2V2.FUNCTION_SET_CO2_CONCENTRATION_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletCO2V2.FUNCTION_GET_CO2_CONCENTRATION_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletCO2V2.FUNCTION_GET_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletCO2V2.FUNCTION_SET_TEMPERATURE_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletCO2V2.FUNCTION_GET_TEMPERATURE_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletCO2V2.FUNCTION_GET_HUMIDITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletCO2V2.FUNCTION_SET_HUMIDITY_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletCO2V2.FUNCTION_GET_HUMIDITY_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletCO2V2.FUNCTION_GET_SPITFP_ERROR_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletCO2V2.FUNCTION_SET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletCO2V2.FUNCTION_GET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletCO2V2.FUNCTION_SET_WRITE_FIRMWARE_POINTER] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletCO2V2.FUNCTION_WRITE_FIRMWARE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletCO2V2.FUNCTION_SET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletCO2V2.FUNCTION_GET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletCO2V2.FUNCTION_GET_CHIP_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletCO2V2.FUNCTION_RESET] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletCO2V2.FUNCTION_WRITE_UID] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletCO2V2.FUNCTION_READ_UID] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletCO2V2.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletCO2V2.CALLBACK_ALL_VALUES] = [14, 'H h H'];
	this.callbackFormats[BrickletCO2V2.CALLBACK_CO2_CONCENTRATION] = [10, 'H'];
	this.callbackFormats[BrickletCO2V2.CALLBACK_TEMPERATURE] = [10, 'h'];
	this.callbackFormats[BrickletCO2V2.CALLBACK_HUMIDITY] = [10, 'H'];



	this.getAllValues = function(returnCallback, errorCallback) {
		/*
		Returns all values measured by the CO2 Bricklet 2.0.
		
		If you want to get the values periodically, it is recommended to use the
		:cb:`All Values` callback. You can set the callback configuration
		with :func:`Set All Values Callback Configuration`.
		
		.. note::
		 The sensor is able to messure up to 120 °C. However it is only specified up to 70 °C.
		 Exposing the Bricklet to higher temperatures might result in permanent damage.
		*/
		this.ipcon.sendRequest(this, BrickletCO2V2.FUNCTION_GET_ALL_VALUES, [], '', 14, 'H h H', returnCallback, errorCallback, false, true);
	};
	this.setAirPressure = function(airPressure, returnCallback, errorCallback) {
		/*
		The CO2 concentration depends (among other things) on the ambient air pressure.
		
		To increase the accuracy of the CO2 Bricklet 2.0 you can set the current air pressure.
		You use the :ref:`Barometer Bricklet 2.0 <barometer_v2_bricklet>` or the
		:ref:`Air Quality Bricklet <air_quality_bricklet>` to get the current air pressure.
		
		By default air pressure compensation is disabled. Once you set a value it
		will be used for compensation. You can turn the compensation off again by
		setting the value to 0.
		
		It is sufficient to update the value every few minutes.
		*/
		this.ipcon.sendRequest(this, BrickletCO2V2.FUNCTION_SET_AIR_PRESSURE, [airPressure], 'H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getAirPressure = function(returnCallback, errorCallback) {
		/*
		Returns the ambient air pressure as set by :func:`Set Air Pressure`.
		*/
		this.ipcon.sendRequest(this, BrickletCO2V2.FUNCTION_GET_AIR_PRESSURE, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.setTemperatureOffset = function(offset, returnCallback, errorCallback) {
		/*
		Sets a temperature offset. A offset of 10 will decrease
		the measured temperature by 0.1 °C.
		
		If you install this Bricklet into an enclosure and you want to measure the ambient
		temperature, you may have to decrease the measured temperature by some value to
		compensate for the error because of the heating inside of the enclosure.
		
		We recommend that you leave the parts in the enclosure running for at least
		24 hours such that a temperature equilibrium can be reached. After that you can measure
		the temperature directly outside of enclosure and set the difference as offset.
		
		This temperature offset is used to calculate the relative humidity and
		CO2 concentration. In case the Bricklet is installed in an enclosure, we
		recommend to measure and set the temperature offset to improve the accuracy of
		the measurements.
		
		It is sufficient to set the temperature offset once. The offset is saved in
		non-volatile memory and is applied again after a power loss.
		*/
		this.ipcon.sendRequest(this, BrickletCO2V2.FUNCTION_SET_TEMPERATURE_OFFSET, [offset], 'H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getTemperatureOffset = function(returnCallback, errorCallback) {
		/*
		Returns the temperature offset as set by
		:func:`Set Temperature Offset`.
		*/
		this.ipcon.sendRequest(this, BrickletCO2V2.FUNCTION_GET_TEMPERATURE_OFFSET, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.setAllValuesCallbackConfiguration = function(period, valueHasToChange, returnCallback, errorCallback) {
		/*
		The period is the period with which the :cb:`All Values`
		callback is triggered periodically. A value of 0 turns the callback off.
		
		If the `value has to change`-parameter is set to true, the callback is only
		triggered after at least one of the values has changed. If the values didn't
		change within the period, the callback is triggered immediately on change.
		
		If it is set to false, the callback is continuously triggered with the period,
		independent of the value.
		*/
		this.ipcon.sendRequest(this, BrickletCO2V2.FUNCTION_SET_ALL_VALUES_CALLBACK_CONFIGURATION, [period, valueHasToChange], 'I ?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getAllValuesCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the callback configuration as set by
		:func:`Set All Values Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletCO2V2.FUNCTION_GET_ALL_VALUES_CALLBACK_CONFIGURATION, [], '', 13, 'I ?', returnCallback, errorCallback, false, true);
	};
	this.getCO2Concentration = function(returnCallback, errorCallback) {
		/*
		Returns CO2 concentration.
		
		
		If you want to get the value periodically, it is recommended to use the
		:cb:`CO2 Concentration` callback. You can set the callback configuration
		with :func:`Set CO2 Concentration Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletCO2V2.FUNCTION_GET_CO2_CONCENTRATION, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.setCO2ConcentrationCallbackConfiguration = function(period, valueHasToChange, option, min, max, returnCallback, errorCallback) {
		/*
		The period is the period with which the :cb:`CO2 Concentration` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		If the `value has to change`-parameter is set to true, the callback is only
		triggered after the value has changed. If the value didn't change
		within the period, the callback is triggered immediately on change.
		
		If it is set to false, the callback is continuously triggered with the period,
		independent of the value.
		
		It is furthermore possible to constrain the callback with thresholds.
		
		The `option`-parameter together with min/max sets a threshold for the :cb:`CO2 Concentration` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Threshold is turned off"
		 "'o'",    "Threshold is triggered when the value is *outside* the min and max values"
		 "'i'",    "Threshold is triggered when the value is *inside* or equal to the min and max values"
		 "'<'",    "Threshold is triggered when the value is smaller than the min value (max is ignored)"
		 "'>'",    "Threshold is triggered when the value is greater than the min value (max is ignored)"
		
		If the option is set to 'x' (threshold turned off) the callback is triggered with the fixed period.
		*/
		this.ipcon.sendRequest(this, BrickletCO2V2.FUNCTION_SET_CO2_CONCENTRATION_CALLBACK_CONFIGURATION, [period, valueHasToChange, option, min, max], 'I ? c H H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getCO2ConcentrationCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the callback configuration as set by :func:`Set CO2 Concentration Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletCO2V2.FUNCTION_GET_CO2_CONCENTRATION_CALLBACK_CONFIGURATION, [], '', 18, 'I ? c H H', returnCallback, errorCallback, false, true);
	};
	this.getTemperature = function(returnCallback, errorCallback) {
		/*
		Returns temperature.
		
		.. note::
		 The sensor is able to messure up to 120 °C. However it is only specified up to 70 °C.
		 Exposing the Bricklet to higher temperatures might result in permanent damage.
		
		
		If you want to get the value periodically, it is recommended to use the
		:cb:`Temperature` callback. You can set the callback configuration
		with :func:`Set Temperature Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletCO2V2.FUNCTION_GET_TEMPERATURE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.setTemperatureCallbackConfiguration = function(period, valueHasToChange, option, min, max, returnCallback, errorCallback) {
		/*
		The period is the period with which the :cb:`Temperature` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		If the `value has to change`-parameter is set to true, the callback is only
		triggered after the value has changed. If the value didn't change
		within the period, the callback is triggered immediately on change.
		
		If it is set to false, the callback is continuously triggered with the period,
		independent of the value.
		
		It is furthermore possible to constrain the callback with thresholds.
		
		The `option`-parameter together with min/max sets a threshold for the :cb:`Temperature` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Threshold is turned off"
		 "'o'",    "Threshold is triggered when the value is *outside* the min and max values"
		 "'i'",    "Threshold is triggered when the value is *inside* or equal to the min and max values"
		 "'<'",    "Threshold is triggered when the value is smaller than the min value (max is ignored)"
		 "'>'",    "Threshold is triggered when the value is greater than the min value (max is ignored)"
		
		If the option is set to 'x' (threshold turned off) the callback is triggered with the fixed period.
		*/
		this.ipcon.sendRequest(this, BrickletCO2V2.FUNCTION_SET_TEMPERATURE_CALLBACK_CONFIGURATION, [period, valueHasToChange, option, min, max], 'I ? c h h', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getTemperatureCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the callback configuration as set by :func:`Set Temperature Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletCO2V2.FUNCTION_GET_TEMPERATURE_CALLBACK_CONFIGURATION, [], '', 18, 'I ? c h h', returnCallback, errorCallback, false, true);
	};
	this.getHumidity = function(returnCallback, errorCallback) {
		/*
		Returns relative humidity.
		
		
		If you want to get the value periodically, it is recommended to use the
		:cb:`Humidity` callback. You can set the callback configuration
		with :func:`Set Humidity Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletCO2V2.FUNCTION_GET_HUMIDITY, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.setHumidityCallbackConfiguration = function(period, valueHasToChange, option, min, max, returnCallback, errorCallback) {
		/*
		The period is the period with which the :cb:`Humidity` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		If the `value has to change`-parameter is set to true, the callback is only
		triggered after the value has changed. If the value didn't change
		within the period, the callback is triggered immediately on change.
		
		If it is set to false, the callback is continuously triggered with the period,
		independent of the value.
		
		It is furthermore possible to constrain the callback with thresholds.
		
		The `option`-parameter together with min/max sets a threshold for the :cb:`Humidity` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Threshold is turned off"
		 "'o'",    "Threshold is triggered when the value is *outside* the min and max values"
		 "'i'",    "Threshold is triggered when the value is *inside* or equal to the min and max values"
		 "'<'",    "Threshold is triggered when the value is smaller than the min value (max is ignored)"
		 "'>'",    "Threshold is triggered when the value is greater than the min value (max is ignored)"
		
		If the option is set to 'x' (threshold turned off) the callback is triggered with the fixed period.
		*/
		this.ipcon.sendRequest(this, BrickletCO2V2.FUNCTION_SET_HUMIDITY_CALLBACK_CONFIGURATION, [period, valueHasToChange, option, min, max], 'I ? c H H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getHumidityCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the callback configuration as set by :func:`Set Humidity Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletCO2V2.FUNCTION_GET_HUMIDITY_CALLBACK_CONFIGURATION, [], '', 18, 'I ? c H H', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPErrorCount = function(returnCallback, errorCallback) {
		/*
		Returns the error count for the communication between Brick and Bricklet.
		
		The errors are divided into
		
		* ACK checksum errors,
		* message checksum errors,
		* framing errors and
		* overflow errors.
		
		The errors counts are for errors that occur on the Bricklet side. All
		Bricks have a similar function that returns the errors on the Brick side.
		*/
		this.ipcon.sendRequest(this, BrickletCO2V2.FUNCTION_GET_SPITFP_ERROR_COUNT, [], '', 24, 'I I I I', returnCallback, errorCallback, false, true);
	};
	this.setBootloaderMode = function(mode, returnCallback, errorCallback) {
		/*
		Sets the bootloader mode and returns the status after the requested
		mode change was instigated.
		
		You can change from bootloader mode to firmware mode and vice versa. A change
		from bootloader mode to firmware mode will only take place if the entry function,
		device identifier and CRC are present and correct.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletCO2V2.FUNCTION_SET_BOOTLOADER_MODE, [mode], 'B', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getBootloaderMode = function(returnCallback, errorCallback) {
		/*
		Returns the current bootloader mode, see :func:`Set Bootloader Mode`.
		*/
		this.ipcon.sendRequest(this, BrickletCO2V2.FUNCTION_GET_BOOTLOADER_MODE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setWriteFirmwarePointer = function(pointer, returnCallback, errorCallback) {
		/*
		Sets the firmware pointer for :func:`Write Firmware`. The pointer has
		to be increased by chunks of size 64. The data is written to flash
		every 4 chunks (which equals to one page of size 256).
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletCO2V2.FUNCTION_SET_WRITE_FIRMWARE_POINTER, [pointer], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeFirmware = function(data, returnCallback, errorCallback) {
		/*
		Writes 64 Bytes of firmware at the position as written by
		:func:`Set Write Firmware Pointer` before. The firmware is written
		to flash every 4 chunks.
		
		You can only write firmware in bootloader mode.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletCO2V2.FUNCTION_WRITE_FIRMWARE, [data], 'B64', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setStatusLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Sets the status LED configuration. By default the LED shows
		communication traffic between Brick and Bricklet, it flickers once
		for every 10 received data packets.
		
		You can also turn the LED permanently on/off or show a heartbeat.
		
		If the Bricklet is in bootloader mode, the LED is will show heartbeat by default.
		*/
		this.ipcon.sendRequest(this, BrickletCO2V2.FUNCTION_SET_STATUS_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getStatusLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Status LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletCO2V2.FUNCTION_GET_STATUS_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getChipTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature as measured inside the microcontroller. The
		value returned is not the ambient temperature!
		
		The temperature is only proportional to the real temperature and it has bad
		accuracy. Practically it is only useful as an indicator for
		temperature changes.
		*/
		this.ipcon.sendRequest(this, BrickletCO2V2.FUNCTION_GET_CHIP_TEMPERATURE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.reset = function(returnCallback, errorCallback) {
		/*
		Calling this function will reset the Bricklet. All configurations
		will be lost.
		
		After a reset you have to create new device objects,
		calling functions on the existing ones will result in
		undefined behavior!
		*/
		this.ipcon.sendRequest(this, BrickletCO2V2.FUNCTION_RESET, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeUID = function(uid, returnCallback, errorCallback) {
		/*
		Writes a new UID into flash. If you want to set a new UID
		you have to decode the Base58 encoded UID string into an
		integer first.
		
		We recommend that you use Brick Viewer to change the UID.
		*/
		this.ipcon.sendRequest(this, BrickletCO2V2.FUNCTION_WRITE_UID, [uid], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.readUID = function(returnCallback, errorCallback) {
		/*
		Returns the current UID as an integer. Encode as
		Base58 to get the usual string version.
		*/
		this.ipcon.sendRequest(this, BrickletCO2V2.FUNCTION_READ_UID, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletCO2V2.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletCO2V2;

},{"./Device":279,"./IPConnection":280}],165:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletColor.DEVICE_IDENTIFIER = 243;
BrickletColor.DEVICE_DISPLAY_NAME = 'Color Bricklet';
BrickletColor.CALLBACK_COLOR = 8;
BrickletColor.CALLBACK_COLOR_REACHED = 9;
BrickletColor.CALLBACK_ILLUMINANCE = 21;
BrickletColor.CALLBACK_COLOR_TEMPERATURE = 22;
BrickletColor.FUNCTION_GET_COLOR = 1;
BrickletColor.FUNCTION_SET_COLOR_CALLBACK_PERIOD = 2;
BrickletColor.FUNCTION_GET_COLOR_CALLBACK_PERIOD = 3;
BrickletColor.FUNCTION_SET_COLOR_CALLBACK_THRESHOLD = 4;
BrickletColor.FUNCTION_GET_COLOR_CALLBACK_THRESHOLD = 5;
BrickletColor.FUNCTION_SET_DEBOUNCE_PERIOD = 6;
BrickletColor.FUNCTION_GET_DEBOUNCE_PERIOD = 7;
BrickletColor.FUNCTION_LIGHT_ON = 10;
BrickletColor.FUNCTION_LIGHT_OFF = 11;
BrickletColor.FUNCTION_IS_LIGHT_ON = 12;
BrickletColor.FUNCTION_SET_CONFIG = 13;
BrickletColor.FUNCTION_GET_CONFIG = 14;
BrickletColor.FUNCTION_GET_ILLUMINANCE = 15;
BrickletColor.FUNCTION_GET_COLOR_TEMPERATURE = 16;
BrickletColor.FUNCTION_SET_ILLUMINANCE_CALLBACK_PERIOD = 17;
BrickletColor.FUNCTION_GET_ILLUMINANCE_CALLBACK_PERIOD = 18;
BrickletColor.FUNCTION_SET_COLOR_TEMPERATURE_CALLBACK_PERIOD = 19;
BrickletColor.FUNCTION_GET_COLOR_TEMPERATURE_CALLBACK_PERIOD = 20;
BrickletColor.FUNCTION_GET_IDENTITY = 255;
BrickletColor.THRESHOLD_OPTION_OFF = 'x';
BrickletColor.THRESHOLD_OPTION_OUTSIDE = 'o';
BrickletColor.THRESHOLD_OPTION_INSIDE = 'i';
BrickletColor.THRESHOLD_OPTION_SMALLER = '<';
BrickletColor.THRESHOLD_OPTION_GREATER = '>';
BrickletColor.LIGHT_ON = 0;
BrickletColor.LIGHT_OFF = 1;
BrickletColor.GAIN_1X = 0;
BrickletColor.GAIN_4X = 1;
BrickletColor.GAIN_16X = 2;
BrickletColor.GAIN_60X = 3;
BrickletColor.INTEGRATION_TIME_2MS = 0;
BrickletColor.INTEGRATION_TIME_24MS = 1;
BrickletColor.INTEGRATION_TIME_101MS = 2;
BrickletColor.INTEGRATION_TIME_154MS = 3;
BrickletColor.INTEGRATION_TIME_700MS = 4;

function BrickletColor(uid, ipcon) {
	//Measures color (RGB value), illuminance and color temperature

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletColor.DEVICE_IDENTIFIER, BrickletColor.DEVICE_DISPLAY_NAME);
	BrickletColor.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickletColor.FUNCTION_GET_COLOR] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletColor.FUNCTION_SET_COLOR_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletColor.FUNCTION_GET_COLOR_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletColor.FUNCTION_SET_COLOR_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletColor.FUNCTION_GET_COLOR_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletColor.FUNCTION_SET_DEBOUNCE_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletColor.FUNCTION_GET_DEBOUNCE_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletColor.FUNCTION_LIGHT_ON] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletColor.FUNCTION_LIGHT_OFF] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletColor.FUNCTION_IS_LIGHT_ON] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletColor.FUNCTION_SET_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletColor.FUNCTION_GET_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletColor.FUNCTION_GET_ILLUMINANCE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletColor.FUNCTION_GET_COLOR_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletColor.FUNCTION_SET_ILLUMINANCE_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletColor.FUNCTION_GET_ILLUMINANCE_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletColor.FUNCTION_SET_COLOR_TEMPERATURE_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletColor.FUNCTION_GET_COLOR_TEMPERATURE_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletColor.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletColor.CALLBACK_COLOR] = [16, 'H H H H'];
	this.callbackFormats[BrickletColor.CALLBACK_COLOR_REACHED] = [16, 'H H H H'];
	this.callbackFormats[BrickletColor.CALLBACK_ILLUMINANCE] = [12, 'I'];
	this.callbackFormats[BrickletColor.CALLBACK_COLOR_TEMPERATURE] = [10, 'H'];



	this.getColor = function(returnCallback, errorCallback) {
		/*
		Returns the measured color of the sensor.
		
		The red (r), green (g), blue (b) and clear (c) colors are measured
		with four different photodiodes that are responsive at different
		wavelengths:
		
		.. image:: /Images/Bricklets/bricklet_color_wavelength_chart_600.jpg
		   :scale: 100 %
		   :alt: Chart Responsivity / Wavelength
		   :align: center
		   :target: ../../_images/Bricklets/bricklet_color_wavelength_chart_600.jpg
		
		If you want to get the color periodically, it is recommended
		to use the :cb:`Color` callback and set the period with
		:func:`Set Color Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletColor.FUNCTION_GET_COLOR, [], '', 16, 'H H H H', returnCallback, errorCallback, false, true);
	};
	this.setColorCallbackPeriod = function(period, returnCallback, errorCallback) {
		/*
		Sets the period with which the :cb:`Color` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		The :cb:`Color` callback is only triggered if the color has changed since the
		last triggering.
		*/
		this.ipcon.sendRequest(this, BrickletColor.FUNCTION_SET_COLOR_CALLBACK_PERIOD, [period], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getColorCallbackPeriod = function(returnCallback, errorCallback) {
		/*
		Returns the period as set by :func:`Set Color Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletColor.FUNCTION_GET_COLOR_CALLBACK_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setColorCallbackThreshold = function(option, minR, maxR, minG, maxG, minB, maxB, minC, maxC, returnCallback, errorCallback) {
		/*
		Sets the thresholds for the :cb:`Color Reached` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Callback is turned off"
		 "'o'",    "Callback is triggered when the temperature is *outside* the min and max values"
		 "'i'",    "Callback is triggered when the temperature is *inside* the min and max values"
		 "'<'",    "Callback is triggered when the temperature is smaller than the min value (max is ignored)"
		 "'>'",    "Callback is triggered when the temperature is greater than the min value (max is ignored)"
		*/
		this.ipcon.sendRequest(this, BrickletColor.FUNCTION_SET_COLOR_CALLBACK_THRESHOLD, [option, minR, maxR, minG, maxG, minB, maxB, minC, maxC], 'c H H H H H H H H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getColorCallbackThreshold = function(returnCallback, errorCallback) {
		/*
		Returns the threshold as set by :func:`Set Color Callback Threshold`.
		*/
		this.ipcon.sendRequest(this, BrickletColor.FUNCTION_GET_COLOR_CALLBACK_THRESHOLD, [], '', 25, 'c H H H H H H H H', returnCallback, errorCallback, false, true);
	};
	this.setDebouncePeriod = function(debounce, returnCallback, errorCallback) {
		/*
		Sets the period with which the threshold callback
		
		* :cb:`Color Reached`
		
		is triggered, if the threshold
		
		* :func:`Set Color Callback Threshold`
		
		keeps being reached.
		*/
		this.ipcon.sendRequest(this, BrickletColor.FUNCTION_SET_DEBOUNCE_PERIOD, [debounce], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getDebouncePeriod = function(returnCallback, errorCallback) {
		/*
		Returns the debounce period as set by :func:`Set Debounce Period`.
		*/
		this.ipcon.sendRequest(this, BrickletColor.FUNCTION_GET_DEBOUNCE_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.lightOn = function(returnCallback, errorCallback) {
		/*
		Turns the LED on.
		*/
		this.ipcon.sendRequest(this, BrickletColor.FUNCTION_LIGHT_ON, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.lightOff = function(returnCallback, errorCallback) {
		/*
		Turns the LED off.
		*/
		this.ipcon.sendRequest(this, BrickletColor.FUNCTION_LIGHT_OFF, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.isLightOn = function(returnCallback, errorCallback) {
		/*
		Returns the state of the LED. Possible values are:
		
		* 0: On
		* 1: Off
		*/
		this.ipcon.sendRequest(this, BrickletColor.FUNCTION_IS_LIGHT_ON, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setConfig = function(gain, integrationTime, returnCallback, errorCallback) {
		/*
		Sets the configuration of the sensor. Gain and integration time
		can be configured in this way.
		
		For configuring the gain:
		
		* 0: 1x Gain
		* 1: 4x Gain
		* 2: 16x Gain
		* 3: 60x Gain
		
		For configuring the integration time:
		
		* 0: 2.4ms
		* 1: 24ms
		* 2: 101ms
		* 3: 154ms
		* 4: 700ms
		
		Increasing the gain enables the sensor to detect a
		color from a higher distance.
		
		The integration time provides a trade-off between conversion time
		and accuracy. With a longer integration time the values read will
		be more accurate but it will take longer time to get the conversion
		results.
		*/
		this.ipcon.sendRequest(this, BrickletColor.FUNCTION_SET_CONFIG, [gain, integrationTime], 'B B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getConfig = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Config`.
		*/
		this.ipcon.sendRequest(this, BrickletColor.FUNCTION_GET_CONFIG, [], '', 10, 'B B', returnCallback, errorCallback, false, true);
	};
	this.getIlluminance = function(returnCallback, errorCallback) {
		/*
		Returns the illuminance affected by the gain and integration time as
		set by :func:`Set Config`. To get the illuminance in Lux apply this formula::
		
		 lux = illuminance * 700 / gain / integration_time
		
		To get a correct illuminance measurement make sure that the color
		values themselves are not saturated. The color value (R, G or B)
		is saturated if it is equal to the maximum value of 65535.
		In that case you have to reduce the gain, see :func:`Set Config`.
		*/
		this.ipcon.sendRequest(this, BrickletColor.FUNCTION_GET_ILLUMINANCE, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getColorTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the color temperature.
		
		To get a correct color temperature measurement make sure that the color
		values themselves are not saturated. The color value (R, G or B)
		is saturated if it is equal to the maximum value of 65535.
		In that case you have to reduce the gain, see :func:`Set Config`.
		*/
		this.ipcon.sendRequest(this, BrickletColor.FUNCTION_GET_COLOR_TEMPERATURE, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.setIlluminanceCallbackPeriod = function(period, returnCallback, errorCallback) {
		/*
		Sets the period with which the :cb:`Illuminance` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		The :cb:`Illuminance` callback is only triggered if the illuminance has changed
		since the last triggering.
		*/
		this.ipcon.sendRequest(this, BrickletColor.FUNCTION_SET_ILLUMINANCE_CALLBACK_PERIOD, [period], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getIlluminanceCallbackPeriod = function(returnCallback, errorCallback) {
		/*
		Returns the period as set by :func:`Set Illuminance Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletColor.FUNCTION_GET_ILLUMINANCE_CALLBACK_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setColorTemperatureCallbackPeriod = function(period, returnCallback, errorCallback) {
		/*
		Sets the period with which the :cb:`Color Temperature` callback is
		triggered periodically. A value of 0 turns the callback off.
		
		The :cb:`Color Temperature` callback is only triggered if the color temperature
		has changed since the last triggering.
		*/
		this.ipcon.sendRequest(this, BrickletColor.FUNCTION_SET_COLOR_TEMPERATURE_CALLBACK_PERIOD, [period], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getColorTemperatureCallbackPeriod = function(returnCallback, errorCallback) {
		/*
		Returns the period as set by :func:`Set Color Temperature Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletColor.FUNCTION_GET_COLOR_TEMPERATURE_CALLBACK_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletColor.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletColor;

},{"./Device":279,"./IPConnection":280}],166:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletColorV2.DEVICE_IDENTIFIER = 2128;
BrickletColorV2.DEVICE_DISPLAY_NAME = 'Color Bricklet 2.0';
BrickletColorV2.CALLBACK_COLOR = 4;
BrickletColorV2.CALLBACK_ILLUMINANCE = 8;
BrickletColorV2.CALLBACK_COLOR_TEMPERATURE = 12;
BrickletColorV2.FUNCTION_GET_COLOR = 1;
BrickletColorV2.FUNCTION_SET_COLOR_CALLBACK_CONFIGURATION = 2;
BrickletColorV2.FUNCTION_GET_COLOR_CALLBACK_CONFIGURATION = 3;
BrickletColorV2.FUNCTION_GET_ILLUMINANCE = 5;
BrickletColorV2.FUNCTION_SET_ILLUMINANCE_CALLBACK_CONFIGURATION = 6;
BrickletColorV2.FUNCTION_GET_ILLUMINANCE_CALLBACK_CONFIGURATION = 7;
BrickletColorV2.FUNCTION_GET_COLOR_TEMPERATURE = 9;
BrickletColorV2.FUNCTION_SET_COLOR_TEMPERATURE_CALLBACK_CONFIGURATION = 10;
BrickletColorV2.FUNCTION_GET_COLOR_TEMPERATURE_CALLBACK_CONFIGURATION = 11;
BrickletColorV2.FUNCTION_SET_LIGHT = 13;
BrickletColorV2.FUNCTION_GET_LIGHT = 14;
BrickletColorV2.FUNCTION_SET_CONFIGURATION = 15;
BrickletColorV2.FUNCTION_GET_CONFIGURATION = 16;
BrickletColorV2.FUNCTION_GET_SPITFP_ERROR_COUNT = 234;
BrickletColorV2.FUNCTION_SET_BOOTLOADER_MODE = 235;
BrickletColorV2.FUNCTION_GET_BOOTLOADER_MODE = 236;
BrickletColorV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER = 237;
BrickletColorV2.FUNCTION_WRITE_FIRMWARE = 238;
BrickletColorV2.FUNCTION_SET_STATUS_LED_CONFIG = 239;
BrickletColorV2.FUNCTION_GET_STATUS_LED_CONFIG = 240;
BrickletColorV2.FUNCTION_GET_CHIP_TEMPERATURE = 242;
BrickletColorV2.FUNCTION_RESET = 243;
BrickletColorV2.FUNCTION_WRITE_UID = 248;
BrickletColorV2.FUNCTION_READ_UID = 249;
BrickletColorV2.FUNCTION_GET_IDENTITY = 255;
BrickletColorV2.THRESHOLD_OPTION_OFF = 'x';
BrickletColorV2.THRESHOLD_OPTION_OUTSIDE = 'o';
BrickletColorV2.THRESHOLD_OPTION_INSIDE = 'i';
BrickletColorV2.THRESHOLD_OPTION_SMALLER = '<';
BrickletColorV2.THRESHOLD_OPTION_GREATER = '>';
BrickletColorV2.GAIN_1X = 0;
BrickletColorV2.GAIN_4X = 1;
BrickletColorV2.GAIN_16X = 2;
BrickletColorV2.GAIN_60X = 3;
BrickletColorV2.INTEGRATION_TIME_2MS = 0;
BrickletColorV2.INTEGRATION_TIME_24MS = 1;
BrickletColorV2.INTEGRATION_TIME_101MS = 2;
BrickletColorV2.INTEGRATION_TIME_154MS = 3;
BrickletColorV2.INTEGRATION_TIME_700MS = 4;
BrickletColorV2.BOOTLOADER_MODE_BOOTLOADER = 0;
BrickletColorV2.BOOTLOADER_MODE_FIRMWARE = 1;
BrickletColorV2.BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT = 2;
BrickletColorV2.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT = 3;
BrickletColorV2.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT = 4;
BrickletColorV2.BOOTLOADER_STATUS_OK = 0;
BrickletColorV2.BOOTLOADER_STATUS_INVALID_MODE = 1;
BrickletColorV2.BOOTLOADER_STATUS_NO_CHANGE = 2;
BrickletColorV2.BOOTLOADER_STATUS_ENTRY_FUNCTION_NOT_PRESENT = 3;
BrickletColorV2.BOOTLOADER_STATUS_DEVICE_IDENTIFIER_INCORRECT = 4;
BrickletColorV2.BOOTLOADER_STATUS_CRC_MISMATCH = 5;
BrickletColorV2.STATUS_LED_CONFIG_OFF = 0;
BrickletColorV2.STATUS_LED_CONFIG_ON = 1;
BrickletColorV2.STATUS_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletColorV2.STATUS_LED_CONFIG_SHOW_STATUS = 3;

function BrickletColorV2(uid, ipcon) {
	//Measures color (RGB value), illuminance and color temperature

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletColorV2.DEVICE_IDENTIFIER, BrickletColorV2.DEVICE_DISPLAY_NAME);
	BrickletColorV2.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickletColorV2.FUNCTION_GET_COLOR] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletColorV2.FUNCTION_SET_COLOR_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletColorV2.FUNCTION_GET_COLOR_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletColorV2.FUNCTION_GET_ILLUMINANCE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletColorV2.FUNCTION_SET_ILLUMINANCE_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletColorV2.FUNCTION_GET_ILLUMINANCE_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletColorV2.FUNCTION_GET_COLOR_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletColorV2.FUNCTION_SET_COLOR_TEMPERATURE_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletColorV2.FUNCTION_GET_COLOR_TEMPERATURE_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletColorV2.FUNCTION_SET_LIGHT] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletColorV2.FUNCTION_GET_LIGHT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletColorV2.FUNCTION_SET_CONFIGURATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletColorV2.FUNCTION_GET_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletColorV2.FUNCTION_GET_SPITFP_ERROR_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletColorV2.FUNCTION_SET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletColorV2.FUNCTION_GET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletColorV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletColorV2.FUNCTION_WRITE_FIRMWARE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletColorV2.FUNCTION_SET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletColorV2.FUNCTION_GET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletColorV2.FUNCTION_GET_CHIP_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletColorV2.FUNCTION_RESET] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletColorV2.FUNCTION_WRITE_UID] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletColorV2.FUNCTION_READ_UID] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletColorV2.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletColorV2.CALLBACK_COLOR] = [16, 'H H H H'];
	this.callbackFormats[BrickletColorV2.CALLBACK_ILLUMINANCE] = [12, 'I'];
	this.callbackFormats[BrickletColorV2.CALLBACK_COLOR_TEMPERATURE] = [10, 'H'];



	this.getColor = function(returnCallback, errorCallback) {
		/*
		Returns the measured color of the sensor.
		
		The red (r), green (g), blue (b) and clear (c) colors are measured
		with four different photodiodes that are responsive at different
		wavelengths:
		
		.. image:: /Images/Bricklets/bricklet_color_wavelength_chart_600.jpg
		   :scale: 100 %
		   :alt: Chart Responsivity / Wavelength
		   :align: center
		   :target: ../../_images/Bricklets/bricklet_color_wavelength_chart_600.jpg
		
		If you want to get the color periodically, it is recommended
		to use the :cb:`Color` callback and set the period with
		:func:`Set Color Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletColorV2.FUNCTION_GET_COLOR, [], '', 16, 'H H H H', returnCallback, errorCallback, false, true);
	};
	this.setColorCallbackConfiguration = function(period, valueHasToChange, returnCallback, errorCallback) {
		/*
		The period is the period with which the :cb:`Color`
		callback is triggered periodically. A value of 0 turns the callback off.
		
		If the `value has to change`-parameter is set to true, the callback is only
		triggered after the value has changed. If the value didn't change within the
		period, the callback is triggered immediately on change.
		
		If it is set to false, the callback is continuously triggered with the period,
		independent of the value.
		*/
		this.ipcon.sendRequest(this, BrickletColorV2.FUNCTION_SET_COLOR_CALLBACK_CONFIGURATION, [period, valueHasToChange], 'I ?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getColorCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the callback configuration as set by
		:func:`Set Color Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletColorV2.FUNCTION_GET_COLOR_CALLBACK_CONFIGURATION, [], '', 13, 'I ?', returnCallback, errorCallback, false, true);
	};
	this.getIlluminance = function(returnCallback, errorCallback) {
		/*
		Returns the illuminance affected by the gain and integration time as
		set by :func:`Set Configuration`. To get the illuminance in Lux apply this formula::
		
		 lux = illuminance * 700 / gain / integration_time
		
		To get a correct illuminance measurement make sure that the color
		values themselves are not saturated. The color value (R, G or B)
		is saturated if it is equal to the maximum value of 65535.
		In that case you have to reduce the gain, see :func:`Set Configuration`.
		
		
		If you want to get the value periodically, it is recommended to use the
		:cb:`Illuminance` callback. You can set the callback configuration
		with :func:`Set Illuminance Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletColorV2.FUNCTION_GET_ILLUMINANCE, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setIlluminanceCallbackConfiguration = function(period, valueHasToChange, option, min, max, returnCallback, errorCallback) {
		/*
		The period is the period with which the :cb:`Illuminance` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		If the `value has to change`-parameter is set to true, the callback is only
		triggered after the value has changed. If the value didn't change
		within the period, the callback is triggered immediately on change.
		
		If it is set to false, the callback is continuously triggered with the period,
		independent of the value.
		
		It is furthermore possible to constrain the callback with thresholds.
		
		The `option`-parameter together with min/max sets a threshold for the :cb:`Illuminance` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Threshold is turned off"
		 "'o'",    "Threshold is triggered when the value is *outside* the min and max values"
		 "'i'",    "Threshold is triggered when the value is *inside* or equal to the min and max values"
		 "'<'",    "Threshold is triggered when the value is smaller than the min value (max is ignored)"
		 "'>'",    "Threshold is triggered when the value is greater than the min value (max is ignored)"
		
		If the option is set to 'x' (threshold turned off) the callback is triggered with the fixed period.
		*/
		this.ipcon.sendRequest(this, BrickletColorV2.FUNCTION_SET_ILLUMINANCE_CALLBACK_CONFIGURATION, [period, valueHasToChange, option, min, max], 'I ? c I I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getIlluminanceCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the callback configuration as set by :func:`Set Illuminance Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletColorV2.FUNCTION_GET_ILLUMINANCE_CALLBACK_CONFIGURATION, [], '', 22, 'I ? c I I', returnCallback, errorCallback, false, true);
	};
	this.getColorTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the color temperature.
		
		To get a correct color temperature measurement make sure that the color
		values themselves are not saturated. The color value (R, G or B)
		is saturated if it is equal to the maximum value of 65535.
		In that case you have to reduce the gain, see :func:`Set Configuration`.
		
		
		If you want to get the value periodically, it is recommended to use the
		:cb:`Color Temperature` callback. You can set the callback configuration
		with :func:`Set Color Temperature Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletColorV2.FUNCTION_GET_COLOR_TEMPERATURE, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.setColorTemperatureCallbackConfiguration = function(period, valueHasToChange, option, min, max, returnCallback, errorCallback) {
		/*
		The period is the period with which the :cb:`Color Temperature` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		If the `value has to change`-parameter is set to true, the callback is only
		triggered after the value has changed. If the value didn't change
		within the period, the callback is triggered immediately on change.
		
		If it is set to false, the callback is continuously triggered with the period,
		independent of the value.
		
		It is furthermore possible to constrain the callback with thresholds.
		
		The `option`-parameter together with min/max sets a threshold for the :cb:`Color Temperature` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Threshold is turned off"
		 "'o'",    "Threshold is triggered when the value is *outside* the min and max values"
		 "'i'",    "Threshold is triggered when the value is *inside* or equal to the min and max values"
		 "'<'",    "Threshold is triggered when the value is smaller than the min value (max is ignored)"
		 "'>'",    "Threshold is triggered when the value is greater than the min value (max is ignored)"
		
		If the option is set to 'x' (threshold turned off) the callback is triggered with the fixed period.
		*/
		this.ipcon.sendRequest(this, BrickletColorV2.FUNCTION_SET_COLOR_TEMPERATURE_CALLBACK_CONFIGURATION, [period, valueHasToChange, option, min, max], 'I ? c H H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getColorTemperatureCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the callback configuration as set by :func:`Set Color Temperature Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletColorV2.FUNCTION_GET_COLOR_TEMPERATURE_CALLBACK_CONFIGURATION, [], '', 18, 'I ? c H H', returnCallback, errorCallback, false, true);
	};
	this.setLight = function(enable, returnCallback, errorCallback) {
		/*
		Turns the white LED on the Bricklet on/off.
		*/
		this.ipcon.sendRequest(this, BrickletColorV2.FUNCTION_SET_LIGHT, [enable], '?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getLight = function(returnCallback, errorCallback) {
		/*
		Returns the value as set by :func:`Set Light`.
		*/
		this.ipcon.sendRequest(this, BrickletColorV2.FUNCTION_GET_LIGHT, [], '', 9, '?', returnCallback, errorCallback, false, true);
	};
	this.setConfiguration = function(gain, integrationTime, returnCallback, errorCallback) {
		/*
		Sets the configuration of the sensor. Gain and integration time
		can be configured this way.
		
		For configuring the gain:
		
		* 0: 1x Gain
		* 1: 4x Gain
		* 2: 16x Gain
		* 3: 60x Gain
		
		For configuring the integration time:
		
		* 0: 2.4ms
		* 1: 24ms
		* 2: 101ms
		* 3: 154ms
		* 4: 700ms
		
		Increasing the gain enables the sensor to detect a
		color from a higher distance.
		
		The integration time provides a trade-off between conversion time
		and accuracy. With a longer integration time the values read will
		be more accurate but it will take longer to get the conversion
		results.
		*/
		this.ipcon.sendRequest(this, BrickletColorV2.FUNCTION_SET_CONFIGURATION, [gain, integrationTime], 'B B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletColorV2.FUNCTION_GET_CONFIGURATION, [], '', 10, 'B B', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPErrorCount = function(returnCallback, errorCallback) {
		/*
		Returns the error count for the communication between Brick and Bricklet.
		
		The errors are divided into
		
		* ACK checksum errors,
		* message checksum errors,
		* framing errors and
		* overflow errors.
		
		The errors counts are for errors that occur on the Bricklet side. All
		Bricks have a similar function that returns the errors on the Brick side.
		*/
		this.ipcon.sendRequest(this, BrickletColorV2.FUNCTION_GET_SPITFP_ERROR_COUNT, [], '', 24, 'I I I I', returnCallback, errorCallback, false, true);
	};
	this.setBootloaderMode = function(mode, returnCallback, errorCallback) {
		/*
		Sets the bootloader mode and returns the status after the requested
		mode change was instigated.
		
		You can change from bootloader mode to firmware mode and vice versa. A change
		from bootloader mode to firmware mode will only take place if the entry function,
		device identifier and CRC are present and correct.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletColorV2.FUNCTION_SET_BOOTLOADER_MODE, [mode], 'B', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getBootloaderMode = function(returnCallback, errorCallback) {
		/*
		Returns the current bootloader mode, see :func:`Set Bootloader Mode`.
		*/
		this.ipcon.sendRequest(this, BrickletColorV2.FUNCTION_GET_BOOTLOADER_MODE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setWriteFirmwarePointer = function(pointer, returnCallback, errorCallback) {
		/*
		Sets the firmware pointer for :func:`Write Firmware`. The pointer has
		to be increased by chunks of size 64. The data is written to flash
		every 4 chunks (which equals to one page of size 256).
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletColorV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER, [pointer], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeFirmware = function(data, returnCallback, errorCallback) {
		/*
		Writes 64 Bytes of firmware at the position as written by
		:func:`Set Write Firmware Pointer` before. The firmware is written
		to flash every 4 chunks.
		
		You can only write firmware in bootloader mode.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletColorV2.FUNCTION_WRITE_FIRMWARE, [data], 'B64', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setStatusLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Sets the status LED configuration. By default the LED shows
		communication traffic between Brick and Bricklet, it flickers once
		for every 10 received data packets.
		
		You can also turn the LED permanently on/off or show a heartbeat.
		
		If the Bricklet is in bootloader mode, the LED is will show heartbeat by default.
		*/
		this.ipcon.sendRequest(this, BrickletColorV2.FUNCTION_SET_STATUS_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getStatusLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Status LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletColorV2.FUNCTION_GET_STATUS_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getChipTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature as measured inside the microcontroller. The
		value returned is not the ambient temperature!
		
		The temperature is only proportional to the real temperature and it has bad
		accuracy. Practically it is only useful as an indicator for
		temperature changes.
		*/
		this.ipcon.sendRequest(this, BrickletColorV2.FUNCTION_GET_CHIP_TEMPERATURE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.reset = function(returnCallback, errorCallback) {
		/*
		Calling this function will reset the Bricklet. All configurations
		will be lost.
		
		After a reset you have to create new device objects,
		calling functions on the existing ones will result in
		undefined behavior!
		*/
		this.ipcon.sendRequest(this, BrickletColorV2.FUNCTION_RESET, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeUID = function(uid, returnCallback, errorCallback) {
		/*
		Writes a new UID into flash. If you want to set a new UID
		you have to decode the Base58 encoded UID string into an
		integer first.
		
		We recommend that you use Brick Viewer to change the UID.
		*/
		this.ipcon.sendRequest(this, BrickletColorV2.FUNCTION_WRITE_UID, [uid], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.readUID = function(returnCallback, errorCallback) {
		/*
		Returns the current UID as an integer. Encode as
		Base58 to get the usual string version.
		*/
		this.ipcon.sendRequest(this, BrickletColorV2.FUNCTION_READ_UID, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletColorV2.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletColorV2;

},{"./Device":279,"./IPConnection":280}],167:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletCompass.DEVICE_IDENTIFIER = 2153;
BrickletCompass.DEVICE_DISPLAY_NAME = 'Compass Bricklet';
BrickletCompass.CALLBACK_HEADING = 4;
BrickletCompass.CALLBACK_MAGNETIC_FLUX_DENSITY = 8;
BrickletCompass.FUNCTION_GET_HEADING = 1;
BrickletCompass.FUNCTION_SET_HEADING_CALLBACK_CONFIGURATION = 2;
BrickletCompass.FUNCTION_GET_HEADING_CALLBACK_CONFIGURATION = 3;
BrickletCompass.FUNCTION_GET_MAGNETIC_FLUX_DENSITY = 5;
BrickletCompass.FUNCTION_SET_MAGNETIC_FLUX_DENSITY_CALLBACK_CONFIGURATION = 6;
BrickletCompass.FUNCTION_GET_MAGNETIC_FLUX_DENSITY_CALLBACK_CONFIGURATION = 7;
BrickletCompass.FUNCTION_SET_CONFIGURATION = 9;
BrickletCompass.FUNCTION_GET_CONFIGURATION = 10;
BrickletCompass.FUNCTION_SET_CALIBRATION = 11;
BrickletCompass.FUNCTION_GET_CALIBRATION = 12;
BrickletCompass.FUNCTION_GET_SPITFP_ERROR_COUNT = 234;
BrickletCompass.FUNCTION_SET_BOOTLOADER_MODE = 235;
BrickletCompass.FUNCTION_GET_BOOTLOADER_MODE = 236;
BrickletCompass.FUNCTION_SET_WRITE_FIRMWARE_POINTER = 237;
BrickletCompass.FUNCTION_WRITE_FIRMWARE = 238;
BrickletCompass.FUNCTION_SET_STATUS_LED_CONFIG = 239;
BrickletCompass.FUNCTION_GET_STATUS_LED_CONFIG = 240;
BrickletCompass.FUNCTION_GET_CHIP_TEMPERATURE = 242;
BrickletCompass.FUNCTION_RESET = 243;
BrickletCompass.FUNCTION_WRITE_UID = 248;
BrickletCompass.FUNCTION_READ_UID = 249;
BrickletCompass.FUNCTION_GET_IDENTITY = 255;
BrickletCompass.THRESHOLD_OPTION_OFF = 'x';
BrickletCompass.THRESHOLD_OPTION_OUTSIDE = 'o';
BrickletCompass.THRESHOLD_OPTION_INSIDE = 'i';
BrickletCompass.THRESHOLD_OPTION_SMALLER = '<';
BrickletCompass.THRESHOLD_OPTION_GREATER = '>';
BrickletCompass.DATA_RATE_100HZ = 0;
BrickletCompass.DATA_RATE_200HZ = 1;
BrickletCompass.DATA_RATE_400HZ = 2;
BrickletCompass.DATA_RATE_600HZ = 3;
BrickletCompass.BOOTLOADER_MODE_BOOTLOADER = 0;
BrickletCompass.BOOTLOADER_MODE_FIRMWARE = 1;
BrickletCompass.BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT = 2;
BrickletCompass.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT = 3;
BrickletCompass.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT = 4;
BrickletCompass.BOOTLOADER_STATUS_OK = 0;
BrickletCompass.BOOTLOADER_STATUS_INVALID_MODE = 1;
BrickletCompass.BOOTLOADER_STATUS_NO_CHANGE = 2;
BrickletCompass.BOOTLOADER_STATUS_ENTRY_FUNCTION_NOT_PRESENT = 3;
BrickletCompass.BOOTLOADER_STATUS_DEVICE_IDENTIFIER_INCORRECT = 4;
BrickletCompass.BOOTLOADER_STATUS_CRC_MISMATCH = 5;
BrickletCompass.STATUS_LED_CONFIG_OFF = 0;
BrickletCompass.STATUS_LED_CONFIG_ON = 1;
BrickletCompass.STATUS_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletCompass.STATUS_LED_CONFIG_SHOW_STATUS = 3;

function BrickletCompass(uid, ipcon) {
	//3-axis compass with 10 nanotesla and 0.1° resolution

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletCompass.DEVICE_IDENTIFIER, BrickletCompass.DEVICE_DISPLAY_NAME);
	BrickletCompass.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickletCompass.FUNCTION_GET_HEADING] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletCompass.FUNCTION_SET_HEADING_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletCompass.FUNCTION_GET_HEADING_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletCompass.FUNCTION_GET_MAGNETIC_FLUX_DENSITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletCompass.FUNCTION_SET_MAGNETIC_FLUX_DENSITY_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletCompass.FUNCTION_GET_MAGNETIC_FLUX_DENSITY_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletCompass.FUNCTION_SET_CONFIGURATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletCompass.FUNCTION_GET_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletCompass.FUNCTION_SET_CALIBRATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletCompass.FUNCTION_GET_CALIBRATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletCompass.FUNCTION_GET_SPITFP_ERROR_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletCompass.FUNCTION_SET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletCompass.FUNCTION_GET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletCompass.FUNCTION_SET_WRITE_FIRMWARE_POINTER] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletCompass.FUNCTION_WRITE_FIRMWARE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletCompass.FUNCTION_SET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletCompass.FUNCTION_GET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletCompass.FUNCTION_GET_CHIP_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletCompass.FUNCTION_RESET] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletCompass.FUNCTION_WRITE_UID] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletCompass.FUNCTION_READ_UID] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletCompass.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletCompass.CALLBACK_HEADING] = [10, 'h'];
	this.callbackFormats[BrickletCompass.CALLBACK_MAGNETIC_FLUX_DENSITY] = [20, 'i i i'];



	this.getHeading = function(returnCallback, errorCallback) {
		/*
		Returns the heading (north = 0 degree, east = 90 degree).
		
		Alternatively you can use :func:`Get Magnetic Flux Density` and calculate the
		heading with ``heading = atan2(y, x) * 180 / PI``.
		
		
		If you want to get the value periodically, it is recommended to use the
		:cb:`Heading` callback. You can set the callback configuration
		with :func:`Set Heading Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletCompass.FUNCTION_GET_HEADING, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.setHeadingCallbackConfiguration = function(period, valueHasToChange, option, min, max, returnCallback, errorCallback) {
		/*
		The period is the period with which the :cb:`Heading` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		If the `value has to change`-parameter is set to true, the callback is only
		triggered after the value has changed. If the value didn't change
		within the period, the callback is triggered immediately on change.
		
		If it is set to false, the callback is continuously triggered with the period,
		independent of the value.
		
		It is furthermore possible to constrain the callback with thresholds.
		
		The `option`-parameter together with min/max sets a threshold for the :cb:`Heading` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Threshold is turned off"
		 "'o'",    "Threshold is triggered when the value is *outside* the min and max values"
		 "'i'",    "Threshold is triggered when the value is *inside* or equal to the min and max values"
		 "'<'",    "Threshold is triggered when the value is smaller than the min value (max is ignored)"
		 "'>'",    "Threshold is triggered when the value is greater than the min value (max is ignored)"
		
		If the option is set to 'x' (threshold turned off) the callback is triggered with the fixed period.
		*/
		this.ipcon.sendRequest(this, BrickletCompass.FUNCTION_SET_HEADING_CALLBACK_CONFIGURATION, [period, valueHasToChange, option, min, max], 'I ? c h h', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getHeadingCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the callback configuration as set by :func:`Set Heading Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletCompass.FUNCTION_GET_HEADING_CALLBACK_CONFIGURATION, [], '', 18, 'I ? c h h', returnCallback, errorCallback, false, true);
	};
	this.getMagneticFluxDensity = function(returnCallback, errorCallback) {
		/*
		Returns the `magnetic flux density (magnetic induction) <https://en.wikipedia.org/wiki/Magnetic_flux>`__
		for all three axis.
		
		If you want to get the value periodically, it is recommended to use the
		:cb:`Magnetic Flux Density` callback. You can set the callback configuration
		with :func:`Set Magnetic Flux Density Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletCompass.FUNCTION_GET_MAGNETIC_FLUX_DENSITY, [], '', 20, 'i i i', returnCallback, errorCallback, false, true);
	};
	this.setMagneticFluxDensityCallbackConfiguration = function(period, valueHasToChange, returnCallback, errorCallback) {
		/*
		The period is the period with which the :cb:`Magnetic Flux Density` callback
		is triggered periodically. A value of 0 turns the callback off.
		
		If the `value has to change`-parameter is set to true, the callback is only
		triggered after the value has changed. If the value didn't change within the
		period, the callback is triggered immediately on change.
		
		If it is set to false, the callback is continuously triggered with the period,
		independent of the value.
		*/
		this.ipcon.sendRequest(this, BrickletCompass.FUNCTION_SET_MAGNETIC_FLUX_DENSITY_CALLBACK_CONFIGURATION, [period, valueHasToChange], 'I ?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getMagneticFluxDensityCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the callback configuration as set by
		:func:`Set Magnetic Flux Density Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletCompass.FUNCTION_GET_MAGNETIC_FLUX_DENSITY_CALLBACK_CONFIGURATION, [], '', 13, 'I ?', returnCallback, errorCallback, false, true);
	};
	this.setConfiguration = function(dataRate, backgroundCalibration, returnCallback, errorCallback) {
		/*
		Configures the data rate and background calibration.
		
		* Data Rate: Sets the data rate that is used by the magnetometer.
		  The lower the data rate, the lower is the noise on the data.
		* Background Calibration: Set to *true* to enable the background
		  calibration and *false* to turn it off. If the background calibration
		  is enabled the sensing polarity is flipped once per second to automatically
		  calculate and remove offset that is caused by temperature changes.
		  This polarity flipping takes about 20ms. This means that once a second
		  you will not get new data for a period of 20ms. We highly recommend that
		  you keep the background calibration enabled and only disable it if the 20ms
		  off-time is a problem in your application.
		*/
		this.ipcon.sendRequest(this, BrickletCompass.FUNCTION_SET_CONFIGURATION, [dataRate, backgroundCalibration], 'B ?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletCompass.FUNCTION_GET_CONFIGURATION, [], '', 10, 'B ?', returnCallback, errorCallback, false, true);
	};
	this.setCalibration = function(offset, gain, returnCallback, errorCallback) {
		/*
		Sets offset and gain for each of the three axes.
		
		The Bricklet is factory calibrated. If you want to re-calibrate the
		Bricklet we recommend that you do the calibration through Brick Viewer.
		
		The calibration is saved in non-volatile memory and only has to be
		done once.
		*/
		this.ipcon.sendRequest(this, BrickletCompass.FUNCTION_SET_CALIBRATION, [offset, gain], 'h3 h3', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getCalibration = function(returnCallback, errorCallback) {
		/*
		Returns the calibration parameters as set by :func:`Set Calibration`.
		*/
		this.ipcon.sendRequest(this, BrickletCompass.FUNCTION_GET_CALIBRATION, [], '', 20, 'h3 h3', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPErrorCount = function(returnCallback, errorCallback) {
		/*
		Returns the error count for the communication between Brick and Bricklet.
		
		The errors are divided into
		
		* ACK checksum errors,
		* message checksum errors,
		* framing errors and
		* overflow errors.
		
		The errors counts are for errors that occur on the Bricklet side. All
		Bricks have a similar function that returns the errors on the Brick side.
		*/
		this.ipcon.sendRequest(this, BrickletCompass.FUNCTION_GET_SPITFP_ERROR_COUNT, [], '', 24, 'I I I I', returnCallback, errorCallback, false, true);
	};
	this.setBootloaderMode = function(mode, returnCallback, errorCallback) {
		/*
		Sets the bootloader mode and returns the status after the requested
		mode change was instigated.
		
		You can change from bootloader mode to firmware mode and vice versa. A change
		from bootloader mode to firmware mode will only take place if the entry function,
		device identifier and CRC are present and correct.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletCompass.FUNCTION_SET_BOOTLOADER_MODE, [mode], 'B', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getBootloaderMode = function(returnCallback, errorCallback) {
		/*
		Returns the current bootloader mode, see :func:`Set Bootloader Mode`.
		*/
		this.ipcon.sendRequest(this, BrickletCompass.FUNCTION_GET_BOOTLOADER_MODE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setWriteFirmwarePointer = function(pointer, returnCallback, errorCallback) {
		/*
		Sets the firmware pointer for :func:`Write Firmware`. The pointer has
		to be increased by chunks of size 64. The data is written to flash
		every 4 chunks (which equals to one page of size 256).
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletCompass.FUNCTION_SET_WRITE_FIRMWARE_POINTER, [pointer], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeFirmware = function(data, returnCallback, errorCallback) {
		/*
		Writes 64 Bytes of firmware at the position as written by
		:func:`Set Write Firmware Pointer` before. The firmware is written
		to flash every 4 chunks.
		
		You can only write firmware in bootloader mode.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletCompass.FUNCTION_WRITE_FIRMWARE, [data], 'B64', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setStatusLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Sets the status LED configuration. By default the LED shows
		communication traffic between Brick and Bricklet, it flickers once
		for every 10 received data packets.
		
		You can also turn the LED permanently on/off or show a heartbeat.
		
		If the Bricklet is in bootloader mode, the LED is will show heartbeat by default.
		*/
		this.ipcon.sendRequest(this, BrickletCompass.FUNCTION_SET_STATUS_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getStatusLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Status LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletCompass.FUNCTION_GET_STATUS_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getChipTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature as measured inside the microcontroller. The
		value returned is not the ambient temperature!
		
		The temperature is only proportional to the real temperature and it has bad
		accuracy. Practically it is only useful as an indicator for
		temperature changes.
		*/
		this.ipcon.sendRequest(this, BrickletCompass.FUNCTION_GET_CHIP_TEMPERATURE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.reset = function(returnCallback, errorCallback) {
		/*
		Calling this function will reset the Bricklet. All configurations
		will be lost.
		
		After a reset you have to create new device objects,
		calling functions on the existing ones will result in
		undefined behavior!
		*/
		this.ipcon.sendRequest(this, BrickletCompass.FUNCTION_RESET, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeUID = function(uid, returnCallback, errorCallback) {
		/*
		Writes a new UID into flash. If you want to set a new UID
		you have to decode the Base58 encoded UID string into an
		integer first.
		
		We recommend that you use Brick Viewer to change the UID.
		*/
		this.ipcon.sendRequest(this, BrickletCompass.FUNCTION_WRITE_UID, [uid], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.readUID = function(returnCallback, errorCallback) {
		/*
		Returns the current UID as an integer. Encode as
		Base58 to get the usual string version.
		*/
		this.ipcon.sendRequest(this, BrickletCompass.FUNCTION_READ_UID, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletCompass.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletCompass;

},{"./Device":279,"./IPConnection":280}],168:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletCurrent12.DEVICE_IDENTIFIER = 23;
BrickletCurrent12.DEVICE_DISPLAY_NAME = 'Current12 Bricklet';
BrickletCurrent12.CALLBACK_CURRENT = 15;
BrickletCurrent12.CALLBACK_ANALOG_VALUE = 16;
BrickletCurrent12.CALLBACK_CURRENT_REACHED = 17;
BrickletCurrent12.CALLBACK_ANALOG_VALUE_REACHED = 18;
BrickletCurrent12.CALLBACK_OVER_CURRENT = 19;
BrickletCurrent12.FUNCTION_GET_CURRENT = 1;
BrickletCurrent12.FUNCTION_CALIBRATE = 2;
BrickletCurrent12.FUNCTION_IS_OVER_CURRENT = 3;
BrickletCurrent12.FUNCTION_GET_ANALOG_VALUE = 4;
BrickletCurrent12.FUNCTION_SET_CURRENT_CALLBACK_PERIOD = 5;
BrickletCurrent12.FUNCTION_GET_CURRENT_CALLBACK_PERIOD = 6;
BrickletCurrent12.FUNCTION_SET_ANALOG_VALUE_CALLBACK_PERIOD = 7;
BrickletCurrent12.FUNCTION_GET_ANALOG_VALUE_CALLBACK_PERIOD = 8;
BrickletCurrent12.FUNCTION_SET_CURRENT_CALLBACK_THRESHOLD = 9;
BrickletCurrent12.FUNCTION_GET_CURRENT_CALLBACK_THRESHOLD = 10;
BrickletCurrent12.FUNCTION_SET_ANALOG_VALUE_CALLBACK_THRESHOLD = 11;
BrickletCurrent12.FUNCTION_GET_ANALOG_VALUE_CALLBACK_THRESHOLD = 12;
BrickletCurrent12.FUNCTION_SET_DEBOUNCE_PERIOD = 13;
BrickletCurrent12.FUNCTION_GET_DEBOUNCE_PERIOD = 14;
BrickletCurrent12.FUNCTION_GET_IDENTITY = 255;
BrickletCurrent12.THRESHOLD_OPTION_OFF = 'x';
BrickletCurrent12.THRESHOLD_OPTION_OUTSIDE = 'o';
BrickletCurrent12.THRESHOLD_OPTION_INSIDE = 'i';
BrickletCurrent12.THRESHOLD_OPTION_SMALLER = '<';
BrickletCurrent12.THRESHOLD_OPTION_GREATER = '>';

function BrickletCurrent12(uid, ipcon) {
	//Measures AC/DC current between -12.5A and +12.5A

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletCurrent12.DEVICE_IDENTIFIER, BrickletCurrent12.DEVICE_DISPLAY_NAME);
	BrickletCurrent12.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickletCurrent12.FUNCTION_GET_CURRENT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletCurrent12.FUNCTION_CALIBRATE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletCurrent12.FUNCTION_IS_OVER_CURRENT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletCurrent12.FUNCTION_GET_ANALOG_VALUE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletCurrent12.FUNCTION_SET_CURRENT_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletCurrent12.FUNCTION_GET_CURRENT_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletCurrent12.FUNCTION_SET_ANALOG_VALUE_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletCurrent12.FUNCTION_GET_ANALOG_VALUE_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletCurrent12.FUNCTION_SET_CURRENT_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletCurrent12.FUNCTION_GET_CURRENT_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletCurrent12.FUNCTION_SET_ANALOG_VALUE_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletCurrent12.FUNCTION_GET_ANALOG_VALUE_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletCurrent12.FUNCTION_SET_DEBOUNCE_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletCurrent12.FUNCTION_GET_DEBOUNCE_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletCurrent12.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletCurrent12.CALLBACK_CURRENT] = [10, 'h'];
	this.callbackFormats[BrickletCurrent12.CALLBACK_ANALOG_VALUE] = [10, 'H'];
	this.callbackFormats[BrickletCurrent12.CALLBACK_CURRENT_REACHED] = [10, 'h'];
	this.callbackFormats[BrickletCurrent12.CALLBACK_ANALOG_VALUE_REACHED] = [10, 'H'];
	this.callbackFormats[BrickletCurrent12.CALLBACK_OVER_CURRENT] = [8, ''];



	this.getCurrent = function(returnCallback, errorCallback) {
		/*
		Returns the current of the sensor.
		
		If you want to get the current periodically, it is recommended to use the
		:cb:`Current` callback and set the period with
		:func:`Set Current Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletCurrent12.FUNCTION_GET_CURRENT, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.calibrate = function(returnCallback, errorCallback) {
		/*
		Calibrates the 0 value of the sensor. You have to call this function
		when there is no current present.
		
		The zero point of the current sensor
		is depending on the exact properties of the analog-to-digital converter,
		the length of the Bricklet cable and the temperature. Thus, if you change
		the Brick or the environment in which the Bricklet is used, you might
		have to recalibrate.
		
		The resulting calibration will be saved on the EEPROM of the Current
		Bricklet.
		*/
		this.ipcon.sendRequest(this, BrickletCurrent12.FUNCTION_CALIBRATE, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.isOverCurrent = function(returnCallback, errorCallback) {
		/*
		Returns *true* if more than 12.5A were measured.
		
		.. note::
		 To reset this value you have to power cycle the Bricklet.
		*/
		this.ipcon.sendRequest(this, BrickletCurrent12.FUNCTION_IS_OVER_CURRENT, [], '', 9, '?', returnCallback, errorCallback, false, true);
	};
	this.getAnalogValue = function(returnCallback, errorCallback) {
		/*
		Returns the value as read by a 12-bit analog-to-digital converter.
		
		.. note::
		 The value returned by :func:`Get Current` is averaged over several samples
		 to yield less noise, while :func:`Get Analog Value` gives back raw
		 unfiltered analog values. The only reason to use :func:`Get Analog Value` is,
		 if you need the full resolution of the analog-to-digital converter.
		
		If you want the analog value periodically, it is recommended to use the
		:cb:`Analog Value` callback and set the period with
		:func:`Set Analog Value Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletCurrent12.FUNCTION_GET_ANALOG_VALUE, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.setCurrentCallbackPeriod = function(period, returnCallback, errorCallback) {
		/*
		Sets the period with which the :cb:`Current` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		The :cb:`Current` callback is only triggered if the current has changed since
		the last triggering.
		*/
		this.ipcon.sendRequest(this, BrickletCurrent12.FUNCTION_SET_CURRENT_CALLBACK_PERIOD, [period], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getCurrentCallbackPeriod = function(returnCallback, errorCallback) {
		/*
		Returns the period as set by :func:`Set Current Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletCurrent12.FUNCTION_GET_CURRENT_CALLBACK_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setAnalogValueCallbackPeriod = function(period, returnCallback, errorCallback) {
		/*
		Sets the period with which the :cb:`Analog Value` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		The :cb:`Analog Value` callback is only triggered if the analog value has
		changed since the last triggering.
		*/
		this.ipcon.sendRequest(this, BrickletCurrent12.FUNCTION_SET_ANALOG_VALUE_CALLBACK_PERIOD, [period], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getAnalogValueCallbackPeriod = function(returnCallback, errorCallback) {
		/*
		Returns the period as set by :func:`Set Analog Value Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletCurrent12.FUNCTION_GET_ANALOG_VALUE_CALLBACK_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setCurrentCallbackThreshold = function(option, min, max, returnCallback, errorCallback) {
		/*
		Sets the thresholds for the :cb:`Current Reached` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Callback is turned off"
		 "'o'",    "Callback is triggered when the current is *outside* the min and max values"
		 "'i'",    "Callback is triggered when the current is *inside* the min and max values"
		 "'<'",    "Callback is triggered when the current is smaller than the min value (max is ignored)"
		 "'>'",    "Callback is triggered when the current is greater than the min value (max is ignored)"
		*/
		this.ipcon.sendRequest(this, BrickletCurrent12.FUNCTION_SET_CURRENT_CALLBACK_THRESHOLD, [option, min, max], 'c h h', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getCurrentCallbackThreshold = function(returnCallback, errorCallback) {
		/*
		Returns the threshold as set by :func:`Set Current Callback Threshold`.
		*/
		this.ipcon.sendRequest(this, BrickletCurrent12.FUNCTION_GET_CURRENT_CALLBACK_THRESHOLD, [], '', 13, 'c h h', returnCallback, errorCallback, false, true);
	};
	this.setAnalogValueCallbackThreshold = function(option, min, max, returnCallback, errorCallback) {
		/*
		Sets the thresholds for the :cb:`Analog Value Reached` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Callback is turned off"
		 "'o'",    "Callback is triggered when the analog value is *outside* the min and max values"
		 "'i'",    "Callback is triggered when the analog value is *inside* the min and max values"
		 "'<'",    "Callback is triggered when the analog value is smaller than the min value (max is ignored)"
		 "'>'",    "Callback is triggered when the analog value is greater than the min value (max is ignored)"
		*/
		this.ipcon.sendRequest(this, BrickletCurrent12.FUNCTION_SET_ANALOG_VALUE_CALLBACK_THRESHOLD, [option, min, max], 'c H H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getAnalogValueCallbackThreshold = function(returnCallback, errorCallback) {
		/*
		Returns the threshold as set by :func:`Set Analog Value Callback Threshold`.
		*/
		this.ipcon.sendRequest(this, BrickletCurrent12.FUNCTION_GET_ANALOG_VALUE_CALLBACK_THRESHOLD, [], '', 13, 'c H H', returnCallback, errorCallback, false, true);
	};
	this.setDebouncePeriod = function(debounce, returnCallback, errorCallback) {
		/*
		Sets the period with which the threshold callbacks
		
		* :cb:`Current Reached`,
		* :cb:`Analog Value Reached`
		
		are triggered, if the thresholds
		
		* :func:`Set Current Callback Threshold`,
		* :func:`Set Analog Value Callback Threshold`
		
		keep being reached.
		*/
		this.ipcon.sendRequest(this, BrickletCurrent12.FUNCTION_SET_DEBOUNCE_PERIOD, [debounce], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getDebouncePeriod = function(returnCallback, errorCallback) {
		/*
		Returns the debounce period as set by :func:`Set Debounce Period`.
		*/
		this.ipcon.sendRequest(this, BrickletCurrent12.FUNCTION_GET_DEBOUNCE_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletCurrent12.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletCurrent12;

},{"./Device":279,"./IPConnection":280}],169:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletCurrent25.DEVICE_IDENTIFIER = 24;
BrickletCurrent25.DEVICE_DISPLAY_NAME = 'Current25 Bricklet';
BrickletCurrent25.CALLBACK_CURRENT = 15;
BrickletCurrent25.CALLBACK_ANALOG_VALUE = 16;
BrickletCurrent25.CALLBACK_CURRENT_REACHED = 17;
BrickletCurrent25.CALLBACK_ANALOG_VALUE_REACHED = 18;
BrickletCurrent25.CALLBACK_OVER_CURRENT = 19;
BrickletCurrent25.FUNCTION_GET_CURRENT = 1;
BrickletCurrent25.FUNCTION_CALIBRATE = 2;
BrickletCurrent25.FUNCTION_IS_OVER_CURRENT = 3;
BrickletCurrent25.FUNCTION_GET_ANALOG_VALUE = 4;
BrickletCurrent25.FUNCTION_SET_CURRENT_CALLBACK_PERIOD = 5;
BrickletCurrent25.FUNCTION_GET_CURRENT_CALLBACK_PERIOD = 6;
BrickletCurrent25.FUNCTION_SET_ANALOG_VALUE_CALLBACK_PERIOD = 7;
BrickletCurrent25.FUNCTION_GET_ANALOG_VALUE_CALLBACK_PERIOD = 8;
BrickletCurrent25.FUNCTION_SET_CURRENT_CALLBACK_THRESHOLD = 9;
BrickletCurrent25.FUNCTION_GET_CURRENT_CALLBACK_THRESHOLD = 10;
BrickletCurrent25.FUNCTION_SET_ANALOG_VALUE_CALLBACK_THRESHOLD = 11;
BrickletCurrent25.FUNCTION_GET_ANALOG_VALUE_CALLBACK_THRESHOLD = 12;
BrickletCurrent25.FUNCTION_SET_DEBOUNCE_PERIOD = 13;
BrickletCurrent25.FUNCTION_GET_DEBOUNCE_PERIOD = 14;
BrickletCurrent25.FUNCTION_GET_IDENTITY = 255;
BrickletCurrent25.THRESHOLD_OPTION_OFF = 'x';
BrickletCurrent25.THRESHOLD_OPTION_OUTSIDE = 'o';
BrickletCurrent25.THRESHOLD_OPTION_INSIDE = 'i';
BrickletCurrent25.THRESHOLD_OPTION_SMALLER = '<';
BrickletCurrent25.THRESHOLD_OPTION_GREATER = '>';

function BrickletCurrent25(uid, ipcon) {
	//Measures AC/DC current between -25A and +25A

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletCurrent25.DEVICE_IDENTIFIER, BrickletCurrent25.DEVICE_DISPLAY_NAME);
	BrickletCurrent25.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickletCurrent25.FUNCTION_GET_CURRENT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletCurrent25.FUNCTION_CALIBRATE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletCurrent25.FUNCTION_IS_OVER_CURRENT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletCurrent25.FUNCTION_GET_ANALOG_VALUE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletCurrent25.FUNCTION_SET_CURRENT_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletCurrent25.FUNCTION_GET_CURRENT_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletCurrent25.FUNCTION_SET_ANALOG_VALUE_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletCurrent25.FUNCTION_GET_ANALOG_VALUE_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletCurrent25.FUNCTION_SET_CURRENT_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletCurrent25.FUNCTION_GET_CURRENT_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletCurrent25.FUNCTION_SET_ANALOG_VALUE_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletCurrent25.FUNCTION_GET_ANALOG_VALUE_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletCurrent25.FUNCTION_SET_DEBOUNCE_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletCurrent25.FUNCTION_GET_DEBOUNCE_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletCurrent25.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletCurrent25.CALLBACK_CURRENT] = [10, 'h'];
	this.callbackFormats[BrickletCurrent25.CALLBACK_ANALOG_VALUE] = [10, 'H'];
	this.callbackFormats[BrickletCurrent25.CALLBACK_CURRENT_REACHED] = [10, 'h'];
	this.callbackFormats[BrickletCurrent25.CALLBACK_ANALOG_VALUE_REACHED] = [10, 'H'];
	this.callbackFormats[BrickletCurrent25.CALLBACK_OVER_CURRENT] = [8, ''];



	this.getCurrent = function(returnCallback, errorCallback) {
		/*
		Returns the current of the sensor.
		
		If you want to get the current periodically, it is recommended to use the
		:cb:`Current` callback and set the period with
		:func:`Set Current Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletCurrent25.FUNCTION_GET_CURRENT, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.calibrate = function(returnCallback, errorCallback) {
		/*
		Calibrates the 0 value of the sensor. You have to call this function
		when there is no current present.
		
		The zero point of the current sensor
		is depending on the exact properties of the analog-to-digital converter,
		the length of the Bricklet cable and the temperature. Thus, if you change
		the Brick or the environment in which the Bricklet is used, you might
		have to recalibrate.
		
		The resulting calibration will be saved on the EEPROM of the Current
		Bricklet.
		*/
		this.ipcon.sendRequest(this, BrickletCurrent25.FUNCTION_CALIBRATE, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.isOverCurrent = function(returnCallback, errorCallback) {
		/*
		Returns *true* if more than 25A were measured.
		
		.. note::
		 To reset this value you have to power cycle the Bricklet.
		*/
		this.ipcon.sendRequest(this, BrickletCurrent25.FUNCTION_IS_OVER_CURRENT, [], '', 9, '?', returnCallback, errorCallback, false, true);
	};
	this.getAnalogValue = function(returnCallback, errorCallback) {
		/*
		Returns the value as read by a 12-bit analog-to-digital converter.
		
		.. note::
		 The value returned by :func:`Get Current` is averaged over several samples
		 to yield less noise, while :func:`Get Analog Value` gives back raw
		 unfiltered analog values. The only reason to use :func:`Get Analog Value` is,
		 if you need the full resolution of the analog-to-digital converter.
		
		If you want the analog value periodically, it is recommended to use the
		:cb:`Analog Value` callback and set the period with
		:func:`Set Analog Value Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletCurrent25.FUNCTION_GET_ANALOG_VALUE, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.setCurrentCallbackPeriod = function(period, returnCallback, errorCallback) {
		/*
		Sets the period with which the :cb:`Current` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		The :cb:`Current` callback is only triggered if the current has changed since
		the last triggering.
		*/
		this.ipcon.sendRequest(this, BrickletCurrent25.FUNCTION_SET_CURRENT_CALLBACK_PERIOD, [period], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getCurrentCallbackPeriod = function(returnCallback, errorCallback) {
		/*
		Returns the period as set by :func:`Set Current Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletCurrent25.FUNCTION_GET_CURRENT_CALLBACK_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setAnalogValueCallbackPeriod = function(period, returnCallback, errorCallback) {
		/*
		Sets the period with which the :cb:`Analog Value` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		The :cb:`Analog Value` callback is only triggered if the analog value has
		changed since the last triggering.
		*/
		this.ipcon.sendRequest(this, BrickletCurrent25.FUNCTION_SET_ANALOG_VALUE_CALLBACK_PERIOD, [period], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getAnalogValueCallbackPeriod = function(returnCallback, errorCallback) {
		/*
		Returns the period as set by :func:`Set Analog Value Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletCurrent25.FUNCTION_GET_ANALOG_VALUE_CALLBACK_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setCurrentCallbackThreshold = function(option, min, max, returnCallback, errorCallback) {
		/*
		Sets the thresholds for the :cb:`Current Reached` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Callback is turned off"
		 "'o'",    "Callback is triggered when the current is *outside* the min and max values"
		 "'i'",    "Callback is triggered when the current is *inside* the min and max values"
		 "'<'",    "Callback is triggered when the current is smaller than the min value (max is ignored)"
		 "'>'",    "Callback is triggered when the current is greater than the min value (max is ignored)"
		*/
		this.ipcon.sendRequest(this, BrickletCurrent25.FUNCTION_SET_CURRENT_CALLBACK_THRESHOLD, [option, min, max], 'c h h', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getCurrentCallbackThreshold = function(returnCallback, errorCallback) {
		/*
		Returns the threshold as set by :func:`Set Current Callback Threshold`.
		*/
		this.ipcon.sendRequest(this, BrickletCurrent25.FUNCTION_GET_CURRENT_CALLBACK_THRESHOLD, [], '', 13, 'c h h', returnCallback, errorCallback, false, true);
	};
	this.setAnalogValueCallbackThreshold = function(option, min, max, returnCallback, errorCallback) {
		/*
		Sets the thresholds for the :cb:`Analog Value Reached` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Callback is turned off"
		 "'o'",    "Callback is triggered when the analog value is *outside* the min and max values"
		 "'i'",    "Callback is triggered when the analog value is *inside* the min and max values"
		 "'<'",    "Callback is triggered when the analog value is smaller than the min value (max is ignored)"
		 "'>'",    "Callback is triggered when the analog value is greater than the min value (max is ignored)"
		*/
		this.ipcon.sendRequest(this, BrickletCurrent25.FUNCTION_SET_ANALOG_VALUE_CALLBACK_THRESHOLD, [option, min, max], 'c H H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getAnalogValueCallbackThreshold = function(returnCallback, errorCallback) {
		/*
		Returns the threshold as set by :func:`Set Analog Value Callback Threshold`.
		*/
		this.ipcon.sendRequest(this, BrickletCurrent25.FUNCTION_GET_ANALOG_VALUE_CALLBACK_THRESHOLD, [], '', 13, 'c H H', returnCallback, errorCallback, false, true);
	};
	this.setDebouncePeriod = function(debounce, returnCallback, errorCallback) {
		/*
		Sets the period with which the threshold callbacks
		
		* :cb:`Current Reached`,
		* :cb:`Analog Value Reached`
		
		are triggered, if the thresholds
		
		* :func:`Set Current Callback Threshold`,
		* :func:`Set Analog Value Callback Threshold`
		
		keep being reached.
		*/
		this.ipcon.sendRequest(this, BrickletCurrent25.FUNCTION_SET_DEBOUNCE_PERIOD, [debounce], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getDebouncePeriod = function(returnCallback, errorCallback) {
		/*
		Returns the debounce period as set by :func:`Set Debounce Period`.
		*/
		this.ipcon.sendRequest(this, BrickletCurrent25.FUNCTION_GET_DEBOUNCE_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletCurrent25.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletCurrent25;

},{"./Device":279,"./IPConnection":280}],170:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletDMX.DEVICE_IDENTIFIER = 285;
BrickletDMX.DEVICE_DISPLAY_NAME = 'DMX Bricklet';
BrickletDMX.CALLBACK_FRAME_STARTED = 14;
BrickletDMX.CALLBACK_FRAME_AVAILABLE = 15;
BrickletDMX.CALLBACK_FRAME_LOW_LEVEL = 16;
BrickletDMX.CALLBACK_FRAME_ERROR_COUNT = 17;
BrickletDMX.CALLBACK_FRAME = -16;
BrickletDMX.FUNCTION_SET_DMX_MODE = 1;
BrickletDMX.FUNCTION_GET_DMX_MODE = 2;
BrickletDMX.FUNCTION_WRITE_FRAME_LOW_LEVEL = 3;
BrickletDMX.FUNCTION_READ_FRAME_LOW_LEVEL = 4;
BrickletDMX.FUNCTION_SET_FRAME_DURATION = 5;
BrickletDMX.FUNCTION_GET_FRAME_DURATION = 6;
BrickletDMX.FUNCTION_GET_FRAME_ERROR_COUNT = 7;
BrickletDMX.FUNCTION_SET_COMMUNICATION_LED_CONFIG = 8;
BrickletDMX.FUNCTION_GET_COMMUNICATION_LED_CONFIG = 9;
BrickletDMX.FUNCTION_SET_ERROR_LED_CONFIG = 10;
BrickletDMX.FUNCTION_GET_ERROR_LED_CONFIG = 11;
BrickletDMX.FUNCTION_SET_FRAME_CALLBACK_CONFIG = 12;
BrickletDMX.FUNCTION_GET_FRAME_CALLBACK_CONFIG = 13;
BrickletDMX.FUNCTION_GET_SPITFP_ERROR_COUNT = 234;
BrickletDMX.FUNCTION_SET_BOOTLOADER_MODE = 235;
BrickletDMX.FUNCTION_GET_BOOTLOADER_MODE = 236;
BrickletDMX.FUNCTION_SET_WRITE_FIRMWARE_POINTER = 237;
BrickletDMX.FUNCTION_WRITE_FIRMWARE = 238;
BrickletDMX.FUNCTION_SET_STATUS_LED_CONFIG = 239;
BrickletDMX.FUNCTION_GET_STATUS_LED_CONFIG = 240;
BrickletDMX.FUNCTION_GET_CHIP_TEMPERATURE = 242;
BrickletDMX.FUNCTION_RESET = 243;
BrickletDMX.FUNCTION_WRITE_UID = 248;
BrickletDMX.FUNCTION_READ_UID = 249;
BrickletDMX.FUNCTION_GET_IDENTITY = 255;
BrickletDMX.DMX_MODE_MASTER = 0;
BrickletDMX.DMX_MODE_SLAVE = 1;
BrickletDMX.COMMUNICATION_LED_CONFIG_OFF = 0;
BrickletDMX.COMMUNICATION_LED_CONFIG_ON = 1;
BrickletDMX.COMMUNICATION_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletDMX.COMMUNICATION_LED_CONFIG_SHOW_COMMUNICATION = 3;
BrickletDMX.ERROR_LED_CONFIG_OFF = 0;
BrickletDMX.ERROR_LED_CONFIG_ON = 1;
BrickletDMX.ERROR_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletDMX.ERROR_LED_CONFIG_SHOW_ERROR = 3;
BrickletDMX.BOOTLOADER_MODE_BOOTLOADER = 0;
BrickletDMX.BOOTLOADER_MODE_FIRMWARE = 1;
BrickletDMX.BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT = 2;
BrickletDMX.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT = 3;
BrickletDMX.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT = 4;
BrickletDMX.BOOTLOADER_STATUS_OK = 0;
BrickletDMX.BOOTLOADER_STATUS_INVALID_MODE = 1;
BrickletDMX.BOOTLOADER_STATUS_NO_CHANGE = 2;
BrickletDMX.BOOTLOADER_STATUS_ENTRY_FUNCTION_NOT_PRESENT = 3;
BrickletDMX.BOOTLOADER_STATUS_DEVICE_IDENTIFIER_INCORRECT = 4;
BrickletDMX.BOOTLOADER_STATUS_CRC_MISMATCH = 5;
BrickletDMX.STATUS_LED_CONFIG_OFF = 0;
BrickletDMX.STATUS_LED_CONFIG_ON = 1;
BrickletDMX.STATUS_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletDMX.STATUS_LED_CONFIG_SHOW_STATUS = 3;

function BrickletDMX(uid, ipcon) {
	//DMX master and slave

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletDMX.DEVICE_IDENTIFIER, BrickletDMX.DEVICE_DISPLAY_NAME);
	BrickletDMX.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickletDMX.FUNCTION_SET_DMX_MODE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletDMX.FUNCTION_GET_DMX_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletDMX.FUNCTION_WRITE_FRAME_LOW_LEVEL] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletDMX.FUNCTION_READ_FRAME_LOW_LEVEL] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletDMX.FUNCTION_SET_FRAME_DURATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletDMX.FUNCTION_GET_FRAME_DURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletDMX.FUNCTION_GET_FRAME_ERROR_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletDMX.FUNCTION_SET_COMMUNICATION_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletDMX.FUNCTION_GET_COMMUNICATION_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletDMX.FUNCTION_SET_ERROR_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletDMX.FUNCTION_GET_ERROR_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletDMX.FUNCTION_SET_FRAME_CALLBACK_CONFIG] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletDMX.FUNCTION_GET_FRAME_CALLBACK_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletDMX.FUNCTION_GET_SPITFP_ERROR_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletDMX.FUNCTION_SET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletDMX.FUNCTION_GET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletDMX.FUNCTION_SET_WRITE_FIRMWARE_POINTER] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletDMX.FUNCTION_WRITE_FIRMWARE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletDMX.FUNCTION_SET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletDMX.FUNCTION_GET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletDMX.FUNCTION_GET_CHIP_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletDMX.FUNCTION_RESET] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletDMX.FUNCTION_WRITE_UID] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletDMX.FUNCTION_READ_UID] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletDMX.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletDMX.CALLBACK_FRAME_STARTED] = [8, ''];
	this.callbackFormats[BrickletDMX.CALLBACK_FRAME_AVAILABLE] = [12, 'I'];
	this.callbackFormats[BrickletDMX.CALLBACK_FRAME_LOW_LEVEL] = [72, 'H H B56 I'];
	this.callbackFormats[BrickletDMX.CALLBACK_FRAME_ERROR_COUNT] = [16, 'I I'];

	this.highLevelCallbacks[BrickletDMX.CALLBACK_FRAME] = [['streamLength', 'streamChunkOffset', 'streamChunkData', null], {'fixedLength': null, 'singleChunk': false}, null];

	this.streamStateObjects[BrickletDMX.FUNCTION_WRITE_FRAME_LOW_LEVEL] = {
		'dataMapping': [],
		'dataMappingStreamIn': ['streamLength', 'streamChunkOffset', 'streamChunkData'],
		'streamProperties': {
			'fixedLength': null,
			'singleChunk': false,
			'shortWrite': false
		},
		'responseProperties': {
			'running': false,
			'runningSubcall': false,
			'runningSubcallOOS': false,
			'waitingFirstChunk': true,
			'timeout': null,
			'data': [],
			'streamInChunkOffset': 0,
			'streamInChunkLength': 0,
			'streamInResponseEmpty': true,
			'streamInWritten': 0,
			'streamInLLParams': null,
			'responseHandler': null,
			'packFormatString': 'H H B60',
			'unpackFormatString': '',
			'returnCB': null,
			'errorCB': null,
			'callQueue': []
		}
	};
	this.streamStateObjects[BrickletDMX.FUNCTION_READ_FRAME_LOW_LEVEL] = {
		'dataMapping': ['streamLength', 'streamChunkOffset', 'streamChunkData', null],
		'dataMappingStreamIn': [],
		'streamProperties': {
			'fixedLength': null,
			'singleChunk': false,
			'shortWrite': false
		},
		'responseProperties': {
			'running': false,
			'runningSubcall': false,
			'runningSubcallOOS': false,
			'waitingFirstChunk': true,
			'timeout': null,
			'data': [],
			'streamInChunkOffset': 0,
			'streamInChunkLength': 0,
			'streamInResponseEmpty': true,
			'streamInWritten': 0,
			'streamInLLParams': null,
			'responseHandler': null,
			'packFormatString': '',
			'unpackFormatString': 'H H B56 I',
			'returnCB': null,
			'errorCB': null,
			'callQueue': []
		}
	};

	this.setDMXMode = function(dmxMode, returnCallback, errorCallback) {
		/*
		Sets the DMX mode to either master or slave.
		
		Calling this function sets frame number to 0.
		*/
		this.ipcon.sendRequest(this, BrickletDMX.FUNCTION_SET_DMX_MODE, [dmxMode], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getDMXMode = function(returnCallback, errorCallback) {
		/*
		Returns the DMX mode, as set by :func:`Set DMX Mode`.
		*/
		this.ipcon.sendRequest(this, BrickletDMX.FUNCTION_GET_DMX_MODE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.writeFrameLowLevel = function(frameLength, frameChunkOffset, frameChunkData, returnCallback, errorCallback) {
		/*
		Writes a DMX frame. The maximum frame size is 512 byte. Each byte represents one channel.
		
		The next frame can be written after the :cb:`Frame Started` callback was called. The frame
		is double buffered, so a new frame can be written as soon as the writing of the prior frame
		starts.
		
		The data will be transfered when the next frame duration ends, see :func:`Set Frame Duration`.
		
		Generic approach:
		
		* Set the frame duration to a value that represents the number of frames per second you want to achieve.
		* Set channels for first frame.
		* Wait for the :cb:`Frame Started` callback.
		* Set channels for next frame.
		* Wait for the :cb:`Frame Started` callback.
		* and so on.
		
		This approach ensures that you can set new DMX data with a fixed frame rate.
		
		This function can only be called in master mode.
		*/
		this.ipcon.sendRequest(this, BrickletDMX.FUNCTION_WRITE_FRAME_LOW_LEVEL, [frameLength, frameChunkOffset, frameChunkData], 'H H B60', 0, '', returnCallback, errorCallback, false, true);
	};
	this.readFrameLowLevel = function(returnCallback, errorCallback) {
		/*
		Returns the last frame that was written by the DMX master. The size of the array
		is equivalent to the number of channels in the frame. Each byte represents one channel.
		
		The next frame is available after the :cb:`Frame Available` callback was called.
		
		Generic approach:
		
		* Call :func:`Read Frame` to get first frame.
		* Wait for the :cb:`Frame Available` callback.
		* Call :func:`Read Frame` to get second frame.
		* Wait for the :cb:`Frame Available` callback.
		* and so on.
		
		Instead of polling this function you can also use the :cb:`Frame` callback.
		You can enable it with :func:`Set Frame Callback Config`.
		
		The frame number starts at 0 and it is increased by one with each received frame.
		
		This function can only be called in slave mode.
		*/
		this.ipcon.sendRequest(this, BrickletDMX.FUNCTION_READ_FRAME_LOW_LEVEL, [], '', 72, 'H H B56 I', returnCallback, errorCallback, false, true);
	};
	this.setFrameDuration = function(frameDuration, returnCallback, errorCallback) {
		/*
		Sets the duration of a frame.
		
		Example: If you want to achieve 20 frames per second, you should
		set the frame duration to 50ms (50ms * 20 = 1 second).
		
		If you always want to send a frame as fast as possible you can set
		this value to 0.
		
		This setting is only used in master mode.
		*/
		this.ipcon.sendRequest(this, BrickletDMX.FUNCTION_SET_FRAME_DURATION, [frameDuration], 'H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getFrameDuration = function(returnCallback, errorCallback) {
		/*
		Returns the frame duration as set by :func:`Set Frame Duration`.
		*/
		this.ipcon.sendRequest(this, BrickletDMX.FUNCTION_GET_FRAME_DURATION, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.getFrameErrorCount = function(returnCallback, errorCallback) {
		/*
		Returns the current number of overrun and framing errors.
		*/
		this.ipcon.sendRequest(this, BrickletDMX.FUNCTION_GET_FRAME_ERROR_COUNT, [], '', 16, 'I I', returnCallback, errorCallback, false, true);
	};
	this.setCommunicationLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Sets the communication LED configuration. By default the LED shows
		communication traffic, it flickers once for every 10 received data packets.
		
		You can also turn the LED permanently on/off or show a heartbeat.
		
		If the Bricklet is in bootloader mode, the LED is off.
		*/
		this.ipcon.sendRequest(this, BrickletDMX.FUNCTION_SET_COMMUNICATION_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getCommunicationLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Communication LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletDMX.FUNCTION_GET_COMMUNICATION_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setErrorLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Sets the error LED configuration.
		
		By default the error LED turns on if there is any error (see :cb:`Frame Error Count`
		callback). If you call this function with the Show-Error option again, the LED
		will turn off until the next error occurs.
		
		You can also turn the LED permanently on/off or show a heartbeat.
		
		If the Bricklet is in bootloader mode, the LED is off.
		*/
		this.ipcon.sendRequest(this, BrickletDMX.FUNCTION_SET_ERROR_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getErrorLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Error LED Config`.
		*/
		this.ipcon.sendRequest(this, BrickletDMX.FUNCTION_GET_ERROR_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setFrameCallbackConfig = function(frameStartedCallbackEnabled, frameAvailableCallbackEnabled, frameCallbackEnabled, frameErrorCountCallbackEnabled, returnCallback, errorCallback) {
		/*
		Enables/Disables the different callbacks. By default the
		:cb:`Frame Started` callback and :cb:`Frame Available` callback are enabled while
		the :cb:`Frame` callback and :cb:`Frame Error Count` callback are disabled.
		
		If you want to use the :cb:`Frame` callback you can enable it and disable
		the cb:`Frame Available` callback at the same time. It becomes redundant in
		this case.
		*/
		this.ipcon.sendRequest(this, BrickletDMX.FUNCTION_SET_FRAME_CALLBACK_CONFIG, [frameStartedCallbackEnabled, frameAvailableCallbackEnabled, frameCallbackEnabled, frameErrorCountCallbackEnabled], '? ? ? ?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getFrameCallbackConfig = function(returnCallback, errorCallback) {
		/*
		Returns the frame callback config as set by :func:`Set Frame Callback Config`.
		*/
		this.ipcon.sendRequest(this, BrickletDMX.FUNCTION_GET_FRAME_CALLBACK_CONFIG, [], '', 12, '? ? ? ?', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPErrorCount = function(returnCallback, errorCallback) {
		/*
		Returns the error count for the communication between Brick and Bricklet.
		
		The errors are divided into
		
		* ACK checksum errors,
		* message checksum errors,
		* framing errors and
		* overflow errors.
		
		The errors counts are for errors that occur on the Bricklet side. All
		Bricks have a similar function that returns the errors on the Brick side.
		*/
		this.ipcon.sendRequest(this, BrickletDMX.FUNCTION_GET_SPITFP_ERROR_COUNT, [], '', 24, 'I I I I', returnCallback, errorCallback, false, true);
	};
	this.setBootloaderMode = function(mode, returnCallback, errorCallback) {
		/*
		Sets the bootloader mode and returns the status after the requested
		mode change was instigated.
		
		You can change from bootloader mode to firmware mode and vice versa. A change
		from bootloader mode to firmware mode will only take place if the entry function,
		device identifier and CRC are present and correct.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletDMX.FUNCTION_SET_BOOTLOADER_MODE, [mode], 'B', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getBootloaderMode = function(returnCallback, errorCallback) {
		/*
		Returns the current bootloader mode, see :func:`Set Bootloader Mode`.
		*/
		this.ipcon.sendRequest(this, BrickletDMX.FUNCTION_GET_BOOTLOADER_MODE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setWriteFirmwarePointer = function(pointer, returnCallback, errorCallback) {
		/*
		Sets the firmware pointer for :func:`Write Firmware`. The pointer has
		to be increased by chunks of size 64. The data is written to flash
		every 4 chunks (which equals to one page of size 256).
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletDMX.FUNCTION_SET_WRITE_FIRMWARE_POINTER, [pointer], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeFirmware = function(data, returnCallback, errorCallback) {
		/*
		Writes 64 Bytes of firmware at the position as written by
		:func:`Set Write Firmware Pointer` before. The firmware is written
		to flash every 4 chunks.
		
		You can only write firmware in bootloader mode.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletDMX.FUNCTION_WRITE_FIRMWARE, [data], 'B64', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setStatusLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Sets the status LED configuration. By default the LED shows
		communication traffic between Brick and Bricklet, it flickers once
		for every 10 received data packets.
		
		You can also turn the LED permanently on/off or show a heartbeat.
		
		If the Bricklet is in bootloader mode, the LED is will show heartbeat by default.
		*/
		this.ipcon.sendRequest(this, BrickletDMX.FUNCTION_SET_STATUS_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getStatusLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Status LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletDMX.FUNCTION_GET_STATUS_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getChipTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature as measured inside the microcontroller. The
		value returned is not the ambient temperature!
		
		The temperature is only proportional to the real temperature and it has bad
		accuracy. Practically it is only useful as an indicator for
		temperature changes.
		*/
		this.ipcon.sendRequest(this, BrickletDMX.FUNCTION_GET_CHIP_TEMPERATURE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.reset = function(returnCallback, errorCallback) {
		/*
		Calling this function will reset the Bricklet. All configurations
		will be lost.
		
		After a reset you have to create new device objects,
		calling functions on the existing ones will result in
		undefined behavior!
		*/
		this.ipcon.sendRequest(this, BrickletDMX.FUNCTION_RESET, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeUID = function(uid, returnCallback, errorCallback) {
		/*
		Writes a new UID into flash. If you want to set a new UID
		you have to decode the Base58 encoded UID string into an
		integer first.
		
		We recommend that you use Brick Viewer to change the UID.
		*/
		this.ipcon.sendRequest(this, BrickletDMX.FUNCTION_WRITE_UID, [uid], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.readUID = function(returnCallback, errorCallback) {
		/*
		Returns the current UID as an integer. Encode as
		Base58 to get the usual string version.
		*/
		this.ipcon.sendRequest(this, BrickletDMX.FUNCTION_READ_UID, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletDMX.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};
	this.writeFrame = function(frame, returnCallback, errorCallback) {
		/*
		Writes a DMX frame. The maximum frame size is 512 byte. Each byte represents one channel.
		
		The next frame can be written after the :cb:`Frame Started` callback was called. The frame
		is double buffered, so a new frame can be written as soon as the writing of the prior frame
		starts.
		
		The data will be transfered when the next frame duration ends, see :func:`Set Frame Duration`.
		
		Generic approach:
		
		* Set the frame duration to a value that represents the number of frames per second you want to achieve.
		* Set channels for first frame.
		* Wait for the :cb:`Frame Started` callback.
		* Set channels for next frame.
		* Wait for the :cb:`Frame Started` callback.
		* and so on.
		
		This approach ensures that you can set new DMX data with a fixed frame rate.
		
		This function can only be called in master mode.
		*/

		var frameLength = 0;
		var frameChunkData = [];
		var frameChunkOffset = 0;
		var streamStateObject = this.streamStateObjects[3];

		if (frame.length > 65535) {
			if (errorCallback !== null){
				errorCallback(IPConnection.ERROR_INVALID_PARAMETER);
			}

			this.resetStreamStateObject(streamStateObject);

			if (streamStateObject['responseProperties']['callQueue'].length > 0) {
				streamStateObject['responseProperties']['callQueue'].shift()(device);
			}

			return;
		}

		if (!this.getResponseExpected(3)) {
			if (streamStateObject['streamProperties']['fixedLength']) {
				frameLength = streamStateObject['streamProperties']['fixedLength'];
			}
			else {
				frameLength = frame.length;
			}

			if (streamStateObject['streamProperties']['singleChunk']) {
				frameChunkData =
					this.ipcon.createChunkData(frame, 0, 60, '\0');

				this.ipcon.sendRequest(this,
				                       BrickletDMX.FUNCTION_WRITE_FRAME_LOW_LEVEL,
				                       [frameLength, frameChunkOffset, frameChunkData],
				                       'H H B60',
				                       0,
				                       '',
				                       returnCallback,
				                       errorCallback,
				                       false,
				                       true);
			}
			else {
				while (frameChunkOffset < frame.length) {
					frameChunkData =
						this.ipcon.createChunkData(frame, frameChunkOffset, 60, '\0');

					this.ipcon.sendRequest(this,
					                       BrickletDMX.FUNCTION_WRITE_FRAME_LOW_LEVEL,
					                       [frameLength, frameChunkOffset, frameChunkData],
					                       'H H B60',
					                       0,
					                       '',
					                       returnCallback,
					                       errorCallback,
					                       false,
					                       true);

					frameChunkOffset += 60;
				}
			}

			if (returnCallback) {
				returnCallback();
			}
		}
		else {
			var responseHandler = null;
			var functionToQueue = null;

			if (streamStateObject['responseProperties']['responseHandler'] === null) {
				responseHandler = function (device, fid, packetResponse) {
					var result = [];
					var payload = null;
					var llvalues = null;
					var packetErrorFlag = 0;
					var rolesMappedData = [];
					var shortWriteWritten = -1;
					var streamStateObject = device.streamStateObjects[fid];
					var responseEmpty = streamStateObject['responseProperties']['streamInResponseEmpty'];
					var frameLength = 0;
					var frameChunkData = [];
					var frameChunkOffset = 0;

					function doNextLLCall() {
						frameLength = streamStateObject['responseProperties']['data'].length;
						frameChunkData =
							device.ipcon.createChunkData(streamStateObject['responseProperties']['data'],
							                             streamStateObject['responseProperties']['streamInChunkOffset'],
							                             streamStateObject['responseProperties']['streamInChunkLength'],
							                             '\0');
						frameChunkOffset = streamStateObject['responseProperties']['streamInChunkOffset'];

						for (var i = 0; i < streamStateObject['dataMappingStreamIn'].length; i++) {
							if (streamStateObject['dataMappingStreamIn'][i] === null) {
								continue;
							}

							if (streamStateObject['dataMappingStreamIn'][i].endsWith('Length')) {
								streamStateObject['responseProperties']['streamInLLParams'][i] = frameLength;
							}
							else if (streamStateObject['dataMappingStreamIn'][i].endsWith('Offset')) {
								streamStateObject['responseProperties']['streamInLLParams'][i] = frameChunkOffset;
							}
							else if (streamStateObject['dataMappingStreamIn'][i].endsWith('Data')) {
								streamStateObject['responseProperties']['streamInLLParams'][i] = frameChunkData;
							}
						}

						device.ipcon.sendRequest(device,
						                         BrickletDMX.FUNCTION_WRITE_FRAME_LOW_LEVEL,
						                         streamStateObject['responseProperties']['streamInLLParams'],
						                         'H H B60',
						                         0,
						                         '',
						                         returnCallback,
						                         errorCallback,
						                         true,
						                         true);

						streamStateObject['responseProperties']['streamInChunkOffset'] += 60;
					}

					function handleStreamInDone() {
						if (streamStateObject['responseProperties']['returnCB']) {
							if (streamStateObject['streamProperties']['shortWrite']) {
								for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
									if (streamStateObject['dataMapping'][i].endsWith('Written')) {
										result[i] = streamStateObject['responseProperties']['streamInWritten'];
										break;
									}
								}
							}

							if (!responseEmpty) {
								streamStateObject['responseProperties']['returnCB'].apply(device, result);
							}
							else {
								streamStateObject['responseProperties']['returnCB'].apply(device);
							}
						}

						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}
					}

					if (!streamStateObject) {
						return;
					}

					packetErrorFlag = device.ipcon.getEFromPacket(packetResponse);

					if (packetErrorFlag !== 0) {
						if (streamStateObject['responseProperties']['errorCB'] !== undefined) {
							if (packetErrorFlag === 1) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_INVALID_PARAMETER);
							}
							else if (packetErrorFlag === 2) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_FUNCTION_NOT_SUPPORTED);
							}
							else {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_UNKNOWN_ERROR);
							}
						}

						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}

						return;
					}

					if (responseEmpty) {
						if (streamStateObject['streamProperties']['singleChunk']) {
							handleStreamInDone();

							return;
						}

						if (streamStateObject['responseProperties']['streamInChunkOffset'] < streamStateObject['responseProperties']['data'].length) {
							doNextLLCall();
						}
						else {
							handleStreamInDone();
						}
					}
					else {
						payload = device.ipcon.getPayloadFromPacket(packetResponse);
						llvalues = device.ipcon.unpack(payload,
						                               streamStateObject['responseProperties']['unpackFormatString']);

						if (!payload || !llvalues) {
							device.resetStreamStateObject(streamStateObject);

							if (streamStateObject['responseProperties']['callQueue'].length > 0) {
								streamStateObject['responseProperties']['callQueue'].shift()(device);
							}

							return;
						}

						for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
							result.push(llvalues[i]);
						}

						if (streamStateObject['streamProperties']['singleChunk']) {
							if (streamStateObject['responseProperties']['returnCB']) {
								streamStateObject['responseProperties']['returnCB'].apply(device, result);
							}

							device.resetStreamStateObject(streamStateObject);

							if (streamStateObject['responseProperties']['callQueue'].length > 0) {
								streamStateObject['responseProperties']['callQueue'].shift()(device);
							}

							return;
						}

						if (streamStateObject['streamProperties']['shortWrite']) {
							for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
								if (streamStateObject['dataMapping'][i].endsWith('Written')) {
									shortWriteWritten = llvalues[i];
									streamStateObject['responseProperties']['streamInWritten'] += shortWriteWritten;
									break;
								}
							}
							if ((shortWriteWritten !== -1) && (shortWriteWritten < 60)) {
								// Either last chunk or short write
								handleStreamInDone();
								return;
							}
						}

						if (streamStateObject['responseProperties']['streamInChunkOffset'] < streamStateObject['responseProperties']['data'].length) {
							doNextLLCall();
						}
						else {
							handleStreamInDone();
						}
					}
				};

				streamStateObject['responseProperties']['responseHandler'] = responseHandler;
			}

			if (!streamStateObject['responseProperties']['running']) {
				streamStateObject['responseProperties']['running'] = true;
				streamStateObject['responseProperties']['returnCB'] = returnCallback;
				streamStateObject['responseProperties']['errorCB'] = errorCallback;
				streamStateObject['responseProperties']['data'].length = 0;
				streamStateObject['responseProperties']['data'].push.apply(streamStateObject['responseProperties']['data'],
				                                                           frame);

				if (streamStateObject['streamProperties']['fixedLength']) {
					frameLength = streamStateObject['streamProperties']['fixedLength'];
				}
				else {
					frameLength = frame.length;
				}

				frameChunkOffset = 0;
				frameChunkData =
					this.ipcon.createChunkData(frame, 0, 60, '\0');

				streamStateObject['responseProperties']['streamInChunkOffset'] = 60;
				streamStateObject['responseProperties']['streamInChunkLength'] = 60;
				streamStateObject['responseProperties']['streamInLLParams'] = [frameLength, frameChunkOffset, frameChunkData];

				this.ipcon.sendRequest(this,
				                       BrickletDMX.FUNCTION_WRITE_FRAME_LOW_LEVEL,
				                       [frameLength, frameChunkOffset, frameChunkData],
				                       'H H B60',
				                       0,
				                       '',
				                       returnCallback,
				                       errorCallback,
				                       true,
				                       true);
			}
			else {
				functionToQueue = function (device) {
					device.writeFrame.call(device, frame, returnCallback, errorCallback);
				}

				streamStateObject['responseProperties']['callQueue'].push(functionToQueue);
			}
		}
	};

	this.readFrame = function(returnCallback, errorCallback) {
		/*
		Returns the last frame that was written by the DMX master. The size of the array
		is equivalent to the number of channels in the frame. Each byte represents one channel.
		
		The next frame is available after the :cb:`Frame Available` callback was called.
		
		Generic approach:
		
		* Call :func:`Read Frame` to get first frame.
		* Wait for the :cb:`Frame Available` callback.
		* Call :func:`Read Frame` to get second frame.
		* Wait for the :cb:`Frame Available` callback.
		* and so on.
		
		Instead of polling this function you can also use the :cb:`Frame` callback.
		You can enable it with :func:`Set Frame Callback Config`.
		
		The frame number starts at 0 and it is increased by one with each received frame.
		
		This function can only be called in slave mode.
		*/
		var responseHandler = null;
		var functionToQueue = null;
		var streamStateObject = this.streamStateObjects[4];
		if (streamStateObject['responseProperties']['responseHandler'] === null) {
			responseHandler = 
				function (device, fid, packetResponse) {
					var result = [];
					var llvalues = null;
					var packetErrorFlag = 0;
					var rolesMappedData = [];
					var frameLength = null;
					var frameChunkData = null;
					var frameOutOfSync = false;
					var streamStateObject = device.streamStateObjects[fid];
					var frameChunkOffset = null;
					var payload = device.ipcon.getPayloadFromPacket(packetResponse);

					packetErrorFlag = device.ipcon.getEFromPacket(packetResponse);

					if (packetErrorFlag !== 0) {
						if (streamStateObject['responseProperties']['errorCB'] !== undefined) {
							if (packetErrorFlag === 1) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_INVALID_PARAMETER);
							}
							else if (packetErrorFlag === 2) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_FUNCTION_NOT_SUPPORTED);
							}
							else {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_UNKNOWN_ERROR);
							}
						}

						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}

						return;
					}

					if (payload.length === 0) {
						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}

						return;
					}

					llvalues = device.ipcon.unpack(payload,
					                               streamStateObject['responseProperties']['unpackFormatString']);

					for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
						if (streamStateObject['dataMapping'][i] === 'streamChunkData') {
							frameChunkData = llvalues[i];
						}
						else if (streamStateObject['dataMapping'][i] === 'streamChunkOffset') {
							frameChunkOffset = llvalues[i];
						}
					}

					for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
						if (streamStateObject['dataMapping'][i] === 'streamLength') {
							frameLength = llvalues[i];
							break;
						}
					}

					function handleOOS() {
						if ((frameChunkOffset + 56) < frameLength) {
							streamStateObject['responseProperties']['runningSubcallOOS'] = true;
							device.ipcon.sendRequest(device, BrickletDMX.FUNCTION_READ_FRAME_LOW_LEVEL, [], '', 72, 'H H B56 I', streamStateObject['responseProperties']['returnCB'], streamStateObject['responseProperties']['errorCB'], true, true);

							return;
						}

						if (streamStateObject['responseProperties']['errorCB']) {
							streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_STREAM_OUT_OF_SYNC);
						}

						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}
					}

					if (streamStateObject['responseProperties']['waitingFirstChunk']) {
						streamStateObject['responseProperties']['waitingFirstChunk'] = false;
						frameOutOfSync = (frameChunkOffset !== 0);
						streamStateObject['responseProperties']['data'] = frameChunkData;
					}

					if (!streamStateObject['responseProperties']['runningSubcallOOS']) {
						if (!streamStateObject['responseProperties']['runningSubcall']) {
							if (!frameOutOfSync &&
							    (streamStateObject['responseProperties']['data'].length < frameLength)) {
							        streamStateObject['responseProperties']['runningSubcall'] = true;
							        device.ipcon.sendRequest(device, BrickletDMX.FUNCTION_READ_FRAME_LOW_LEVEL, [], '', 72, 'H H B56 I', streamStateObject['responseProperties']['returnCB'], streamStateObject['responseProperties']['errorCB'], true, true);

							        return;
							}
						}
						else {
							frameOutOfSync =
								(frameChunkOffset !== streamStateObject['responseProperties']['data'].length);

							if (!frameOutOfSync &&
								(streamStateObject['responseProperties']['data'].length < frameLength)) {
									streamStateObject['responseProperties']['data'] =
										streamStateObject['responseProperties']['data'].concat(frameChunkData);

									if (streamStateObject['responseProperties']['data'].length >= frameLength) {
										streamStateObject['responseProperties']['data'] =
											streamStateObject['responseProperties']['data'].splice(0, frameLength);
									}
									else {
										device.ipcon.sendRequest(device, BrickletDMX.FUNCTION_READ_FRAME_LOW_LEVEL, [], '', 72, 'H H B56 I', streamStateObject['responseProperties']['returnCB'], streamStateObject['responseProperties']['errorCB'], true, true);

										return;
									}
							}
						}
					}
					else{
						handleOOS();

						return;
					}

					if (frameOutOfSync) { // Discard remaining stream to bring it back in-sync
						handleOOS();

						return;
					}

					if (streamStateObject['responseProperties']['returnCB']) {
						for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
							rolesMappedData.push({'role': streamStateObject['dataMapping'][i], 'llvalue': llvalues[i]});
						}

						for (var i = 0; i < rolesMappedData.length; i++) {
							if (rolesMappedData[i]['role'] === 'streamChunkData') {
								result.push(streamStateObject['responseProperties']['data'].splice(0, frameLength));
							}
							else if (rolesMappedData[i]['role'] === null) {
								result.push(rolesMappedData[i]['llvalue']);
							}
						}

						streamStateObject['responseProperties']['returnCB'].apply(device, result);
					}

					device.resetStreamStateObject(streamStateObject);

					if (streamStateObject['responseProperties']['callQueue'].length > 0) {
						streamStateObject['responseProperties']['callQueue'].shift()(device);
					}
					
				};

			streamStateObject['responseProperties']['responseHandler'] = responseHandler;
		}
		if (!streamStateObject['responseProperties']['running']) {
			streamStateObject['responseProperties']['running'] = true;
			streamStateObject['responseProperties']['returnCB'] = returnCallback;
			streamStateObject['responseProperties']['errorCB'] = errorCallback;
			this.ipcon.sendRequest(this,
			                       BrickletDMX.FUNCTION_READ_FRAME_LOW_LEVEL,
			                       [],
			                       '',
			                       72,
			                       'H H B56 I',
			                       returnCallback,
			                       errorCallback,
			                       true,
			                       true);
		}
		else {
			functionToQueue = function (device) {
				device.readFrame.call(device, returnCallback, errorCallback);
			}
			streamStateObject['responseProperties']['callQueue'].push(functionToQueue);
		}
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletDMX;

},{"./Device":279,"./IPConnection":280}],171:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletDistanceIR.DEVICE_IDENTIFIER = 25;
BrickletDistanceIR.DEVICE_DISPLAY_NAME = 'Distance IR Bricklet';
BrickletDistanceIR.CALLBACK_DISTANCE = 15;
BrickletDistanceIR.CALLBACK_ANALOG_VALUE = 16;
BrickletDistanceIR.CALLBACK_DISTANCE_REACHED = 17;
BrickletDistanceIR.CALLBACK_ANALOG_VALUE_REACHED = 18;
BrickletDistanceIR.FUNCTION_GET_DISTANCE = 1;
BrickletDistanceIR.FUNCTION_GET_ANALOG_VALUE = 2;
BrickletDistanceIR.FUNCTION_SET_SAMPLING_POINT = 3;
BrickletDistanceIR.FUNCTION_GET_SAMPLING_POINT = 4;
BrickletDistanceIR.FUNCTION_SET_DISTANCE_CALLBACK_PERIOD = 5;
BrickletDistanceIR.FUNCTION_GET_DISTANCE_CALLBACK_PERIOD = 6;
BrickletDistanceIR.FUNCTION_SET_ANALOG_VALUE_CALLBACK_PERIOD = 7;
BrickletDistanceIR.FUNCTION_GET_ANALOG_VALUE_CALLBACK_PERIOD = 8;
BrickletDistanceIR.FUNCTION_SET_DISTANCE_CALLBACK_THRESHOLD = 9;
BrickletDistanceIR.FUNCTION_GET_DISTANCE_CALLBACK_THRESHOLD = 10;
BrickletDistanceIR.FUNCTION_SET_ANALOG_VALUE_CALLBACK_THRESHOLD = 11;
BrickletDistanceIR.FUNCTION_GET_ANALOG_VALUE_CALLBACK_THRESHOLD = 12;
BrickletDistanceIR.FUNCTION_SET_DEBOUNCE_PERIOD = 13;
BrickletDistanceIR.FUNCTION_GET_DEBOUNCE_PERIOD = 14;
BrickletDistanceIR.FUNCTION_GET_IDENTITY = 255;
BrickletDistanceIR.THRESHOLD_OPTION_OFF = 'x';
BrickletDistanceIR.THRESHOLD_OPTION_OUTSIDE = 'o';
BrickletDistanceIR.THRESHOLD_OPTION_INSIDE = 'i';
BrickletDistanceIR.THRESHOLD_OPTION_SMALLER = '<';
BrickletDistanceIR.THRESHOLD_OPTION_GREATER = '>';

function BrickletDistanceIR(uid, ipcon) {
	//Measures distance up to 150cm with infrared light

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletDistanceIR.DEVICE_IDENTIFIER, BrickletDistanceIR.DEVICE_DISPLAY_NAME);
	BrickletDistanceIR.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 1];
	this.responseExpected[BrickletDistanceIR.FUNCTION_GET_DISTANCE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletDistanceIR.FUNCTION_GET_ANALOG_VALUE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletDistanceIR.FUNCTION_SET_SAMPLING_POINT] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletDistanceIR.FUNCTION_GET_SAMPLING_POINT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletDistanceIR.FUNCTION_SET_DISTANCE_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletDistanceIR.FUNCTION_GET_DISTANCE_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletDistanceIR.FUNCTION_SET_ANALOG_VALUE_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletDistanceIR.FUNCTION_GET_ANALOG_VALUE_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletDistanceIR.FUNCTION_SET_DISTANCE_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletDistanceIR.FUNCTION_GET_DISTANCE_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletDistanceIR.FUNCTION_SET_ANALOG_VALUE_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletDistanceIR.FUNCTION_GET_ANALOG_VALUE_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletDistanceIR.FUNCTION_SET_DEBOUNCE_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletDistanceIR.FUNCTION_GET_DEBOUNCE_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletDistanceIR.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletDistanceIR.CALLBACK_DISTANCE] = [10, 'H'];
	this.callbackFormats[BrickletDistanceIR.CALLBACK_ANALOG_VALUE] = [10, 'H'];
	this.callbackFormats[BrickletDistanceIR.CALLBACK_DISTANCE_REACHED] = [10, 'H'];
	this.callbackFormats[BrickletDistanceIR.CALLBACK_ANALOG_VALUE_REACHED] = [10, 'H'];



	this.getDistance = function(returnCallback, errorCallback) {
		/*
		Returns the distance measured by the sensor. Possible
		distance ranges are 40 to 300, 100 to 800 and 200 to 1500, depending on the
		selected IR sensor.
		
		If you want to get the distance periodically, it is recommended to use the
		:cb:`Distance` callback and set the period with
		:func:`Set Distance Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletDistanceIR.FUNCTION_GET_DISTANCE, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.getAnalogValue = function(returnCallback, errorCallback) {
		/*
		Returns the value as read by a 12-bit analog-to-digital converter.
		
		.. note::
		 The value returned by :func:`Get Distance` is averaged over several samples
		 to yield less noise, while :func:`Get Analog Value` gives back raw
		 unfiltered analog values. The only reason to use :func:`Get Analog Value` is,
		 if you need the full resolution of the analog-to-digital converter.
		
		If you want the analog value periodically, it is recommended to use the
		:cb:`Analog Value` callback and set the period with
		:func:`Set Analog Value Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletDistanceIR.FUNCTION_GET_ANALOG_VALUE, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.setSamplingPoint = function(position, distance, returnCallback, errorCallback) {
		/*
		Sets a sampling point value to a specific position of the lookup table.
		The lookup table comprises 128 equidistant analog values with
		corresponding distances.
		
		If you measure a distance of 50cm at the analog value 2048, you
		should call this function with (64, 5000). The utilized analog-to-digital
		converter has a resolution of 12 bit. With 128 sampling points on the
		whole range, this means that every sampling point has a size of 32
		analog values. Thus the analog value 2048 has the corresponding sampling
		point 64 = 2048/32.
		
		Sampling points are saved on the EEPROM of the Distance IR Bricklet and
		loaded again on startup.
		
		.. note::
		 An easy way to calibrate the sampling points of the Distance IR Bricklet is
		 implemented in the Brick Viewer. If you want to calibrate your Bricklet it is
		 highly recommended to use this implementation.
		*/
		this.ipcon.sendRequest(this, BrickletDistanceIR.FUNCTION_SET_SAMPLING_POINT, [position, distance], 'B H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getSamplingPoint = function(position, returnCallback, errorCallback) {
		/*
		Returns the distance to a sampling point position as set by
		:func:`Set Sampling Point`.
		*/
		this.ipcon.sendRequest(this, BrickletDistanceIR.FUNCTION_GET_SAMPLING_POINT, [position], 'B', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.setDistanceCallbackPeriod = function(period, returnCallback, errorCallback) {
		/*
		Sets the period with which the :cb:`Distance` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		The :cb:`Distance` callback is only triggered if the distance has changed since the
		last triggering.
		*/
		this.ipcon.sendRequest(this, BrickletDistanceIR.FUNCTION_SET_DISTANCE_CALLBACK_PERIOD, [period], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getDistanceCallbackPeriod = function(returnCallback, errorCallback) {
		/*
		Returns the period as set by :func:`Set Distance Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletDistanceIR.FUNCTION_GET_DISTANCE_CALLBACK_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setAnalogValueCallbackPeriod = function(period, returnCallback, errorCallback) {
		/*
		Sets the period with which the :cb:`Analog Value` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		The :cb:`Analog Value` callback is only triggered if the analog value has
		changed since the last triggering.
		*/
		this.ipcon.sendRequest(this, BrickletDistanceIR.FUNCTION_SET_ANALOG_VALUE_CALLBACK_PERIOD, [period], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getAnalogValueCallbackPeriod = function(returnCallback, errorCallback) {
		/*
		Returns the period as set by :func:`Set Analog Value Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletDistanceIR.FUNCTION_GET_ANALOG_VALUE_CALLBACK_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setDistanceCallbackThreshold = function(option, min, max, returnCallback, errorCallback) {
		/*
		Sets the thresholds for the :cb:`Distance Reached` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Callback is turned off"
		 "'o'",    "Callback is triggered when the distance is *outside* the min and max values"
		 "'i'",    "Callback is triggered when the distance is *inside* the min and max values"
		 "'<'",    "Callback is triggered when the distance is smaller than the min value (max is ignored)"
		 "'>'",    "Callback is triggered when the distance is greater than the min value (max is ignored)"
		*/
		this.ipcon.sendRequest(this, BrickletDistanceIR.FUNCTION_SET_DISTANCE_CALLBACK_THRESHOLD, [option, min, max], 'c H H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getDistanceCallbackThreshold = function(returnCallback, errorCallback) {
		/*
		Returns the threshold as set by :func:`Set Distance Callback Threshold`.
		*/
		this.ipcon.sendRequest(this, BrickletDistanceIR.FUNCTION_GET_DISTANCE_CALLBACK_THRESHOLD, [], '', 13, 'c H H', returnCallback, errorCallback, false, true);
	};
	this.setAnalogValueCallbackThreshold = function(option, min, max, returnCallback, errorCallback) {
		/*
		Sets the thresholds for the :cb:`Analog Value Reached` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Callback is turned off"
		 "'o'",    "Callback is triggered when the analog value is *outside* the min and max values"
		 "'i'",    "Callback is triggered when the analog value is *inside* the min and max values"
		 "'<'",    "Callback is triggered when the analog value is smaller than the min value (max is ignored)"
		 "'>'",    "Callback is triggered when the analog value is greater than the min value (max is ignored)"
		*/
		this.ipcon.sendRequest(this, BrickletDistanceIR.FUNCTION_SET_ANALOG_VALUE_CALLBACK_THRESHOLD, [option, min, max], 'c H H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getAnalogValueCallbackThreshold = function(returnCallback, errorCallback) {
		/*
		Returns the threshold as set by :func:`Set Analog Value Callback Threshold`.
		*/
		this.ipcon.sendRequest(this, BrickletDistanceIR.FUNCTION_GET_ANALOG_VALUE_CALLBACK_THRESHOLD, [], '', 13, 'c H H', returnCallback, errorCallback, false, true);
	};
	this.setDebouncePeriod = function(debounce, returnCallback, errorCallback) {
		/*
		Sets the period with which the threshold callbacks
		
		* :cb:`Distance Reached`,
		* :cb:`Analog Value Reached`
		
		are triggered, if the thresholds
		
		* :func:`Set Distance Callback Threshold`,
		* :func:`Set Analog Value Callback Threshold`
		
		keep being reached.
		*/
		this.ipcon.sendRequest(this, BrickletDistanceIR.FUNCTION_SET_DEBOUNCE_PERIOD, [debounce], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getDebouncePeriod = function(returnCallback, errorCallback) {
		/*
		Returns the debounce period as set by :func:`Set Debounce Period`.
		*/
		this.ipcon.sendRequest(this, BrickletDistanceIR.FUNCTION_GET_DEBOUNCE_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletDistanceIR.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletDistanceIR;

},{"./Device":279,"./IPConnection":280}],172:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletDistanceIRV2.DEVICE_IDENTIFIER = 2125;
BrickletDistanceIRV2.DEVICE_DISPLAY_NAME = 'Distance IR Bricklet 2.0';
BrickletDistanceIRV2.CALLBACK_DISTANCE = 4;
BrickletDistanceIRV2.CALLBACK_ANALOG_VALUE = 8;
BrickletDistanceIRV2.FUNCTION_GET_DISTANCE = 1;
BrickletDistanceIRV2.FUNCTION_SET_DISTANCE_CALLBACK_CONFIGURATION = 2;
BrickletDistanceIRV2.FUNCTION_GET_DISTANCE_CALLBACK_CONFIGURATION = 3;
BrickletDistanceIRV2.FUNCTION_GET_ANALOG_VALUE = 5;
BrickletDistanceIRV2.FUNCTION_SET_ANALOG_VALUE_CALLBACK_CONFIGURATION = 6;
BrickletDistanceIRV2.FUNCTION_GET_ANALOG_VALUE_CALLBACK_CONFIGURATION = 7;
BrickletDistanceIRV2.FUNCTION_SET_MOVING_AVERAGE_CONFIGURATION = 9;
BrickletDistanceIRV2.FUNCTION_GET_MOVING_AVERAGE_CONFIGURATION = 10;
BrickletDistanceIRV2.FUNCTION_SET_DISTANCE_LED_CONFIG = 11;
BrickletDistanceIRV2.FUNCTION_GET_DISTANCE_LED_CONFIG = 12;
BrickletDistanceIRV2.FUNCTION_SET_SENSOR_TYPE = 13;
BrickletDistanceIRV2.FUNCTION_GET_SENSOR_TYPE = 14;
BrickletDistanceIRV2.FUNCTION_GET_SPITFP_ERROR_COUNT = 234;
BrickletDistanceIRV2.FUNCTION_SET_BOOTLOADER_MODE = 235;
BrickletDistanceIRV2.FUNCTION_GET_BOOTLOADER_MODE = 236;
BrickletDistanceIRV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER = 237;
BrickletDistanceIRV2.FUNCTION_WRITE_FIRMWARE = 238;
BrickletDistanceIRV2.FUNCTION_SET_STATUS_LED_CONFIG = 239;
BrickletDistanceIRV2.FUNCTION_GET_STATUS_LED_CONFIG = 240;
BrickletDistanceIRV2.FUNCTION_GET_CHIP_TEMPERATURE = 242;
BrickletDistanceIRV2.FUNCTION_RESET = 243;
BrickletDistanceIRV2.FUNCTION_WRITE_UID = 248;
BrickletDistanceIRV2.FUNCTION_READ_UID = 249;
BrickletDistanceIRV2.FUNCTION_GET_IDENTITY = 255;
BrickletDistanceIRV2.THRESHOLD_OPTION_OFF = 'x';
BrickletDistanceIRV2.THRESHOLD_OPTION_OUTSIDE = 'o';
BrickletDistanceIRV2.THRESHOLD_OPTION_INSIDE = 'i';
BrickletDistanceIRV2.THRESHOLD_OPTION_SMALLER = '<';
BrickletDistanceIRV2.THRESHOLD_OPTION_GREATER = '>';
BrickletDistanceIRV2.DISTANCE_LED_CONFIG_OFF = 0;
BrickletDistanceIRV2.DISTANCE_LED_CONFIG_ON = 1;
BrickletDistanceIRV2.DISTANCE_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletDistanceIRV2.DISTANCE_LED_CONFIG_SHOW_DISTANCE = 3;
BrickletDistanceIRV2.SENSOR_TYPE_2Y0A41 = 0;
BrickletDistanceIRV2.SENSOR_TYPE_2Y0A21 = 1;
BrickletDistanceIRV2.SENSOR_TYPE_2Y0A02 = 2;
BrickletDistanceIRV2.BOOTLOADER_MODE_BOOTLOADER = 0;
BrickletDistanceIRV2.BOOTLOADER_MODE_FIRMWARE = 1;
BrickletDistanceIRV2.BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT = 2;
BrickletDistanceIRV2.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT = 3;
BrickletDistanceIRV2.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT = 4;
BrickletDistanceIRV2.BOOTLOADER_STATUS_OK = 0;
BrickletDistanceIRV2.BOOTLOADER_STATUS_INVALID_MODE = 1;
BrickletDistanceIRV2.BOOTLOADER_STATUS_NO_CHANGE = 2;
BrickletDistanceIRV2.BOOTLOADER_STATUS_ENTRY_FUNCTION_NOT_PRESENT = 3;
BrickletDistanceIRV2.BOOTLOADER_STATUS_DEVICE_IDENTIFIER_INCORRECT = 4;
BrickletDistanceIRV2.BOOTLOADER_STATUS_CRC_MISMATCH = 5;
BrickletDistanceIRV2.STATUS_LED_CONFIG_OFF = 0;
BrickletDistanceIRV2.STATUS_LED_CONFIG_ON = 1;
BrickletDistanceIRV2.STATUS_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletDistanceIRV2.STATUS_LED_CONFIG_SHOW_STATUS = 3;

function BrickletDistanceIRV2(uid, ipcon) {
	//Measures distance up to 150cm with infrared light

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletDistanceIRV2.DEVICE_IDENTIFIER, BrickletDistanceIRV2.DEVICE_DISPLAY_NAME);
	BrickletDistanceIRV2.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 1];
	this.responseExpected[BrickletDistanceIRV2.FUNCTION_GET_DISTANCE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletDistanceIRV2.FUNCTION_SET_DISTANCE_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletDistanceIRV2.FUNCTION_GET_DISTANCE_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletDistanceIRV2.FUNCTION_GET_ANALOG_VALUE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletDistanceIRV2.FUNCTION_SET_ANALOG_VALUE_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletDistanceIRV2.FUNCTION_GET_ANALOG_VALUE_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletDistanceIRV2.FUNCTION_SET_MOVING_AVERAGE_CONFIGURATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletDistanceIRV2.FUNCTION_GET_MOVING_AVERAGE_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletDistanceIRV2.FUNCTION_SET_DISTANCE_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletDistanceIRV2.FUNCTION_GET_DISTANCE_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletDistanceIRV2.FUNCTION_SET_SENSOR_TYPE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletDistanceIRV2.FUNCTION_GET_SENSOR_TYPE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletDistanceIRV2.FUNCTION_GET_SPITFP_ERROR_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletDistanceIRV2.FUNCTION_SET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletDistanceIRV2.FUNCTION_GET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletDistanceIRV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletDistanceIRV2.FUNCTION_WRITE_FIRMWARE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletDistanceIRV2.FUNCTION_SET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletDistanceIRV2.FUNCTION_GET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletDistanceIRV2.FUNCTION_GET_CHIP_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletDistanceIRV2.FUNCTION_RESET] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletDistanceIRV2.FUNCTION_WRITE_UID] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletDistanceIRV2.FUNCTION_READ_UID] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletDistanceIRV2.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletDistanceIRV2.CALLBACK_DISTANCE] = [10, 'H'];
	this.callbackFormats[BrickletDistanceIRV2.CALLBACK_ANALOG_VALUE] = [12, 'I'];



	this.getDistance = function(returnCallback, errorCallback) {
		/*
		Returns the distance measured by the sensor. Possible
		distance ranges are 40 to 300, 100 to 800 and 200 to 1500, depending on the
		selected IR sensor.
		
		
		If you want to get the value periodically, it is recommended to use the
		:cb:`Distance` callback. You can set the callback configuration
		with :func:`Set Distance Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletDistanceIRV2.FUNCTION_GET_DISTANCE, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.setDistanceCallbackConfiguration = function(period, valueHasToChange, option, min, max, returnCallback, errorCallback) {
		/*
		The period is the period with which the :cb:`Distance` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		If the `value has to change`-parameter is set to true, the callback is only
		triggered after the value has changed. If the value didn't change
		within the period, the callback is triggered immediately on change.
		
		If it is set to false, the callback is continuously triggered with the period,
		independent of the value.
		
		It is furthermore possible to constrain the callback with thresholds.
		
		The `option`-parameter together with min/max sets a threshold for the :cb:`Distance` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Threshold is turned off"
		 "'o'",    "Threshold is triggered when the value is *outside* the min and max values"
		 "'i'",    "Threshold is triggered when the value is *inside* or equal to the min and max values"
		 "'<'",    "Threshold is triggered when the value is smaller than the min value (max is ignored)"
		 "'>'",    "Threshold is triggered when the value is greater than the min value (max is ignored)"
		
		If the option is set to 'x' (threshold turned off) the callback is triggered with the fixed period.
		*/
		this.ipcon.sendRequest(this, BrickletDistanceIRV2.FUNCTION_SET_DISTANCE_CALLBACK_CONFIGURATION, [period, valueHasToChange, option, min, max], 'I ? c H H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getDistanceCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the callback configuration as set by :func:`Set Distance Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletDistanceIRV2.FUNCTION_GET_DISTANCE_CALLBACK_CONFIGURATION, [], '', 18, 'I ? c H H', returnCallback, errorCallback, false, true);
	};
	this.getAnalogValue = function(returnCallback, errorCallback) {
		/*
		Returns the analog value as read by a analog-to-digital converter.
		
		This is unfiltered raw data. We made sure that the integration time
		of the ADC is shorter then the measurement interval of the sensor
		(10ms vs 16.5ms). So there is no information lost.
		
		If you want to do your own calibration or create your own lookup table
		you can use this value.
		
		
		If you want to get the value periodically, it is recommended to use the
		:cb:`Analog Value` callback. You can set the callback configuration
		with :func:`Set Analog Value Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletDistanceIRV2.FUNCTION_GET_ANALOG_VALUE, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setAnalogValueCallbackConfiguration = function(period, valueHasToChange, option, min, max, returnCallback, errorCallback) {
		/*
		The period is the period with which the :cb:`Analog Value` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		If the `value has to change`-parameter is set to true, the callback is only
		triggered after the value has changed. If the value didn't change
		within the period, the callback is triggered immediately on change.
		
		If it is set to false, the callback is continuously triggered with the period,
		independent of the value.
		
		It is furthermore possible to constrain the callback with thresholds.
		
		The `option`-parameter together with min/max sets a threshold for the :cb:`Analog Value` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Threshold is turned off"
		 "'o'",    "Threshold is triggered when the value is *outside* the min and max values"
		 "'i'",    "Threshold is triggered when the value is *inside* or equal to the min and max values"
		 "'<'",    "Threshold is triggered when the value is smaller than the min value (max is ignored)"
		 "'>'",    "Threshold is triggered when the value is greater than the min value (max is ignored)"
		
		If the option is set to 'x' (threshold turned off) the callback is triggered with the fixed period.
		*/
		this.ipcon.sendRequest(this, BrickletDistanceIRV2.FUNCTION_SET_ANALOG_VALUE_CALLBACK_CONFIGURATION, [period, valueHasToChange, option, min, max], 'I ? c I I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getAnalogValueCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the callback configuration as set by :func:`Set Analog Value Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletDistanceIRV2.FUNCTION_GET_ANALOG_VALUE_CALLBACK_CONFIGURATION, [], '', 22, 'I ? c I I', returnCallback, errorCallback, false, true);
	};
	this.setMovingAverageConfiguration = function(movingAverageLength, returnCallback, errorCallback) {
		/*
		Sets the length of a `moving averaging <https://en.wikipedia.org/wiki/Moving_average>`__
		for the distance.
		
		Setting the length to 1 will turn the averaging off. With less averaging, there
		is more noise on the data.
		
		New data is gathered every ~10ms. With a moving average of length 1000 the
		resulting averaging window has a length of approximately 10s. If you want to do
		long term measurements the longest moving average will give the cleanest results.
		*/
		this.ipcon.sendRequest(this, BrickletDistanceIRV2.FUNCTION_SET_MOVING_AVERAGE_CONFIGURATION, [movingAverageLength], 'H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getMovingAverageConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the moving average configuration as set by :func:`Set Moving Average Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletDistanceIRV2.FUNCTION_GET_MOVING_AVERAGE_CONFIGURATION, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.setDistanceLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Configures the distance LED to be either turned off, turned on, blink in
		heartbeat mode or show the distance (brighter = object is nearer).
		*/
		this.ipcon.sendRequest(this, BrickletDistanceIRV2.FUNCTION_SET_DISTANCE_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getDistanceLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the LED configuration as set by :func:`Set Distance LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletDistanceIRV2.FUNCTION_GET_DISTANCE_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setSensorType = function(sensor, returnCallback, errorCallback) {
		/*
		Sets the sensor type.
		
		The Bricklet comes configured with the correct sensor type
		and the type is saved in flash (i.e. the Bricklet retains the information if
		power is lost).
		
		If you want to change the sensor you can set the type in Brick Viewer,
		you will likely never need to call this function from your program.
		*/
		this.ipcon.sendRequest(this, BrickletDistanceIRV2.FUNCTION_SET_SENSOR_TYPE, [sensor], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getSensorType = function(returnCallback, errorCallback) {
		/*
		Returns the sensor type as set by :func:`Set Sensor Type`.
		*/
		this.ipcon.sendRequest(this, BrickletDistanceIRV2.FUNCTION_GET_SENSOR_TYPE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPErrorCount = function(returnCallback, errorCallback) {
		/*
		Returns the error count for the communication between Brick and Bricklet.
		
		The errors are divided into
		
		* ACK checksum errors,
		* message checksum errors,
		* framing errors and
		* overflow errors.
		
		The errors counts are for errors that occur on the Bricklet side. All
		Bricks have a similar function that returns the errors on the Brick side.
		*/
		this.ipcon.sendRequest(this, BrickletDistanceIRV2.FUNCTION_GET_SPITFP_ERROR_COUNT, [], '', 24, 'I I I I', returnCallback, errorCallback, false, true);
	};
	this.setBootloaderMode = function(mode, returnCallback, errorCallback) {
		/*
		Sets the bootloader mode and returns the status after the requested
		mode change was instigated.
		
		You can change from bootloader mode to firmware mode and vice versa. A change
		from bootloader mode to firmware mode will only take place if the entry function,
		device identifier and CRC are present and correct.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletDistanceIRV2.FUNCTION_SET_BOOTLOADER_MODE, [mode], 'B', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getBootloaderMode = function(returnCallback, errorCallback) {
		/*
		Returns the current bootloader mode, see :func:`Set Bootloader Mode`.
		*/
		this.ipcon.sendRequest(this, BrickletDistanceIRV2.FUNCTION_GET_BOOTLOADER_MODE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setWriteFirmwarePointer = function(pointer, returnCallback, errorCallback) {
		/*
		Sets the firmware pointer for :func:`Write Firmware`. The pointer has
		to be increased by chunks of size 64. The data is written to flash
		every 4 chunks (which equals to one page of size 256).
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletDistanceIRV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER, [pointer], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeFirmware = function(data, returnCallback, errorCallback) {
		/*
		Writes 64 Bytes of firmware at the position as written by
		:func:`Set Write Firmware Pointer` before. The firmware is written
		to flash every 4 chunks.
		
		You can only write firmware in bootloader mode.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletDistanceIRV2.FUNCTION_WRITE_FIRMWARE, [data], 'B64', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setStatusLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Sets the status LED configuration. By default the LED shows
		communication traffic between Brick and Bricklet, it flickers once
		for every 10 received data packets.
		
		You can also turn the LED permanently on/off or show a heartbeat.
		
		If the Bricklet is in bootloader mode, the LED is will show heartbeat by default.
		*/
		this.ipcon.sendRequest(this, BrickletDistanceIRV2.FUNCTION_SET_STATUS_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getStatusLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Status LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletDistanceIRV2.FUNCTION_GET_STATUS_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getChipTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature as measured inside the microcontroller. The
		value returned is not the ambient temperature!
		
		The temperature is only proportional to the real temperature and it has bad
		accuracy. Practically it is only useful as an indicator for
		temperature changes.
		*/
		this.ipcon.sendRequest(this, BrickletDistanceIRV2.FUNCTION_GET_CHIP_TEMPERATURE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.reset = function(returnCallback, errorCallback) {
		/*
		Calling this function will reset the Bricklet. All configurations
		will be lost.
		
		After a reset you have to create new device objects,
		calling functions on the existing ones will result in
		undefined behavior!
		*/
		this.ipcon.sendRequest(this, BrickletDistanceIRV2.FUNCTION_RESET, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeUID = function(uid, returnCallback, errorCallback) {
		/*
		Writes a new UID into flash. If you want to set a new UID
		you have to decode the Base58 encoded UID string into an
		integer first.
		
		We recommend that you use Brick Viewer to change the UID.
		*/
		this.ipcon.sendRequest(this, BrickletDistanceIRV2.FUNCTION_WRITE_UID, [uid], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.readUID = function(returnCallback, errorCallback) {
		/*
		Returns the current UID as an integer. Encode as
		Base58 to get the usual string version.
		*/
		this.ipcon.sendRequest(this, BrickletDistanceIRV2.FUNCTION_READ_UID, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletDistanceIRV2.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletDistanceIRV2;

},{"./Device":279,"./IPConnection":280}],173:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletDistanceUS.DEVICE_IDENTIFIER = 229;
BrickletDistanceUS.DEVICE_DISPLAY_NAME = 'Distance US Bricklet';
BrickletDistanceUS.CALLBACK_DISTANCE = 8;
BrickletDistanceUS.CALLBACK_DISTANCE_REACHED = 9;
BrickletDistanceUS.FUNCTION_GET_DISTANCE_VALUE = 1;
BrickletDistanceUS.FUNCTION_SET_DISTANCE_CALLBACK_PERIOD = 2;
BrickletDistanceUS.FUNCTION_GET_DISTANCE_CALLBACK_PERIOD = 3;
BrickletDistanceUS.FUNCTION_SET_DISTANCE_CALLBACK_THRESHOLD = 4;
BrickletDistanceUS.FUNCTION_GET_DISTANCE_CALLBACK_THRESHOLD = 5;
BrickletDistanceUS.FUNCTION_SET_DEBOUNCE_PERIOD = 6;
BrickletDistanceUS.FUNCTION_GET_DEBOUNCE_PERIOD = 7;
BrickletDistanceUS.FUNCTION_SET_MOVING_AVERAGE = 10;
BrickletDistanceUS.FUNCTION_GET_MOVING_AVERAGE = 11;
BrickletDistanceUS.FUNCTION_GET_IDENTITY = 255;
BrickletDistanceUS.THRESHOLD_OPTION_OFF = 'x';
BrickletDistanceUS.THRESHOLD_OPTION_OUTSIDE = 'o';
BrickletDistanceUS.THRESHOLD_OPTION_INSIDE = 'i';
BrickletDistanceUS.THRESHOLD_OPTION_SMALLER = '<';
BrickletDistanceUS.THRESHOLD_OPTION_GREATER = '>';

function BrickletDistanceUS(uid, ipcon) {
	//Measures distance between 2cm and 400cm with ultrasound

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletDistanceUS.DEVICE_IDENTIFIER, BrickletDistanceUS.DEVICE_DISPLAY_NAME);
	BrickletDistanceUS.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 1];
	this.responseExpected[BrickletDistanceUS.FUNCTION_GET_DISTANCE_VALUE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletDistanceUS.FUNCTION_SET_DISTANCE_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletDistanceUS.FUNCTION_GET_DISTANCE_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletDistanceUS.FUNCTION_SET_DISTANCE_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletDistanceUS.FUNCTION_GET_DISTANCE_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletDistanceUS.FUNCTION_SET_DEBOUNCE_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletDistanceUS.FUNCTION_GET_DEBOUNCE_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletDistanceUS.FUNCTION_SET_MOVING_AVERAGE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletDistanceUS.FUNCTION_GET_MOVING_AVERAGE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletDistanceUS.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletDistanceUS.CALLBACK_DISTANCE] = [10, 'H'];
	this.callbackFormats[BrickletDistanceUS.CALLBACK_DISTANCE_REACHED] = [10, 'H'];



	this.getDistanceValue = function(returnCallback, errorCallback) {
		/*
		Returns the current distance value measured by the sensor.
		A small value corresponds to a small distance, a big
		value corresponds to a big distance. The relation between the measured distance
		value and the actual distance is affected by the 5V supply voltage (deviations
		in the supply voltage result in deviations in the distance values) and is
		non-linear (resolution is bigger at close range).
		
		If you want to get the distance value periodically, it is recommended to
		use the :cb:`Distance` callback and set the period with
		:func:`Set Distance Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletDistanceUS.FUNCTION_GET_DISTANCE_VALUE, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.setDistanceCallbackPeriod = function(period, returnCallback, errorCallback) {
		/*
		Sets the period with which the :cb:`Distance` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		Der :cb:`Distance` callback is only triggered if the distance value has changed
		since the last triggering.
		*/
		this.ipcon.sendRequest(this, BrickletDistanceUS.FUNCTION_SET_DISTANCE_CALLBACK_PERIOD, [period], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getDistanceCallbackPeriod = function(returnCallback, errorCallback) {
		/*
		Returns the period as set by :func:`Set Distance Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletDistanceUS.FUNCTION_GET_DISTANCE_CALLBACK_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setDistanceCallbackThreshold = function(option, min, max, returnCallback, errorCallback) {
		/*
		Sets the thresholds for the :cb:`Distance Reached` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Callback is turned off"
		 "'o'",    "Callback is triggered when the distance value is *outside* the min and max values"
		 "'i'",    "Callback is triggered when the distance value is *inside* the min and max values"
		 "'<'",    "Callback is triggered when the distance value is smaller than the min value (max is ignored)"
		 "'>'",    "Callback is triggered when the distance value is greater than the min value (max is ignored)"
		*/
		this.ipcon.sendRequest(this, BrickletDistanceUS.FUNCTION_SET_DISTANCE_CALLBACK_THRESHOLD, [option, min, max], 'c H H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getDistanceCallbackThreshold = function(returnCallback, errorCallback) {
		/*
		Returns the threshold as set by :func:`Set Distance Callback Threshold`.
		*/
		this.ipcon.sendRequest(this, BrickletDistanceUS.FUNCTION_GET_DISTANCE_CALLBACK_THRESHOLD, [], '', 13, 'c H H', returnCallback, errorCallback, false, true);
	};
	this.setDebouncePeriod = function(debounce, returnCallback, errorCallback) {
		/*
		Sets the period with which the threshold callbacks
		
		* :cb:`Distance Reached`,
		
		are triggered, if the thresholds
		
		* :func:`Set Distance Callback Threshold`,
		
		keep being reached.
		*/
		this.ipcon.sendRequest(this, BrickletDistanceUS.FUNCTION_SET_DEBOUNCE_PERIOD, [debounce], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getDebouncePeriod = function(returnCallback, errorCallback) {
		/*
		Returns the debounce period as set by :func:`Set Debounce Period`.
		*/
		this.ipcon.sendRequest(this, BrickletDistanceUS.FUNCTION_GET_DEBOUNCE_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setMovingAverage = function(average, returnCallback, errorCallback) {
		/*
		Sets the length of a `moving averaging <https://en.wikipedia.org/wiki/Moving_average>`__
		for the distance value.
		
		Setting the length to 0 will turn the averaging completely off. With less
		averaging, there is more noise on the data.
		*/
		this.ipcon.sendRequest(this, BrickletDistanceUS.FUNCTION_SET_MOVING_AVERAGE, [average], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getMovingAverage = function(returnCallback, errorCallback) {
		/*
		Returns the length moving average as set by :func:`Set Moving Average`.
		*/
		this.ipcon.sendRequest(this, BrickletDistanceUS.FUNCTION_GET_MOVING_AVERAGE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletDistanceUS.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletDistanceUS;

},{"./Device":279,"./IPConnection":280}],174:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletDistanceUSV2.DEVICE_IDENTIFIER = 299;
BrickletDistanceUSV2.DEVICE_DISPLAY_NAME = 'Distance US Bricklet 2.0';
BrickletDistanceUSV2.CALLBACK_DISTANCE = 4;
BrickletDistanceUSV2.FUNCTION_GET_DISTANCE = 1;
BrickletDistanceUSV2.FUNCTION_SET_DISTANCE_CALLBACK_CONFIGURATION = 2;
BrickletDistanceUSV2.FUNCTION_GET_DISTANCE_CALLBACK_CONFIGURATION = 3;
BrickletDistanceUSV2.FUNCTION_SET_UPDATE_RATE = 5;
BrickletDistanceUSV2.FUNCTION_GET_UPDATE_RATE = 6;
BrickletDistanceUSV2.FUNCTION_SET_DISTANCE_LED_CONFIG = 7;
BrickletDistanceUSV2.FUNCTION_GET_DISTANCE_LED_CONFIG = 8;
BrickletDistanceUSV2.FUNCTION_GET_SPITFP_ERROR_COUNT = 234;
BrickletDistanceUSV2.FUNCTION_SET_BOOTLOADER_MODE = 235;
BrickletDistanceUSV2.FUNCTION_GET_BOOTLOADER_MODE = 236;
BrickletDistanceUSV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER = 237;
BrickletDistanceUSV2.FUNCTION_WRITE_FIRMWARE = 238;
BrickletDistanceUSV2.FUNCTION_SET_STATUS_LED_CONFIG = 239;
BrickletDistanceUSV2.FUNCTION_GET_STATUS_LED_CONFIG = 240;
BrickletDistanceUSV2.FUNCTION_GET_CHIP_TEMPERATURE = 242;
BrickletDistanceUSV2.FUNCTION_RESET = 243;
BrickletDistanceUSV2.FUNCTION_WRITE_UID = 248;
BrickletDistanceUSV2.FUNCTION_READ_UID = 249;
BrickletDistanceUSV2.FUNCTION_GET_IDENTITY = 255;
BrickletDistanceUSV2.THRESHOLD_OPTION_OFF = 'x';
BrickletDistanceUSV2.THRESHOLD_OPTION_OUTSIDE = 'o';
BrickletDistanceUSV2.THRESHOLD_OPTION_INSIDE = 'i';
BrickletDistanceUSV2.THRESHOLD_OPTION_SMALLER = '<';
BrickletDistanceUSV2.THRESHOLD_OPTION_GREATER = '>';
BrickletDistanceUSV2.UPDATE_RATE_2_HZ = 0;
BrickletDistanceUSV2.UPDATE_RATE_10_HZ = 1;
BrickletDistanceUSV2.DISTANCE_LED_CONFIG_OFF = 0;
BrickletDistanceUSV2.DISTANCE_LED_CONFIG_ON = 1;
BrickletDistanceUSV2.DISTANCE_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletDistanceUSV2.DISTANCE_LED_CONFIG_SHOW_DISTANCE = 3;
BrickletDistanceUSV2.BOOTLOADER_MODE_BOOTLOADER = 0;
BrickletDistanceUSV2.BOOTLOADER_MODE_FIRMWARE = 1;
BrickletDistanceUSV2.BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT = 2;
BrickletDistanceUSV2.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT = 3;
BrickletDistanceUSV2.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT = 4;
BrickletDistanceUSV2.BOOTLOADER_STATUS_OK = 0;
BrickletDistanceUSV2.BOOTLOADER_STATUS_INVALID_MODE = 1;
BrickletDistanceUSV2.BOOTLOADER_STATUS_NO_CHANGE = 2;
BrickletDistanceUSV2.BOOTLOADER_STATUS_ENTRY_FUNCTION_NOT_PRESENT = 3;
BrickletDistanceUSV2.BOOTLOADER_STATUS_DEVICE_IDENTIFIER_INCORRECT = 4;
BrickletDistanceUSV2.BOOTLOADER_STATUS_CRC_MISMATCH = 5;
BrickletDistanceUSV2.STATUS_LED_CONFIG_OFF = 0;
BrickletDistanceUSV2.STATUS_LED_CONFIG_ON = 1;
BrickletDistanceUSV2.STATUS_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletDistanceUSV2.STATUS_LED_CONFIG_SHOW_STATUS = 3;

function BrickletDistanceUSV2(uid, ipcon) {
	//Measures distance between 30cm and 500cm with ultrasound

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletDistanceUSV2.DEVICE_IDENTIFIER, BrickletDistanceUSV2.DEVICE_DISPLAY_NAME);
	BrickletDistanceUSV2.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickletDistanceUSV2.FUNCTION_GET_DISTANCE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletDistanceUSV2.FUNCTION_SET_DISTANCE_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletDistanceUSV2.FUNCTION_GET_DISTANCE_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletDistanceUSV2.FUNCTION_SET_UPDATE_RATE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletDistanceUSV2.FUNCTION_GET_UPDATE_RATE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletDistanceUSV2.FUNCTION_SET_DISTANCE_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletDistanceUSV2.FUNCTION_GET_DISTANCE_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletDistanceUSV2.FUNCTION_GET_SPITFP_ERROR_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletDistanceUSV2.FUNCTION_SET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletDistanceUSV2.FUNCTION_GET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletDistanceUSV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletDistanceUSV2.FUNCTION_WRITE_FIRMWARE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletDistanceUSV2.FUNCTION_SET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletDistanceUSV2.FUNCTION_GET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletDistanceUSV2.FUNCTION_GET_CHIP_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletDistanceUSV2.FUNCTION_RESET] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletDistanceUSV2.FUNCTION_WRITE_UID] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletDistanceUSV2.FUNCTION_READ_UID] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletDistanceUSV2.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletDistanceUSV2.CALLBACK_DISTANCE] = [10, 'H'];



	this.getDistance = function(returnCallback, errorCallback) {
		/*
		Returns the distance.
		
		
		If you want to get the value periodically, it is recommended to use the
		:cb:`Distance` callback. You can set the callback configuration
		with :func:`Set Distance Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletDistanceUSV2.FUNCTION_GET_DISTANCE, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.setDistanceCallbackConfiguration = function(period, valueHasToChange, option, min, max, returnCallback, errorCallback) {
		/*
		The period is the period with which the :cb:`Distance` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		If the `value has to change`-parameter is set to true, the callback is only
		triggered after the value has changed. If the value didn't change
		within the period, the callback is triggered immediately on change.
		
		If it is set to false, the callback is continuously triggered with the period,
		independent of the value.
		
		It is furthermore possible to constrain the callback with thresholds.
		
		The `option`-parameter together with min/max sets a threshold for the :cb:`Distance` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Threshold is turned off"
		 "'o'",    "Threshold is triggered when the value is *outside* the min and max values"
		 "'i'",    "Threshold is triggered when the value is *inside* or equal to the min and max values"
		 "'<'",    "Threshold is triggered when the value is smaller than the min value (max is ignored)"
		 "'>'",    "Threshold is triggered when the value is greater than the min value (max is ignored)"
		
		If the option is set to 'x' (threshold turned off) the callback is triggered with the fixed period.
		*/
		this.ipcon.sendRequest(this, BrickletDistanceUSV2.FUNCTION_SET_DISTANCE_CALLBACK_CONFIGURATION, [period, valueHasToChange, option, min, max], 'I ? c H H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getDistanceCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the callback configuration as set by :func:`Set Distance Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletDistanceUSV2.FUNCTION_GET_DISTANCE_CALLBACK_CONFIGURATION, [], '', 18, 'I ? c H H', returnCallback, errorCallback, false, true);
	};
	this.setUpdateRate = function(updateRate, returnCallback, errorCallback) {
		/*
		Sets the update rate to 2 Hz or 10 Hz.
		
		With 2 Hz update rate the noise is about ±1mm, while with 10 Hz update rate the noise
		increases to about ±5mm.
		*/
		this.ipcon.sendRequest(this, BrickletDistanceUSV2.FUNCTION_SET_UPDATE_RATE, [updateRate], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getUpdateRate = function(returnCallback, errorCallback) {
		/*
		Returns the update rate as set by :func:`Set Update Rate`.
		*/
		this.ipcon.sendRequest(this, BrickletDistanceUSV2.FUNCTION_GET_UPDATE_RATE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setDistanceLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Configures the distance LED to be either turned off, turned on, blink in
		heartbeat mode or show the distance (brighter = object is nearer).
		*/
		this.ipcon.sendRequest(this, BrickletDistanceUSV2.FUNCTION_SET_DISTANCE_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getDistanceLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the LED configuration as set by :func:`Set Distance LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletDistanceUSV2.FUNCTION_GET_DISTANCE_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPErrorCount = function(returnCallback, errorCallback) {
		/*
		Returns the error count for the communication between Brick and Bricklet.
		
		The errors are divided into
		
		* ACK checksum errors,
		* message checksum errors,
		* framing errors and
		* overflow errors.
		
		The errors counts are for errors that occur on the Bricklet side. All
		Bricks have a similar function that returns the errors on the Brick side.
		*/
		this.ipcon.sendRequest(this, BrickletDistanceUSV2.FUNCTION_GET_SPITFP_ERROR_COUNT, [], '', 24, 'I I I I', returnCallback, errorCallback, false, true);
	};
	this.setBootloaderMode = function(mode, returnCallback, errorCallback) {
		/*
		Sets the bootloader mode and returns the status after the requested
		mode change was instigated.
		
		You can change from bootloader mode to firmware mode and vice versa. A change
		from bootloader mode to firmware mode will only take place if the entry function,
		device identifier and CRC are present and correct.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletDistanceUSV2.FUNCTION_SET_BOOTLOADER_MODE, [mode], 'B', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getBootloaderMode = function(returnCallback, errorCallback) {
		/*
		Returns the current bootloader mode, see :func:`Set Bootloader Mode`.
		*/
		this.ipcon.sendRequest(this, BrickletDistanceUSV2.FUNCTION_GET_BOOTLOADER_MODE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setWriteFirmwarePointer = function(pointer, returnCallback, errorCallback) {
		/*
		Sets the firmware pointer for :func:`Write Firmware`. The pointer has
		to be increased by chunks of size 64. The data is written to flash
		every 4 chunks (which equals to one page of size 256).
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletDistanceUSV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER, [pointer], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeFirmware = function(data, returnCallback, errorCallback) {
		/*
		Writes 64 Bytes of firmware at the position as written by
		:func:`Set Write Firmware Pointer` before. The firmware is written
		to flash every 4 chunks.
		
		You can only write firmware in bootloader mode.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletDistanceUSV2.FUNCTION_WRITE_FIRMWARE, [data], 'B64', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setStatusLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Sets the status LED configuration. By default the LED shows
		communication traffic between Brick and Bricklet, it flickers once
		for every 10 received data packets.
		
		You can also turn the LED permanently on/off or show a heartbeat.
		
		If the Bricklet is in bootloader mode, the LED is will show heartbeat by default.
		*/
		this.ipcon.sendRequest(this, BrickletDistanceUSV2.FUNCTION_SET_STATUS_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getStatusLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Status LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletDistanceUSV2.FUNCTION_GET_STATUS_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getChipTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature as measured inside the microcontroller. The
		value returned is not the ambient temperature!
		
		The temperature is only proportional to the real temperature and it has bad
		accuracy. Practically it is only useful as an indicator for
		temperature changes.
		*/
		this.ipcon.sendRequest(this, BrickletDistanceUSV2.FUNCTION_GET_CHIP_TEMPERATURE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.reset = function(returnCallback, errorCallback) {
		/*
		Calling this function will reset the Bricklet. All configurations
		will be lost.
		
		After a reset you have to create new device objects,
		calling functions on the existing ones will result in
		undefined behavior!
		*/
		this.ipcon.sendRequest(this, BrickletDistanceUSV2.FUNCTION_RESET, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeUID = function(uid, returnCallback, errorCallback) {
		/*
		Writes a new UID into flash. If you want to set a new UID
		you have to decode the Base58 encoded UID string into an
		integer first.
		
		We recommend that you use Brick Viewer to change the UID.
		*/
		this.ipcon.sendRequest(this, BrickletDistanceUSV2.FUNCTION_WRITE_UID, [uid], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.readUID = function(returnCallback, errorCallback) {
		/*
		Returns the current UID as an integer. Encode as
		Base58 to get the usual string version.
		*/
		this.ipcon.sendRequest(this, BrickletDistanceUSV2.FUNCTION_READ_UID, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletDistanceUSV2.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletDistanceUSV2;

},{"./Device":279,"./IPConnection":280}],175:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletDualButton.DEVICE_IDENTIFIER = 230;
BrickletDualButton.DEVICE_DISPLAY_NAME = 'Dual Button Bricklet';
BrickletDualButton.CALLBACK_STATE_CHANGED = 4;
BrickletDualButton.FUNCTION_SET_LED_STATE = 1;
BrickletDualButton.FUNCTION_GET_LED_STATE = 2;
BrickletDualButton.FUNCTION_GET_BUTTON_STATE = 3;
BrickletDualButton.FUNCTION_SET_SELECTED_LED_STATE = 5;
BrickletDualButton.FUNCTION_GET_IDENTITY = 255;
BrickletDualButton.LED_STATE_AUTO_TOGGLE_ON = 0;
BrickletDualButton.LED_STATE_AUTO_TOGGLE_OFF = 1;
BrickletDualButton.LED_STATE_ON = 2;
BrickletDualButton.LED_STATE_OFF = 3;
BrickletDualButton.BUTTON_STATE_PRESSED = 0;
BrickletDualButton.BUTTON_STATE_RELEASED = 1;
BrickletDualButton.LED_LEFT = 0;
BrickletDualButton.LED_RIGHT = 1;

function BrickletDualButton(uid, ipcon) {
	//Two tactile buttons with built-in blue LEDs

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletDualButton.DEVICE_IDENTIFIER, BrickletDualButton.DEVICE_DISPLAY_NAME);
	BrickletDualButton.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickletDualButton.FUNCTION_SET_LED_STATE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletDualButton.FUNCTION_GET_LED_STATE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletDualButton.FUNCTION_GET_BUTTON_STATE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletDualButton.FUNCTION_SET_SELECTED_LED_STATE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletDualButton.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletDualButton.CALLBACK_STATE_CHANGED] = [12, 'B B B B'];



	this.setLEDState = function(ledL, ledR, returnCallback, errorCallback) {
		/*
		Sets the state of the LEDs. Possible states are:
		
		* 0 = AutoToggleOn: Enables auto toggle with initially enabled LED.
		* 1 = AutoToggleOff: Activates auto toggle with initially disabled LED.
		* 2 = On: Enables LED (auto toggle is disabled).
		* 3 = Off: Disables LED (auto toggle is disabled).
		
		In auto toggle mode the LED is toggled automatically at each press of a button.
		
		If you just want to set one of the LEDs and don't know the current state
		of the other LED, you can get the state with :func:`Get LED State` or you
		can use :func:`Set Selected LED State`.
		*/
		this.ipcon.sendRequest(this, BrickletDualButton.FUNCTION_SET_LED_STATE, [ledL, ledR], 'B B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getLEDState = function(returnCallback, errorCallback) {
		/*
		Returns the current state of the LEDs, as set by :func:`Set LED State`.
		*/
		this.ipcon.sendRequest(this, BrickletDualButton.FUNCTION_GET_LED_STATE, [], '', 10, 'B B', returnCallback, errorCallback, false, true);
	};
	this.getButtonState = function(returnCallback, errorCallback) {
		/*
		Returns the current state for both buttons. Possible states are:
		
		* 0 = pressed
		* 1 = released
		*/
		this.ipcon.sendRequest(this, BrickletDualButton.FUNCTION_GET_BUTTON_STATE, [], '', 10, 'B B', returnCallback, errorCallback, false, true);
	};
	this.setSelectedLEDState = function(led, state, returnCallback, errorCallback) {
		/*
		Sets the state of the selected LED (0 or 1).
		
		The other LED remains untouched.
		*/
		this.ipcon.sendRequest(this, BrickletDualButton.FUNCTION_SET_SELECTED_LED_STATE, [led, state], 'B B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletDualButton.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletDualButton;

},{"./Device":279,"./IPConnection":280}],176:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletDualButtonV2.DEVICE_IDENTIFIER = 2119;
BrickletDualButtonV2.DEVICE_DISPLAY_NAME = 'Dual Button Bricklet 2.0';
BrickletDualButtonV2.CALLBACK_STATE_CHANGED = 4;
BrickletDualButtonV2.FUNCTION_SET_LED_STATE = 1;
BrickletDualButtonV2.FUNCTION_GET_LED_STATE = 2;
BrickletDualButtonV2.FUNCTION_GET_BUTTON_STATE = 3;
BrickletDualButtonV2.FUNCTION_SET_SELECTED_LED_STATE = 5;
BrickletDualButtonV2.FUNCTION_SET_STATE_CHANGED_CALLBACK_CONFIGURATION = 6;
BrickletDualButtonV2.FUNCTION_GET_STATE_CHANGED_CALLBACK_CONFIGURATION = 7;
BrickletDualButtonV2.FUNCTION_GET_SPITFP_ERROR_COUNT = 234;
BrickletDualButtonV2.FUNCTION_SET_BOOTLOADER_MODE = 235;
BrickletDualButtonV2.FUNCTION_GET_BOOTLOADER_MODE = 236;
BrickletDualButtonV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER = 237;
BrickletDualButtonV2.FUNCTION_WRITE_FIRMWARE = 238;
BrickletDualButtonV2.FUNCTION_SET_STATUS_LED_CONFIG = 239;
BrickletDualButtonV2.FUNCTION_GET_STATUS_LED_CONFIG = 240;
BrickletDualButtonV2.FUNCTION_GET_CHIP_TEMPERATURE = 242;
BrickletDualButtonV2.FUNCTION_RESET = 243;
BrickletDualButtonV2.FUNCTION_WRITE_UID = 248;
BrickletDualButtonV2.FUNCTION_READ_UID = 249;
BrickletDualButtonV2.FUNCTION_GET_IDENTITY = 255;
BrickletDualButtonV2.LED_STATE_AUTO_TOGGLE_ON = 0;
BrickletDualButtonV2.LED_STATE_AUTO_TOGGLE_OFF = 1;
BrickletDualButtonV2.LED_STATE_ON = 2;
BrickletDualButtonV2.LED_STATE_OFF = 3;
BrickletDualButtonV2.BUTTON_STATE_PRESSED = 0;
BrickletDualButtonV2.BUTTON_STATE_RELEASED = 1;
BrickletDualButtonV2.LED_LEFT = 0;
BrickletDualButtonV2.LED_RIGHT = 1;
BrickletDualButtonV2.BOOTLOADER_MODE_BOOTLOADER = 0;
BrickletDualButtonV2.BOOTLOADER_MODE_FIRMWARE = 1;
BrickletDualButtonV2.BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT = 2;
BrickletDualButtonV2.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT = 3;
BrickletDualButtonV2.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT = 4;
BrickletDualButtonV2.BOOTLOADER_STATUS_OK = 0;
BrickletDualButtonV2.BOOTLOADER_STATUS_INVALID_MODE = 1;
BrickletDualButtonV2.BOOTLOADER_STATUS_NO_CHANGE = 2;
BrickletDualButtonV2.BOOTLOADER_STATUS_ENTRY_FUNCTION_NOT_PRESENT = 3;
BrickletDualButtonV2.BOOTLOADER_STATUS_DEVICE_IDENTIFIER_INCORRECT = 4;
BrickletDualButtonV2.BOOTLOADER_STATUS_CRC_MISMATCH = 5;
BrickletDualButtonV2.STATUS_LED_CONFIG_OFF = 0;
BrickletDualButtonV2.STATUS_LED_CONFIG_ON = 1;
BrickletDualButtonV2.STATUS_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletDualButtonV2.STATUS_LED_CONFIG_SHOW_STATUS = 3;

function BrickletDualButtonV2(uid, ipcon) {
	//Two tactile buttons with built-in blue LEDs

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletDualButtonV2.DEVICE_IDENTIFIER, BrickletDualButtonV2.DEVICE_DISPLAY_NAME);
	BrickletDualButtonV2.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickletDualButtonV2.FUNCTION_SET_LED_STATE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletDualButtonV2.FUNCTION_GET_LED_STATE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletDualButtonV2.FUNCTION_GET_BUTTON_STATE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletDualButtonV2.FUNCTION_SET_SELECTED_LED_STATE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletDualButtonV2.FUNCTION_SET_STATE_CHANGED_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletDualButtonV2.FUNCTION_GET_STATE_CHANGED_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletDualButtonV2.FUNCTION_GET_SPITFP_ERROR_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletDualButtonV2.FUNCTION_SET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletDualButtonV2.FUNCTION_GET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletDualButtonV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletDualButtonV2.FUNCTION_WRITE_FIRMWARE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletDualButtonV2.FUNCTION_SET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletDualButtonV2.FUNCTION_GET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletDualButtonV2.FUNCTION_GET_CHIP_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletDualButtonV2.FUNCTION_RESET] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletDualButtonV2.FUNCTION_WRITE_UID] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletDualButtonV2.FUNCTION_READ_UID] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletDualButtonV2.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletDualButtonV2.CALLBACK_STATE_CHANGED] = [12, 'B B B B'];



	this.setLEDState = function(ledL, ledR, returnCallback, errorCallback) {
		/*
		Sets the state of the LEDs. Possible states are:
		
		* 0 = AutoToggleOn: Enables auto toggle with initially enabled LED.
		* 1 = AutoToggleOff: Activates auto toggle with initially disabled LED.
		* 2 = On: Enables LED (auto toggle is disabled).
		* 3 = Off: Disables LED (auto toggle is disabled).
		
		In auto toggle mode the LED is toggled automatically at each press of a button.
		
		If you just want to set one of the LEDs and don't know the current state
		of the other LED, you can get the state with :func:`Get LED State` or you
		can use :func:`Set Selected LED State`.
		*/
		this.ipcon.sendRequest(this, BrickletDualButtonV2.FUNCTION_SET_LED_STATE, [ledL, ledR], 'B B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getLEDState = function(returnCallback, errorCallback) {
		/*
		Returns the current state of the LEDs, as set by :func:`Set LED State`.
		*/
		this.ipcon.sendRequest(this, BrickletDualButtonV2.FUNCTION_GET_LED_STATE, [], '', 10, 'B B', returnCallback, errorCallback, false, true);
	};
	this.getButtonState = function(returnCallback, errorCallback) {
		/*
		Returns the current state for both buttons. Possible states are:
		
		* 0 = pressed
		* 1 = released
		*/
		this.ipcon.sendRequest(this, BrickletDualButtonV2.FUNCTION_GET_BUTTON_STATE, [], '', 10, 'B B', returnCallback, errorCallback, false, true);
	};
	this.setSelectedLEDState = function(led, state, returnCallback, errorCallback) {
		/*
		Sets the state of the selected LED.
		
		The other LED remains untouched.
		*/
		this.ipcon.sendRequest(this, BrickletDualButtonV2.FUNCTION_SET_SELECTED_LED_STATE, [led, state], 'B B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.setStateChangedCallbackConfiguration = function(enabled, returnCallback, errorCallback) {
		/*
		If you enable this callback, the :cb:`State Changed` callback is triggered
		every time a button is pressed/released
		*/
		this.ipcon.sendRequest(this, BrickletDualButtonV2.FUNCTION_SET_STATE_CHANGED_CALLBACK_CONFIGURATION, [enabled], '?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getStateChangedCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set State Changed Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletDualButtonV2.FUNCTION_GET_STATE_CHANGED_CALLBACK_CONFIGURATION, [], '', 9, '?', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPErrorCount = function(returnCallback, errorCallback) {
		/*
		Returns the error count for the communication between Brick and Bricklet.
		
		The errors are divided into
		
		* ACK checksum errors,
		* message checksum errors,
		* framing errors and
		* overflow errors.
		
		The errors counts are for errors that occur on the Bricklet side. All
		Bricks have a similar function that returns the errors on the Brick side.
		*/
		this.ipcon.sendRequest(this, BrickletDualButtonV2.FUNCTION_GET_SPITFP_ERROR_COUNT, [], '', 24, 'I I I I', returnCallback, errorCallback, false, true);
	};
	this.setBootloaderMode = function(mode, returnCallback, errorCallback) {
		/*
		Sets the bootloader mode and returns the status after the requested
		mode change was instigated.
		
		You can change from bootloader mode to firmware mode and vice versa. A change
		from bootloader mode to firmware mode will only take place if the entry function,
		device identifier and CRC are present and correct.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletDualButtonV2.FUNCTION_SET_BOOTLOADER_MODE, [mode], 'B', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getBootloaderMode = function(returnCallback, errorCallback) {
		/*
		Returns the current bootloader mode, see :func:`Set Bootloader Mode`.
		*/
		this.ipcon.sendRequest(this, BrickletDualButtonV2.FUNCTION_GET_BOOTLOADER_MODE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setWriteFirmwarePointer = function(pointer, returnCallback, errorCallback) {
		/*
		Sets the firmware pointer for :func:`Write Firmware`. The pointer has
		to be increased by chunks of size 64. The data is written to flash
		every 4 chunks (which equals to one page of size 256).
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletDualButtonV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER, [pointer], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeFirmware = function(data, returnCallback, errorCallback) {
		/*
		Writes 64 Bytes of firmware at the position as written by
		:func:`Set Write Firmware Pointer` before. The firmware is written
		to flash every 4 chunks.
		
		You can only write firmware in bootloader mode.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletDualButtonV2.FUNCTION_WRITE_FIRMWARE, [data], 'B64', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setStatusLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Sets the status LED configuration. By default the LED shows
		communication traffic between Brick and Bricklet, it flickers once
		for every 10 received data packets.
		
		You can also turn the LED permanently on/off or show a heartbeat.
		
		If the Bricklet is in bootloader mode, the LED is will show heartbeat by default.
		*/
		this.ipcon.sendRequest(this, BrickletDualButtonV2.FUNCTION_SET_STATUS_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getStatusLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Status LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletDualButtonV2.FUNCTION_GET_STATUS_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getChipTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature as measured inside the microcontroller. The
		value returned is not the ambient temperature!
		
		The temperature is only proportional to the real temperature and it has bad
		accuracy. Practically it is only useful as an indicator for
		temperature changes.
		*/
		this.ipcon.sendRequest(this, BrickletDualButtonV2.FUNCTION_GET_CHIP_TEMPERATURE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.reset = function(returnCallback, errorCallback) {
		/*
		Calling this function will reset the Bricklet. All configurations
		will be lost.
		
		After a reset you have to create new device objects,
		calling functions on the existing ones will result in
		undefined behavior!
		*/
		this.ipcon.sendRequest(this, BrickletDualButtonV2.FUNCTION_RESET, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeUID = function(uid, returnCallback, errorCallback) {
		/*
		Writes a new UID into flash. If you want to set a new UID
		you have to decode the Base58 encoded UID string into an
		integer first.
		
		We recommend that you use Brick Viewer to change the UID.
		*/
		this.ipcon.sendRequest(this, BrickletDualButtonV2.FUNCTION_WRITE_UID, [uid], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.readUID = function(returnCallback, errorCallback) {
		/*
		Returns the current UID as an integer. Encode as
		Base58 to get the usual string version.
		*/
		this.ipcon.sendRequest(this, BrickletDualButtonV2.FUNCTION_READ_UID, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletDualButtonV2.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletDualButtonV2;

},{"./Device":279,"./IPConnection":280}],177:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletDualRelay.DEVICE_IDENTIFIER = 26;
BrickletDualRelay.DEVICE_DISPLAY_NAME = 'Dual Relay Bricklet';
BrickletDualRelay.CALLBACK_MONOFLOP_DONE = 5;
BrickletDualRelay.FUNCTION_SET_STATE = 1;
BrickletDualRelay.FUNCTION_GET_STATE = 2;
BrickletDualRelay.FUNCTION_SET_MONOFLOP = 3;
BrickletDualRelay.FUNCTION_GET_MONOFLOP = 4;
BrickletDualRelay.FUNCTION_SET_SELECTED_STATE = 6;
BrickletDualRelay.FUNCTION_GET_IDENTITY = 255;

function BrickletDualRelay(uid, ipcon) {
	//Two relays to switch AC/DC devices

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletDualRelay.DEVICE_IDENTIFIER, BrickletDualRelay.DEVICE_DISPLAY_NAME);
	BrickletDualRelay.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickletDualRelay.FUNCTION_SET_STATE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletDualRelay.FUNCTION_GET_STATE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletDualRelay.FUNCTION_SET_MONOFLOP] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletDualRelay.FUNCTION_GET_MONOFLOP] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletDualRelay.FUNCTION_SET_SELECTED_STATE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletDualRelay.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletDualRelay.CALLBACK_MONOFLOP_DONE] = [10, 'B ?'];



	this.setState = function(relay1, relay2, returnCallback, errorCallback) {
		/*
		Sets the state of the relays, *true* means on and *false* means off.
		For example: (true, false) turns relay 1 on and relay 2 off.
		
		If you just want to set one of the relays and don't know the current state
		of the other relay, you can get the state with :func:`Get State` or you
		can use :func:`Set Selected State`.
		
		All running monoflop timers will be aborted if this function is called.
		*/
		this.ipcon.sendRequest(this, BrickletDualRelay.FUNCTION_SET_STATE, [relay1, relay2], '? ?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getState = function(returnCallback, errorCallback) {
		/*
		Returns the state of the relays, *true* means on and *false* means off.
		*/
		this.ipcon.sendRequest(this, BrickletDualRelay.FUNCTION_GET_STATE, [], '', 10, '? ?', returnCallback, errorCallback, false, true);
	};
	this.setMonoflop = function(relay, state, time, returnCallback, errorCallback) {
		/*
		The first parameter can be 1 or 2 (relay 1 or relay 2). The second parameter
		is the desired state of the relay (*true* means on and *false* means off).
		The third parameter indicates the time that the relay should hold
		the state.
		
		If this function is called with the parameters (1, true, 1500):
		Relay 1 will turn on and in 1.5s it will turn off again.
		
		A monoflop can be used as a failsafe mechanism. For example: Lets assume you
		have a RS485 bus and a Dual Relay Bricklet connected to one of the slave
		stacks. You can now call this function every second, with a time parameter
		of two seconds. The relay will be on all the time. If now the RS485
		connection is lost, the relay will turn off in at most two seconds.
		*/
		this.ipcon.sendRequest(this, BrickletDualRelay.FUNCTION_SET_MONOFLOP, [relay, state, time], 'B ? I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getMonoflop = function(relay, returnCallback, errorCallback) {
		/*
		Returns (for the given relay) the current state and the time as set by
		:func:`Set Monoflop` as well as the remaining time until the state flips.
		
		If the timer is not running currently, the remaining time will be returned
		as 0.
		*/
		this.ipcon.sendRequest(this, BrickletDualRelay.FUNCTION_GET_MONOFLOP, [relay], 'B', 17, '? I I', returnCallback, errorCallback, false, true);
	};
	this.setSelectedState = function(relay, state, returnCallback, errorCallback) {
		/*
		Sets the state of the selected relay (1 or 2), *true* means on and *false* means off.
		
		A running monoflop timer for the selected relay will be aborted if this function is called.
		
		The other relay remains untouched.
		*/
		this.ipcon.sendRequest(this, BrickletDualRelay.FUNCTION_SET_SELECTED_STATE, [relay, state], 'B ?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletDualRelay.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletDualRelay;

},{"./Device":279,"./IPConnection":280}],178:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletDustDetector.DEVICE_IDENTIFIER = 260;
BrickletDustDetector.DEVICE_DISPLAY_NAME = 'Dust Detector Bricklet';
BrickletDustDetector.CALLBACK_DUST_DENSITY = 8;
BrickletDustDetector.CALLBACK_DUST_DENSITY_REACHED = 9;
BrickletDustDetector.FUNCTION_GET_DUST_DENSITY = 1;
BrickletDustDetector.FUNCTION_SET_DUST_DENSITY_CALLBACK_PERIOD = 2;
BrickletDustDetector.FUNCTION_GET_DUST_DENSITY_CALLBACK_PERIOD = 3;
BrickletDustDetector.FUNCTION_SET_DUST_DENSITY_CALLBACK_THRESHOLD = 4;
BrickletDustDetector.FUNCTION_GET_DUST_DENSITY_CALLBACK_THRESHOLD = 5;
BrickletDustDetector.FUNCTION_SET_DEBOUNCE_PERIOD = 6;
BrickletDustDetector.FUNCTION_GET_DEBOUNCE_PERIOD = 7;
BrickletDustDetector.FUNCTION_SET_MOVING_AVERAGE = 10;
BrickletDustDetector.FUNCTION_GET_MOVING_AVERAGE = 11;
BrickletDustDetector.FUNCTION_GET_IDENTITY = 255;
BrickletDustDetector.THRESHOLD_OPTION_OFF = 'x';
BrickletDustDetector.THRESHOLD_OPTION_OUTSIDE = 'o';
BrickletDustDetector.THRESHOLD_OPTION_INSIDE = 'i';
BrickletDustDetector.THRESHOLD_OPTION_SMALLER = '<';
BrickletDustDetector.THRESHOLD_OPTION_GREATER = '>';

function BrickletDustDetector(uid, ipcon) {
	//Measures dust density

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletDustDetector.DEVICE_IDENTIFIER, BrickletDustDetector.DEVICE_DISPLAY_NAME);
	BrickletDustDetector.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickletDustDetector.FUNCTION_GET_DUST_DENSITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletDustDetector.FUNCTION_SET_DUST_DENSITY_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletDustDetector.FUNCTION_GET_DUST_DENSITY_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletDustDetector.FUNCTION_SET_DUST_DENSITY_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletDustDetector.FUNCTION_GET_DUST_DENSITY_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletDustDetector.FUNCTION_SET_DEBOUNCE_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletDustDetector.FUNCTION_GET_DEBOUNCE_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletDustDetector.FUNCTION_SET_MOVING_AVERAGE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletDustDetector.FUNCTION_GET_MOVING_AVERAGE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletDustDetector.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletDustDetector.CALLBACK_DUST_DENSITY] = [10, 'H'];
	this.callbackFormats[BrickletDustDetector.CALLBACK_DUST_DENSITY_REACHED] = [10, 'H'];



	this.getDustDensity = function(returnCallback, errorCallback) {
		/*
		Returns the dust density.
		
		If you want to get the dust density periodically, it is recommended
		to use the :cb:`Dust Density` callback and set the period with
		:func:`Set Dust Density Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletDustDetector.FUNCTION_GET_DUST_DENSITY, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.setDustDensityCallbackPeriod = function(period, returnCallback, errorCallback) {
		/*
		Sets the period with which the :cb:`Dust Density` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		The :cb:`Dust Density` callback is only triggered if the dust density has
		changed since the last triggering.
		*/
		this.ipcon.sendRequest(this, BrickletDustDetector.FUNCTION_SET_DUST_DENSITY_CALLBACK_PERIOD, [period], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getDustDensityCallbackPeriod = function(returnCallback, errorCallback) {
		/*
		Returns the period as set by :func:`Set Dust Density Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletDustDetector.FUNCTION_GET_DUST_DENSITY_CALLBACK_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setDustDensityCallbackThreshold = function(option, min, max, returnCallback, errorCallback) {
		/*
		Sets the thresholds for the :cb:`Dust Density Reached` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Callback is turned off"
		 "'o'",    "Callback is triggered when the dust density value is *outside* the min and max values"
		 "'i'",    "Callback is triggered when the dust density value is *inside* the min and max values"
		 "'<'",    "Callback is triggered when the dust density value is smaller than the min value (max is ignored)"
		 "'>'",    "Callback is triggered when the dust density value is greater than the min value (max is ignored)"
		*/
		this.ipcon.sendRequest(this, BrickletDustDetector.FUNCTION_SET_DUST_DENSITY_CALLBACK_THRESHOLD, [option, min, max], 'c H H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getDustDensityCallbackThreshold = function(returnCallback, errorCallback) {
		/*
		Returns the threshold as set by :func:`Set Dust Density Callback Threshold`.
		*/
		this.ipcon.sendRequest(this, BrickletDustDetector.FUNCTION_GET_DUST_DENSITY_CALLBACK_THRESHOLD, [], '', 13, 'c H H', returnCallback, errorCallback, false, true);
	};
	this.setDebouncePeriod = function(debounce, returnCallback, errorCallback) {
		/*
		Sets the period with which the threshold callback
		
		* :cb:`Dust Density Reached`
		
		is triggered, if the threshold
		
		* :func:`Set Dust Density Callback Threshold`
		
		keeps being reached.
		*/
		this.ipcon.sendRequest(this, BrickletDustDetector.FUNCTION_SET_DEBOUNCE_PERIOD, [debounce], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getDebouncePeriod = function(returnCallback, errorCallback) {
		/*
		Returns the debounce period as set by :func:`Set Debounce Period`.
		*/
		this.ipcon.sendRequest(this, BrickletDustDetector.FUNCTION_GET_DEBOUNCE_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setMovingAverage = function(average, returnCallback, errorCallback) {
		/*
		Sets the length of a `moving averaging <https://en.wikipedia.org/wiki/Moving_average>`__
		for the dust density.
		
		Setting the length to 0 will turn the averaging completely off. With less
		averaging, there is more noise on the data.
		*/
		this.ipcon.sendRequest(this, BrickletDustDetector.FUNCTION_SET_MOVING_AVERAGE, [average], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getMovingAverage = function(returnCallback, errorCallback) {
		/*
		Returns the length moving average as set by :func:`Set Moving Average`.
		*/
		this.ipcon.sendRequest(this, BrickletDustDetector.FUNCTION_GET_MOVING_AVERAGE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletDustDetector.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletDustDetector;

},{"./Device":279,"./IPConnection":280}],179:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletEPaper296x128.DEVICE_IDENTIFIER = 2146;
BrickletEPaper296x128.DEVICE_DISPLAY_NAME = 'E-Paper 296x128 Bricklet';
BrickletEPaper296x128.CALLBACK_DRAW_STATUS = 11;
BrickletEPaper296x128.FUNCTION_DRAW = 1;
BrickletEPaper296x128.FUNCTION_GET_DRAW_STATUS = 2;
BrickletEPaper296x128.FUNCTION_WRITE_BLACK_WHITE_LOW_LEVEL = 3;
BrickletEPaper296x128.FUNCTION_READ_BLACK_WHITE_LOW_LEVEL = 4;
BrickletEPaper296x128.FUNCTION_WRITE_COLOR_LOW_LEVEL = 5;
BrickletEPaper296x128.FUNCTION_READ_COLOR_LOW_LEVEL = 6;
BrickletEPaper296x128.FUNCTION_FILL_DISPLAY = 7;
BrickletEPaper296x128.FUNCTION_DRAW_TEXT = 8;
BrickletEPaper296x128.FUNCTION_DRAW_LINE = 9;
BrickletEPaper296x128.FUNCTION_DRAW_BOX = 10;
BrickletEPaper296x128.FUNCTION_SET_UPDATE_MODE = 12;
BrickletEPaper296x128.FUNCTION_GET_UPDATE_MODE = 13;
BrickletEPaper296x128.FUNCTION_SET_DISPLAY_TYPE = 14;
BrickletEPaper296x128.FUNCTION_GET_DISPLAY_TYPE = 15;
BrickletEPaper296x128.FUNCTION_GET_SPITFP_ERROR_COUNT = 234;
BrickletEPaper296x128.FUNCTION_SET_BOOTLOADER_MODE = 235;
BrickletEPaper296x128.FUNCTION_GET_BOOTLOADER_MODE = 236;
BrickletEPaper296x128.FUNCTION_SET_WRITE_FIRMWARE_POINTER = 237;
BrickletEPaper296x128.FUNCTION_WRITE_FIRMWARE = 238;
BrickletEPaper296x128.FUNCTION_SET_STATUS_LED_CONFIG = 239;
BrickletEPaper296x128.FUNCTION_GET_STATUS_LED_CONFIG = 240;
BrickletEPaper296x128.FUNCTION_GET_CHIP_TEMPERATURE = 242;
BrickletEPaper296x128.FUNCTION_RESET = 243;
BrickletEPaper296x128.FUNCTION_WRITE_UID = 248;
BrickletEPaper296x128.FUNCTION_READ_UID = 249;
BrickletEPaper296x128.FUNCTION_GET_IDENTITY = 255;
BrickletEPaper296x128.DRAW_STATUS_IDLE = 0;
BrickletEPaper296x128.DRAW_STATUS_COPYING = 1;
BrickletEPaper296x128.DRAW_STATUS_DRAWING = 2;
BrickletEPaper296x128.COLOR_BLACK = 0;
BrickletEPaper296x128.COLOR_WHITE = 1;
BrickletEPaper296x128.COLOR_RED = 2;
BrickletEPaper296x128.COLOR_GRAY = 2;
BrickletEPaper296x128.FONT_6X8 = 0;
BrickletEPaper296x128.FONT_6X16 = 1;
BrickletEPaper296x128.FONT_6X24 = 2;
BrickletEPaper296x128.FONT_6X32 = 3;
BrickletEPaper296x128.FONT_12X16 = 4;
BrickletEPaper296x128.FONT_12X24 = 5;
BrickletEPaper296x128.FONT_12X32 = 6;
BrickletEPaper296x128.FONT_18X24 = 7;
BrickletEPaper296x128.FONT_18X32 = 8;
BrickletEPaper296x128.FONT_24X32 = 9;
BrickletEPaper296x128.ORIENTATION_HORIZONTAL = 0;
BrickletEPaper296x128.ORIENTATION_VERTICAL = 1;
BrickletEPaper296x128.UPDATE_MODE_DEFAULT = 0;
BrickletEPaper296x128.UPDATE_MODE_BLACK_WHITE = 1;
BrickletEPaper296x128.UPDATE_MODE_DELTA = 2;
BrickletEPaper296x128.DISPLAY_TYPE_BLACK_WHITE_RED = 0;
BrickletEPaper296x128.DISPLAY_TYPE_BLACK_WHITE_GRAY = 1;
BrickletEPaper296x128.BOOTLOADER_MODE_BOOTLOADER = 0;
BrickletEPaper296x128.BOOTLOADER_MODE_FIRMWARE = 1;
BrickletEPaper296x128.BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT = 2;
BrickletEPaper296x128.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT = 3;
BrickletEPaper296x128.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT = 4;
BrickletEPaper296x128.BOOTLOADER_STATUS_OK = 0;
BrickletEPaper296x128.BOOTLOADER_STATUS_INVALID_MODE = 1;
BrickletEPaper296x128.BOOTLOADER_STATUS_NO_CHANGE = 2;
BrickletEPaper296x128.BOOTLOADER_STATUS_ENTRY_FUNCTION_NOT_PRESENT = 3;
BrickletEPaper296x128.BOOTLOADER_STATUS_DEVICE_IDENTIFIER_INCORRECT = 4;
BrickletEPaper296x128.BOOTLOADER_STATUS_CRC_MISMATCH = 5;
BrickletEPaper296x128.STATUS_LED_CONFIG_OFF = 0;
BrickletEPaper296x128.STATUS_LED_CONFIG_ON = 1;
BrickletEPaper296x128.STATUS_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletEPaper296x128.STATUS_LED_CONFIG_SHOW_STATUS = 3;

function BrickletEPaper296x128(uid, ipcon) {
	//Three color 296x128 e-paper display

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletEPaper296x128.DEVICE_IDENTIFIER, BrickletEPaper296x128.DEVICE_DISPLAY_NAME);
	BrickletEPaper296x128.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickletEPaper296x128.FUNCTION_DRAW] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletEPaper296x128.FUNCTION_GET_DRAW_STATUS] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletEPaper296x128.FUNCTION_WRITE_BLACK_WHITE_LOW_LEVEL] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletEPaper296x128.FUNCTION_READ_BLACK_WHITE_LOW_LEVEL] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletEPaper296x128.FUNCTION_WRITE_COLOR_LOW_LEVEL] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletEPaper296x128.FUNCTION_READ_COLOR_LOW_LEVEL] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletEPaper296x128.FUNCTION_FILL_DISPLAY] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletEPaper296x128.FUNCTION_DRAW_TEXT] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletEPaper296x128.FUNCTION_DRAW_LINE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletEPaper296x128.FUNCTION_DRAW_BOX] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletEPaper296x128.FUNCTION_SET_UPDATE_MODE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletEPaper296x128.FUNCTION_GET_UPDATE_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletEPaper296x128.FUNCTION_SET_DISPLAY_TYPE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletEPaper296x128.FUNCTION_GET_DISPLAY_TYPE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletEPaper296x128.FUNCTION_GET_SPITFP_ERROR_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletEPaper296x128.FUNCTION_SET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletEPaper296x128.FUNCTION_GET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletEPaper296x128.FUNCTION_SET_WRITE_FIRMWARE_POINTER] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletEPaper296x128.FUNCTION_WRITE_FIRMWARE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletEPaper296x128.FUNCTION_SET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletEPaper296x128.FUNCTION_GET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletEPaper296x128.FUNCTION_GET_CHIP_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletEPaper296x128.FUNCTION_RESET] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletEPaper296x128.FUNCTION_WRITE_UID] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletEPaper296x128.FUNCTION_READ_UID] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletEPaper296x128.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletEPaper296x128.CALLBACK_DRAW_STATUS] = [9, 'B'];


	this.streamStateObjects[BrickletEPaper296x128.FUNCTION_WRITE_BLACK_WHITE_LOW_LEVEL] = {
		'dataMapping': [],
		'dataMappingStreamIn': [null, null, null, null, 'streamLength', 'streamChunkOffset', 'streamChunkData'],
		'streamProperties': {
			'fixedLength': null,
			'singleChunk': false,
			'shortWrite': false
		},
		'responseProperties': {
			'running': false,
			'runningSubcall': false,
			'runningSubcallOOS': false,
			'waitingFirstChunk': true,
			'timeout': null,
			'data': [],
			'streamInChunkOffset': 0,
			'streamInChunkLength': 0,
			'streamInResponseEmpty': true,
			'streamInWritten': 0,
			'streamInLLParams': null,
			'responseHandler': null,
			'packFormatString': 'H B H B H H ?432',
			'unpackFormatString': '',
			'returnCB': null,
			'errorCB': null,
			'callQueue': []
		}
	};
	this.streamStateObjects[BrickletEPaper296x128.FUNCTION_READ_BLACK_WHITE_LOW_LEVEL] = {
		'dataMapping': ['streamLength', 'streamChunkOffset', 'streamChunkData'],
		'dataMappingStreamIn': [],
		'streamProperties': {
			'fixedLength': null,
			'singleChunk': false,
			'shortWrite': false
		},
		'responseProperties': {
			'running': false,
			'runningSubcall': false,
			'runningSubcallOOS': false,
			'waitingFirstChunk': true,
			'timeout': null,
			'data': [],
			'streamInChunkOffset': 0,
			'streamInChunkLength': 0,
			'streamInResponseEmpty': true,
			'streamInWritten': 0,
			'streamInLLParams': null,
			'responseHandler': null,
			'packFormatString': 'H B H B',
			'unpackFormatString': 'H H ?464',
			'returnCB': null,
			'errorCB': null,
			'callQueue': []
		}
	};
	this.streamStateObjects[BrickletEPaper296x128.FUNCTION_WRITE_COLOR_LOW_LEVEL] = {
		'dataMapping': [],
		'dataMappingStreamIn': [null, null, null, null, 'streamLength', 'streamChunkOffset', 'streamChunkData'],
		'streamProperties': {
			'fixedLength': null,
			'singleChunk': false,
			'shortWrite': false
		},
		'responseProperties': {
			'running': false,
			'runningSubcall': false,
			'runningSubcallOOS': false,
			'waitingFirstChunk': true,
			'timeout': null,
			'data': [],
			'streamInChunkOffset': 0,
			'streamInChunkLength': 0,
			'streamInResponseEmpty': true,
			'streamInWritten': 0,
			'streamInLLParams': null,
			'responseHandler': null,
			'packFormatString': 'H B H B H H ?432',
			'unpackFormatString': '',
			'returnCB': null,
			'errorCB': null,
			'callQueue': []
		}
	};
	this.streamStateObjects[BrickletEPaper296x128.FUNCTION_READ_COLOR_LOW_LEVEL] = {
		'dataMapping': ['streamLength', 'streamChunkOffset', 'streamChunkData'],
		'dataMappingStreamIn': [],
		'streamProperties': {
			'fixedLength': null,
			'singleChunk': false,
			'shortWrite': false
		},
		'responseProperties': {
			'running': false,
			'runningSubcall': false,
			'runningSubcallOOS': false,
			'waitingFirstChunk': true,
			'timeout': null,
			'data': [],
			'streamInChunkOffset': 0,
			'streamInChunkLength': 0,
			'streamInResponseEmpty': true,
			'streamInWritten': 0,
			'streamInLLParams': null,
			'responseHandler': null,
			'packFormatString': 'H B H B',
			'unpackFormatString': 'H H ?464',
			'returnCB': null,
			'errorCB': null,
			'callQueue': []
		}
	};

	this.draw = function(returnCallback, errorCallback) {
		/*
		Draws the current black/white and red or gray buffer to the e-paper display.
		
		The Bricklet does not have any double-buffering. You should not call
		this function while writing to the buffer. See :func:`Get Draw Status`.
		*/
		this.ipcon.sendRequest(this, BrickletEPaper296x128.FUNCTION_DRAW, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getDrawStatus = function(returnCallback, errorCallback) {
		/*
		Returns one of three draw statuses:
		
		* Idle
		* Copying: Data is being copied from the buffer of the Bricklet to the buffer of the display.
		* Drawing: The display is updating its content (during this phase the flickering etc happens).
		
		You can write to the buffer (through one of the write or draw functions) when the status is
		either *idle* or *drawing*. You should not write to the buffer while it is being *copied* to the
		display. There is no double-buffering.
		*/
		this.ipcon.sendRequest(this, BrickletEPaper296x128.FUNCTION_GET_DRAW_STATUS, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.writeBlackWhiteLowLevel = function(xStart, yStart, xEnd, yEnd, pixelsLength, pixelsChunkOffset, pixelsChunkData, returnCallback, errorCallback) {
		/*
		Writes black/white pixels to the specified window into the buffer.
		
		The pixels are written into the window line by line top to bottom
		and each line is written from left to right.
		
		The value 0 (false) corresponds to a black pixel and the value 1 (true) to a
		white pixel.
		
		This function writes the pixels into the black/white pixel buffer, to draw the
		buffer to the display use :func:`Draw`.
		
		Use :func:`Write Color` to write red or gray pixels.
		*/
		this.ipcon.sendRequest(this, BrickletEPaper296x128.FUNCTION_WRITE_BLACK_WHITE_LOW_LEVEL, [xStart, yStart, xEnd, yEnd, pixelsLength, pixelsChunkOffset, pixelsChunkData], 'H B H B H H ?432', 0, '', returnCallback, errorCallback, false, true);
	};
	this.readBlackWhiteLowLevel = function(xStart, yStart, xEnd, yEnd, returnCallback, errorCallback) {
		/*
		Returns the current content of the black/white pixel buffer for the specified window.
		
		The pixels are read into the window line by line top to bottom and
		each line is read from left to right.
		
		The current content of the buffer does not have to be the current content of the display.
		It is possible that the data was not drawn to the display yet and after a restart of
		the Bricklet the buffer will be reset to black, while the display retains its content.
		*/
		this.ipcon.sendRequest(this, BrickletEPaper296x128.FUNCTION_READ_BLACK_WHITE_LOW_LEVEL, [xStart, yStart, xEnd, yEnd], 'H B H B', 70, 'H H ?464', returnCallback, errorCallback, false, true);
	};
	this.writeColorLowLevel = function(xStart, yStart, xEnd, yEnd, pixelsLength, pixelsChunkOffset, pixelsChunkData, returnCallback, errorCallback) {
		/*
		The E-Paper 296x128 Bricklet is available with the colors black/white/red and
		black/white/gray. Depending on the model this function writes either red or
		gray pixels to the specified window into the buffer.
		
		The pixels are written into the window line by line top to bottom
		and each line is written from left to right.
		
		The value 0 (false) means that this pixel does not have color. It will be either black
		or white (see :func:`Write Black White`). The value 1 (true) corresponds to a red or gray
		pixel, depending on the Bricklet model.
		
		This function writes the pixels into the red or gray pixel buffer, to draw the buffer
		to the display use :func:`Draw`.
		
		Use :func:`Write Black White` to write black/white pixels.
		*/
		this.ipcon.sendRequest(this, BrickletEPaper296x128.FUNCTION_WRITE_COLOR_LOW_LEVEL, [xStart, yStart, xEnd, yEnd, pixelsLength, pixelsChunkOffset, pixelsChunkData], 'H B H B H H ?432', 0, '', returnCallback, errorCallback, false, true);
	};
	this.readColorLowLevel = function(xStart, yStart, xEnd, yEnd, returnCallback, errorCallback) {
		/*
		Returns the current content of the red or gray pixel buffer for the specified window.
		
		The pixels are written into the window line by line top to bottom
		and each line is written from left to right.
		
		The current content of the buffer does not have to be the current content of the display.
		It is possible that the data was not drawn to the display yet and after a restart of
		the Bricklet the buffer will be reset to black, while the display retains its content.
		*/
		this.ipcon.sendRequest(this, BrickletEPaper296x128.FUNCTION_READ_COLOR_LOW_LEVEL, [xStart, yStart, xEnd, yEnd], 'H B H B', 70, 'H H ?464', returnCallback, errorCallback, false, true);
	};
	this.fillDisplay = function(color, returnCallback, errorCallback) {
		/*
		Fills the complete content of the display with the given color.
		
		This function writes the pixels into the black/white/red|gray pixel buffer, to draw the buffer
		to the display use :func:`Draw`.
		*/
		this.ipcon.sendRequest(this, BrickletEPaper296x128.FUNCTION_FILL_DISPLAY, [color], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.drawText = function(positionX, positionY, font, color, orientation, text, returnCallback, errorCallback) {
		/*
		Draws a text with up to 50 characters at the pixel position (x, y).
		
		You can use one of 9 different font sizes and draw the text in
		black/white/red|gray. The text can be drawn horizontal or vertical.
		
		This function writes the pixels into the black/white/red|gray pixel buffer, to draw the buffer
		to the display use :func:`Draw`.
		*/
		this.ipcon.sendRequest(this, BrickletEPaper296x128.FUNCTION_DRAW_TEXT, [positionX, positionY, font, color, orientation, text], 'H B B B B s50', 0, '', returnCallback, errorCallback, false, true);
	};
	this.drawLine = function(positionXStart, positionYStart, positionXEnd, positionYEnd, color, returnCallback, errorCallback) {
		/*
		Draws a line from (x, y)-start to (x, y)-end in the given color.
		
		This function writes the pixels into the black/white/red|gray pixel buffer, to draw the buffer
		to the display use :func:`Draw`.
		*/
		this.ipcon.sendRequest(this, BrickletEPaper296x128.FUNCTION_DRAW_LINE, [positionXStart, positionYStart, positionXEnd, positionYEnd, color], 'H B H B B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.drawBox = function(positionXStart, positionYStart, positionXEnd, positionYEnd, fill, color, returnCallback, errorCallback) {
		/*
		Draws a box from (x, y)-start to (x, y)-end in the given color.
		
		If you set fill to true, the box will be filled with the
		color. Otherwise only the outline will be drawn.
		
		This function writes the pixels into the black/white/red|gray pixel buffer, to draw the buffer
		to the display use :func:`Draw`.
		*/
		this.ipcon.sendRequest(this, BrickletEPaper296x128.FUNCTION_DRAW_BOX, [positionXStart, positionYStart, positionXEnd, positionYEnd, fill, color], 'H B H B ? B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.setUpdateMode = function(updateMode, returnCallback, errorCallback) {
		/*
		.. note::
		 The default update mode corresponds to the default e-paper display
		 manufacturer settings. All of the other modes are experimental and
		 will result in increased ghosting and possibly other long-term
		 side effects.
		
		 If you want to know more about the inner workings of an e-paper display
		 take a look at this excellent video from Ben Krasnow:
		 `https://www.youtube.com/watch?v=MsbiO8EAsGw <https://www.youtube.com/watch?v=MsbiO8EAsGw>`__.
		
		 If you are not sure about this option, leave the update mode at default.
		
		Currently there are three update modes available:
		
		* Default: Settings as given by the manufacturer. An update will take about
		  7.5 seconds and during the update the screen will flicker several times.
		* Black/White: This will only update the black/white pixel. It uses the manufacturer
		  settings for black/white and ignores the red or gray pixel buffer. With this mode the
		  display will flicker once and it takes about 2.5 seconds. Compared to the default settings
		  there is more ghosting.
		* Delta: This will only update the black/white pixel. It uses an aggressive method where
		  the changes are not applied for a whole buffer but only for the delta between the last
		  and the next buffer. With this mode the display will not flicker during an update and
		  it takes about 900-950ms. Compared to the other two settings there is more ghosting. This
		  mode can be used for something like a flicker-free live update of a text.
		
		With the black/white/red display if you use either the black/white or the delta mode,
		after a while of going back and forth between black and white the white color will
		start to appear red-ish or pink-ish.
		
		If you use the aggressive delta mode and rapidly change the content, we recommend that you
		change back to the default mode every few hours and in the default mode cycle between the
		three available colors a few times. This will get rid of the ghosting and after that you can
		go back to the delta mode with flicker-free updates.
		*/
		this.ipcon.sendRequest(this, BrickletEPaper296x128.FUNCTION_SET_UPDATE_MODE, [updateMode], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getUpdateMode = function(returnCallback, errorCallback) {
		/*
		Returns the update mode as set by :func:`Set Update Mode`.
		*/
		this.ipcon.sendRequest(this, BrickletEPaper296x128.FUNCTION_GET_UPDATE_MODE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setDisplayType = function(displayType, returnCallback, errorCallback) {
		/*
		Sets the type of the display. The e-paper display is available
		in black/white/red and black/white/gray. This will be factory set
		during the flashing and testing phase. The value is saved in
		non-volatile memory and will stay after a power cycle.
		*/
		this.ipcon.sendRequest(this, BrickletEPaper296x128.FUNCTION_SET_DISPLAY_TYPE, [displayType], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getDisplayType = function(returnCallback, errorCallback) {
		/*
		Returns the type of the e-paper display. It can either be
		black/white/red or black/white/gray.
		*/
		this.ipcon.sendRequest(this, BrickletEPaper296x128.FUNCTION_GET_DISPLAY_TYPE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPErrorCount = function(returnCallback, errorCallback) {
		/*
		Returns the error count for the communication between Brick and Bricklet.
		
		The errors are divided into
		
		* ACK checksum errors,
		* message checksum errors,
		* framing errors and
		* overflow errors.
		
		The errors counts are for errors that occur on the Bricklet side. All
		Bricks have a similar function that returns the errors on the Brick side.
		*/
		this.ipcon.sendRequest(this, BrickletEPaper296x128.FUNCTION_GET_SPITFP_ERROR_COUNT, [], '', 24, 'I I I I', returnCallback, errorCallback, false, true);
	};
	this.setBootloaderMode = function(mode, returnCallback, errorCallback) {
		/*
		Sets the bootloader mode and returns the status after the requested
		mode change was instigated.
		
		You can change from bootloader mode to firmware mode and vice versa. A change
		from bootloader mode to firmware mode will only take place if the entry function,
		device identifier and CRC are present and correct.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletEPaper296x128.FUNCTION_SET_BOOTLOADER_MODE, [mode], 'B', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getBootloaderMode = function(returnCallback, errorCallback) {
		/*
		Returns the current bootloader mode, see :func:`Set Bootloader Mode`.
		*/
		this.ipcon.sendRequest(this, BrickletEPaper296x128.FUNCTION_GET_BOOTLOADER_MODE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setWriteFirmwarePointer = function(pointer, returnCallback, errorCallback) {
		/*
		Sets the firmware pointer for :func:`Write Firmware`. The pointer has
		to be increased by chunks of size 64. The data is written to flash
		every 4 chunks (which equals to one page of size 256).
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletEPaper296x128.FUNCTION_SET_WRITE_FIRMWARE_POINTER, [pointer], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeFirmware = function(data, returnCallback, errorCallback) {
		/*
		Writes 64 Bytes of firmware at the position as written by
		:func:`Set Write Firmware Pointer` before. The firmware is written
		to flash every 4 chunks.
		
		You can only write firmware in bootloader mode.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletEPaper296x128.FUNCTION_WRITE_FIRMWARE, [data], 'B64', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setStatusLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Sets the status LED configuration. By default the LED shows
		communication traffic between Brick and Bricklet, it flickers once
		for every 10 received data packets.
		
		You can also turn the LED permanently on/off or show a heartbeat.
		
		If the Bricklet is in bootloader mode, the LED is will show heartbeat by default.
		*/
		this.ipcon.sendRequest(this, BrickletEPaper296x128.FUNCTION_SET_STATUS_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getStatusLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Status LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletEPaper296x128.FUNCTION_GET_STATUS_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getChipTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature as measured inside the microcontroller. The
		value returned is not the ambient temperature!
		
		The temperature is only proportional to the real temperature and it has bad
		accuracy. Practically it is only useful as an indicator for
		temperature changes.
		*/
		this.ipcon.sendRequest(this, BrickletEPaper296x128.FUNCTION_GET_CHIP_TEMPERATURE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.reset = function(returnCallback, errorCallback) {
		/*
		Calling this function will reset the Bricklet. All configurations
		will be lost.
		
		After a reset you have to create new device objects,
		calling functions on the existing ones will result in
		undefined behavior!
		*/
		this.ipcon.sendRequest(this, BrickletEPaper296x128.FUNCTION_RESET, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeUID = function(uid, returnCallback, errorCallback) {
		/*
		Writes a new UID into flash. If you want to set a new UID
		you have to decode the Base58 encoded UID string into an
		integer first.
		
		We recommend that you use Brick Viewer to change the UID.
		*/
		this.ipcon.sendRequest(this, BrickletEPaper296x128.FUNCTION_WRITE_UID, [uid], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.readUID = function(returnCallback, errorCallback) {
		/*
		Returns the current UID as an integer. Encode as
		Base58 to get the usual string version.
		*/
		this.ipcon.sendRequest(this, BrickletEPaper296x128.FUNCTION_READ_UID, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletEPaper296x128.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};
	this.writeBlackWhite = function(xStart, yStart, xEnd, yEnd, pixels, returnCallback, errorCallback) {
		/*
		Writes black/white pixels to the specified window into the buffer.
		
		The pixels are written into the window line by line top to bottom
		and each line is written from left to right.
		
		The value 0 (false) corresponds to a black pixel and the value 1 (true) to a
		white pixel.
		
		This function writes the pixels into the black/white pixel buffer, to draw the
		buffer to the display use :func:`Draw`.
		
		Use :func:`Write Color` to write red or gray pixels.
		*/

		var pixelsLength = 0;
		var pixelsChunkData = [];
		var pixelsChunkOffset = 0;
		var streamStateObject = this.streamStateObjects[3];

		if (pixels.length > 65535) {
			if (errorCallback !== null){
				errorCallback(IPConnection.ERROR_INVALID_PARAMETER);
			}

			this.resetStreamStateObject(streamStateObject);

			if (streamStateObject['responseProperties']['callQueue'].length > 0) {
				streamStateObject['responseProperties']['callQueue'].shift()(device);
			}

			return;
		}

		if (!this.getResponseExpected(3)) {
			if (streamStateObject['streamProperties']['fixedLength']) {
				pixelsLength = streamStateObject['streamProperties']['fixedLength'];
			}
			else {
				pixelsLength = pixels.length;
			}

			if (streamStateObject['streamProperties']['singleChunk']) {
				pixelsChunkData =
					this.ipcon.createChunkData(pixels, 0, 432, '\0');

				this.ipcon.sendRequest(this,
				                       BrickletEPaper296x128.FUNCTION_WRITE_BLACK_WHITE_LOW_LEVEL,
				                       [xStart, yStart, xEnd, yEnd, pixelsLength, pixelsChunkOffset, pixelsChunkData],
				                       'H B H B H H ?432',
				                       0,
				                       '',
				                       returnCallback,
				                       errorCallback,
				                       false,
				                       true);
			}
			else {
				while (pixelsChunkOffset < pixels.length) {
					pixelsChunkData =
						this.ipcon.createChunkData(pixels, pixelsChunkOffset, 432, '\0');

					this.ipcon.sendRequest(this,
					                       BrickletEPaper296x128.FUNCTION_WRITE_BLACK_WHITE_LOW_LEVEL,
					                       [xStart, yStart, xEnd, yEnd, pixelsLength, pixelsChunkOffset, pixelsChunkData],
					                       'H B H B H H ?432',
					                       0,
					                       '',
					                       returnCallback,
					                       errorCallback,
					                       false,
					                       true);

					pixelsChunkOffset += 432;
				}
			}

			if (returnCallback) {
				returnCallback();
			}
		}
		else {
			var responseHandler = null;
			var functionToQueue = null;

			if (streamStateObject['responseProperties']['responseHandler'] === null) {
				responseHandler = function (device, fid, packetResponse) {
					var result = [];
					var payload = null;
					var llvalues = null;
					var packetErrorFlag = 0;
					var rolesMappedData = [];
					var shortWriteWritten = -1;
					var streamStateObject = device.streamStateObjects[fid];
					var responseEmpty = streamStateObject['responseProperties']['streamInResponseEmpty'];
					var pixelsLength = 0;
					var pixelsChunkData = [];
					var pixelsChunkOffset = 0;

					function doNextLLCall() {
						pixelsLength = streamStateObject['responseProperties']['data'].length;
						pixelsChunkData =
							device.ipcon.createChunkData(streamStateObject['responseProperties']['data'],
							                             streamStateObject['responseProperties']['streamInChunkOffset'],
							                             streamStateObject['responseProperties']['streamInChunkLength'],
							                             '\0');
						pixelsChunkOffset = streamStateObject['responseProperties']['streamInChunkOffset'];

						for (var i = 0; i < streamStateObject['dataMappingStreamIn'].length; i++) {
							if (streamStateObject['dataMappingStreamIn'][i] === null) {
								continue;
							}

							if (streamStateObject['dataMappingStreamIn'][i].endsWith('Length')) {
								streamStateObject['responseProperties']['streamInLLParams'][i] = pixelsLength;
							}
							else if (streamStateObject['dataMappingStreamIn'][i].endsWith('Offset')) {
								streamStateObject['responseProperties']['streamInLLParams'][i] = pixelsChunkOffset;
							}
							else if (streamStateObject['dataMappingStreamIn'][i].endsWith('Data')) {
								streamStateObject['responseProperties']['streamInLLParams'][i] = pixelsChunkData;
							}
						}

						device.ipcon.sendRequest(device,
						                         BrickletEPaper296x128.FUNCTION_WRITE_BLACK_WHITE_LOW_LEVEL,
						                         streamStateObject['responseProperties']['streamInLLParams'],
						                         'H B H B H H ?432',
						                         0,
						                         '',
						                         returnCallback,
						                         errorCallback,
						                         true,
						                         true);

						streamStateObject['responseProperties']['streamInChunkOffset'] += 432;
					}

					function handleStreamInDone() {
						if (streamStateObject['responseProperties']['returnCB']) {
							if (streamStateObject['streamProperties']['shortWrite']) {
								for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
									if (streamStateObject['dataMapping'][i].endsWith('Written')) {
										result[i] = streamStateObject['responseProperties']['streamInWritten'];
										break;
									}
								}
							}

							if (!responseEmpty) {
								streamStateObject['responseProperties']['returnCB'].apply(device, result);
							}
							else {
								streamStateObject['responseProperties']['returnCB'].apply(device);
							}
						}

						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}
					}

					if (!streamStateObject) {
						return;
					}

					packetErrorFlag = device.ipcon.getEFromPacket(packetResponse);

					if (packetErrorFlag !== 0) {
						if (streamStateObject['responseProperties']['errorCB'] !== undefined) {
							if (packetErrorFlag === 1) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_INVALID_PARAMETER);
							}
							else if (packetErrorFlag === 2) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_FUNCTION_NOT_SUPPORTED);
							}
							else {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_UNKNOWN_ERROR);
							}
						}

						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}

						return;
					}

					if (responseEmpty) {
						if (streamStateObject['streamProperties']['singleChunk']) {
							handleStreamInDone();

							return;
						}

						if (streamStateObject['responseProperties']['streamInChunkOffset'] < streamStateObject['responseProperties']['data'].length) {
							doNextLLCall();
						}
						else {
							handleStreamInDone();
						}
					}
					else {
						payload = device.ipcon.getPayloadFromPacket(packetResponse);
						llvalues = device.ipcon.unpack(payload,
						                               streamStateObject['responseProperties']['unpackFormatString']);

						if (!payload || !llvalues) {
							device.resetStreamStateObject(streamStateObject);

							if (streamStateObject['responseProperties']['callQueue'].length > 0) {
								streamStateObject['responseProperties']['callQueue'].shift()(device);
							}

							return;
						}

						for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
							result.push(llvalues[i]);
						}

						if (streamStateObject['streamProperties']['singleChunk']) {
							if (streamStateObject['responseProperties']['returnCB']) {
								streamStateObject['responseProperties']['returnCB'].apply(device, result);
							}

							device.resetStreamStateObject(streamStateObject);

							if (streamStateObject['responseProperties']['callQueue'].length > 0) {
								streamStateObject['responseProperties']['callQueue'].shift()(device);
							}

							return;
						}

						if (streamStateObject['streamProperties']['shortWrite']) {
							for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
								if (streamStateObject['dataMapping'][i].endsWith('Written')) {
									shortWriteWritten = llvalues[i];
									streamStateObject['responseProperties']['streamInWritten'] += shortWriteWritten;
									break;
								}
							}
							if ((shortWriteWritten !== -1) && (shortWriteWritten < 432)) {
								// Either last chunk or short write
								handleStreamInDone();
								return;
							}
						}

						if (streamStateObject['responseProperties']['streamInChunkOffset'] < streamStateObject['responseProperties']['data'].length) {
							doNextLLCall();
						}
						else {
							handleStreamInDone();
						}
					}
				};

				streamStateObject['responseProperties']['responseHandler'] = responseHandler;
			}

			if (!streamStateObject['responseProperties']['running']) {
				streamStateObject['responseProperties']['running'] = true;
				streamStateObject['responseProperties']['returnCB'] = returnCallback;
				streamStateObject['responseProperties']['errorCB'] = errorCallback;
				streamStateObject['responseProperties']['data'].length = 0;
				streamStateObject['responseProperties']['data'].push.apply(streamStateObject['responseProperties']['data'],
				                                                           pixels);

				if (streamStateObject['streamProperties']['fixedLength']) {
					pixelsLength = streamStateObject['streamProperties']['fixedLength'];
				}
				else {
					pixelsLength = pixels.length;
				}

				pixelsChunkOffset = 0;
				pixelsChunkData =
					this.ipcon.createChunkData(pixels, 0, 432, '\0');

				streamStateObject['responseProperties']['streamInChunkOffset'] = 432;
				streamStateObject['responseProperties']['streamInChunkLength'] = 432;
				streamStateObject['responseProperties']['streamInLLParams'] = [xStart, yStart, xEnd, yEnd, pixelsLength, pixelsChunkOffset, pixelsChunkData];

				this.ipcon.sendRequest(this,
				                       BrickletEPaper296x128.FUNCTION_WRITE_BLACK_WHITE_LOW_LEVEL,
				                       [xStart, yStart, xEnd, yEnd, pixelsLength, pixelsChunkOffset, pixelsChunkData],
				                       'H B H B H H ?432',
				                       0,
				                       '',
				                       returnCallback,
				                       errorCallback,
				                       true,
				                       true);
			}
			else {
				functionToQueue = function (device) {
					device.writeBlackWhite.call(device, xStart, yStart, xEnd, yEnd, pixels, returnCallback, errorCallback);
				}

				streamStateObject['responseProperties']['callQueue'].push(functionToQueue);
			}
		}
	};

	this.readBlackWhite = function(xStart, yStart, xEnd, yEnd, returnCallback, errorCallback) {
		/*
		Returns the current content of the black/white pixel buffer for the specified window.
		
		The pixels are read into the window line by line top to bottom and
		each line is read from left to right.
		
		The current content of the buffer does not have to be the current content of the display.
		It is possible that the data was not drawn to the display yet and after a restart of
		the Bricklet the buffer will be reset to black, while the display retains its content.
		*/
		var responseHandler = null;
		var functionToQueue = null;
		var streamStateObject = this.streamStateObjects[4];
		if (streamStateObject['responseProperties']['responseHandler'] === null) {
			responseHandler = 
				function (device, fid, packetResponse) {
					var result = [];
					var llvalues = null;
					var packetErrorFlag = 0;
					var rolesMappedData = [];
					var pixelsLength = null;
					var pixelsChunkData = null;
					var pixelsOutOfSync = false;
					var streamStateObject = device.streamStateObjects[fid];
					var pixelsChunkOffset = null;
					var payload = device.ipcon.getPayloadFromPacket(packetResponse);

					packetErrorFlag = device.ipcon.getEFromPacket(packetResponse);

					if (packetErrorFlag !== 0) {
						if (streamStateObject['responseProperties']['errorCB'] !== undefined) {
							if (packetErrorFlag === 1) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_INVALID_PARAMETER);
							}
							else if (packetErrorFlag === 2) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_FUNCTION_NOT_SUPPORTED);
							}
							else {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_UNKNOWN_ERROR);
							}
						}

						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}

						return;
					}

					if (payload.length === 0) {
						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}

						return;
					}

					llvalues = device.ipcon.unpack(payload,
					                               streamStateObject['responseProperties']['unpackFormatString']);

					for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
						if (streamStateObject['dataMapping'][i] === 'streamChunkData') {
							pixelsChunkData = llvalues[i];
						}
						else if (streamStateObject['dataMapping'][i] === 'streamChunkOffset') {
							pixelsChunkOffset = llvalues[i];
						}
					}

					for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
						if (streamStateObject['dataMapping'][i] === 'streamLength') {
							pixelsLength = llvalues[i];
							break;
						}
					}

					function handleOOS() {
						if ((pixelsChunkOffset + 464) < pixelsLength) {
							streamStateObject['responseProperties']['runningSubcallOOS'] = true;
							device.ipcon.sendRequest(device, BrickletEPaper296x128.FUNCTION_READ_BLACK_WHITE_LOW_LEVEL, [xStart, yStart, xEnd, yEnd], 'H B H B', 70, 'H H ?464', streamStateObject['responseProperties']['returnCB'], streamStateObject['responseProperties']['errorCB'], true, true);

							return;
						}

						if (streamStateObject['responseProperties']['errorCB']) {
							streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_STREAM_OUT_OF_SYNC);
						}

						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}
					}

					if (streamStateObject['responseProperties']['waitingFirstChunk']) {
						streamStateObject['responseProperties']['waitingFirstChunk'] = false;
						pixelsOutOfSync = (pixelsChunkOffset !== 0);
						streamStateObject['responseProperties']['data'] = pixelsChunkData;
					}

					if (!streamStateObject['responseProperties']['runningSubcallOOS']) {
						if (!streamStateObject['responseProperties']['runningSubcall']) {
							if (!pixelsOutOfSync &&
							    (streamStateObject['responseProperties']['data'].length < pixelsLength)) {
							        streamStateObject['responseProperties']['runningSubcall'] = true;
							        device.ipcon.sendRequest(device, BrickletEPaper296x128.FUNCTION_READ_BLACK_WHITE_LOW_LEVEL, [xStart, yStart, xEnd, yEnd], 'H B H B', 70, 'H H ?464', streamStateObject['responseProperties']['returnCB'], streamStateObject['responseProperties']['errorCB'], true, true);

							        return;
							}
						}
						else {
							pixelsOutOfSync =
								(pixelsChunkOffset !== streamStateObject['responseProperties']['data'].length);

							if (!pixelsOutOfSync &&
								(streamStateObject['responseProperties']['data'].length < pixelsLength)) {
									streamStateObject['responseProperties']['data'] =
										streamStateObject['responseProperties']['data'].concat(pixelsChunkData);

									if (streamStateObject['responseProperties']['data'].length >= pixelsLength) {
										streamStateObject['responseProperties']['data'] =
											streamStateObject['responseProperties']['data'].splice(0, pixelsLength);
									}
									else {
										device.ipcon.sendRequest(device, BrickletEPaper296x128.FUNCTION_READ_BLACK_WHITE_LOW_LEVEL, [xStart, yStart, xEnd, yEnd], 'H B H B', 70, 'H H ?464', streamStateObject['responseProperties']['returnCB'], streamStateObject['responseProperties']['errorCB'], true, true);

										return;
									}
							}
						}
					}
					else{
						handleOOS();

						return;
					}

					if (pixelsOutOfSync) { // Discard remaining stream to bring it back in-sync
						handleOOS();

						return;
					}

					if (streamStateObject['responseProperties']['returnCB']) {
						for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
							rolesMappedData.push({'role': streamStateObject['dataMapping'][i], 'llvalue': llvalues[i]});
						}

						for (var i = 0; i < rolesMappedData.length; i++) {
							if (rolesMappedData[i]['role'] === 'streamChunkData') {
								result.push(streamStateObject['responseProperties']['data'].splice(0, pixelsLength));
							}
							else if (rolesMappedData[i]['role'] === null) {
								result.push(rolesMappedData[i]['llvalue']);
							}
						}

						streamStateObject['responseProperties']['returnCB'].apply(device, result);
					}

					device.resetStreamStateObject(streamStateObject);

					if (streamStateObject['responseProperties']['callQueue'].length > 0) {
						streamStateObject['responseProperties']['callQueue'].shift()(device);
					}
					
				};

			streamStateObject['responseProperties']['responseHandler'] = responseHandler;
		}
		if (!streamStateObject['responseProperties']['running']) {
			streamStateObject['responseProperties']['running'] = true;
			streamStateObject['responseProperties']['returnCB'] = returnCallback;
			streamStateObject['responseProperties']['errorCB'] = errorCallback;
			this.ipcon.sendRequest(this,
			                       BrickletEPaper296x128.FUNCTION_READ_BLACK_WHITE_LOW_LEVEL,
			                       [xStart, yStart, xEnd, yEnd],
			                       'H B H B',
			                       70,
			                       'H H ?464',
			                       returnCallback,
			                       errorCallback,
			                       true,
			                       true);
		}
		else {
			functionToQueue = function (device) {
				device.readBlackWhite.call(device, xStart, yStart, xEnd, yEnd, returnCallback, errorCallback);
			}
			streamStateObject['responseProperties']['callQueue'].push(functionToQueue);
		}
	};
	this.writeColor = function(xStart, yStart, xEnd, yEnd, pixels, returnCallback, errorCallback) {
		/*
		The E-Paper 296x128 Bricklet is available with the colors black/white/red and
		black/white/gray. Depending on the model this function writes either red or
		gray pixels to the specified window into the buffer.
		
		The pixels are written into the window line by line top to bottom
		and each line is written from left to right.
		
		The value 0 (false) means that this pixel does not have color. It will be either black
		or white (see :func:`Write Black White`). The value 1 (true) corresponds to a red or gray
		pixel, depending on the Bricklet model.
		
		This function writes the pixels into the red or gray pixel buffer, to draw the buffer
		to the display use :func:`Draw`.
		
		Use :func:`Write Black White` to write black/white pixels.
		*/

		var pixelsLength = 0;
		var pixelsChunkData = [];
		var pixelsChunkOffset = 0;
		var streamStateObject = this.streamStateObjects[5];

		if (pixels.length > 65535) {
			if (errorCallback !== null){
				errorCallback(IPConnection.ERROR_INVALID_PARAMETER);
			}

			this.resetStreamStateObject(streamStateObject);

			if (streamStateObject['responseProperties']['callQueue'].length > 0) {
				streamStateObject['responseProperties']['callQueue'].shift()(device);
			}

			return;
		}

		if (!this.getResponseExpected(5)) {
			if (streamStateObject['streamProperties']['fixedLength']) {
				pixelsLength = streamStateObject['streamProperties']['fixedLength'];
			}
			else {
				pixelsLength = pixels.length;
			}

			if (streamStateObject['streamProperties']['singleChunk']) {
				pixelsChunkData =
					this.ipcon.createChunkData(pixels, 0, 432, '\0');

				this.ipcon.sendRequest(this,
				                       BrickletEPaper296x128.FUNCTION_WRITE_COLOR_LOW_LEVEL,
				                       [xStart, yStart, xEnd, yEnd, pixelsLength, pixelsChunkOffset, pixelsChunkData],
				                       'H B H B H H ?432',
				                       0,
				                       '',
				                       returnCallback,
				                       errorCallback,
				                       false,
				                       true);
			}
			else {
				while (pixelsChunkOffset < pixels.length) {
					pixelsChunkData =
						this.ipcon.createChunkData(pixels, pixelsChunkOffset, 432, '\0');

					this.ipcon.sendRequest(this,
					                       BrickletEPaper296x128.FUNCTION_WRITE_COLOR_LOW_LEVEL,
					                       [xStart, yStart, xEnd, yEnd, pixelsLength, pixelsChunkOffset, pixelsChunkData],
					                       'H B H B H H ?432',
					                       0,
					                       '',
					                       returnCallback,
					                       errorCallback,
					                       false,
					                       true);

					pixelsChunkOffset += 432;
				}
			}

			if (returnCallback) {
				returnCallback();
			}
		}
		else {
			var responseHandler = null;
			var functionToQueue = null;

			if (streamStateObject['responseProperties']['responseHandler'] === null) {
				responseHandler = function (device, fid, packetResponse) {
					var result = [];
					var payload = null;
					var llvalues = null;
					var packetErrorFlag = 0;
					var rolesMappedData = [];
					var shortWriteWritten = -1;
					var streamStateObject = device.streamStateObjects[fid];
					var responseEmpty = streamStateObject['responseProperties']['streamInResponseEmpty'];
					var pixelsLength = 0;
					var pixelsChunkData = [];
					var pixelsChunkOffset = 0;

					function doNextLLCall() {
						pixelsLength = streamStateObject['responseProperties']['data'].length;
						pixelsChunkData =
							device.ipcon.createChunkData(streamStateObject['responseProperties']['data'],
							                             streamStateObject['responseProperties']['streamInChunkOffset'],
							                             streamStateObject['responseProperties']['streamInChunkLength'],
							                             '\0');
						pixelsChunkOffset = streamStateObject['responseProperties']['streamInChunkOffset'];

						for (var i = 0; i < streamStateObject['dataMappingStreamIn'].length; i++) {
							if (streamStateObject['dataMappingStreamIn'][i] === null) {
								continue;
							}

							if (streamStateObject['dataMappingStreamIn'][i].endsWith('Length')) {
								streamStateObject['responseProperties']['streamInLLParams'][i] = pixelsLength;
							}
							else if (streamStateObject['dataMappingStreamIn'][i].endsWith('Offset')) {
								streamStateObject['responseProperties']['streamInLLParams'][i] = pixelsChunkOffset;
							}
							else if (streamStateObject['dataMappingStreamIn'][i].endsWith('Data')) {
								streamStateObject['responseProperties']['streamInLLParams'][i] = pixelsChunkData;
							}
						}

						device.ipcon.sendRequest(device,
						                         BrickletEPaper296x128.FUNCTION_WRITE_COLOR_LOW_LEVEL,
						                         streamStateObject['responseProperties']['streamInLLParams'],
						                         'H B H B H H ?432',
						                         0,
						                         '',
						                         returnCallback,
						                         errorCallback,
						                         true,
						                         true);

						streamStateObject['responseProperties']['streamInChunkOffset'] += 432;
					}

					function handleStreamInDone() {
						if (streamStateObject['responseProperties']['returnCB']) {
							if (streamStateObject['streamProperties']['shortWrite']) {
								for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
									if (streamStateObject['dataMapping'][i].endsWith('Written')) {
										result[i] = streamStateObject['responseProperties']['streamInWritten'];
										break;
									}
								}
							}

							if (!responseEmpty) {
								streamStateObject['responseProperties']['returnCB'].apply(device, result);
							}
							else {
								streamStateObject['responseProperties']['returnCB'].apply(device);
							}
						}

						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}
					}

					if (!streamStateObject) {
						return;
					}

					packetErrorFlag = device.ipcon.getEFromPacket(packetResponse);

					if (packetErrorFlag !== 0) {
						if (streamStateObject['responseProperties']['errorCB'] !== undefined) {
							if (packetErrorFlag === 1) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_INVALID_PARAMETER);
							}
							else if (packetErrorFlag === 2) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_FUNCTION_NOT_SUPPORTED);
							}
							else {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_UNKNOWN_ERROR);
							}
						}

						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}

						return;
					}

					if (responseEmpty) {
						if (streamStateObject['streamProperties']['singleChunk']) {
							handleStreamInDone();

							return;
						}

						if (streamStateObject['responseProperties']['streamInChunkOffset'] < streamStateObject['responseProperties']['data'].length) {
							doNextLLCall();
						}
						else {
							handleStreamInDone();
						}
					}
					else {
						payload = device.ipcon.getPayloadFromPacket(packetResponse);
						llvalues = device.ipcon.unpack(payload,
						                               streamStateObject['responseProperties']['unpackFormatString']);

						if (!payload || !llvalues) {
							device.resetStreamStateObject(streamStateObject);

							if (streamStateObject['responseProperties']['callQueue'].length > 0) {
								streamStateObject['responseProperties']['callQueue'].shift()(device);
							}

							return;
						}

						for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
							result.push(llvalues[i]);
						}

						if (streamStateObject['streamProperties']['singleChunk']) {
							if (streamStateObject['responseProperties']['returnCB']) {
								streamStateObject['responseProperties']['returnCB'].apply(device, result);
							}

							device.resetStreamStateObject(streamStateObject);

							if (streamStateObject['responseProperties']['callQueue'].length > 0) {
								streamStateObject['responseProperties']['callQueue'].shift()(device);
							}

							return;
						}

						if (streamStateObject['streamProperties']['shortWrite']) {
							for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
								if (streamStateObject['dataMapping'][i].endsWith('Written')) {
									shortWriteWritten = llvalues[i];
									streamStateObject['responseProperties']['streamInWritten'] += shortWriteWritten;
									break;
								}
							}
							if ((shortWriteWritten !== -1) && (shortWriteWritten < 432)) {
								// Either last chunk or short write
								handleStreamInDone();
								return;
							}
						}

						if (streamStateObject['responseProperties']['streamInChunkOffset'] < streamStateObject['responseProperties']['data'].length) {
							doNextLLCall();
						}
						else {
							handleStreamInDone();
						}
					}
				};

				streamStateObject['responseProperties']['responseHandler'] = responseHandler;
			}

			if (!streamStateObject['responseProperties']['running']) {
				streamStateObject['responseProperties']['running'] = true;
				streamStateObject['responseProperties']['returnCB'] = returnCallback;
				streamStateObject['responseProperties']['errorCB'] = errorCallback;
				streamStateObject['responseProperties']['data'].length = 0;
				streamStateObject['responseProperties']['data'].push.apply(streamStateObject['responseProperties']['data'],
				                                                           pixels);

				if (streamStateObject['streamProperties']['fixedLength']) {
					pixelsLength = streamStateObject['streamProperties']['fixedLength'];
				}
				else {
					pixelsLength = pixels.length;
				}

				pixelsChunkOffset = 0;
				pixelsChunkData =
					this.ipcon.createChunkData(pixels, 0, 432, '\0');

				streamStateObject['responseProperties']['streamInChunkOffset'] = 432;
				streamStateObject['responseProperties']['streamInChunkLength'] = 432;
				streamStateObject['responseProperties']['streamInLLParams'] = [xStart, yStart, xEnd, yEnd, pixelsLength, pixelsChunkOffset, pixelsChunkData];

				this.ipcon.sendRequest(this,
				                       BrickletEPaper296x128.FUNCTION_WRITE_COLOR_LOW_LEVEL,
				                       [xStart, yStart, xEnd, yEnd, pixelsLength, pixelsChunkOffset, pixelsChunkData],
				                       'H B H B H H ?432',
				                       0,
				                       '',
				                       returnCallback,
				                       errorCallback,
				                       true,
				                       true);
			}
			else {
				functionToQueue = function (device) {
					device.writeColor.call(device, xStart, yStart, xEnd, yEnd, pixels, returnCallback, errorCallback);
				}

				streamStateObject['responseProperties']['callQueue'].push(functionToQueue);
			}
		}
	};

	this.readColor = function(xStart, yStart, xEnd, yEnd, returnCallback, errorCallback) {
		/*
		Returns the current content of the red or gray pixel buffer for the specified window.
		
		The pixels are written into the window line by line top to bottom
		and each line is written from left to right.
		
		The current content of the buffer does not have to be the current content of the display.
		It is possible that the data was not drawn to the display yet and after a restart of
		the Bricklet the buffer will be reset to black, while the display retains its content.
		*/
		var responseHandler = null;
		var functionToQueue = null;
		var streamStateObject = this.streamStateObjects[6];
		if (streamStateObject['responseProperties']['responseHandler'] === null) {
			responseHandler = 
				function (device, fid, packetResponse) {
					var result = [];
					var llvalues = null;
					var packetErrorFlag = 0;
					var rolesMappedData = [];
					var pixelsLength = null;
					var pixelsChunkData = null;
					var pixelsOutOfSync = false;
					var streamStateObject = device.streamStateObjects[fid];
					var pixelsChunkOffset = null;
					var payload = device.ipcon.getPayloadFromPacket(packetResponse);

					packetErrorFlag = device.ipcon.getEFromPacket(packetResponse);

					if (packetErrorFlag !== 0) {
						if (streamStateObject['responseProperties']['errorCB'] !== undefined) {
							if (packetErrorFlag === 1) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_INVALID_PARAMETER);
							}
							else if (packetErrorFlag === 2) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_FUNCTION_NOT_SUPPORTED);
							}
							else {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_UNKNOWN_ERROR);
							}
						}

						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}

						return;
					}

					if (payload.length === 0) {
						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}

						return;
					}

					llvalues = device.ipcon.unpack(payload,
					                               streamStateObject['responseProperties']['unpackFormatString']);

					for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
						if (streamStateObject['dataMapping'][i] === 'streamChunkData') {
							pixelsChunkData = llvalues[i];
						}
						else if (streamStateObject['dataMapping'][i] === 'streamChunkOffset') {
							pixelsChunkOffset = llvalues[i];
						}
					}

					for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
						if (streamStateObject['dataMapping'][i] === 'streamLength') {
							pixelsLength = llvalues[i];
							break;
						}
					}

					function handleOOS() {
						if ((pixelsChunkOffset + 464) < pixelsLength) {
							streamStateObject['responseProperties']['runningSubcallOOS'] = true;
							device.ipcon.sendRequest(device, BrickletEPaper296x128.FUNCTION_READ_COLOR_LOW_LEVEL, [xStart, yStart, xEnd, yEnd], 'H B H B', 70, 'H H ?464', streamStateObject['responseProperties']['returnCB'], streamStateObject['responseProperties']['errorCB'], true, true);

							return;
						}

						if (streamStateObject['responseProperties']['errorCB']) {
							streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_STREAM_OUT_OF_SYNC);
						}

						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}
					}

					if (streamStateObject['responseProperties']['waitingFirstChunk']) {
						streamStateObject['responseProperties']['waitingFirstChunk'] = false;
						pixelsOutOfSync = (pixelsChunkOffset !== 0);
						streamStateObject['responseProperties']['data'] = pixelsChunkData;
					}

					if (!streamStateObject['responseProperties']['runningSubcallOOS']) {
						if (!streamStateObject['responseProperties']['runningSubcall']) {
							if (!pixelsOutOfSync &&
							    (streamStateObject['responseProperties']['data'].length < pixelsLength)) {
							        streamStateObject['responseProperties']['runningSubcall'] = true;
							        device.ipcon.sendRequest(device, BrickletEPaper296x128.FUNCTION_READ_COLOR_LOW_LEVEL, [xStart, yStart, xEnd, yEnd], 'H B H B', 70, 'H H ?464', streamStateObject['responseProperties']['returnCB'], streamStateObject['responseProperties']['errorCB'], true, true);

							        return;
							}
						}
						else {
							pixelsOutOfSync =
								(pixelsChunkOffset !== streamStateObject['responseProperties']['data'].length);

							if (!pixelsOutOfSync &&
								(streamStateObject['responseProperties']['data'].length < pixelsLength)) {
									streamStateObject['responseProperties']['data'] =
										streamStateObject['responseProperties']['data'].concat(pixelsChunkData);

									if (streamStateObject['responseProperties']['data'].length >= pixelsLength) {
										streamStateObject['responseProperties']['data'] =
											streamStateObject['responseProperties']['data'].splice(0, pixelsLength);
									}
									else {
										device.ipcon.sendRequest(device, BrickletEPaper296x128.FUNCTION_READ_COLOR_LOW_LEVEL, [xStart, yStart, xEnd, yEnd], 'H B H B', 70, 'H H ?464', streamStateObject['responseProperties']['returnCB'], streamStateObject['responseProperties']['errorCB'], true, true);

										return;
									}
							}
						}
					}
					else{
						handleOOS();

						return;
					}

					if (pixelsOutOfSync) { // Discard remaining stream to bring it back in-sync
						handleOOS();

						return;
					}

					if (streamStateObject['responseProperties']['returnCB']) {
						for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
							rolesMappedData.push({'role': streamStateObject['dataMapping'][i], 'llvalue': llvalues[i]});
						}

						for (var i = 0; i < rolesMappedData.length; i++) {
							if (rolesMappedData[i]['role'] === 'streamChunkData') {
								result.push(streamStateObject['responseProperties']['data'].splice(0, pixelsLength));
							}
							else if (rolesMappedData[i]['role'] === null) {
								result.push(rolesMappedData[i]['llvalue']);
							}
						}

						streamStateObject['responseProperties']['returnCB'].apply(device, result);
					}

					device.resetStreamStateObject(streamStateObject);

					if (streamStateObject['responseProperties']['callQueue'].length > 0) {
						streamStateObject['responseProperties']['callQueue'].shift()(device);
					}
					
				};

			streamStateObject['responseProperties']['responseHandler'] = responseHandler;
		}
		if (!streamStateObject['responseProperties']['running']) {
			streamStateObject['responseProperties']['running'] = true;
			streamStateObject['responseProperties']['returnCB'] = returnCallback;
			streamStateObject['responseProperties']['errorCB'] = errorCallback;
			this.ipcon.sendRequest(this,
			                       BrickletEPaper296x128.FUNCTION_READ_COLOR_LOW_LEVEL,
			                       [xStart, yStart, xEnd, yEnd],
			                       'H B H B',
			                       70,
			                       'H H ?464',
			                       returnCallback,
			                       errorCallback,
			                       true,
			                       true);
		}
		else {
			functionToQueue = function (device) {
				device.readColor.call(device, xStart, yStart, xEnd, yEnd, returnCallback, errorCallback);
			}
			streamStateObject['responseProperties']['callQueue'].push(functionToQueue);
		}
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletEPaper296x128;

},{"./Device":279,"./IPConnection":280}],180:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletEnergyMonitor.DEVICE_IDENTIFIER = 2152;
BrickletEnergyMonitor.DEVICE_DISPLAY_NAME = 'Energy Monitor Bricklet';
BrickletEnergyMonitor.CALLBACK_ENERGY_DATA = 10;
BrickletEnergyMonitor.FUNCTION_GET_ENERGY_DATA = 1;
BrickletEnergyMonitor.FUNCTION_RESET_ENERGY = 2;
BrickletEnergyMonitor.FUNCTION_GET_WAVEFORM_LOW_LEVEL = 3;
BrickletEnergyMonitor.FUNCTION_GET_TRANSFORMER_STATUS = 4;
BrickletEnergyMonitor.FUNCTION_SET_TRANSFORMER_CALIBRATION = 5;
BrickletEnergyMonitor.FUNCTION_GET_TRANSFORMER_CALIBRATION = 6;
BrickletEnergyMonitor.FUNCTION_CALIBRATE_OFFSET = 7;
BrickletEnergyMonitor.FUNCTION_SET_ENERGY_DATA_CALLBACK_CONFIGURATION = 8;
BrickletEnergyMonitor.FUNCTION_GET_ENERGY_DATA_CALLBACK_CONFIGURATION = 9;
BrickletEnergyMonitor.FUNCTION_GET_SPITFP_ERROR_COUNT = 234;
BrickletEnergyMonitor.FUNCTION_SET_BOOTLOADER_MODE = 235;
BrickletEnergyMonitor.FUNCTION_GET_BOOTLOADER_MODE = 236;
BrickletEnergyMonitor.FUNCTION_SET_WRITE_FIRMWARE_POINTER = 237;
BrickletEnergyMonitor.FUNCTION_WRITE_FIRMWARE = 238;
BrickletEnergyMonitor.FUNCTION_SET_STATUS_LED_CONFIG = 239;
BrickletEnergyMonitor.FUNCTION_GET_STATUS_LED_CONFIG = 240;
BrickletEnergyMonitor.FUNCTION_GET_CHIP_TEMPERATURE = 242;
BrickletEnergyMonitor.FUNCTION_RESET = 243;
BrickletEnergyMonitor.FUNCTION_WRITE_UID = 248;
BrickletEnergyMonitor.FUNCTION_READ_UID = 249;
BrickletEnergyMonitor.FUNCTION_GET_IDENTITY = 255;
BrickletEnergyMonitor.BOOTLOADER_MODE_BOOTLOADER = 0;
BrickletEnergyMonitor.BOOTLOADER_MODE_FIRMWARE = 1;
BrickletEnergyMonitor.BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT = 2;
BrickletEnergyMonitor.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT = 3;
BrickletEnergyMonitor.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT = 4;
BrickletEnergyMonitor.BOOTLOADER_STATUS_OK = 0;
BrickletEnergyMonitor.BOOTLOADER_STATUS_INVALID_MODE = 1;
BrickletEnergyMonitor.BOOTLOADER_STATUS_NO_CHANGE = 2;
BrickletEnergyMonitor.BOOTLOADER_STATUS_ENTRY_FUNCTION_NOT_PRESENT = 3;
BrickletEnergyMonitor.BOOTLOADER_STATUS_DEVICE_IDENTIFIER_INCORRECT = 4;
BrickletEnergyMonitor.BOOTLOADER_STATUS_CRC_MISMATCH = 5;
BrickletEnergyMonitor.STATUS_LED_CONFIG_OFF = 0;
BrickletEnergyMonitor.STATUS_LED_CONFIG_ON = 1;
BrickletEnergyMonitor.STATUS_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletEnergyMonitor.STATUS_LED_CONFIG_SHOW_STATUS = 3;

function BrickletEnergyMonitor(uid, ipcon) {
	//Measures Voltage, Current, Energy, Real/Apparent/Reactive Power, Power Factor and Frequency

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletEnergyMonitor.DEVICE_IDENTIFIER, BrickletEnergyMonitor.DEVICE_DISPLAY_NAME);
	BrickletEnergyMonitor.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickletEnergyMonitor.FUNCTION_GET_ENERGY_DATA] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletEnergyMonitor.FUNCTION_RESET_ENERGY] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletEnergyMonitor.FUNCTION_GET_WAVEFORM_LOW_LEVEL] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletEnergyMonitor.FUNCTION_GET_TRANSFORMER_STATUS] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletEnergyMonitor.FUNCTION_SET_TRANSFORMER_CALIBRATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletEnergyMonitor.FUNCTION_GET_TRANSFORMER_CALIBRATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletEnergyMonitor.FUNCTION_CALIBRATE_OFFSET] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletEnergyMonitor.FUNCTION_SET_ENERGY_DATA_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletEnergyMonitor.FUNCTION_GET_ENERGY_DATA_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletEnergyMonitor.FUNCTION_GET_SPITFP_ERROR_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletEnergyMonitor.FUNCTION_SET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletEnergyMonitor.FUNCTION_GET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletEnergyMonitor.FUNCTION_SET_WRITE_FIRMWARE_POINTER] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletEnergyMonitor.FUNCTION_WRITE_FIRMWARE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletEnergyMonitor.FUNCTION_SET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletEnergyMonitor.FUNCTION_GET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletEnergyMonitor.FUNCTION_GET_CHIP_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletEnergyMonitor.FUNCTION_RESET] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletEnergyMonitor.FUNCTION_WRITE_UID] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletEnergyMonitor.FUNCTION_READ_UID] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletEnergyMonitor.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletEnergyMonitor.CALLBACK_ENERGY_DATA] = [36, 'i i i i i i H H'];


	this.streamStateObjects[BrickletEnergyMonitor.FUNCTION_GET_WAVEFORM_LOW_LEVEL] = {
		'dataMapping': ['streamChunkOffset', 'streamChunkData'],
		'dataMappingStreamIn': [],
		'streamProperties': {
			'fixedLength': 1536,
			'singleChunk': false,
			'shortWrite': false
		},
		'responseProperties': {
			'running': false,
			'runningSubcall': false,
			'runningSubcallOOS': false,
			'waitingFirstChunk': true,
			'timeout': null,
			'data': [],
			'streamInChunkOffset': 0,
			'streamInChunkLength': 0,
			'streamInResponseEmpty': true,
			'streamInWritten': 0,
			'streamInLLParams': null,
			'responseHandler': null,
			'packFormatString': '',
			'unpackFormatString': 'H h30',
			'returnCB': null,
			'errorCB': null,
			'callQueue': []
		}
	};

	this.getEnergyData = function(returnCallback, errorCallback) {
		/*
		Returns all of the measurements that are done by the Energy Monitor Bricklet.
		
		* Voltage RMS
		* Current RMS
		* Energy (integrated over time)
		* Real Power
		* Apparent Power
		* Reactive Power
		* Power Factor
		* Frequency (AC Frequency of the mains voltage)
		
		The frequency is recalculated every 6 seconds.
		
		All other values are integrated over 10 zero-crossings of the voltage sine wave.
		With a standard AC mains voltage frequency of 50Hz this results in a 5 measurements
		per second (or an integration time of 200ms per measurement).
		
		If no voltage transformer is connected, the Bricklet will use the current waveform
		to calculate the frequency and it will use an integration time of
		10 zero-crossings of the current waveform.
		*/
		this.ipcon.sendRequest(this, BrickletEnergyMonitor.FUNCTION_GET_ENERGY_DATA, [], '', 36, 'i i i i i i H H', returnCallback, errorCallback, false, true);
	};
	this.resetEnergy = function(returnCallback, errorCallback) {
		/*
		Sets the energy value (see :func:`Get Energy Data`) back to 0Wh.
		*/
		this.ipcon.sendRequest(this, BrickletEnergyMonitor.FUNCTION_RESET_ENERGY, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getWaveformLowLevel = function(returnCallback, errorCallback) {
		/*
		Returns a snapshot of the voltage and current waveform. The values
		in the returned array alternate between voltage and current. The data from
		one getter call contains 768 data points for voltage and current, which
		correspond to about 3 full sine waves.
		
		The voltage is given with a resolution of 100mV and the current is given
		with a resolution of 10mA.
		
		This data is meant to be used for a non-realtime graphical representation of
		the voltage and current waveforms.
		*/
		this.ipcon.sendRequest(this, BrickletEnergyMonitor.FUNCTION_GET_WAVEFORM_LOW_LEVEL, [], '', 70, 'H h30', returnCallback, errorCallback, false, true);
	};
	this.getTransformerStatus = function(returnCallback, errorCallback) {
		/*
		Returns *true* if a voltage/current transformer is connected to the Bricklet.
		*/
		this.ipcon.sendRequest(this, BrickletEnergyMonitor.FUNCTION_GET_TRANSFORMER_STATUS, [], '', 10, '? ?', returnCallback, errorCallback, false, true);
	};
	this.setTransformerCalibration = function(voltageRatio, currentRatio, phaseShift, returnCallback, errorCallback) {
		/*
		Sets the transformer ratio for the voltage and current transformer in 1/100 form.
		
		Example: If your mains voltage is 230V, you use 9V voltage transformer and a
		1V:30A current clamp your voltage ratio is 230/9 = 25.56 and your current ratio
		is 30/1 = 30.
		
		In this case you have to set the values 2556 and 3000 for voltage ratio and current
		ratio.
		
		The calibration is saved in non-volatile memory, you only have to set it once.
		
		Set the phase shift to 0. It is for future use and currently not supported by the Bricklet.
		*/
		this.ipcon.sendRequest(this, BrickletEnergyMonitor.FUNCTION_SET_TRANSFORMER_CALIBRATION, [voltageRatio, currentRatio, phaseShift], 'H H h', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getTransformerCalibration = function(returnCallback, errorCallback) {
		/*
		Returns the transformer calibration as set by :func:`Set Transformer Calibration`.
		*/
		this.ipcon.sendRequest(this, BrickletEnergyMonitor.FUNCTION_GET_TRANSFORMER_CALIBRATION, [], '', 14, 'H H h', returnCallback, errorCallback, false, true);
	};
	this.calibrateOffset = function(returnCallback, errorCallback) {
		/*
		Calling this function will start an offset calibration. The offset calibration will
		integrate the voltage and current waveform over a longer time period to find the 0
		transition point in the sine wave.
		
		The Bricklet comes with a factory-calibrated offset value, you should not have to
		call this function.
		
		If you want to re-calibrate the offset we recommend that you connect a load that
		has a smooth sinusoidal voltage and current waveform. Alternatively you can also
		short both inputs.
		
		The calibration is saved in non-volatile memory, you only have to set it once.
		*/
		this.ipcon.sendRequest(this, BrickletEnergyMonitor.FUNCTION_CALIBRATE_OFFSET, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.setEnergyDataCallbackConfiguration = function(period, valueHasToChange, returnCallback, errorCallback) {
		/*
		The period is the period with which the :cb:`Energy Data`
		callback is triggered periodically. A value of 0 turns the callback off.
		
		If the `value has to change`-parameter is set to true, the callback is only
		triggered after the value has changed. If the value didn't change within the
		period, the callback is triggered immediately on change.
		
		If it is set to false, the callback is continuously triggered with the period,
		independent of the value.
		*/
		this.ipcon.sendRequest(this, BrickletEnergyMonitor.FUNCTION_SET_ENERGY_DATA_CALLBACK_CONFIGURATION, [period, valueHasToChange], 'I ?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getEnergyDataCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the callback configuration as set by
		:func:`Set Energy Data Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletEnergyMonitor.FUNCTION_GET_ENERGY_DATA_CALLBACK_CONFIGURATION, [], '', 13, 'I ?', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPErrorCount = function(returnCallback, errorCallback) {
		/*
		Returns the error count for the communication between Brick and Bricklet.
		
		The errors are divided into
		
		* ACK checksum errors,
		* message checksum errors,
		* framing errors and
		* overflow errors.
		
		The errors counts are for errors that occur on the Bricklet side. All
		Bricks have a similar function that returns the errors on the Brick side.
		*/
		this.ipcon.sendRequest(this, BrickletEnergyMonitor.FUNCTION_GET_SPITFP_ERROR_COUNT, [], '', 24, 'I I I I', returnCallback, errorCallback, false, true);
	};
	this.setBootloaderMode = function(mode, returnCallback, errorCallback) {
		/*
		Sets the bootloader mode and returns the status after the requested
		mode change was instigated.
		
		You can change from bootloader mode to firmware mode and vice versa. A change
		from bootloader mode to firmware mode will only take place if the entry function,
		device identifier and CRC are present and correct.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletEnergyMonitor.FUNCTION_SET_BOOTLOADER_MODE, [mode], 'B', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getBootloaderMode = function(returnCallback, errorCallback) {
		/*
		Returns the current bootloader mode, see :func:`Set Bootloader Mode`.
		*/
		this.ipcon.sendRequest(this, BrickletEnergyMonitor.FUNCTION_GET_BOOTLOADER_MODE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setWriteFirmwarePointer = function(pointer, returnCallback, errorCallback) {
		/*
		Sets the firmware pointer for :func:`Write Firmware`. The pointer has
		to be increased by chunks of size 64. The data is written to flash
		every 4 chunks (which equals to one page of size 256).
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletEnergyMonitor.FUNCTION_SET_WRITE_FIRMWARE_POINTER, [pointer], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeFirmware = function(data, returnCallback, errorCallback) {
		/*
		Writes 64 Bytes of firmware at the position as written by
		:func:`Set Write Firmware Pointer` before. The firmware is written
		to flash every 4 chunks.
		
		You can only write firmware in bootloader mode.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletEnergyMonitor.FUNCTION_WRITE_FIRMWARE, [data], 'B64', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setStatusLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Sets the status LED configuration. By default the LED shows
		communication traffic between Brick and Bricklet, it flickers once
		for every 10 received data packets.
		
		You can also turn the LED permanently on/off or show a heartbeat.
		
		If the Bricklet is in bootloader mode, the LED is will show heartbeat by default.
		*/
		this.ipcon.sendRequest(this, BrickletEnergyMonitor.FUNCTION_SET_STATUS_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getStatusLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Status LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletEnergyMonitor.FUNCTION_GET_STATUS_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getChipTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature as measured inside the microcontroller. The
		value returned is not the ambient temperature!
		
		The temperature is only proportional to the real temperature and it has bad
		accuracy. Practically it is only useful as an indicator for
		temperature changes.
		*/
		this.ipcon.sendRequest(this, BrickletEnergyMonitor.FUNCTION_GET_CHIP_TEMPERATURE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.reset = function(returnCallback, errorCallback) {
		/*
		Calling this function will reset the Bricklet. All configurations
		will be lost.
		
		After a reset you have to create new device objects,
		calling functions on the existing ones will result in
		undefined behavior!
		*/
		this.ipcon.sendRequest(this, BrickletEnergyMonitor.FUNCTION_RESET, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeUID = function(uid, returnCallback, errorCallback) {
		/*
		Writes a new UID into flash. If you want to set a new UID
		you have to decode the Base58 encoded UID string into an
		integer first.
		
		We recommend that you use Brick Viewer to change the UID.
		*/
		this.ipcon.sendRequest(this, BrickletEnergyMonitor.FUNCTION_WRITE_UID, [uid], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.readUID = function(returnCallback, errorCallback) {
		/*
		Returns the current UID as an integer. Encode as
		Base58 to get the usual string version.
		*/
		this.ipcon.sendRequest(this, BrickletEnergyMonitor.FUNCTION_READ_UID, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletEnergyMonitor.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.getWaveform = function(returnCallback, errorCallback) {
		/*
		Returns a snapshot of the voltage and current waveform. The values
		in the returned array alternate between voltage and current. The data from
		one getter call contains 768 data points for voltage and current, which
		correspond to about 3 full sine waves.
		
		The voltage is given with a resolution of 100mV and the current is given
		with a resolution of 10mA.
		
		This data is meant to be used for a non-realtime graphical representation of
		the voltage and current waveforms.
		*/
		var responseHandler = null;
		var functionToQueue = null;
		var streamStateObject = this.streamStateObjects[3];
		if (streamStateObject['responseProperties']['responseHandler'] === null) {
			responseHandler = 
				function (device, fid, packetResponse) {
					var result = [];
					var llvalues = null;
					var packetErrorFlag = 0;
					var rolesMappedData = [];
					var waveformLength = null;
					var waveformChunkData = null;
					var waveformOutOfSync = false;
					var streamStateObject = device.streamStateObjects[fid];
					var waveformChunkOffset = null;
					var payload = device.ipcon.getPayloadFromPacket(packetResponse);

					packetErrorFlag = device.ipcon.getEFromPacket(packetResponse);

					if (packetErrorFlag !== 0) {
						if (streamStateObject['responseProperties']['errorCB'] !== undefined) {
							if (packetErrorFlag === 1) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_INVALID_PARAMETER);
							}
							else if (packetErrorFlag === 2) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_FUNCTION_NOT_SUPPORTED);
							}
							else {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_UNKNOWN_ERROR);
							}
						}

						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}

						return;
					}

					if (payload.length === 0) {
						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}

						return;
					}

					llvalues = device.ipcon.unpack(payload,
					                               streamStateObject['responseProperties']['unpackFormatString']);

					for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
						if (streamStateObject['dataMapping'][i] === 'streamChunkData') {
							waveformChunkData = llvalues[i];
						}
						else if (streamStateObject['dataMapping'][i] === 'streamChunkOffset') {
							waveformChunkOffset = llvalues[i];
						}
					}

					waveformLength = streamStateObject['streamProperties']['fixedLength'];

					function handleOOS() {
						if ((waveformChunkOffset + 30) < waveformLength) {
							streamStateObject['responseProperties']['runningSubcallOOS'] = true;
							device.ipcon.sendRequest(device, BrickletEnergyMonitor.FUNCTION_GET_WAVEFORM_LOW_LEVEL, [], '', 70, 'H h30', streamStateObject['responseProperties']['returnCB'], streamStateObject['responseProperties']['errorCB'], true, true);

							return;
						}

						if (streamStateObject['responseProperties']['errorCB']) {
							streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_STREAM_OUT_OF_SYNC);
						}

						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}
					}

					if (streamStateObject['responseProperties']['waitingFirstChunk']) {
						streamStateObject['responseProperties']['waitingFirstChunk'] = false;

						if (waveformChunkOffset === ((1 << 16) - 1)) { // maximum chunk offset -> stream has no data
							waveformLength = 0;
							waveformOutOfSync = false;
							streamStateObject['responseProperties']['data'].length = 0;
						}
						else {
								waveformOutOfSync = (waveformChunkOffset !== 0);
								streamStateObject['responseProperties']['data'] = waveformChunkData;
						}
					}

					if (!streamStateObject['responseProperties']['runningSubcallOOS']) {
						if (!streamStateObject['responseProperties']['runningSubcall']) {
							if (!waveformOutOfSync &&
								(streamStateObject['responseProperties']['data'].length < waveformLength)) {
									streamStateObject['responseProperties']['runningSubcall'] = true;
									device.ipcon.sendRequest(device, BrickletEnergyMonitor.FUNCTION_GET_WAVEFORM_LOW_LEVEL, [], '', 70, 'H h30', streamStateObject['responseProperties']['returnCB'], streamStateObject['responseProperties']['errorCB'], true, true);

									return;
							}
						}
						else {
							waveformOutOfSync =
								(waveformChunkOffset !== streamStateObject['responseProperties']['data'].length);

							if (!waveformOutOfSync &&
								(streamStateObject['responseProperties']['data'].length < waveformLength)) {
									streamStateObject['responseProperties']['data'] =
										streamStateObject['responseProperties']['data'].concat(waveformChunkData);
									if (streamStateObject['responseProperties']['data'].length >= waveformLength) {
										streamStateObject['responseProperties']['data'] =
											streamStateObject['responseProperties']['data'].splice(0, waveformLength);
									}
									else {
										device.ipcon.sendRequest(device, BrickletEnergyMonitor.FUNCTION_GET_WAVEFORM_LOW_LEVEL, [], '', 70, 'H h30', streamStateObject['responseProperties']['returnCB'], streamStateObject['responseProperties']['errorCB'], true, true);

										return;
									}
							}
						}
					}
					else {
						handleOOS();

						return;
					}

					if (waveformOutOfSync) { // Discard remaining stream to bring it back in-sync
						handleOOS();

						return;
					}

					if (streamStateObject['responseProperties']['returnCB']) {
						for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
							rolesMappedData.push({'role': streamStateObject['dataMapping'][i], 'llvalue': llvalues[i]});
						}

						for (var i = 0; i < rolesMappedData.length; i++) {
							if (rolesMappedData[i]['role'] === 'streamChunkData') {
								result.push(streamStateObject['responseProperties']['data'].splice(0, waveformLength));
							}
							else if (rolesMappedData[i]['role'] === null) {
								result.push(rolesMappedData[i]['llvalue']);
							}
						}

						streamStateObject['responseProperties']['returnCB'].apply(device, result);
					}

					device.resetStreamStateObject(streamStateObject);

					if (streamStateObject['responseProperties']['callQueue'].length > 0) {
						streamStateObject['responseProperties']['callQueue'].shift()(device);
					}
				};

			streamStateObject['responseProperties']['responseHandler'] = responseHandler;
		}
		if (!streamStateObject['responseProperties']['running']) {
			streamStateObject['responseProperties']['running'] = true;
			streamStateObject['responseProperties']['returnCB'] = returnCallback;
			streamStateObject['responseProperties']['errorCB'] = errorCallback;
			this.ipcon.sendRequest(this,
			                       BrickletEnergyMonitor.FUNCTION_GET_WAVEFORM_LOW_LEVEL,
			                       [],
			                       '',
			                       70,
			                       'H h30',
			                       returnCallback,
			                       errorCallback,
			                       true,
			                       true);
		}
		else {
			functionToQueue = function (device) {
				device.getWaveform.call(device, returnCallback, errorCallback);
			}
			streamStateObject['responseProperties']['callQueue'].push(functionToQueue);
		}
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletEnergyMonitor;

},{"./Device":279,"./IPConnection":280}],181:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletGPS.DEVICE_IDENTIFIER = 222;
BrickletGPS.DEVICE_DISPLAY_NAME = 'GPS Bricklet';
BrickletGPS.CALLBACK_COORDINATES = 17;
BrickletGPS.CALLBACK_STATUS = 18;
BrickletGPS.CALLBACK_ALTITUDE = 19;
BrickletGPS.CALLBACK_MOTION = 20;
BrickletGPS.CALLBACK_DATE_TIME = 21;
BrickletGPS.FUNCTION_GET_COORDINATES = 1;
BrickletGPS.FUNCTION_GET_STATUS = 2;
BrickletGPS.FUNCTION_GET_ALTITUDE = 3;
BrickletGPS.FUNCTION_GET_MOTION = 4;
BrickletGPS.FUNCTION_GET_DATE_TIME = 5;
BrickletGPS.FUNCTION_RESTART = 6;
BrickletGPS.FUNCTION_SET_COORDINATES_CALLBACK_PERIOD = 7;
BrickletGPS.FUNCTION_GET_COORDINATES_CALLBACK_PERIOD = 8;
BrickletGPS.FUNCTION_SET_STATUS_CALLBACK_PERIOD = 9;
BrickletGPS.FUNCTION_GET_STATUS_CALLBACK_PERIOD = 10;
BrickletGPS.FUNCTION_SET_ALTITUDE_CALLBACK_PERIOD = 11;
BrickletGPS.FUNCTION_GET_ALTITUDE_CALLBACK_PERIOD = 12;
BrickletGPS.FUNCTION_SET_MOTION_CALLBACK_PERIOD = 13;
BrickletGPS.FUNCTION_GET_MOTION_CALLBACK_PERIOD = 14;
BrickletGPS.FUNCTION_SET_DATE_TIME_CALLBACK_PERIOD = 15;
BrickletGPS.FUNCTION_GET_DATE_TIME_CALLBACK_PERIOD = 16;
BrickletGPS.FUNCTION_GET_IDENTITY = 255;
BrickletGPS.FIX_NO_FIX = 1;
BrickletGPS.FIX_2D_FIX = 2;
BrickletGPS.FIX_3D_FIX = 3;
BrickletGPS.RESTART_TYPE_HOT_START = 0;
BrickletGPS.RESTART_TYPE_WARM_START = 1;
BrickletGPS.RESTART_TYPE_COLD_START = 2;
BrickletGPS.RESTART_TYPE_FACTORY_RESET = 3;

function BrickletGPS(uid, ipcon) {
	//Determine position, velocity and altitude using GPS

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletGPS.DEVICE_IDENTIFIER, BrickletGPS.DEVICE_DISPLAY_NAME);
	BrickletGPS.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 1];
	this.responseExpected[BrickletGPS.FUNCTION_GET_COORDINATES] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletGPS.FUNCTION_GET_STATUS] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletGPS.FUNCTION_GET_ALTITUDE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletGPS.FUNCTION_GET_MOTION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletGPS.FUNCTION_GET_DATE_TIME] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletGPS.FUNCTION_RESTART] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletGPS.FUNCTION_SET_COORDINATES_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletGPS.FUNCTION_GET_COORDINATES_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletGPS.FUNCTION_SET_STATUS_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletGPS.FUNCTION_GET_STATUS_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletGPS.FUNCTION_SET_ALTITUDE_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletGPS.FUNCTION_GET_ALTITUDE_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletGPS.FUNCTION_SET_MOTION_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletGPS.FUNCTION_GET_MOTION_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletGPS.FUNCTION_SET_DATE_TIME_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletGPS.FUNCTION_GET_DATE_TIME_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletGPS.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletGPS.CALLBACK_COORDINATES] = [26, 'I c I c H H H H'];
	this.callbackFormats[BrickletGPS.CALLBACK_STATUS] = [11, 'B B B'];
	this.callbackFormats[BrickletGPS.CALLBACK_ALTITUDE] = [16, 'i i'];
	this.callbackFormats[BrickletGPS.CALLBACK_MOTION] = [16, 'I I'];
	this.callbackFormats[BrickletGPS.CALLBACK_DATE_TIME] = [16, 'I I'];



	this.getCoordinates = function(returnCallback, errorCallback) {
		/*
		Returns the GPS coordinates. Latitude and longitude are given in the
		``DD.dddddd°`` format, the value 57123468 means 57.123468°.
		The parameter ``ns`` and ``ew`` are the cardinal directions for
		latitude and longitude. Possible values for ``ns`` and ``ew`` are 'N', 'S', 'E'
		and 'W' (north, south, east and west).
		
		PDOP, HDOP and VDOP are the dilution of precision (DOP) values. They specify
		the additional multiplicative effect of GPS satellite geometry on GPS
		precision. See
		`here <https://en.wikipedia.org/wiki/Dilution_of_precision_(GPS)>`__
		for more information.
		
		EPE is the "Estimated Position Error". This is not the
		absolute maximum error, it is the error with a specific confidence. See
		`here <https://www.nps.gov/gis/gps/WhatisEPE.html>`__ for more information.
		
		This data is only valid if there is currently a fix as indicated by
		:func:`Get Status`.
		*/
		this.ipcon.sendRequest(this, BrickletGPS.FUNCTION_GET_COORDINATES, [], '', 26, 'I c I c H H H H', returnCallback, errorCallback, false, true);
	};
	this.getStatus = function(returnCallback, errorCallback) {
		/*
		Returns the current fix status, the number of satellites that are in view and
		the number of satellites that are currently used.
		
		Possible fix status values can be:
		
		.. csv-table::
		 :header: "Value", "Description"
		 :widths: 10, 100
		
		 "1", "No Fix, :func:`Get Coordinates`, :func:`Get Altitude` and :func:`Get Motion` return invalid data"
		 "2", "2D Fix, only :func:`Get Coordinates` and :func:`Get Motion` return valid data"
		 "3", "3D Fix, :func:`Get Coordinates`, :func:`Get Altitude` and :func:`Get Motion` return valid data"
		
		There is also a :ref:`blue LED <gps_bricklet_fix_led>` on the Bricklet that
		indicates the fix status.
		*/
		this.ipcon.sendRequest(this, BrickletGPS.FUNCTION_GET_STATUS, [], '', 11, 'B B B', returnCallback, errorCallback, false, true);
	};
	this.getAltitude = function(returnCallback, errorCallback) {
		/*
		Returns the current altitude and corresponding geoidal separation.
		
		This data is only valid if there is currently a fix as indicated by
		:func:`Get Status`.
		*/
		this.ipcon.sendRequest(this, BrickletGPS.FUNCTION_GET_ALTITUDE, [], '', 16, 'i i', returnCallback, errorCallback, false, true);
	};
	this.getMotion = function(returnCallback, errorCallback) {
		/*
		Returns the current course and speed. A course of 0° means the Bricklet is
		traveling north bound and 90° means it is traveling east bound.
		
		Please note that this only returns useful values if an actual movement
		is present.
		
		This data is only valid if there is currently a fix as indicated by
		:func:`Get Status`.
		*/
		this.ipcon.sendRequest(this, BrickletGPS.FUNCTION_GET_MOTION, [], '', 16, 'I I', returnCallback, errorCallback, false, true);
	};
	this.getDateTime = function(returnCallback, errorCallback) {
		/*
		Returns the current date and time. The date is
		given in the format ``ddmmyy`` and the time is given
		in the format ``hhmmss.sss``. For example, 140713 means
		14.07.13 as date and 195923568 means 19:59:23.568 as time.
		*/
		this.ipcon.sendRequest(this, BrickletGPS.FUNCTION_GET_DATE_TIME, [], '', 16, 'I I', returnCallback, errorCallback, false, true);
	};
	this.restart = function(restartType, returnCallback, errorCallback) {
		/*
		Restarts the GPS Bricklet, the following restart types are available:
		
		.. csv-table::
		 :header: "Value", "Description"
		 :widths: 10, 100
		
		 "0", "Hot start (use all available data in the NV store)"
		 "1", "Warm start (don't use ephemeris at restart)"
		 "2", "Cold start (don't use time, position, almanacs and ephemeris at restart)"
		 "3", "Factory reset (clear all system/user configurations at restart)"
		*/
		this.ipcon.sendRequest(this, BrickletGPS.FUNCTION_RESTART, [restartType], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.setCoordinatesCallbackPeriod = function(period, returnCallback, errorCallback) {
		/*
		Sets the period with which the :cb:`Coordinates` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		The :cb:`Coordinates` callback is only triggered if the coordinates changed
		since the last triggering.
		*/
		this.ipcon.sendRequest(this, BrickletGPS.FUNCTION_SET_COORDINATES_CALLBACK_PERIOD, [period], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getCoordinatesCallbackPeriod = function(returnCallback, errorCallback) {
		/*
		Returns the period as set by :func:`Set Coordinates Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletGPS.FUNCTION_GET_COORDINATES_CALLBACK_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setStatusCallbackPeriod = function(period, returnCallback, errorCallback) {
		/*
		Sets the period with which the :cb:`Status` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		The :cb:`Status` callback is only triggered if the status changed since the
		last triggering.
		*/
		this.ipcon.sendRequest(this, BrickletGPS.FUNCTION_SET_STATUS_CALLBACK_PERIOD, [period], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getStatusCallbackPeriod = function(returnCallback, errorCallback) {
		/*
		Returns the period as set by :func:`Set Status Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletGPS.FUNCTION_GET_STATUS_CALLBACK_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setAltitudeCallbackPeriod = function(period, returnCallback, errorCallback) {
		/*
		Sets the period with which the :cb:`Altitude` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		The :cb:`Altitude` callback is only triggered if the altitude changed since
		the last triggering.
		*/
		this.ipcon.sendRequest(this, BrickletGPS.FUNCTION_SET_ALTITUDE_CALLBACK_PERIOD, [period], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getAltitudeCallbackPeriod = function(returnCallback, errorCallback) {
		/*
		Returns the period as set by :func:`Set Altitude Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletGPS.FUNCTION_GET_ALTITUDE_CALLBACK_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setMotionCallbackPeriod = function(period, returnCallback, errorCallback) {
		/*
		Sets the period with which the :cb:`Motion` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		The :cb:`Motion` callback is only triggered if the motion changed since the
		last triggering.
		*/
		this.ipcon.sendRequest(this, BrickletGPS.FUNCTION_SET_MOTION_CALLBACK_PERIOD, [period], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getMotionCallbackPeriod = function(returnCallback, errorCallback) {
		/*
		Returns the period as set by :func:`Set Motion Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletGPS.FUNCTION_GET_MOTION_CALLBACK_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setDateTimeCallbackPeriod = function(period, returnCallback, errorCallback) {
		/*
		Sets the period with which the :cb:`Date Time` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		The :cb:`Date Time` callback is only triggered if the date or time changed
		since the last triggering.
		*/
		this.ipcon.sendRequest(this, BrickletGPS.FUNCTION_SET_DATE_TIME_CALLBACK_PERIOD, [period], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getDateTimeCallbackPeriod = function(returnCallback, errorCallback) {
		/*
		Returns the period as set by :func:`Set Date Time Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletGPS.FUNCTION_GET_DATE_TIME_CALLBACK_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletGPS.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletGPS;

},{"./Device":279,"./IPConnection":280}],182:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletGPSV2.DEVICE_IDENTIFIER = 276;
BrickletGPSV2.DEVICE_DISPLAY_NAME = 'GPS Bricklet 2.0';
BrickletGPSV2.CALLBACK_PULSE_PER_SECOND = 21;
BrickletGPSV2.CALLBACK_COORDINATES = 22;
BrickletGPSV2.CALLBACK_STATUS = 23;
BrickletGPSV2.CALLBACK_ALTITUDE = 24;
BrickletGPSV2.CALLBACK_MOTION = 25;
BrickletGPSV2.CALLBACK_DATE_TIME = 26;
BrickletGPSV2.FUNCTION_GET_COORDINATES = 1;
BrickletGPSV2.FUNCTION_GET_STATUS = 2;
BrickletGPSV2.FUNCTION_GET_ALTITUDE = 3;
BrickletGPSV2.FUNCTION_GET_MOTION = 4;
BrickletGPSV2.FUNCTION_GET_DATE_TIME = 5;
BrickletGPSV2.FUNCTION_RESTART = 6;
BrickletGPSV2.FUNCTION_GET_SATELLITE_SYSTEM_STATUS_LOW_LEVEL = 7;
BrickletGPSV2.FUNCTION_GET_SATELLITE_STATUS = 8;
BrickletGPSV2.FUNCTION_SET_FIX_LED_CONFIG = 9;
BrickletGPSV2.FUNCTION_GET_FIX_LED_CONFIG = 10;
BrickletGPSV2.FUNCTION_SET_COORDINATES_CALLBACK_PERIOD = 11;
BrickletGPSV2.FUNCTION_GET_COORDINATES_CALLBACK_PERIOD = 12;
BrickletGPSV2.FUNCTION_SET_STATUS_CALLBACK_PERIOD = 13;
BrickletGPSV2.FUNCTION_GET_STATUS_CALLBACK_PERIOD = 14;
BrickletGPSV2.FUNCTION_SET_ALTITUDE_CALLBACK_PERIOD = 15;
BrickletGPSV2.FUNCTION_GET_ALTITUDE_CALLBACK_PERIOD = 16;
BrickletGPSV2.FUNCTION_SET_MOTION_CALLBACK_PERIOD = 17;
BrickletGPSV2.FUNCTION_GET_MOTION_CALLBACK_PERIOD = 18;
BrickletGPSV2.FUNCTION_SET_DATE_TIME_CALLBACK_PERIOD = 19;
BrickletGPSV2.FUNCTION_GET_DATE_TIME_CALLBACK_PERIOD = 20;
BrickletGPSV2.FUNCTION_SET_SBAS_CONFIG = 27;
BrickletGPSV2.FUNCTION_GET_SBAS_CONFIG = 28;
BrickletGPSV2.FUNCTION_GET_SPITFP_ERROR_COUNT = 234;
BrickletGPSV2.FUNCTION_SET_BOOTLOADER_MODE = 235;
BrickletGPSV2.FUNCTION_GET_BOOTLOADER_MODE = 236;
BrickletGPSV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER = 237;
BrickletGPSV2.FUNCTION_WRITE_FIRMWARE = 238;
BrickletGPSV2.FUNCTION_SET_STATUS_LED_CONFIG = 239;
BrickletGPSV2.FUNCTION_GET_STATUS_LED_CONFIG = 240;
BrickletGPSV2.FUNCTION_GET_CHIP_TEMPERATURE = 242;
BrickletGPSV2.FUNCTION_RESET = 243;
BrickletGPSV2.FUNCTION_WRITE_UID = 248;
BrickletGPSV2.FUNCTION_READ_UID = 249;
BrickletGPSV2.FUNCTION_GET_IDENTITY = 255;
BrickletGPSV2.RESTART_TYPE_HOT_START = 0;
BrickletGPSV2.RESTART_TYPE_WARM_START = 1;
BrickletGPSV2.RESTART_TYPE_COLD_START = 2;
BrickletGPSV2.RESTART_TYPE_FACTORY_RESET = 3;
BrickletGPSV2.SATELLITE_SYSTEM_GPS = 0;
BrickletGPSV2.SATELLITE_SYSTEM_GLONASS = 1;
BrickletGPSV2.SATELLITE_SYSTEM_GALILEO = 2;
BrickletGPSV2.FIX_NO_FIX = 1;
BrickletGPSV2.FIX_2D_FIX = 2;
BrickletGPSV2.FIX_3D_FIX = 3;
BrickletGPSV2.FIX_LED_CONFIG_OFF = 0;
BrickletGPSV2.FIX_LED_CONFIG_ON = 1;
BrickletGPSV2.FIX_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletGPSV2.FIX_LED_CONFIG_SHOW_FIX = 3;
BrickletGPSV2.FIX_LED_CONFIG_SHOW_PPS = 4;
BrickletGPSV2.SBAS_ENABLED = 0;
BrickletGPSV2.SBAS_DISABLED = 1;
BrickletGPSV2.BOOTLOADER_MODE_BOOTLOADER = 0;
BrickletGPSV2.BOOTLOADER_MODE_FIRMWARE = 1;
BrickletGPSV2.BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT = 2;
BrickletGPSV2.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT = 3;
BrickletGPSV2.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT = 4;
BrickletGPSV2.BOOTLOADER_STATUS_OK = 0;
BrickletGPSV2.BOOTLOADER_STATUS_INVALID_MODE = 1;
BrickletGPSV2.BOOTLOADER_STATUS_NO_CHANGE = 2;
BrickletGPSV2.BOOTLOADER_STATUS_ENTRY_FUNCTION_NOT_PRESENT = 3;
BrickletGPSV2.BOOTLOADER_STATUS_DEVICE_IDENTIFIER_INCORRECT = 4;
BrickletGPSV2.BOOTLOADER_STATUS_CRC_MISMATCH = 5;
BrickletGPSV2.STATUS_LED_CONFIG_OFF = 0;
BrickletGPSV2.STATUS_LED_CONFIG_ON = 1;
BrickletGPSV2.STATUS_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletGPSV2.STATUS_LED_CONFIG_SHOW_STATUS = 3;

function BrickletGPSV2(uid, ipcon) {
	//Determine position, velocity and altitude using GPS

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletGPSV2.DEVICE_IDENTIFIER, BrickletGPSV2.DEVICE_DISPLAY_NAME);
	BrickletGPSV2.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 1];
	this.responseExpected[BrickletGPSV2.FUNCTION_GET_COORDINATES] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletGPSV2.FUNCTION_GET_STATUS] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletGPSV2.FUNCTION_GET_ALTITUDE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletGPSV2.FUNCTION_GET_MOTION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletGPSV2.FUNCTION_GET_DATE_TIME] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletGPSV2.FUNCTION_RESTART] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletGPSV2.FUNCTION_GET_SATELLITE_SYSTEM_STATUS_LOW_LEVEL] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletGPSV2.FUNCTION_GET_SATELLITE_STATUS] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletGPSV2.FUNCTION_SET_FIX_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletGPSV2.FUNCTION_GET_FIX_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletGPSV2.FUNCTION_SET_COORDINATES_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletGPSV2.FUNCTION_GET_COORDINATES_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletGPSV2.FUNCTION_SET_STATUS_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletGPSV2.FUNCTION_GET_STATUS_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletGPSV2.FUNCTION_SET_ALTITUDE_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletGPSV2.FUNCTION_GET_ALTITUDE_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletGPSV2.FUNCTION_SET_MOTION_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletGPSV2.FUNCTION_GET_MOTION_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletGPSV2.FUNCTION_SET_DATE_TIME_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletGPSV2.FUNCTION_GET_DATE_TIME_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletGPSV2.FUNCTION_SET_SBAS_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletGPSV2.FUNCTION_GET_SBAS_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletGPSV2.FUNCTION_GET_SPITFP_ERROR_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletGPSV2.FUNCTION_SET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletGPSV2.FUNCTION_GET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletGPSV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletGPSV2.FUNCTION_WRITE_FIRMWARE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletGPSV2.FUNCTION_SET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletGPSV2.FUNCTION_GET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletGPSV2.FUNCTION_GET_CHIP_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletGPSV2.FUNCTION_RESET] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletGPSV2.FUNCTION_WRITE_UID] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletGPSV2.FUNCTION_READ_UID] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletGPSV2.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletGPSV2.CALLBACK_PULSE_PER_SECOND] = [8, ''];
	this.callbackFormats[BrickletGPSV2.CALLBACK_COORDINATES] = [18, 'I c I c'];
	this.callbackFormats[BrickletGPSV2.CALLBACK_STATUS] = [10, '? B'];
	this.callbackFormats[BrickletGPSV2.CALLBACK_ALTITUDE] = [16, 'i i'];
	this.callbackFormats[BrickletGPSV2.CALLBACK_MOTION] = [16, 'I I'];
	this.callbackFormats[BrickletGPSV2.CALLBACK_DATE_TIME] = [16, 'I I'];


	this.streamStateObjects[BrickletGPSV2.FUNCTION_GET_SATELLITE_SYSTEM_STATUS_LOW_LEVEL] = {
		'dataMapping': ['streamLength', 'streamChunkData', null, null, null, null],
		'dataMappingStreamIn': [],
		'streamProperties': {
			'fixedLength': null,
			'singleChunk': true,
			'shortWrite': false
		},
		'responseProperties': {
			'running': false,
			'runningSubcall': false,
			'runningSubcallOOS': false,
			'waitingFirstChunk': true,
			'timeout': null,
			'data': [],
			'streamInChunkOffset': 0,
			'streamInChunkLength': 0,
			'streamInResponseEmpty': true,
			'streamInWritten': 0,
			'streamInLLParams': null,
			'responseHandler': null,
			'packFormatString': 'B',
			'unpackFormatString': 'B B12 B H H H',
			'returnCB': null,
			'errorCB': null,
			'callQueue': []
		}
	};

	this.getCoordinates = function(returnCallback, errorCallback) {
		/*
		Returns the GPS coordinates. Latitude and longitude are given in the
		``DD.dddddd°`` format, the value 57123468 means 57.123468°.
		The parameter ``ns`` and ``ew`` are the cardinal directions for
		latitude and longitude. Possible values for ``ns`` and ``ew`` are 'N', 'S', 'E'
		and 'W' (north, south, east and west).
		
		This data is only valid if there is currently a fix as indicated by
		:func:`Get Status`.
		*/
		this.ipcon.sendRequest(this, BrickletGPSV2.FUNCTION_GET_COORDINATES, [], '', 18, 'I c I c', returnCallback, errorCallback, false, true);
	};
	this.getStatus = function(returnCallback, errorCallback) {
		/*
		Returns if a fix is currently available as well as the, the number of
		satellites that are in view.
		
		There is also a :ref:`green LED <gps_v2_bricklet_fix_led>` on the Bricklet that
		indicates the fix status.
		*/
		this.ipcon.sendRequest(this, BrickletGPSV2.FUNCTION_GET_STATUS, [], '', 10, '? B', returnCallback, errorCallback, false, true);
	};
	this.getAltitude = function(returnCallback, errorCallback) {
		/*
		Returns the current altitude and corresponding geoidal separation.
		
		This data is only valid if there is currently a fix as indicated by
		:func:`Get Status`.
		*/
		this.ipcon.sendRequest(this, BrickletGPSV2.FUNCTION_GET_ALTITUDE, [], '', 16, 'i i', returnCallback, errorCallback, false, true);
	};
	this.getMotion = function(returnCallback, errorCallback) {
		/*
		Returns the current course and speed. A course of 0° means the Bricklet is
		traveling north bound and 90° means it is traveling east bound.
		
		Please note that this only returns useful values if an actual movement
		is present.
		
		This data is only valid if there is currently a fix as indicated by
		:func:`Get Status`.
		*/
		this.ipcon.sendRequest(this, BrickletGPSV2.FUNCTION_GET_MOTION, [], '', 16, 'I I', returnCallback, errorCallback, false, true);
	};
	this.getDateTime = function(returnCallback, errorCallback) {
		/*
		Returns the current date and time. The date is
		given in the format ``ddmmyy`` and the time is given
		in the format ``hhmmss.sss``. For example, 140713 means
		14.07.13 as date and 195923568 means 19:59:23.568 as time.
		*/
		this.ipcon.sendRequest(this, BrickletGPSV2.FUNCTION_GET_DATE_TIME, [], '', 16, 'I I', returnCallback, errorCallback, false, true);
	};
	this.restart = function(restartType, returnCallback, errorCallback) {
		/*
		Restarts the GPS Bricklet, the following restart types are available:
		
		.. csv-table::
		 :header: "Value", "Description"
		 :widths: 10, 100
		
		 "0", "Hot start (use all available data in the NV store)"
		 "1", "Warm start (don't use ephemeris at restart)"
		 "2", "Cold start (don't use time, position, almanacs and ephemeris at restart)"
		 "3", "Factory reset (clear all system/user configurations at restart)"
		*/
		this.ipcon.sendRequest(this, BrickletGPSV2.FUNCTION_RESTART, [restartType], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getSatelliteSystemStatusLowLevel = function(satelliteSystem, returnCallback, errorCallback) {
		/*
		Returns the
		
		* satellite numbers list (up to 12 items)
		* fix value,
		* PDOP value,
		* HDOP value and
		* VDOP value
		
		for a given satellite system. Currently GPS and GLONASS are supported, Galileo
		is not yet supported.
		
		The GPS and GLONASS satellites have unique numbers and the satellite list gives
		the numbers of the satellites that are currently utilized. The number 0 is not
		a valid satellite number and can be ignored in the list.
		*/
		this.ipcon.sendRequest(this, BrickletGPSV2.FUNCTION_GET_SATELLITE_SYSTEM_STATUS_LOW_LEVEL, [satelliteSystem], 'B', 28, 'B B12 B H H H', returnCallback, errorCallback, false, true);
	};
	this.getSatelliteStatus = function(satelliteSystem, satelliteNumber, returnCallback, errorCallback) {
		/*
		Returns the current elevation, azimuth and SNR
		for a given satellite and satellite system.
		
		The satellite number here always goes from 1 to 32. For GLONASS it corresponds to
		the satellites 65-96.
		
		Galileo is not yet supported.
		*/
		this.ipcon.sendRequest(this, BrickletGPSV2.FUNCTION_GET_SATELLITE_STATUS, [satelliteSystem, satelliteNumber], 'B B', 14, 'h h h', returnCallback, errorCallback, false, true);
	};
	this.setFixLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Sets the fix LED configuration. By default the LED shows if
		the Bricklet got a GPS fix yet. If a fix is established the LED turns on.
		If there is no fix then the LED is turned off.
		
		You can also turn the LED permanently on/off, show a heartbeat or let it blink
		in sync with the PPS (pulse per second) output of the GPS module.
		
		If the Bricklet is in bootloader mode, the LED is off.
		*/
		this.ipcon.sendRequest(this, BrickletGPSV2.FUNCTION_SET_FIX_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getFixLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Fix LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletGPSV2.FUNCTION_GET_FIX_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setCoordinatesCallbackPeriod = function(period, returnCallback, errorCallback) {
		/*
		Sets the period with which the :cb:`Coordinates` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		The :cb:`Coordinates` callback is only triggered if the coordinates changed
		since the last triggering.
		*/
		this.ipcon.sendRequest(this, BrickletGPSV2.FUNCTION_SET_COORDINATES_CALLBACK_PERIOD, [period], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getCoordinatesCallbackPeriod = function(returnCallback, errorCallback) {
		/*
		Returns the period as set by :func:`Set Coordinates Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletGPSV2.FUNCTION_GET_COORDINATES_CALLBACK_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setStatusCallbackPeriod = function(period, returnCallback, errorCallback) {
		/*
		Sets the period with which the :cb:`Status` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		The :cb:`Status` callback is only triggered if the status changed since the
		last triggering.
		*/
		this.ipcon.sendRequest(this, BrickletGPSV2.FUNCTION_SET_STATUS_CALLBACK_PERIOD, [period], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getStatusCallbackPeriod = function(returnCallback, errorCallback) {
		/*
		Returns the period as set by :func:`Set Status Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletGPSV2.FUNCTION_GET_STATUS_CALLBACK_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setAltitudeCallbackPeriod = function(period, returnCallback, errorCallback) {
		/*
		Sets the period with which the :cb:`Altitude` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		The :cb:`Altitude` callback is only triggered if the altitude changed since the
		last triggering.
		*/
		this.ipcon.sendRequest(this, BrickletGPSV2.FUNCTION_SET_ALTITUDE_CALLBACK_PERIOD, [period], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getAltitudeCallbackPeriod = function(returnCallback, errorCallback) {
		/*
		Returns the period as set by :func:`Set Altitude Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletGPSV2.FUNCTION_GET_ALTITUDE_CALLBACK_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setMotionCallbackPeriod = function(period, returnCallback, errorCallback) {
		/*
		Sets the period with which the :cb:`Motion` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		The :cb:`Motion` callback is only triggered if the motion changed since the
		last triggering.
		*/
		this.ipcon.sendRequest(this, BrickletGPSV2.FUNCTION_SET_MOTION_CALLBACK_PERIOD, [period], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getMotionCallbackPeriod = function(returnCallback, errorCallback) {
		/*
		Returns the period as set by :func:`Set Motion Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletGPSV2.FUNCTION_GET_MOTION_CALLBACK_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setDateTimeCallbackPeriod = function(period, returnCallback, errorCallback) {
		/*
		Sets the period with which the :cb:`Date Time` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		The :cb:`Date Time` callback is only triggered if the date or time changed
		since the last triggering.
		*/
		this.ipcon.sendRequest(this, BrickletGPSV2.FUNCTION_SET_DATE_TIME_CALLBACK_PERIOD, [period], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getDateTimeCallbackPeriod = function(returnCallback, errorCallback) {
		/*
		Returns the period as set by :func:`Set Date Time Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletGPSV2.FUNCTION_GET_DATE_TIME_CALLBACK_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setSBASConfig = function(sbasConfig, returnCallback, errorCallback) {
		/*
		If `SBAS <https://en.wikipedia.org/wiki/GNSS_augmentation#Satellite-based_augmentation_system>`__ is enabled,
		the position accuracy increases (if SBAS satellites are in view),
		but the update rate is limited to 5Hz. With SBAS disabled the update rate is increased to 10Hz.
		
		.. versionadded:: 2.0.2$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletGPSV2.FUNCTION_SET_SBAS_CONFIG, [sbasConfig], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getSBASConfig = function(returnCallback, errorCallback) {
		/*
		Returns the SBAS configuration as set by :func:`Set SBAS Config`
		
		.. versionadded:: 2.0.2$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletGPSV2.FUNCTION_GET_SBAS_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPErrorCount = function(returnCallback, errorCallback) {
		/*
		Returns the error count for the communication between Brick and Bricklet.
		
		The errors are divided into
		
		* ACK checksum errors,
		* message checksum errors,
		* framing errors and
		* overflow errors.
		
		The errors counts are for errors that occur on the Bricklet side. All
		Bricks have a similar function that returns the errors on the Brick side.
		*/
		this.ipcon.sendRequest(this, BrickletGPSV2.FUNCTION_GET_SPITFP_ERROR_COUNT, [], '', 24, 'I I I I', returnCallback, errorCallback, false, true);
	};
	this.setBootloaderMode = function(mode, returnCallback, errorCallback) {
		/*
		Sets the bootloader mode and returns the status after the requested
		mode change was instigated.
		
		You can change from bootloader mode to firmware mode and vice versa. A change
		from bootloader mode to firmware mode will only take place if the entry function,
		device identifier and CRC are present and correct.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletGPSV2.FUNCTION_SET_BOOTLOADER_MODE, [mode], 'B', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getBootloaderMode = function(returnCallback, errorCallback) {
		/*
		Returns the current bootloader mode, see :func:`Set Bootloader Mode`.
		*/
		this.ipcon.sendRequest(this, BrickletGPSV2.FUNCTION_GET_BOOTLOADER_MODE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setWriteFirmwarePointer = function(pointer, returnCallback, errorCallback) {
		/*
		Sets the firmware pointer for :func:`Write Firmware`. The pointer has
		to be increased by chunks of size 64. The data is written to flash
		every 4 chunks (which equals to one page of size 256).
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletGPSV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER, [pointer], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeFirmware = function(data, returnCallback, errorCallback) {
		/*
		Writes 64 Bytes of firmware at the position as written by
		:func:`Set Write Firmware Pointer` before. The firmware is written
		to flash every 4 chunks.
		
		You can only write firmware in bootloader mode.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletGPSV2.FUNCTION_WRITE_FIRMWARE, [data], 'B64', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setStatusLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Sets the status LED configuration. By default the LED shows
		communication traffic between Brick and Bricklet, it flickers once
		for every 10 received data packets.
		
		You can also turn the LED permanently on/off or show a heartbeat.
		
		If the Bricklet is in bootloader mode, the LED is will show heartbeat by default.
		*/
		this.ipcon.sendRequest(this, BrickletGPSV2.FUNCTION_SET_STATUS_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getStatusLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Status LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletGPSV2.FUNCTION_GET_STATUS_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getChipTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature as measured inside the microcontroller. The
		value returned is not the ambient temperature!
		
		The temperature is only proportional to the real temperature and it has bad
		accuracy. Practically it is only useful as an indicator for
		temperature changes.
		*/
		this.ipcon.sendRequest(this, BrickletGPSV2.FUNCTION_GET_CHIP_TEMPERATURE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.reset = function(returnCallback, errorCallback) {
		/*
		Calling this function will reset the Bricklet. All configurations
		will be lost.
		
		After a reset you have to create new device objects,
		calling functions on the existing ones will result in
		undefined behavior!
		*/
		this.ipcon.sendRequest(this, BrickletGPSV2.FUNCTION_RESET, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeUID = function(uid, returnCallback, errorCallback) {
		/*
		Writes a new UID into flash. If you want to set a new UID
		you have to decode the Base58 encoded UID string into an
		integer first.
		
		We recommend that you use Brick Viewer to change the UID.
		*/
		this.ipcon.sendRequest(this, BrickletGPSV2.FUNCTION_WRITE_UID, [uid], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.readUID = function(returnCallback, errorCallback) {
		/*
		Returns the current UID as an integer. Encode as
		Base58 to get the usual string version.
		*/
		this.ipcon.sendRequest(this, BrickletGPSV2.FUNCTION_READ_UID, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletGPSV2.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.getSatelliteSystemStatus = function(satelliteSystem, returnCallback, errorCallback) {
		/*
		Returns the
		
		* satellite numbers list (up to 12 items)
		* fix value,
		* PDOP value,
		* HDOP value and
		* VDOP value
		
		for a given satellite system. Currently GPS and GLONASS are supported, Galileo
		is not yet supported.
		
		The GPS and GLONASS satellites have unique numbers and the satellite list gives
		the numbers of the satellites that are currently utilized. The number 0 is not
		a valid satellite number and can be ignored in the list.
		*/
		var responseHandler = null;
		var functionToQueue = null;
		var streamStateObject = this.streamStateObjects[7];
		if (streamStateObject['responseProperties']['responseHandler'] === null) {
			responseHandler = 
				function (device, fid, packetResponse) {
					var result = [];
					var llvalues = null;
					var packetErrorFlag = 0;
					var rolesMappedData = [];
					var satelliteNumbersLength = null;
					var satelliteNumbersChunkData = null;
					var satelliteNumbersOutOfSync = false;
					var streamStateObject = device.streamStateObjects[fid];
					var satelliteNumbersChunkOffset = null;
					var payload = device.ipcon.getPayloadFromPacket(packetResponse);

					packetErrorFlag = device.ipcon.getEFromPacket(packetResponse);

					if (packetErrorFlag !== 0) {
						if (streamStateObject['responseProperties']['errorCB'] !== undefined) {
							if (packetErrorFlag === 1) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_INVALID_PARAMETER);
							}
							else if (packetErrorFlag === 2) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_FUNCTION_NOT_SUPPORTED);
							}
							else {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_UNKNOWN_ERROR);
							}
						}

						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}

						return;
					}

					if (payload.length === 0) {
						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}

						return;
					}

					llvalues = device.ipcon.unpack(payload,
					                               streamStateObject['responseProperties']['unpackFormatString']);

					for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
						if (streamStateObject['dataMapping'][i] === 'streamChunkData') {
							satelliteNumbersChunkData = llvalues[i];
						}
						else if (streamStateObject['dataMapping'][i] === 'streamChunkOffset') {
							satelliteNumbersChunkOffset = llvalues[i];
						}
					}

					for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
						if (streamStateObject['dataMapping'][i] === 'streamLength') {
							satelliteNumbersLength = llvalues[i];
							break;
						}
					}

					satelliteNumbersChunkOffset = 0;

					if (streamStateObject['responseProperties']['returnCB']) {
						for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
							rolesMappedData.push({'role': streamStateObject['dataMapping'][i], 'llvalue': llvalues[i]});
						}

						for (var i = 0; i < rolesMappedData.length; i++) {
							if (rolesMappedData[i]['role'] === 'streamChunkData') {
								result.push(satelliteNumbersChunkData.splice(0, satelliteNumbersLength));
							}
							else if (rolesMappedData[i]['role'] === null) {
								result.push(rolesMappedData[i]['llvalue']);
							}
						}

						streamStateObject['responseProperties']['returnCB'].apply(device, result);
					}

					device.resetStreamStateObject(streamStateObject);

					if (streamStateObject['responseProperties']['callQueue'].length > 0) {
						streamStateObject['responseProperties']['callQueue'].shift()(device);
					}
				};

			streamStateObject['responseProperties']['responseHandler'] = responseHandler;
		}
		if (!streamStateObject['responseProperties']['running']) {
			streamStateObject['responseProperties']['running'] = true;
			streamStateObject['responseProperties']['returnCB'] = returnCallback;
			streamStateObject['responseProperties']['errorCB'] = errorCallback;
			this.ipcon.sendRequest(this,
			                       BrickletGPSV2.FUNCTION_GET_SATELLITE_SYSTEM_STATUS_LOW_LEVEL,
			                       [satelliteSystem],
			                       'B',
			                       28,
			                       'B B12 B H H H',
			                       returnCallback,
			                       errorCallback,
			                       true,
			                       true);
		}
		else {
			functionToQueue = function (device) {
				device.getSatelliteSystemStatus.call(device, satelliteSystem, returnCallback, errorCallback);
			}
			streamStateObject['responseProperties']['callQueue'].push(functionToQueue);
		}
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletGPSV2;

},{"./Device":279,"./IPConnection":280}],183:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletHallEffect.DEVICE_IDENTIFIER = 240;
BrickletHallEffect.DEVICE_DISPLAY_NAME = 'Hall Effect Bricklet';
BrickletHallEffect.CALLBACK_EDGE_COUNT = 10;
BrickletHallEffect.FUNCTION_GET_VALUE = 1;
BrickletHallEffect.FUNCTION_GET_EDGE_COUNT = 2;
BrickletHallEffect.FUNCTION_SET_EDGE_COUNT_CONFIG = 3;
BrickletHallEffect.FUNCTION_GET_EDGE_COUNT_CONFIG = 4;
BrickletHallEffect.FUNCTION_SET_EDGE_INTERRUPT = 5;
BrickletHallEffect.FUNCTION_GET_EDGE_INTERRUPT = 6;
BrickletHallEffect.FUNCTION_SET_EDGE_COUNT_CALLBACK_PERIOD = 7;
BrickletHallEffect.FUNCTION_GET_EDGE_COUNT_CALLBACK_PERIOD = 8;
BrickletHallEffect.FUNCTION_EDGE_INTERRUPT = 9;
BrickletHallEffect.FUNCTION_GET_IDENTITY = 255;
BrickletHallEffect.EDGE_TYPE_RISING = 0;
BrickletHallEffect.EDGE_TYPE_FALLING = 1;
BrickletHallEffect.EDGE_TYPE_BOTH = 2;

function BrickletHallEffect(uid, ipcon) {
	//Detects presence of magnetic field

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletHallEffect.DEVICE_IDENTIFIER, BrickletHallEffect.DEVICE_DISPLAY_NAME);
	BrickletHallEffect.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickletHallEffect.FUNCTION_GET_VALUE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletHallEffect.FUNCTION_GET_EDGE_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletHallEffect.FUNCTION_SET_EDGE_COUNT_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletHallEffect.FUNCTION_GET_EDGE_COUNT_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletHallEffect.FUNCTION_SET_EDGE_INTERRUPT] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletHallEffect.FUNCTION_GET_EDGE_INTERRUPT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletHallEffect.FUNCTION_SET_EDGE_COUNT_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletHallEffect.FUNCTION_GET_EDGE_COUNT_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletHallEffect.FUNCTION_EDGE_INTERRUPT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletHallEffect.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletHallEffect.CALLBACK_EDGE_COUNT] = [13, 'I ?'];



	this.getValue = function(returnCallback, errorCallback) {
		/*
		Returns *true* if a magnetic field of 3.5 millitesla or greater is detected.
		*/
		this.ipcon.sendRequest(this, BrickletHallEffect.FUNCTION_GET_VALUE, [], '', 9, '?', returnCallback, errorCallback, false, true);
	};
	this.getEdgeCount = function(resetCounter, returnCallback, errorCallback) {
		/*
		Returns the current value of the edge counter. You can configure
		edge type (rising, falling, both) that is counted with
		:func:`Set Edge Count Config`.
		
		If you set the reset counter to *true*, the count is set back to 0
		directly after it is read.
		*/
		this.ipcon.sendRequest(this, BrickletHallEffect.FUNCTION_GET_EDGE_COUNT, [resetCounter], '?', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setEdgeCountConfig = function(edgeType, debounce, returnCallback, errorCallback) {
		/*
		The edge type parameter configures if rising edges, falling edges or
		both are counted. Possible edge types are:
		
		* 0 = rising
		* 1 = falling
		* 2 = both
		
		A magnetic field of 3.5 millitesla or greater causes a falling edge and a
		magnetic field of 2.5 millitesla or smaller causes a rising edge.
		
		If a magnet comes near the Bricklet the signal goes low (falling edge), if
		a magnet is removed from the vicinity the signal goes high (rising edge).
		
		Configuring an edge counter resets its value to 0.
		
		If you don't know what any of this means, just leave it at default. The
		default configuration is very likely OK for you.
		*/
		this.ipcon.sendRequest(this, BrickletHallEffect.FUNCTION_SET_EDGE_COUNT_CONFIG, [edgeType, debounce], 'B B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getEdgeCountConfig = function(returnCallback, errorCallback) {
		/*
		Returns the edge type and debounce time as set by :func:`Set Edge Count Config`.
		*/
		this.ipcon.sendRequest(this, BrickletHallEffect.FUNCTION_GET_EDGE_COUNT_CONFIG, [], '', 10, 'B B', returnCallback, errorCallback, false, true);
	};
	this.setEdgeInterrupt = function(edges, returnCallback, errorCallback) {
		/*
		Sets the number of edges until an interrupt is invoked.
		
		If *edges* is set to n, an interrupt is invoked for every n-th detected edge.
		
		If *edges* is set to 0, the interrupt is disabled.
		*/
		this.ipcon.sendRequest(this, BrickletHallEffect.FUNCTION_SET_EDGE_INTERRUPT, [edges], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getEdgeInterrupt = function(returnCallback, errorCallback) {
		/*
		Returns the edges as set by :func:`Set Edge Interrupt`.
		*/
		this.ipcon.sendRequest(this, BrickletHallEffect.FUNCTION_GET_EDGE_INTERRUPT, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setEdgeCountCallbackPeriod = function(period, returnCallback, errorCallback) {
		/*
		Sets the period with which the :cb:`Edge Count` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		The :cb:`Edge Count` callback is only triggered if the edge count has changed
		since the last triggering.
		*/
		this.ipcon.sendRequest(this, BrickletHallEffect.FUNCTION_SET_EDGE_COUNT_CALLBACK_PERIOD, [period], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getEdgeCountCallbackPeriod = function(returnCallback, errorCallback) {
		/*
		Returns the period as set by :func:`Set Edge Count Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletHallEffect.FUNCTION_GET_EDGE_COUNT_CALLBACK_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.edgeInterrupt = function(returnCallback, errorCallback) {
		/*
		This callback is triggered every n-th count, as configured with
		:func:`Set Edge Interrupt`. The parameters are the
		current count and the current value (see :func:`Get Value` and
		:func:`Get Edge Count`).
		*/
		this.ipcon.sendRequest(this, BrickletHallEffect.FUNCTION_EDGE_INTERRUPT, [], '', 13, 'I ?', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletHallEffect.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletHallEffect;

},{"./Device":279,"./IPConnection":280}],184:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletHallEffectV2.DEVICE_IDENTIFIER = 2132;
BrickletHallEffectV2.DEVICE_DISPLAY_NAME = 'Hall Effect Bricklet 2.0';
BrickletHallEffectV2.CALLBACK_MAGNETIC_FLUX_DENSITY = 4;
BrickletHallEffectV2.CALLBACK_COUNTER = 10;
BrickletHallEffectV2.FUNCTION_GET_MAGNETIC_FLUX_DENSITY = 1;
BrickletHallEffectV2.FUNCTION_SET_MAGNETIC_FLUX_DENSITY_CALLBACK_CONFIGURATION = 2;
BrickletHallEffectV2.FUNCTION_GET_MAGNETIC_FLUX_DENSITY_CALLBACK_CONFIGURATION = 3;
BrickletHallEffectV2.FUNCTION_GET_COUNTER = 5;
BrickletHallEffectV2.FUNCTION_SET_COUNTER_CONFIG = 6;
BrickletHallEffectV2.FUNCTION_GET_COUNTER_CONFIG = 7;
BrickletHallEffectV2.FUNCTION_SET_COUNTER_CALLBACK_CONFIGURATION = 8;
BrickletHallEffectV2.FUNCTION_GET_COUNTER_CALLBACK_CONFIGURATION = 9;
BrickletHallEffectV2.FUNCTION_GET_SPITFP_ERROR_COUNT = 234;
BrickletHallEffectV2.FUNCTION_SET_BOOTLOADER_MODE = 235;
BrickletHallEffectV2.FUNCTION_GET_BOOTLOADER_MODE = 236;
BrickletHallEffectV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER = 237;
BrickletHallEffectV2.FUNCTION_WRITE_FIRMWARE = 238;
BrickletHallEffectV2.FUNCTION_SET_STATUS_LED_CONFIG = 239;
BrickletHallEffectV2.FUNCTION_GET_STATUS_LED_CONFIG = 240;
BrickletHallEffectV2.FUNCTION_GET_CHIP_TEMPERATURE = 242;
BrickletHallEffectV2.FUNCTION_RESET = 243;
BrickletHallEffectV2.FUNCTION_WRITE_UID = 248;
BrickletHallEffectV2.FUNCTION_READ_UID = 249;
BrickletHallEffectV2.FUNCTION_GET_IDENTITY = 255;
BrickletHallEffectV2.THRESHOLD_OPTION_OFF = 'x';
BrickletHallEffectV2.THRESHOLD_OPTION_OUTSIDE = 'o';
BrickletHallEffectV2.THRESHOLD_OPTION_INSIDE = 'i';
BrickletHallEffectV2.THRESHOLD_OPTION_SMALLER = '<';
BrickletHallEffectV2.THRESHOLD_OPTION_GREATER = '>';
BrickletHallEffectV2.BOOTLOADER_MODE_BOOTLOADER = 0;
BrickletHallEffectV2.BOOTLOADER_MODE_FIRMWARE = 1;
BrickletHallEffectV2.BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT = 2;
BrickletHallEffectV2.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT = 3;
BrickletHallEffectV2.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT = 4;
BrickletHallEffectV2.BOOTLOADER_STATUS_OK = 0;
BrickletHallEffectV2.BOOTLOADER_STATUS_INVALID_MODE = 1;
BrickletHallEffectV2.BOOTLOADER_STATUS_NO_CHANGE = 2;
BrickletHallEffectV2.BOOTLOADER_STATUS_ENTRY_FUNCTION_NOT_PRESENT = 3;
BrickletHallEffectV2.BOOTLOADER_STATUS_DEVICE_IDENTIFIER_INCORRECT = 4;
BrickletHallEffectV2.BOOTLOADER_STATUS_CRC_MISMATCH = 5;
BrickletHallEffectV2.STATUS_LED_CONFIG_OFF = 0;
BrickletHallEffectV2.STATUS_LED_CONFIG_ON = 1;
BrickletHallEffectV2.STATUS_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletHallEffectV2.STATUS_LED_CONFIG_SHOW_STATUS = 3;

function BrickletHallEffectV2(uid, ipcon) {
	//Measures magnetic flux density between -7mT and +7mT

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletHallEffectV2.DEVICE_IDENTIFIER, BrickletHallEffectV2.DEVICE_DISPLAY_NAME);
	BrickletHallEffectV2.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickletHallEffectV2.FUNCTION_GET_MAGNETIC_FLUX_DENSITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletHallEffectV2.FUNCTION_SET_MAGNETIC_FLUX_DENSITY_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletHallEffectV2.FUNCTION_GET_MAGNETIC_FLUX_DENSITY_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletHallEffectV2.FUNCTION_GET_COUNTER] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletHallEffectV2.FUNCTION_SET_COUNTER_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletHallEffectV2.FUNCTION_GET_COUNTER_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletHallEffectV2.FUNCTION_SET_COUNTER_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletHallEffectV2.FUNCTION_GET_COUNTER_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletHallEffectV2.FUNCTION_GET_SPITFP_ERROR_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletHallEffectV2.FUNCTION_SET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletHallEffectV2.FUNCTION_GET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletHallEffectV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletHallEffectV2.FUNCTION_WRITE_FIRMWARE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletHallEffectV2.FUNCTION_SET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletHallEffectV2.FUNCTION_GET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletHallEffectV2.FUNCTION_GET_CHIP_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletHallEffectV2.FUNCTION_RESET] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletHallEffectV2.FUNCTION_WRITE_UID] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletHallEffectV2.FUNCTION_READ_UID] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletHallEffectV2.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletHallEffectV2.CALLBACK_MAGNETIC_FLUX_DENSITY] = [10, 'h'];
	this.callbackFormats[BrickletHallEffectV2.CALLBACK_COUNTER] = [12, 'I'];



	this.getMagneticFluxDensity = function(returnCallback, errorCallback) {
		/*
		Returns the `magnetic flux density (magnetic induction) <https://en.wikipedia.org/wiki/Magnetic_flux>`__.
		
		
		If you want to get the value periodically, it is recommended to use the
		:cb:`Magnetic Flux Density` callback. You can set the callback configuration
		with :func:`Set Magnetic Flux Density Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletHallEffectV2.FUNCTION_GET_MAGNETIC_FLUX_DENSITY, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.setMagneticFluxDensityCallbackConfiguration = function(period, valueHasToChange, option, min, max, returnCallback, errorCallback) {
		/*
		The period is the period with which the :cb:`Magnetic Flux Density` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		If the `value has to change`-parameter is set to true, the callback is only
		triggered after the value has changed. If the value didn't change
		within the period, the callback is triggered immediately on change.
		
		If it is set to false, the callback is continuously triggered with the period,
		independent of the value.
		
		It is furthermore possible to constrain the callback with thresholds.
		
		The `option`-parameter together with min/max sets a threshold for the :cb:`Magnetic Flux Density` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Threshold is turned off"
		 "'o'",    "Threshold is triggered when the value is *outside* the min and max values"
		 "'i'",    "Threshold is triggered when the value is *inside* or equal to the min and max values"
		 "'<'",    "Threshold is triggered when the value is smaller than the min value (max is ignored)"
		 "'>'",    "Threshold is triggered when the value is greater than the min value (max is ignored)"
		
		If the option is set to 'x' (threshold turned off) the callback is triggered with the fixed period.
		*/
		this.ipcon.sendRequest(this, BrickletHallEffectV2.FUNCTION_SET_MAGNETIC_FLUX_DENSITY_CALLBACK_CONFIGURATION, [period, valueHasToChange, option, min, max], 'I ? c h h', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getMagneticFluxDensityCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the callback configuration as set by :func:`Set Magnetic Flux Density Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletHallEffectV2.FUNCTION_GET_MAGNETIC_FLUX_DENSITY_CALLBACK_CONFIGURATION, [], '', 18, 'I ? c h h', returnCallback, errorCallback, false, true);
	};
	this.getCounter = function(resetCounter, returnCallback, errorCallback) {
		/*
		Returns the current value of the counter.
		
		You can configure the low/high thresholds and the debounce time
		with :func:`Set Counter Config`.
		
		If you set reset counter to *true*, the count is set back to 0
		directly after it is read.
		
		If you want to get the count periodically, it is recommended to use the
		:cb:`Counter` callback. You can set the callback configuration
		with :func:`Set Counter Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletHallEffectV2.FUNCTION_GET_COUNTER, [resetCounter], '?', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setCounterConfig = function(highThreshold, lowThreshold, debounce, returnCallback, errorCallback) {
		/*
		Sets a high and a low threshold as well as a debounce time.
		
		If the measured magnetic flux density goes above the high threshold or
		below the low threshold, the count of the counter is increased by 1.
		
		The debounce time is the minimum time between two count increments.
		*/
		this.ipcon.sendRequest(this, BrickletHallEffectV2.FUNCTION_SET_COUNTER_CONFIG, [highThreshold, lowThreshold, debounce], 'h h I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getCounterConfig = function(returnCallback, errorCallback) {
		/*
		Returns the counter config as set by :func:`Set Counter Config`.
		*/
		this.ipcon.sendRequest(this, BrickletHallEffectV2.FUNCTION_GET_COUNTER_CONFIG, [], '', 16, 'h h I', returnCallback, errorCallback, false, true);
	};
	this.setCounterCallbackConfiguration = function(period, valueHasToChange, returnCallback, errorCallback) {
		/*
		The period is the period with which the :cb:`Counter`
		callback is triggered periodically. A value of 0 turns the callback off.
		
		If the `value has to change`-parameter is set to true, the callback is only
		triggered after at least one of the values has changed. If the values didn't
		change within the period, the callback is triggered immediately on change.
		
		If it is set to false, the callback is continuously triggered with the period,
		independent of the value.
		*/
		this.ipcon.sendRequest(this, BrickletHallEffectV2.FUNCTION_SET_COUNTER_CALLBACK_CONFIGURATION, [period, valueHasToChange], 'I ?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getCounterCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the callback configuration as set by
		:func:`Set Counter Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletHallEffectV2.FUNCTION_GET_COUNTER_CALLBACK_CONFIGURATION, [], '', 13, 'I ?', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPErrorCount = function(returnCallback, errorCallback) {
		/*
		Returns the error count for the communication between Brick and Bricklet.
		
		The errors are divided into
		
		* ACK checksum errors,
		* message checksum errors,
		* framing errors and
		* overflow errors.
		
		The errors counts are for errors that occur on the Bricklet side. All
		Bricks have a similar function that returns the errors on the Brick side.
		*/
		this.ipcon.sendRequest(this, BrickletHallEffectV2.FUNCTION_GET_SPITFP_ERROR_COUNT, [], '', 24, 'I I I I', returnCallback, errorCallback, false, true);
	};
	this.setBootloaderMode = function(mode, returnCallback, errorCallback) {
		/*
		Sets the bootloader mode and returns the status after the requested
		mode change was instigated.
		
		You can change from bootloader mode to firmware mode and vice versa. A change
		from bootloader mode to firmware mode will only take place if the entry function,
		device identifier and CRC are present and correct.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletHallEffectV2.FUNCTION_SET_BOOTLOADER_MODE, [mode], 'B', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getBootloaderMode = function(returnCallback, errorCallback) {
		/*
		Returns the current bootloader mode, see :func:`Set Bootloader Mode`.
		*/
		this.ipcon.sendRequest(this, BrickletHallEffectV2.FUNCTION_GET_BOOTLOADER_MODE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setWriteFirmwarePointer = function(pointer, returnCallback, errorCallback) {
		/*
		Sets the firmware pointer for :func:`Write Firmware`. The pointer has
		to be increased by chunks of size 64. The data is written to flash
		every 4 chunks (which equals to one page of size 256).
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletHallEffectV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER, [pointer], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeFirmware = function(data, returnCallback, errorCallback) {
		/*
		Writes 64 Bytes of firmware at the position as written by
		:func:`Set Write Firmware Pointer` before. The firmware is written
		to flash every 4 chunks.
		
		You can only write firmware in bootloader mode.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletHallEffectV2.FUNCTION_WRITE_FIRMWARE, [data], 'B64', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setStatusLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Sets the status LED configuration. By default the LED shows
		communication traffic between Brick and Bricklet, it flickers once
		for every 10 received data packets.
		
		You can also turn the LED permanently on/off or show a heartbeat.
		
		If the Bricklet is in bootloader mode, the LED is will show heartbeat by default.
		*/
		this.ipcon.sendRequest(this, BrickletHallEffectV2.FUNCTION_SET_STATUS_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getStatusLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Status LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletHallEffectV2.FUNCTION_GET_STATUS_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getChipTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature as measured inside the microcontroller. The
		value returned is not the ambient temperature!
		
		The temperature is only proportional to the real temperature and it has bad
		accuracy. Practically it is only useful as an indicator for
		temperature changes.
		*/
		this.ipcon.sendRequest(this, BrickletHallEffectV2.FUNCTION_GET_CHIP_TEMPERATURE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.reset = function(returnCallback, errorCallback) {
		/*
		Calling this function will reset the Bricklet. All configurations
		will be lost.
		
		After a reset you have to create new device objects,
		calling functions on the existing ones will result in
		undefined behavior!
		*/
		this.ipcon.sendRequest(this, BrickletHallEffectV2.FUNCTION_RESET, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeUID = function(uid, returnCallback, errorCallback) {
		/*
		Writes a new UID into flash. If you want to set a new UID
		you have to decode the Base58 encoded UID string into an
		integer first.
		
		We recommend that you use Brick Viewer to change the UID.
		*/
		this.ipcon.sendRequest(this, BrickletHallEffectV2.FUNCTION_WRITE_UID, [uid], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.readUID = function(returnCallback, errorCallback) {
		/*
		Returns the current UID as an integer. Encode as
		Base58 to get the usual string version.
		*/
		this.ipcon.sendRequest(this, BrickletHallEffectV2.FUNCTION_READ_UID, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletHallEffectV2.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletHallEffectV2;

},{"./Device":279,"./IPConnection":280}],185:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletHumidity.DEVICE_IDENTIFIER = 27;
BrickletHumidity.DEVICE_DISPLAY_NAME = 'Humidity Bricklet';
BrickletHumidity.CALLBACK_HUMIDITY = 13;
BrickletHumidity.CALLBACK_ANALOG_VALUE = 14;
BrickletHumidity.CALLBACK_HUMIDITY_REACHED = 15;
BrickletHumidity.CALLBACK_ANALOG_VALUE_REACHED = 16;
BrickletHumidity.FUNCTION_GET_HUMIDITY = 1;
BrickletHumidity.FUNCTION_GET_ANALOG_VALUE = 2;
BrickletHumidity.FUNCTION_SET_HUMIDITY_CALLBACK_PERIOD = 3;
BrickletHumidity.FUNCTION_GET_HUMIDITY_CALLBACK_PERIOD = 4;
BrickletHumidity.FUNCTION_SET_ANALOG_VALUE_CALLBACK_PERIOD = 5;
BrickletHumidity.FUNCTION_GET_ANALOG_VALUE_CALLBACK_PERIOD = 6;
BrickletHumidity.FUNCTION_SET_HUMIDITY_CALLBACK_THRESHOLD = 7;
BrickletHumidity.FUNCTION_GET_HUMIDITY_CALLBACK_THRESHOLD = 8;
BrickletHumidity.FUNCTION_SET_ANALOG_VALUE_CALLBACK_THRESHOLD = 9;
BrickletHumidity.FUNCTION_GET_ANALOG_VALUE_CALLBACK_THRESHOLD = 10;
BrickletHumidity.FUNCTION_SET_DEBOUNCE_PERIOD = 11;
BrickletHumidity.FUNCTION_GET_DEBOUNCE_PERIOD = 12;
BrickletHumidity.FUNCTION_GET_IDENTITY = 255;
BrickletHumidity.THRESHOLD_OPTION_OFF = 'x';
BrickletHumidity.THRESHOLD_OPTION_OUTSIDE = 'o';
BrickletHumidity.THRESHOLD_OPTION_INSIDE = 'i';
BrickletHumidity.THRESHOLD_OPTION_SMALLER = '<';
BrickletHumidity.THRESHOLD_OPTION_GREATER = '>';

function BrickletHumidity(uid, ipcon) {
	//Measures relative humidity

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletHumidity.DEVICE_IDENTIFIER, BrickletHumidity.DEVICE_DISPLAY_NAME);
	BrickletHumidity.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 1];
	this.responseExpected[BrickletHumidity.FUNCTION_GET_HUMIDITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletHumidity.FUNCTION_GET_ANALOG_VALUE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletHumidity.FUNCTION_SET_HUMIDITY_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletHumidity.FUNCTION_GET_HUMIDITY_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletHumidity.FUNCTION_SET_ANALOG_VALUE_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletHumidity.FUNCTION_GET_ANALOG_VALUE_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletHumidity.FUNCTION_SET_HUMIDITY_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletHumidity.FUNCTION_GET_HUMIDITY_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletHumidity.FUNCTION_SET_ANALOG_VALUE_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletHumidity.FUNCTION_GET_ANALOG_VALUE_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletHumidity.FUNCTION_SET_DEBOUNCE_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletHumidity.FUNCTION_GET_DEBOUNCE_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletHumidity.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletHumidity.CALLBACK_HUMIDITY] = [10, 'H'];
	this.callbackFormats[BrickletHumidity.CALLBACK_ANALOG_VALUE] = [10, 'H'];
	this.callbackFormats[BrickletHumidity.CALLBACK_HUMIDITY_REACHED] = [10, 'H'];
	this.callbackFormats[BrickletHumidity.CALLBACK_ANALOG_VALUE_REACHED] = [10, 'H'];



	this.getHumidity = function(returnCallback, errorCallback) {
		/*
		Returns the humidity of the sensor.
		
		If you want to get the humidity periodically, it is recommended to use the
		:cb:`Humidity` callback and set the period with
		:func:`Set Humidity Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletHumidity.FUNCTION_GET_HUMIDITY, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.getAnalogValue = function(returnCallback, errorCallback) {
		/*
		Returns the value as read by a 12-bit analog-to-digital converter.
		
		.. note::
		 The value returned by :func:`Get Humidity` is averaged over several samples
		 to yield less noise, while :func:`Get Analog Value` gives back raw
		 unfiltered analog values. The returned humidity value is calibrated for
		 room temperatures, if you use the sensor in extreme cold or extreme
		 warm environments, you might want to calculate the humidity from
		 the analog value yourself. See the `HIH 5030 datasheet
		 <https://github.com/Tinkerforge/humidity-bricklet/raw/master/datasheets/hih-5030.pdf>`__.
		
		If you want the analog value periodically, it is recommended to use the
		:cb:`Analog Value` callback and set the period with
		:func:`Set Analog Value Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletHumidity.FUNCTION_GET_ANALOG_VALUE, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.setHumidityCallbackPeriod = function(period, returnCallback, errorCallback) {
		/*
		Sets the period with which the :cb:`Humidity` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		The :cb:`Humidity` callback is only triggered if the humidity has changed
		since the last triggering.
		*/
		this.ipcon.sendRequest(this, BrickletHumidity.FUNCTION_SET_HUMIDITY_CALLBACK_PERIOD, [period], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getHumidityCallbackPeriod = function(returnCallback, errorCallback) {
		/*
		Returns the period as set by :func:`Set Humidity Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletHumidity.FUNCTION_GET_HUMIDITY_CALLBACK_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setAnalogValueCallbackPeriod = function(period, returnCallback, errorCallback) {
		/*
		Sets the period with which the :cb:`Analog Value` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		The :cb:`Analog Value` callback is only triggered if the analog value has
		changed since the last triggering.
		*/
		this.ipcon.sendRequest(this, BrickletHumidity.FUNCTION_SET_ANALOG_VALUE_CALLBACK_PERIOD, [period], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getAnalogValueCallbackPeriod = function(returnCallback, errorCallback) {
		/*
		Returns the period as set by :func:`Set Analog Value Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletHumidity.FUNCTION_GET_ANALOG_VALUE_CALLBACK_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setHumidityCallbackThreshold = function(option, min, max, returnCallback, errorCallback) {
		/*
		Sets the thresholds for the :cb:`Humidity Reached` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Callback is turned off"
		 "'o'",    "Callback is triggered when the humidity is *outside* the min and max values"
		 "'i'",    "Callback is triggered when the humidity is *inside* the min and max values"
		 "'<'",    "Callback is triggered when the humidity is smaller than the min value (max is ignored)"
		 "'>'",    "Callback is triggered when the humidity is greater than the min value (max is ignored)"
		*/
		this.ipcon.sendRequest(this, BrickletHumidity.FUNCTION_SET_HUMIDITY_CALLBACK_THRESHOLD, [option, min, max], 'c H H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getHumidityCallbackThreshold = function(returnCallback, errorCallback) {
		/*
		Returns the threshold as set by :func:`Set Humidity Callback Threshold`.
		*/
		this.ipcon.sendRequest(this, BrickletHumidity.FUNCTION_GET_HUMIDITY_CALLBACK_THRESHOLD, [], '', 13, 'c H H', returnCallback, errorCallback, false, true);
	};
	this.setAnalogValueCallbackThreshold = function(option, min, max, returnCallback, errorCallback) {
		/*
		Sets the thresholds for the :cb:`Analog Value Reached` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Callback is turned off"
		 "'o'",    "Callback is triggered when the analog value is *outside* the min and max values"
		 "'i'",    "Callback is triggered when the analog value is *inside* the min and max values"
		 "'<'",    "Callback is triggered when the analog value is smaller than the min value (max is ignored)"
		 "'>'",    "Callback is triggered when the analog value is greater than the min value (max is ignored)"
		*/
		this.ipcon.sendRequest(this, BrickletHumidity.FUNCTION_SET_ANALOG_VALUE_CALLBACK_THRESHOLD, [option, min, max], 'c H H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getAnalogValueCallbackThreshold = function(returnCallback, errorCallback) {
		/*
		Returns the threshold as set by :func:`Set Analog Value Callback Threshold`.
		*/
		this.ipcon.sendRequest(this, BrickletHumidity.FUNCTION_GET_ANALOG_VALUE_CALLBACK_THRESHOLD, [], '', 13, 'c H H', returnCallback, errorCallback, false, true);
	};
	this.setDebouncePeriod = function(debounce, returnCallback, errorCallback) {
		/*
		Sets the period with which the threshold callbacks
		
		* :cb:`Humidity Reached`,
		* :cb:`Analog Value Reached`
		
		are triggered, if the thresholds
		
		* :func:`Set Humidity Callback Threshold`,
		* :func:`Set Analog Value Callback Threshold`
		
		keep being reached.
		*/
		this.ipcon.sendRequest(this, BrickletHumidity.FUNCTION_SET_DEBOUNCE_PERIOD, [debounce], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getDebouncePeriod = function(returnCallback, errorCallback) {
		/*
		Returns the debounce period as set by :func:`Set Debounce Period`.
		*/
		this.ipcon.sendRequest(this, BrickletHumidity.FUNCTION_GET_DEBOUNCE_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletHumidity.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletHumidity;

},{"./Device":279,"./IPConnection":280}],186:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletHumidityV2.DEVICE_IDENTIFIER = 283;
BrickletHumidityV2.DEVICE_DISPLAY_NAME = 'Humidity Bricklet 2.0';
BrickletHumidityV2.CALLBACK_HUMIDITY = 4;
BrickletHumidityV2.CALLBACK_TEMPERATURE = 8;
BrickletHumidityV2.FUNCTION_GET_HUMIDITY = 1;
BrickletHumidityV2.FUNCTION_SET_HUMIDITY_CALLBACK_CONFIGURATION = 2;
BrickletHumidityV2.FUNCTION_GET_HUMIDITY_CALLBACK_CONFIGURATION = 3;
BrickletHumidityV2.FUNCTION_GET_TEMPERATURE = 5;
BrickletHumidityV2.FUNCTION_SET_TEMPERATURE_CALLBACK_CONFIGURATION = 6;
BrickletHumidityV2.FUNCTION_GET_TEMPERATURE_CALLBACK_CONFIGURATION = 7;
BrickletHumidityV2.FUNCTION_SET_HEATER_CONFIGURATION = 9;
BrickletHumidityV2.FUNCTION_GET_HEATER_CONFIGURATION = 10;
BrickletHumidityV2.FUNCTION_SET_MOVING_AVERAGE_CONFIGURATION = 11;
BrickletHumidityV2.FUNCTION_GET_MOVING_AVERAGE_CONFIGURATION = 12;
BrickletHumidityV2.FUNCTION_SET_SAMPLES_PER_SECOND = 13;
BrickletHumidityV2.FUNCTION_GET_SAMPLES_PER_SECOND = 14;
BrickletHumidityV2.FUNCTION_GET_SPITFP_ERROR_COUNT = 234;
BrickletHumidityV2.FUNCTION_SET_BOOTLOADER_MODE = 235;
BrickletHumidityV2.FUNCTION_GET_BOOTLOADER_MODE = 236;
BrickletHumidityV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER = 237;
BrickletHumidityV2.FUNCTION_WRITE_FIRMWARE = 238;
BrickletHumidityV2.FUNCTION_SET_STATUS_LED_CONFIG = 239;
BrickletHumidityV2.FUNCTION_GET_STATUS_LED_CONFIG = 240;
BrickletHumidityV2.FUNCTION_GET_CHIP_TEMPERATURE = 242;
BrickletHumidityV2.FUNCTION_RESET = 243;
BrickletHumidityV2.FUNCTION_WRITE_UID = 248;
BrickletHumidityV2.FUNCTION_READ_UID = 249;
BrickletHumidityV2.FUNCTION_GET_IDENTITY = 255;
BrickletHumidityV2.THRESHOLD_OPTION_OFF = 'x';
BrickletHumidityV2.THRESHOLD_OPTION_OUTSIDE = 'o';
BrickletHumidityV2.THRESHOLD_OPTION_INSIDE = 'i';
BrickletHumidityV2.THRESHOLD_OPTION_SMALLER = '<';
BrickletHumidityV2.THRESHOLD_OPTION_GREATER = '>';
BrickletHumidityV2.HEATER_CONFIG_DISABLED = 0;
BrickletHumidityV2.HEATER_CONFIG_ENABLED = 1;
BrickletHumidityV2.SPS_20 = 0;
BrickletHumidityV2.SPS_10 = 1;
BrickletHumidityV2.SPS_5 = 2;
BrickletHumidityV2.SPS_1 = 3;
BrickletHumidityV2.SPS_02 = 4;
BrickletHumidityV2.SPS_01 = 5;
BrickletHumidityV2.BOOTLOADER_MODE_BOOTLOADER = 0;
BrickletHumidityV2.BOOTLOADER_MODE_FIRMWARE = 1;
BrickletHumidityV2.BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT = 2;
BrickletHumidityV2.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT = 3;
BrickletHumidityV2.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT = 4;
BrickletHumidityV2.BOOTLOADER_STATUS_OK = 0;
BrickletHumidityV2.BOOTLOADER_STATUS_INVALID_MODE = 1;
BrickletHumidityV2.BOOTLOADER_STATUS_NO_CHANGE = 2;
BrickletHumidityV2.BOOTLOADER_STATUS_ENTRY_FUNCTION_NOT_PRESENT = 3;
BrickletHumidityV2.BOOTLOADER_STATUS_DEVICE_IDENTIFIER_INCORRECT = 4;
BrickletHumidityV2.BOOTLOADER_STATUS_CRC_MISMATCH = 5;
BrickletHumidityV2.STATUS_LED_CONFIG_OFF = 0;
BrickletHumidityV2.STATUS_LED_CONFIG_ON = 1;
BrickletHumidityV2.STATUS_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletHumidityV2.STATUS_LED_CONFIG_SHOW_STATUS = 3;

function BrickletHumidityV2(uid, ipcon) {
	//Measures relative humidity

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletHumidityV2.DEVICE_IDENTIFIER, BrickletHumidityV2.DEVICE_DISPLAY_NAME);
	BrickletHumidityV2.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 2];
	this.responseExpected[BrickletHumidityV2.FUNCTION_GET_HUMIDITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletHumidityV2.FUNCTION_SET_HUMIDITY_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletHumidityV2.FUNCTION_GET_HUMIDITY_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletHumidityV2.FUNCTION_GET_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletHumidityV2.FUNCTION_SET_TEMPERATURE_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletHumidityV2.FUNCTION_GET_TEMPERATURE_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletHumidityV2.FUNCTION_SET_HEATER_CONFIGURATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletHumidityV2.FUNCTION_GET_HEATER_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletHumidityV2.FUNCTION_SET_MOVING_AVERAGE_CONFIGURATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletHumidityV2.FUNCTION_GET_MOVING_AVERAGE_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletHumidityV2.FUNCTION_SET_SAMPLES_PER_SECOND] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletHumidityV2.FUNCTION_GET_SAMPLES_PER_SECOND] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletHumidityV2.FUNCTION_GET_SPITFP_ERROR_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletHumidityV2.FUNCTION_SET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletHumidityV2.FUNCTION_GET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletHumidityV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletHumidityV2.FUNCTION_WRITE_FIRMWARE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletHumidityV2.FUNCTION_SET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletHumidityV2.FUNCTION_GET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletHumidityV2.FUNCTION_GET_CHIP_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletHumidityV2.FUNCTION_RESET] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletHumidityV2.FUNCTION_WRITE_UID] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletHumidityV2.FUNCTION_READ_UID] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletHumidityV2.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletHumidityV2.CALLBACK_HUMIDITY] = [10, 'H'];
	this.callbackFormats[BrickletHumidityV2.CALLBACK_TEMPERATURE] = [10, 'h'];



	this.getHumidity = function(returnCallback, errorCallback) {
		/*
		Returns the humidity measured by the sensor.
		
		
		If you want to get the value periodically, it is recommended to use the
		:cb:`Humidity` callback. You can set the callback configuration
		with :func:`Set Humidity Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletHumidityV2.FUNCTION_GET_HUMIDITY, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.setHumidityCallbackConfiguration = function(period, valueHasToChange, option, min, max, returnCallback, errorCallback) {
		/*
		The period is the period with which the :cb:`Humidity` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		If the `value has to change`-parameter is set to true, the callback is only
		triggered after the value has changed. If the value didn't change
		within the period, the callback is triggered immediately on change.
		
		If it is set to false, the callback is continuously triggered with the period,
		independent of the value.
		
		It is furthermore possible to constrain the callback with thresholds.
		
		The `option`-parameter together with min/max sets a threshold for the :cb:`Humidity` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Threshold is turned off"
		 "'o'",    "Threshold is triggered when the value is *outside* the min and max values"
		 "'i'",    "Threshold is triggered when the value is *inside* or equal to the min and max values"
		 "'<'",    "Threshold is triggered when the value is smaller than the min value (max is ignored)"
		 "'>'",    "Threshold is triggered when the value is greater than the min value (max is ignored)"
		
		If the option is set to 'x' (threshold turned off) the callback is triggered with the fixed period.
		*/
		this.ipcon.sendRequest(this, BrickletHumidityV2.FUNCTION_SET_HUMIDITY_CALLBACK_CONFIGURATION, [period, valueHasToChange, option, min, max], 'I ? c H H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getHumidityCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the callback configuration as set by :func:`Set Humidity Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletHumidityV2.FUNCTION_GET_HUMIDITY_CALLBACK_CONFIGURATION, [], '', 18, 'I ? c H H', returnCallback, errorCallback, false, true);
	};
	this.getTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature measured by the sensor.
		
		
		If you want to get the value periodically, it is recommended to use the
		:cb:`Temperature` callback. You can set the callback configuration
		with :func:`Set Temperature Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletHumidityV2.FUNCTION_GET_TEMPERATURE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.setTemperatureCallbackConfiguration = function(period, valueHasToChange, option, min, max, returnCallback, errorCallback) {
		/*
		The period is the period with which the :cb:`Temperature` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		If the `value has to change`-parameter is set to true, the callback is only
		triggered after the value has changed. If the value didn't change
		within the period, the callback is triggered immediately on change.
		
		If it is set to false, the callback is continuously triggered with the period,
		independent of the value.
		
		It is furthermore possible to constrain the callback with thresholds.
		
		The `option`-parameter together with min/max sets a threshold for the :cb:`Temperature` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Threshold is turned off"
		 "'o'",    "Threshold is triggered when the value is *outside* the min and max values"
		 "'i'",    "Threshold is triggered when the value is *inside* or equal to the min and max values"
		 "'<'",    "Threshold is triggered when the value is smaller than the min value (max is ignored)"
		 "'>'",    "Threshold is triggered when the value is greater than the min value (max is ignored)"
		
		If the option is set to 'x' (threshold turned off) the callback is triggered with the fixed period.
		*/
		this.ipcon.sendRequest(this, BrickletHumidityV2.FUNCTION_SET_TEMPERATURE_CALLBACK_CONFIGURATION, [period, valueHasToChange, option, min, max], 'I ? c h h', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getTemperatureCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the callback configuration as set by :func:`Set Temperature Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletHumidityV2.FUNCTION_GET_TEMPERATURE_CALLBACK_CONFIGURATION, [], '', 18, 'I ? c h h', returnCallback, errorCallback, false, true);
	};
	this.setHeaterConfiguration = function(heaterConfig, returnCallback, errorCallback) {
		/*
		Enables/disables the heater. The heater can be used to dry the sensor in
		extremely wet conditions.
		*/
		this.ipcon.sendRequest(this, BrickletHumidityV2.FUNCTION_SET_HEATER_CONFIGURATION, [heaterConfig], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getHeaterConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the heater configuration as set by :func:`Set Heater Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletHumidityV2.FUNCTION_GET_HEATER_CONFIGURATION, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setMovingAverageConfiguration = function(movingAverageLengthHumidity, movingAverageLengthTemperature, returnCallback, errorCallback) {
		/*
		Sets the length of a `moving averaging <https://en.wikipedia.org/wiki/Moving_average>`__
		for the humidity and temperature.
		
		Setting the length to 1 will turn the averaging off. With less
		averaging, there is more noise on the data.
		
		New data is gathered every 50ms*. With a moving average of length 1000 the resulting
		averaging window has a length of 50s. If you want to do long term measurements the longest
		moving average will give the cleanest results.
		
		\* In firmware version 2.0.3 we added the :func:`Set Samples Per Second` function. It
		configures the measurement frequency. Since high frequencies can result in self-heating
		of th IC, changed the default value from 20 samples per second to 1. With 1 sample per second
		a moving average length of 1000 would result in an averaging window of 1000 seconds!
		*/
		this.ipcon.sendRequest(this, BrickletHumidityV2.FUNCTION_SET_MOVING_AVERAGE_CONFIGURATION, [movingAverageLengthHumidity, movingAverageLengthTemperature], 'H H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getMovingAverageConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the moving average configuration as set by :func:`Set Moving Average Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletHumidityV2.FUNCTION_GET_MOVING_AVERAGE_CONFIGURATION, [], '', 12, 'H H', returnCallback, errorCallback, false, true);
	};
	this.setSamplesPerSecond = function(sps, returnCallback, errorCallback) {
		/*
		Sets the samples per second that are gathered by the humidity/temperature sensor HDC1080.
		
		We added this function since we found out that a high measurement frequency can lead to
		self-heating of the sensor. Which can distort the temperature measurement.
		
		If you don't need a lot of measurements, you can use the lowest available measurement
		frequency of 0.1 samples per second for the least amount of self-heating.
		
		Before version 2.0.3 the default was 20 samples per second. The new default is 1 sample per second.
		
		.. versionadded:: 2.0.3$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletHumidityV2.FUNCTION_SET_SAMPLES_PER_SECOND, [sps], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getSamplesPerSecond = function(returnCallback, errorCallback) {
		/*
		Returnes the samples per second, as set by :func:`Set Samples Per Second`.
		
		.. versionadded:: 2.0.3$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletHumidityV2.FUNCTION_GET_SAMPLES_PER_SECOND, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPErrorCount = function(returnCallback, errorCallback) {
		/*
		Returns the error count for the communication between Brick and Bricklet.
		
		The errors are divided into
		
		* ACK checksum errors,
		* message checksum errors,
		* framing errors and
		* overflow errors.
		
		The errors counts are for errors that occur on the Bricklet side. All
		Bricks have a similar function that returns the errors on the Brick side.
		*/
		this.ipcon.sendRequest(this, BrickletHumidityV2.FUNCTION_GET_SPITFP_ERROR_COUNT, [], '', 24, 'I I I I', returnCallback, errorCallback, false, true);
	};
	this.setBootloaderMode = function(mode, returnCallback, errorCallback) {
		/*
		Sets the bootloader mode and returns the status after the requested
		mode change was instigated.
		
		You can change from bootloader mode to firmware mode and vice versa. A change
		from bootloader mode to firmware mode will only take place if the entry function,
		device identifier and CRC are present and correct.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletHumidityV2.FUNCTION_SET_BOOTLOADER_MODE, [mode], 'B', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getBootloaderMode = function(returnCallback, errorCallback) {
		/*
		Returns the current bootloader mode, see :func:`Set Bootloader Mode`.
		*/
		this.ipcon.sendRequest(this, BrickletHumidityV2.FUNCTION_GET_BOOTLOADER_MODE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setWriteFirmwarePointer = function(pointer, returnCallback, errorCallback) {
		/*
		Sets the firmware pointer for :func:`Write Firmware`. The pointer has
		to be increased by chunks of size 64. The data is written to flash
		every 4 chunks (which equals to one page of size 256).
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletHumidityV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER, [pointer], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeFirmware = function(data, returnCallback, errorCallback) {
		/*
		Writes 64 Bytes of firmware at the position as written by
		:func:`Set Write Firmware Pointer` before. The firmware is written
		to flash every 4 chunks.
		
		You can only write firmware in bootloader mode.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletHumidityV2.FUNCTION_WRITE_FIRMWARE, [data], 'B64', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setStatusLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Sets the status LED configuration. By default the LED shows
		communication traffic between Brick and Bricklet, it flickers once
		for every 10 received data packets.
		
		You can also turn the LED permanently on/off or show a heartbeat.
		
		If the Bricklet is in bootloader mode, the LED is will show heartbeat by default.
		*/
		this.ipcon.sendRequest(this, BrickletHumidityV2.FUNCTION_SET_STATUS_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getStatusLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Status LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletHumidityV2.FUNCTION_GET_STATUS_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getChipTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature as measured inside the microcontroller. The
		value returned is not the ambient temperature!
		
		The temperature is only proportional to the real temperature and it has bad
		accuracy. Practically it is only useful as an indicator for
		temperature changes.
		*/
		this.ipcon.sendRequest(this, BrickletHumidityV2.FUNCTION_GET_CHIP_TEMPERATURE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.reset = function(returnCallback, errorCallback) {
		/*
		Calling this function will reset the Bricklet. All configurations
		will be lost.
		
		After a reset you have to create new device objects,
		calling functions on the existing ones will result in
		undefined behavior!
		*/
		this.ipcon.sendRequest(this, BrickletHumidityV2.FUNCTION_RESET, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeUID = function(uid, returnCallback, errorCallback) {
		/*
		Writes a new UID into flash. If you want to set a new UID
		you have to decode the Base58 encoded UID string into an
		integer first.
		
		We recommend that you use Brick Viewer to change the UID.
		*/
		this.ipcon.sendRequest(this, BrickletHumidityV2.FUNCTION_WRITE_UID, [uid], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.readUID = function(returnCallback, errorCallback) {
		/*
		Returns the current UID as an integer. Encode as
		Base58 to get the usual string version.
		*/
		this.ipcon.sendRequest(this, BrickletHumidityV2.FUNCTION_READ_UID, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletHumidityV2.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletHumidityV2;

},{"./Device":279,"./IPConnection":280}],187:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletIMUV3.DEVICE_IDENTIFIER = 2161;
BrickletIMUV3.DEVICE_DISPLAY_NAME = 'IMU Bricklet 3.0';
BrickletIMUV3.CALLBACK_ACCELERATION = 33;
BrickletIMUV3.CALLBACK_MAGNETIC_FIELD = 34;
BrickletIMUV3.CALLBACK_ANGULAR_VELOCITY = 35;
BrickletIMUV3.CALLBACK_TEMPERATURE = 36;
BrickletIMUV3.CALLBACK_LINEAR_ACCELERATION = 37;
BrickletIMUV3.CALLBACK_GRAVITY_VECTOR = 38;
BrickletIMUV3.CALLBACK_ORIENTATION = 39;
BrickletIMUV3.CALLBACK_QUATERNION = 40;
BrickletIMUV3.CALLBACK_ALL_DATA = 41;
BrickletIMUV3.FUNCTION_GET_ACCELERATION = 1;
BrickletIMUV3.FUNCTION_GET_MAGNETIC_FIELD = 2;
BrickletIMUV3.FUNCTION_GET_ANGULAR_VELOCITY = 3;
BrickletIMUV3.FUNCTION_GET_TEMPERATURE = 4;
BrickletIMUV3.FUNCTION_GET_ORIENTATION = 5;
BrickletIMUV3.FUNCTION_GET_LINEAR_ACCELERATION = 6;
BrickletIMUV3.FUNCTION_GET_GRAVITY_VECTOR = 7;
BrickletIMUV3.FUNCTION_GET_QUATERNION = 8;
BrickletIMUV3.FUNCTION_GET_ALL_DATA = 9;
BrickletIMUV3.FUNCTION_SAVE_CALIBRATION = 10;
BrickletIMUV3.FUNCTION_SET_SENSOR_CONFIGURATION = 11;
BrickletIMUV3.FUNCTION_GET_SENSOR_CONFIGURATION = 12;
BrickletIMUV3.FUNCTION_SET_SENSOR_FUSION_MODE = 13;
BrickletIMUV3.FUNCTION_GET_SENSOR_FUSION_MODE = 14;
BrickletIMUV3.FUNCTION_SET_ACCELERATION_CALLBACK_CONFIGURATION = 15;
BrickletIMUV3.FUNCTION_GET_ACCELERATION_CALLBACK_CONFIGURATION = 16;
BrickletIMUV3.FUNCTION_SET_MAGNETIC_FIELD_CALLBACK_CONFIGURATION = 17;
BrickletIMUV3.FUNCTION_GET_MAGNETIC_FIELD_CALLBACK_CONFIGURATION = 18;
BrickletIMUV3.FUNCTION_SET_ANGULAR_VELOCITY_CALLBACK_CONFIGURATION = 19;
BrickletIMUV3.FUNCTION_GET_ANGULAR_VELOCITY_CALLBACK_CONFIGURATION = 20;
BrickletIMUV3.FUNCTION_SET_TEMPERATURE_CALLBACK_CONFIGURATION = 21;
BrickletIMUV3.FUNCTION_GET_TEMPERATURE_CALLBACK_CONFIGURATION = 22;
BrickletIMUV3.FUNCTION_SET_ORIENTATION_CALLBACK_CONFIGURATION = 23;
BrickletIMUV3.FUNCTION_GET_ORIENTATION_CALLBACK_CONFIGURATION = 24;
BrickletIMUV3.FUNCTION_SET_LINEAR_ACCELERATION_CALLBACK_CONFIGURATION = 25;
BrickletIMUV3.FUNCTION_GET_LINEAR_ACCELERATION_CALLBACK_CONFIGURATION = 26;
BrickletIMUV3.FUNCTION_SET_GRAVITY_VECTOR_CALLBACK_CONFIGURATION = 27;
BrickletIMUV3.FUNCTION_GET_GRAVITY_VECTOR_CALLBACK_CONFIGURATION = 28;
BrickletIMUV3.FUNCTION_SET_QUATERNION_CALLBACK_CONFIGURATION = 29;
BrickletIMUV3.FUNCTION_GET_QUATERNION_CALLBACK_CONFIGURATION = 30;
BrickletIMUV3.FUNCTION_SET_ALL_DATA_CALLBACK_CONFIGURATION = 31;
BrickletIMUV3.FUNCTION_GET_ALL_DATA_CALLBACK_CONFIGURATION = 32;
BrickletIMUV3.FUNCTION_GET_SPITFP_ERROR_COUNT = 234;
BrickletIMUV3.FUNCTION_SET_BOOTLOADER_MODE = 235;
BrickletIMUV3.FUNCTION_GET_BOOTLOADER_MODE = 236;
BrickletIMUV3.FUNCTION_SET_WRITE_FIRMWARE_POINTER = 237;
BrickletIMUV3.FUNCTION_WRITE_FIRMWARE = 238;
BrickletIMUV3.FUNCTION_SET_STATUS_LED_CONFIG = 239;
BrickletIMUV3.FUNCTION_GET_STATUS_LED_CONFIG = 240;
BrickletIMUV3.FUNCTION_GET_CHIP_TEMPERATURE = 242;
BrickletIMUV3.FUNCTION_RESET = 243;
BrickletIMUV3.FUNCTION_WRITE_UID = 248;
BrickletIMUV3.FUNCTION_READ_UID = 249;
BrickletIMUV3.FUNCTION_GET_IDENTITY = 255;
BrickletIMUV3.MAGNETOMETER_RATE_2HZ = 0;
BrickletIMUV3.MAGNETOMETER_RATE_6HZ = 1;
BrickletIMUV3.MAGNETOMETER_RATE_8HZ = 2;
BrickletIMUV3.MAGNETOMETER_RATE_10HZ = 3;
BrickletIMUV3.MAGNETOMETER_RATE_15HZ = 4;
BrickletIMUV3.MAGNETOMETER_RATE_20HZ = 5;
BrickletIMUV3.MAGNETOMETER_RATE_25HZ = 6;
BrickletIMUV3.MAGNETOMETER_RATE_30HZ = 7;
BrickletIMUV3.GYROSCOPE_RANGE_2000DPS = 0;
BrickletIMUV3.GYROSCOPE_RANGE_1000DPS = 1;
BrickletIMUV3.GYROSCOPE_RANGE_500DPS = 2;
BrickletIMUV3.GYROSCOPE_RANGE_250DPS = 3;
BrickletIMUV3.GYROSCOPE_RANGE_125DPS = 4;
BrickletIMUV3.GYROSCOPE_BANDWIDTH_523HZ = 0;
BrickletIMUV3.GYROSCOPE_BANDWIDTH_230HZ = 1;
BrickletIMUV3.GYROSCOPE_BANDWIDTH_116HZ = 2;
BrickletIMUV3.GYROSCOPE_BANDWIDTH_47HZ = 3;
BrickletIMUV3.GYROSCOPE_BANDWIDTH_23HZ = 4;
BrickletIMUV3.GYROSCOPE_BANDWIDTH_12HZ = 5;
BrickletIMUV3.GYROSCOPE_BANDWIDTH_64HZ = 6;
BrickletIMUV3.GYROSCOPE_BANDWIDTH_32HZ = 7;
BrickletIMUV3.ACCELEROMETER_RANGE_2G = 0;
BrickletIMUV3.ACCELEROMETER_RANGE_4G = 1;
BrickletIMUV3.ACCELEROMETER_RANGE_8G = 2;
BrickletIMUV3.ACCELEROMETER_RANGE_16G = 3;
BrickletIMUV3.ACCELEROMETER_BANDWIDTH_7_81HZ = 0;
BrickletIMUV3.ACCELEROMETER_BANDWIDTH_15_63HZ = 1;
BrickletIMUV3.ACCELEROMETER_BANDWIDTH_31_25HZ = 2;
BrickletIMUV3.ACCELEROMETER_BANDWIDTH_62_5HZ = 3;
BrickletIMUV3.ACCELEROMETER_BANDWIDTH_125HZ = 4;
BrickletIMUV3.ACCELEROMETER_BANDWIDTH_250HZ = 5;
BrickletIMUV3.ACCELEROMETER_BANDWIDTH_500HZ = 6;
BrickletIMUV3.ACCELEROMETER_BANDWIDTH_1000HZ = 7;
BrickletIMUV3.SENSOR_FUSION_OFF = 0;
BrickletIMUV3.SENSOR_FUSION_ON = 1;
BrickletIMUV3.SENSOR_FUSION_ON_WITHOUT_MAGNETOMETER = 2;
BrickletIMUV3.SENSOR_FUSION_ON_WITHOUT_FAST_MAGNETOMETER_CALIBRATION = 3;
BrickletIMUV3.BOOTLOADER_MODE_BOOTLOADER = 0;
BrickletIMUV3.BOOTLOADER_MODE_FIRMWARE = 1;
BrickletIMUV3.BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT = 2;
BrickletIMUV3.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT = 3;
BrickletIMUV3.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT = 4;
BrickletIMUV3.BOOTLOADER_STATUS_OK = 0;
BrickletIMUV3.BOOTLOADER_STATUS_INVALID_MODE = 1;
BrickletIMUV3.BOOTLOADER_STATUS_NO_CHANGE = 2;
BrickletIMUV3.BOOTLOADER_STATUS_ENTRY_FUNCTION_NOT_PRESENT = 3;
BrickletIMUV3.BOOTLOADER_STATUS_DEVICE_IDENTIFIER_INCORRECT = 4;
BrickletIMUV3.BOOTLOADER_STATUS_CRC_MISMATCH = 5;
BrickletIMUV3.STATUS_LED_CONFIG_OFF = 0;
BrickletIMUV3.STATUS_LED_CONFIG_ON = 1;
BrickletIMUV3.STATUS_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletIMUV3.STATUS_LED_CONFIG_SHOW_STATUS = 3;

function BrickletIMUV3(uid, ipcon) {
	//Full fledged AHRS with 9 degrees of freedom

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletIMUV3.DEVICE_IDENTIFIER, BrickletIMUV3.DEVICE_DISPLAY_NAME);
	BrickletIMUV3.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickletIMUV3.FUNCTION_GET_ACCELERATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIMUV3.FUNCTION_GET_MAGNETIC_FIELD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIMUV3.FUNCTION_GET_ANGULAR_VELOCITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIMUV3.FUNCTION_GET_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIMUV3.FUNCTION_GET_ORIENTATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIMUV3.FUNCTION_GET_LINEAR_ACCELERATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIMUV3.FUNCTION_GET_GRAVITY_VECTOR] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIMUV3.FUNCTION_GET_QUATERNION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIMUV3.FUNCTION_GET_ALL_DATA] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIMUV3.FUNCTION_SAVE_CALIBRATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIMUV3.FUNCTION_SET_SENSOR_CONFIGURATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIMUV3.FUNCTION_GET_SENSOR_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIMUV3.FUNCTION_SET_SENSOR_FUSION_MODE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIMUV3.FUNCTION_GET_SENSOR_FUSION_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIMUV3.FUNCTION_SET_ACCELERATION_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletIMUV3.FUNCTION_GET_ACCELERATION_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIMUV3.FUNCTION_SET_MAGNETIC_FIELD_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletIMUV3.FUNCTION_GET_MAGNETIC_FIELD_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIMUV3.FUNCTION_SET_ANGULAR_VELOCITY_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletIMUV3.FUNCTION_GET_ANGULAR_VELOCITY_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIMUV3.FUNCTION_SET_TEMPERATURE_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletIMUV3.FUNCTION_GET_TEMPERATURE_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIMUV3.FUNCTION_SET_ORIENTATION_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletIMUV3.FUNCTION_GET_ORIENTATION_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIMUV3.FUNCTION_SET_LINEAR_ACCELERATION_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletIMUV3.FUNCTION_GET_LINEAR_ACCELERATION_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIMUV3.FUNCTION_SET_GRAVITY_VECTOR_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletIMUV3.FUNCTION_GET_GRAVITY_VECTOR_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIMUV3.FUNCTION_SET_QUATERNION_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletIMUV3.FUNCTION_GET_QUATERNION_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIMUV3.FUNCTION_SET_ALL_DATA_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletIMUV3.FUNCTION_GET_ALL_DATA_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIMUV3.FUNCTION_GET_SPITFP_ERROR_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIMUV3.FUNCTION_SET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIMUV3.FUNCTION_GET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIMUV3.FUNCTION_SET_WRITE_FIRMWARE_POINTER] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIMUV3.FUNCTION_WRITE_FIRMWARE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIMUV3.FUNCTION_SET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIMUV3.FUNCTION_GET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIMUV3.FUNCTION_GET_CHIP_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIMUV3.FUNCTION_RESET] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIMUV3.FUNCTION_WRITE_UID] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIMUV3.FUNCTION_READ_UID] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIMUV3.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletIMUV3.CALLBACK_ACCELERATION] = [14, 'h h h'];
	this.callbackFormats[BrickletIMUV3.CALLBACK_MAGNETIC_FIELD] = [14, 'h h h'];
	this.callbackFormats[BrickletIMUV3.CALLBACK_ANGULAR_VELOCITY] = [14, 'h h h'];
	this.callbackFormats[BrickletIMUV3.CALLBACK_TEMPERATURE] = [9, 'b'];
	this.callbackFormats[BrickletIMUV3.CALLBACK_LINEAR_ACCELERATION] = [14, 'h h h'];
	this.callbackFormats[BrickletIMUV3.CALLBACK_GRAVITY_VECTOR] = [14, 'h h h'];
	this.callbackFormats[BrickletIMUV3.CALLBACK_ORIENTATION] = [14, 'h h h'];
	this.callbackFormats[BrickletIMUV3.CALLBACK_QUATERNION] = [16, 'h h h h'];
	this.callbackFormats[BrickletIMUV3.CALLBACK_ALL_DATA] = [54, 'h3 h3 h3 h3 h4 h3 h3 b B'];



	this.getAcceleration = function(returnCallback, errorCallback) {
		/*
		Returns the calibrated acceleration from the accelerometer for the
		x, y and z axis. The acceleration is in the range configured with
		:func:`Set Sensor Configuration`.
		
		If you want to get the acceleration periodically, it is recommended
		to use the :cb:`Acceleration` callback and set the period with
		:func:`Set Acceleration Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletIMUV3.FUNCTION_GET_ACCELERATION, [], '', 14, 'h h h', returnCallback, errorCallback, false, true);
	};
	this.getMagneticField = function(returnCallback, errorCallback) {
		/*
		Returns the calibrated magnetic field from the magnetometer for the
		x, y and z axis.
		
		If you want to get the magnetic field periodically, it is recommended
		to use the :cb:`Magnetic Field` callback and set the period with
		:func:`Set Magnetic Field Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletIMUV3.FUNCTION_GET_MAGNETIC_FIELD, [], '', 14, 'h h h', returnCallback, errorCallback, false, true);
	};
	this.getAngularVelocity = function(returnCallback, errorCallback) {
		/*
		Returns the calibrated angular velocity from the gyroscope for the
		x, y and z axis. The angular velocity is in the range configured with
		:func:`Set Sensor Configuration`.
		
		If you want to get the angular velocity periodically, it is recommended
		to use the :cb:`Angular Velocity` acallback nd set the period with
		:func:`Set Angular Velocity Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletIMUV3.FUNCTION_GET_ANGULAR_VELOCITY, [], '', 14, 'h h h', returnCallback, errorCallback, false, true);
	};
	this.getTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature of the IMU Brick.
		The temperature is measured in the core of the BNO055 IC, it is not the
		ambient temperature
		*/
		this.ipcon.sendRequest(this, BrickletIMUV3.FUNCTION_GET_TEMPERATURE, [], '', 9, 'b', returnCallback, errorCallback, false, true);
	};
	this.getOrientation = function(returnCallback, errorCallback) {
		/*
		Returns the current orientation (heading, roll, pitch) of the IMU Brick as
		independent Euler angles. Note that Euler angles always
		experience a `gimbal lock <https://en.wikipedia.org/wiki/Gimbal_lock>`__.
		We recommend that you use quaternions instead, if you need the absolute
		orientation.
		
		If you want to get the orientation periodically, it is recommended
		to use the :cb:`Orientation` callback and set the period with
		:func:`Set Orientation Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletIMUV3.FUNCTION_GET_ORIENTATION, [], '', 14, 'h h h', returnCallback, errorCallback, false, true);
	};
	this.getLinearAcceleration = function(returnCallback, errorCallback) {
		/*
		Returns the linear acceleration of the IMU Brick for the
		x, y and z axis. The acceleration is in the range configured with
		:func:`Set Sensor Configuration`.
		
		The linear acceleration is the acceleration in each of the three
		axis of the IMU Brick with the influences of gravity removed.
		
		It is also possible to get the gravity vector with the influence of linear
		acceleration removed, see :func:`Get Gravity Vector`.
		
		If you want to get the linear acceleration periodically, it is recommended
		to use the :cb:`Linear Acceleration` callback and set the period with
		:func:`Set Linear Acceleration Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletIMUV3.FUNCTION_GET_LINEAR_ACCELERATION, [], '', 14, 'h h h', returnCallback, errorCallback, false, true);
	};
	this.getGravityVector = function(returnCallback, errorCallback) {
		/*
		Returns the current gravity vector of the IMU Brick for the
		x, y and z axis.
		
		The gravity vector is the acceleration that occurs due to gravity.
		Influences of additional linear acceleration are removed.
		
		It is also possible to get the linear acceleration with the influence
		of gravity removed, see :func:`Get Linear Acceleration`.
		
		If you want to get the gravity vector periodically, it is recommended
		to use the :cb:`Gravity Vector` callback and set the period with
		:func:`Set Gravity Vector Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletIMUV3.FUNCTION_GET_GRAVITY_VECTOR, [], '', 14, 'h h h', returnCallback, errorCallback, false, true);
	};
	this.getQuaternion = function(returnCallback, errorCallback) {
		/*
		Returns the current orientation (w, x, y, z) of the IMU Brick as
		`quaternions <https://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation>`__.
		
		You have to divide the return values by 16383 (14 bit) to get
		the usual range of -1.0 to +1.0 for quaternions.
		
		If you want to get the quaternions periodically, it is recommended
		to use the :cb:`Quaternion` callback and set the period with
		:func:`Set Quaternion Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletIMUV3.FUNCTION_GET_QUATERNION, [], '', 16, 'h h h h', returnCallback, errorCallback, false, true);
	};
	this.getAllData = function(returnCallback, errorCallback) {
		/*
		Return all of the available data of the IMU Brick.
		
		* acceleration (see :func:`Get Acceleration`)
		* magnetic field (see :func:`Get Magnetic Field`)
		* angular velocity (see :func:`Get Angular Velocity`)
		* Euler angles (see :func:`Get Orientation`)
		* quaternion (see :func:`Get Quaternion`)
		* linear acceleration (see :func:`Get Linear Acceleration`)
		* gravity vector (see :func:`Get Gravity Vector`)
		* temperature (see :func:`Get Temperature`)
		* calibration status (see below)
		
		The calibration status consists of four pairs of two bits. Each pair
		of bits represents the status of the current calibration.
		
		* bit 0-1: Magnetometer
		* bit 2-3: Accelerometer
		* bit 4-5: Gyroscope
		* bit 6-7: System
		
		A value of 0 means for "not calibrated" and a value of 3 means
		"fully calibrated". In your program you should always be able to
		ignore the calibration status, it is used by the calibration
		window of the Brick Viewer and it can be ignored after the first
		calibration. See the documentation in the calibration window for
		more information regarding the calibration of the IMU Brick.
		
		If you want to get the data periodically, it is recommended
		to use the :cb:`All Data` callback and set the period with
		:func:`Set All Data Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletIMUV3.FUNCTION_GET_ALL_DATA, [], '', 54, 'h3 h3 h3 h3 h4 h3 h3 b B', returnCallback, errorCallback, false, true);
	};
	this.saveCalibration = function(returnCallback, errorCallback) {
		/*
		A call of this function saves the current calibration to be used
		as a starting point for the next restart of continuous calibration
		of the IMU Brick.
		
		A return value of *true* means that the calibration could be used and
		*false* means that it could not be used (this happens if the calibration
		status is not "fully calibrated").
		
		This function is used by the calibration window of the Brick Viewer, you
		should not need to call it in your program.
		*/
		this.ipcon.sendRequest(this, BrickletIMUV3.FUNCTION_SAVE_CALIBRATION, [], '', 9, '?', returnCallback, errorCallback, false, true);
	};
	this.setSensorConfiguration = function(magnetometerRate, gyroscopeRange, gyroscopeBandwidth, accelerometerRange, accelerometerBandwidth, returnCallback, errorCallback) {
		/*
		Sets the available sensor configuration for the Magnetometer, Gyroscope and
		Accelerometer. The Accelerometer Range is user selectable in all fusion modes,
		all other configurations are auto-controlled in fusion mode.
		*/
		this.ipcon.sendRequest(this, BrickletIMUV3.FUNCTION_SET_SENSOR_CONFIGURATION, [magnetometerRate, gyroscopeRange, gyroscopeBandwidth, accelerometerRange, accelerometerBandwidth], 'B B B B B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getSensorConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the sensor configuration as set by :func:`Set Sensor Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletIMUV3.FUNCTION_GET_SENSOR_CONFIGURATION, [], '', 13, 'B B B B B', returnCallback, errorCallback, false, true);
	};
	this.setSensorFusionMode = function(mode, returnCallback, errorCallback) {
		/*
		If the fusion mode is turned off, the functions :func:`Get Acceleration`,
		:func:`Get Magnetic Field` and :func:`Get Angular Velocity` return uncalibrated
		and uncompensated sensor data. All other sensor data getters return no data.
		
		Since firmware version 2.0.6 you can also use a fusion mode without magnetometer.
		In this mode the calculated orientation is relative (with magnetometer it is
		absolute with respect to the earth). However, the calculation can't be influenced
		by spurious magnetic fields.
		
		Since firmware version 2.0.13 you can also use a fusion mode without fast
		magnetometer calibration. This mode is the same as the normal fusion mode,
		but the fast magnetometer calibration is turned off. So to find the orientation
		the first time will likely take longer, but small magnetic influences might
		not affect the automatic calibration as much.
		*/
		this.ipcon.sendRequest(this, BrickletIMUV3.FUNCTION_SET_SENSOR_FUSION_MODE, [mode], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getSensorFusionMode = function(returnCallback, errorCallback) {
		/*
		Returns the sensor fusion mode as set by :func:`Set Sensor Fusion Mode`.
		*/
		this.ipcon.sendRequest(this, BrickletIMUV3.FUNCTION_GET_SENSOR_FUSION_MODE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setAccelerationCallbackConfiguration = function(period, valueHasToChange, returnCallback, errorCallback) {
		/*
		The period is the period with which the :cb:`Acceleration` callback
		is triggered periodically. A value of 0 turns the callback off.
		
		If the `value has to change`-parameter is set to true, the callback is only
		triggered after the value has changed. If the value didn't change within the
		period, the callback is triggered immediately on change.
		
		If it is set to false, the callback is continuously triggered with the period,
		independent of the value.
		*/
		this.ipcon.sendRequest(this, BrickletIMUV3.FUNCTION_SET_ACCELERATION_CALLBACK_CONFIGURATION, [period, valueHasToChange], 'I ?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getAccelerationCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the callback configuration as set by :func:`Set Acceleration Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletIMUV3.FUNCTION_GET_ACCELERATION_CALLBACK_CONFIGURATION, [], '', 13, 'I ?', returnCallback, errorCallback, false, true);
	};
	this.setMagneticFieldCallbackConfiguration = function(period, valueHasToChange, returnCallback, errorCallback) {
		/*
		The period is the period with which the :cb:`Magnetic Field` callback
		is triggered periodically. A value of 0 turns the callback off.
		
		If the `value has to change`-parameter is set to true, the callback is only
		triggered after the value has changed. If the value didn't change within the
		period, the callback is triggered immediately on change.
		
		If it is set to false, the callback is continuously triggered with the period,
		independent of the value.
		*/
		this.ipcon.sendRequest(this, BrickletIMUV3.FUNCTION_SET_MAGNETIC_FIELD_CALLBACK_CONFIGURATION, [period, valueHasToChange], 'I ?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getMagneticFieldCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the callback configuration as set by :func:`Set Magnetic Field Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletIMUV3.FUNCTION_GET_MAGNETIC_FIELD_CALLBACK_CONFIGURATION, [], '', 13, 'I ?', returnCallback, errorCallback, false, true);
	};
	this.setAngularVelocityCallbackConfiguration = function(period, valueHasToChange, returnCallback, errorCallback) {
		/*
		The period is the period with which the :cb:`Angular Velocity` callback
		is triggered periodically. A value of 0 turns the callback off.
		
		If the `value has to change`-parameter is set to true, the callback is only
		triggered after the value has changed. If the value didn't change within the
		period, the callback is triggered immediately on change.
		
		If it is set to false, the callback is continuously triggered with the period,
		independent of the value.
		*/
		this.ipcon.sendRequest(this, BrickletIMUV3.FUNCTION_SET_ANGULAR_VELOCITY_CALLBACK_CONFIGURATION, [period, valueHasToChange], 'I ?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getAngularVelocityCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the callback configuration as set by :func:`Set Angular Velocity Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletIMUV3.FUNCTION_GET_ANGULAR_VELOCITY_CALLBACK_CONFIGURATION, [], '', 13, 'I ?', returnCallback, errorCallback, false, true);
	};
	this.setTemperatureCallbackConfiguration = function(period, valueHasToChange, returnCallback, errorCallback) {
		/*
		The period is the period with which the :cb:`Temperature` callback
		is triggered periodically. A value of 0 turns the callback off.
		
		If the `value has to change`-parameter is set to true, the callback is only
		triggered after the value has changed. If the value didn't change within the
		period, the callback is triggered immediately on change.
		
		If it is set to false, the callback is continuously triggered with the period,
		independent of the value.
		*/
		this.ipcon.sendRequest(this, BrickletIMUV3.FUNCTION_SET_TEMPERATURE_CALLBACK_CONFIGURATION, [period, valueHasToChange], 'I ?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getTemperatureCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the callback configuration as set by :func:`Set Temperature Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletIMUV3.FUNCTION_GET_TEMPERATURE_CALLBACK_CONFIGURATION, [], '', 13, 'I ?', returnCallback, errorCallback, false, true);
	};
	this.setOrientationCallbackConfiguration = function(period, valueHasToChange, returnCallback, errorCallback) {
		/*
		The period is the period with which the :cb:`Orientation` callback
		is triggered periodically. A value of 0 turns the callback off.
		
		If the `value has to change`-parameter is set to true, the callback is only
		triggered after the value has changed. If the value didn't change within the
		period, the callback is triggered immediately on change.
		
		If it is set to false, the callback is continuously triggered with the period,
		independent of the value.
		*/
		this.ipcon.sendRequest(this, BrickletIMUV3.FUNCTION_SET_ORIENTATION_CALLBACK_CONFIGURATION, [period, valueHasToChange], 'I ?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getOrientationCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the callback configuration as set by :func:`Set Orientation Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletIMUV3.FUNCTION_GET_ORIENTATION_CALLBACK_CONFIGURATION, [], '', 13, 'I ?', returnCallback, errorCallback, false, true);
	};
	this.setLinearAccelerationCallbackConfiguration = function(period, valueHasToChange, returnCallback, errorCallback) {
		/*
		The period is the period with which the :cb:`Linear Acceleration` callback
		is triggered periodically. A value of 0 turns the callback off.
		
		If the `value has to change`-parameter is set to true, the callback is only
		triggered after the value has changed. If the value didn't change within the
		period, the callback is triggered immediately on change.
		
		If it is set to false, the callback is continuously triggered with the period,
		independent of the value.
		*/
		this.ipcon.sendRequest(this, BrickletIMUV3.FUNCTION_SET_LINEAR_ACCELERATION_CALLBACK_CONFIGURATION, [period, valueHasToChange], 'I ?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getLinearAccelerationCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the callback configuration as set by :func:`Set Linear Acceleration Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletIMUV3.FUNCTION_GET_LINEAR_ACCELERATION_CALLBACK_CONFIGURATION, [], '', 13, 'I ?', returnCallback, errorCallback, false, true);
	};
	this.setGravityVectorCallbackConfiguration = function(period, valueHasToChange, returnCallback, errorCallback) {
		/*
		The period is the period with which the :cb:`Gravity Vector` callback
		is triggered periodically. A value of 0 turns the callback off.
		
		If the `value has to change`-parameter is set to true, the callback is only
		triggered after the value has changed. If the value didn't change within the
		period, the callback is triggered immediately on change.
		
		If it is set to false, the callback is continuously triggered with the period,
		independent of the value.
		*/
		this.ipcon.sendRequest(this, BrickletIMUV3.FUNCTION_SET_GRAVITY_VECTOR_CALLBACK_CONFIGURATION, [period, valueHasToChange], 'I ?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getGravityVectorCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the callback configuration as set by :func:`Set Gravity Vector Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletIMUV3.FUNCTION_GET_GRAVITY_VECTOR_CALLBACK_CONFIGURATION, [], '', 13, 'I ?', returnCallback, errorCallback, false, true);
	};
	this.setQuaternionCallbackConfiguration = function(period, valueHasToChange, returnCallback, errorCallback) {
		/*
		The period is the period with which the :cb:`Quaternion` callback
		is triggered periodically. A value of 0 turns the callback off.
		
		If the `value has to change`-parameter is set to true, the callback is only
		triggered after the value has changed. If the value didn't change within the
		period, the callback is triggered immediately on change.
		
		If it is set to false, the callback is continuously triggered with the period,
		independent of the value.
		*/
		this.ipcon.sendRequest(this, BrickletIMUV3.FUNCTION_SET_QUATERNION_CALLBACK_CONFIGURATION, [period, valueHasToChange], 'I ?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getQuaternionCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the callback configuration as set by :func:`Set Quaternion Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletIMUV3.FUNCTION_GET_QUATERNION_CALLBACK_CONFIGURATION, [], '', 13, 'I ?', returnCallback, errorCallback, false, true);
	};
	this.setAllDataCallbackConfiguration = function(period, valueHasToChange, returnCallback, errorCallback) {
		/*
		The period is the period with which the :cb:`All Data` callback
		is triggered periodically. A value of 0 turns the callback off.
		
		If the `value has to change`-parameter is set to true, the callback is only
		triggered after the value has changed. If the value didn't change within the
		period, the callback is triggered immediately on change.
		
		If it is set to false, the callback is continuously triggered with the period,
		independent of the value.
		*/
		this.ipcon.sendRequest(this, BrickletIMUV3.FUNCTION_SET_ALL_DATA_CALLBACK_CONFIGURATION, [period, valueHasToChange], 'I ?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getAllDataCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the callback configuration as set by :func:`Set All Data Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletIMUV3.FUNCTION_GET_ALL_DATA_CALLBACK_CONFIGURATION, [], '', 13, 'I ?', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPErrorCount = function(returnCallback, errorCallback) {
		/*
		Returns the error count for the communication between Brick and Bricklet.
		
		The errors are divided into
		
		* ACK checksum errors,
		* message checksum errors,
		* framing errors and
		* overflow errors.
		
		The errors counts are for errors that occur on the Bricklet side. All
		Bricks have a similar function that returns the errors on the Brick side.
		*/
		this.ipcon.sendRequest(this, BrickletIMUV3.FUNCTION_GET_SPITFP_ERROR_COUNT, [], '', 24, 'I I I I', returnCallback, errorCallback, false, true);
	};
	this.setBootloaderMode = function(mode, returnCallback, errorCallback) {
		/*
		Sets the bootloader mode and returns the status after the requested
		mode change was instigated.
		
		You can change from bootloader mode to firmware mode and vice versa. A change
		from bootloader mode to firmware mode will only take place if the entry function,
		device identifier and CRC are present and correct.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletIMUV3.FUNCTION_SET_BOOTLOADER_MODE, [mode], 'B', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getBootloaderMode = function(returnCallback, errorCallback) {
		/*
		Returns the current bootloader mode, see :func:`Set Bootloader Mode`.
		*/
		this.ipcon.sendRequest(this, BrickletIMUV3.FUNCTION_GET_BOOTLOADER_MODE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setWriteFirmwarePointer = function(pointer, returnCallback, errorCallback) {
		/*
		Sets the firmware pointer for :func:`Write Firmware`. The pointer has
		to be increased by chunks of size 64. The data is written to flash
		every 4 chunks (which equals to one page of size 256).
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletIMUV3.FUNCTION_SET_WRITE_FIRMWARE_POINTER, [pointer], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeFirmware = function(data, returnCallback, errorCallback) {
		/*
		Writes 64 Bytes of firmware at the position as written by
		:func:`Set Write Firmware Pointer` before. The firmware is written
		to flash every 4 chunks.
		
		You can only write firmware in bootloader mode.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletIMUV3.FUNCTION_WRITE_FIRMWARE, [data], 'B64', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setStatusLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Sets the status LED configuration. By default the LED shows
		communication traffic between Brick and Bricklet, it flickers once
		for every 10 received data packets.
		
		You can also turn the LED permanently on/off or show a heartbeat.
		
		If the Bricklet is in bootloader mode, the LED is will show heartbeat by default.
		*/
		this.ipcon.sendRequest(this, BrickletIMUV3.FUNCTION_SET_STATUS_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getStatusLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Status LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletIMUV3.FUNCTION_GET_STATUS_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getChipTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature as measured inside the microcontroller. The
		value returned is not the ambient temperature!
		
		The temperature is only proportional to the real temperature and it has bad
		accuracy. Practically it is only useful as an indicator for
		temperature changes.
		*/
		this.ipcon.sendRequest(this, BrickletIMUV3.FUNCTION_GET_CHIP_TEMPERATURE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.reset = function(returnCallback, errorCallback) {
		/*
		Calling this function will reset the Bricklet. All configurations
		will be lost.
		
		After a reset you have to create new device objects,
		calling functions on the existing ones will result in
		undefined behavior!
		*/
		this.ipcon.sendRequest(this, BrickletIMUV3.FUNCTION_RESET, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeUID = function(uid, returnCallback, errorCallback) {
		/*
		Writes a new UID into flash. If you want to set a new UID
		you have to decode the Base58 encoded UID string into an
		integer first.
		
		We recommend that you use Brick Viewer to change the UID.
		*/
		this.ipcon.sendRequest(this, BrickletIMUV3.FUNCTION_WRITE_UID, [uid], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.readUID = function(returnCallback, errorCallback) {
		/*
		Returns the current UID as an integer. Encode as
		Base58 to get the usual string version.
		*/
		this.ipcon.sendRequest(this, BrickletIMUV3.FUNCTION_READ_UID, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletIMUV3.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletIMUV3;

},{"./Device":279,"./IPConnection":280}],188:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletIO16.DEVICE_IDENTIFIER = 28;
BrickletIO16.DEVICE_DISPLAY_NAME = 'IO-16 Bricklet';
BrickletIO16.CALLBACK_INTERRUPT = 9;
BrickletIO16.CALLBACK_MONOFLOP_DONE = 12;
BrickletIO16.FUNCTION_SET_PORT = 1;
BrickletIO16.FUNCTION_GET_PORT = 2;
BrickletIO16.FUNCTION_SET_PORT_CONFIGURATION = 3;
BrickletIO16.FUNCTION_GET_PORT_CONFIGURATION = 4;
BrickletIO16.FUNCTION_SET_DEBOUNCE_PERIOD = 5;
BrickletIO16.FUNCTION_GET_DEBOUNCE_PERIOD = 6;
BrickletIO16.FUNCTION_SET_PORT_INTERRUPT = 7;
BrickletIO16.FUNCTION_GET_PORT_INTERRUPT = 8;
BrickletIO16.FUNCTION_SET_PORT_MONOFLOP = 10;
BrickletIO16.FUNCTION_GET_PORT_MONOFLOP = 11;
BrickletIO16.FUNCTION_SET_SELECTED_VALUES = 13;
BrickletIO16.FUNCTION_GET_EDGE_COUNT = 14;
BrickletIO16.FUNCTION_SET_EDGE_COUNT_CONFIG = 15;
BrickletIO16.FUNCTION_GET_EDGE_COUNT_CONFIG = 16;
BrickletIO16.FUNCTION_GET_IDENTITY = 255;
BrickletIO16.DIRECTION_IN = 'i';
BrickletIO16.DIRECTION_OUT = 'o';
BrickletIO16.EDGE_TYPE_RISING = 0;
BrickletIO16.EDGE_TYPE_FALLING = 1;
BrickletIO16.EDGE_TYPE_BOTH = 2;

function BrickletIO16(uid, ipcon) {
	//16-channel digital input/output

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletIO16.DEVICE_IDENTIFIER, BrickletIO16.DEVICE_DISPLAY_NAME);
	BrickletIO16.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 1];
	this.responseExpected[BrickletIO16.FUNCTION_SET_PORT] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIO16.FUNCTION_GET_PORT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIO16.FUNCTION_SET_PORT_CONFIGURATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIO16.FUNCTION_GET_PORT_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIO16.FUNCTION_SET_DEBOUNCE_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletIO16.FUNCTION_GET_DEBOUNCE_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIO16.FUNCTION_SET_PORT_INTERRUPT] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletIO16.FUNCTION_GET_PORT_INTERRUPT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIO16.FUNCTION_SET_PORT_MONOFLOP] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIO16.FUNCTION_GET_PORT_MONOFLOP] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIO16.FUNCTION_SET_SELECTED_VALUES] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIO16.FUNCTION_GET_EDGE_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIO16.FUNCTION_SET_EDGE_COUNT_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIO16.FUNCTION_GET_EDGE_COUNT_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIO16.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletIO16.CALLBACK_INTERRUPT] = [11, 'c B B'];
	this.callbackFormats[BrickletIO16.CALLBACK_MONOFLOP_DONE] = [11, 'c B B'];



	this.setPort = function(port, valueMask, returnCallback, errorCallback) {
		/*
		Sets the output value (high or low) for a port ("a" or "b") with a bitmask
		(8bit). A 1 in the bitmask means high and a 0 in the bitmask means low.
		
		For example: The value 15 or 0b00001111 will turn the pins 0-3 high and the
		pins 4-7 low for the specified port.
		
		All running monoflop timers of the given port will be aborted if this function
		is called.
		
		.. note::
		 This function does nothing for pins that are configured as input.
		 Pull-up resistors can be switched on with :func:`Set Port Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletIO16.FUNCTION_SET_PORT, [port, valueMask], 'c B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getPort = function(port, returnCallback, errorCallback) {
		/*
		Returns a bitmask of the values that are currently measured on the
		specified port. This function works if the pin is configured to input
		as well as if it is configured to output.
		*/
		this.ipcon.sendRequest(this, BrickletIO16.FUNCTION_GET_PORT, [port], 'c', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setPortConfiguration = function(port, selectionMask, direction, value, returnCallback, errorCallback) {
		/*
		Configures the value and direction of a specified port. Possible directions
		are 'i' and 'o' for input and output.
		
		If the direction is configured as output, the value is either high or low
		(set as *true* or *false*).
		
		If the direction is configured as input, the value is either pull-up or
		default (set as *true* or *false*).
		
		For example:
		
		* ('a', 255, 'i', true) or ('a', 0b11111111, 'i', true) will set all pins of port A as input pull-up.
		* ('a', 128, 'i', false) or ('a', 0b10000000, 'i', false) will set pin 7 of port A as input default (floating if nothing is connected).
		* ('b', 3, 'o', false) or ('b', 0b00000011, 'o', false) will set pins 0 and 1 of port B as output low.
		* ('b', 4, 'o', true) or ('b', 0b00000100, 'o', true) will set pin 2 of port B as output high.
		
		Running monoflop timers for the selected pins will be aborted if this
		function is called.
		*/
		this.ipcon.sendRequest(this, BrickletIO16.FUNCTION_SET_PORT_CONFIGURATION, [port, selectionMask, direction, value], 'c B c ?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getPortConfiguration = function(port, returnCallback, errorCallback) {
		/*
		Returns a direction bitmask and a value bitmask for the specified port. A 1 in
		the direction bitmask means input and a 0 in the bitmask means output.
		
		For example: A return value of (15, 51) or (0b00001111, 0b00110011) for
		direction and value means that:
		
		* pins 0 and 1 are configured as input pull-up,
		* pins 2 and 3 are configured as input default,
		* pins 4 and 5 are configured as output high
		* and pins 6 and 7 are configured as output low.
		*/
		this.ipcon.sendRequest(this, BrickletIO16.FUNCTION_GET_PORT_CONFIGURATION, [port], 'c', 10, 'B B', returnCallback, errorCallback, false, true);
	};
	this.setDebouncePeriod = function(debounce, returnCallback, errorCallback) {
		/*
		Sets the debounce period of the :cb:`Interrupt` callback.
		
		For example: If you set this value to 100, you will get the interrupt
		maximal every 100ms. This is necessary if something that bounces is
		connected to the IO-16 Bricklet, such as a button.
		*/
		this.ipcon.sendRequest(this, BrickletIO16.FUNCTION_SET_DEBOUNCE_PERIOD, [debounce], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getDebouncePeriod = function(returnCallback, errorCallback) {
		/*
		Returns the debounce period as set by :func:`Set Debounce Period`.
		*/
		this.ipcon.sendRequest(this, BrickletIO16.FUNCTION_GET_DEBOUNCE_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setPortInterrupt = function(port, interruptMask, returnCallback, errorCallback) {
		/*
		Sets the pins on which an interrupt is activated with a bitmask.
		Interrupts are triggered on changes of the voltage level of the pin,
		i.e. changes from high to low and low to high.
		
		For example: ('a', 129) or ('a', 0b10000001) will enable the interrupt for
		pins 0 and 7 of port a.
		
		The interrupt is delivered with the :cb:`Interrupt` callback.
		*/
		this.ipcon.sendRequest(this, BrickletIO16.FUNCTION_SET_PORT_INTERRUPT, [port, interruptMask], 'c B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getPortInterrupt = function(port, returnCallback, errorCallback) {
		/*
		Returns the interrupt bitmask for the specified port as set by
		:func:`Set Port Interrupt`.
		*/
		this.ipcon.sendRequest(this, BrickletIO16.FUNCTION_GET_PORT_INTERRUPT, [port], 'c', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setPortMonoflop = function(port, selectionMask, valueMask, time, returnCallback, errorCallback) {
		/*
		Configures a monoflop of the pins specified by the second parameter as 8 bit
		long bitmask. The specified pins must be configured for output. Non-output
		pins will be ignored.
		
		The third parameter is a bitmask with the desired value of the specified
		output pins. A 1 in the bitmask means high and a 0 in the bitmask means low.
		
		The forth parameter indicates the time that the pins should hold
		the value.
		
		If this function is called with the parameters ('a', 9, 1, 1500) or
		('a', 0b00001001, 0b00000001, 1500): Pin 0 will get high and pin 3 will get
		low on port 'a'. In 1.5s pin 0 will get low and pin 3 will get high again.
		
		A monoflop can be used as a fail-safe mechanism. For example: Lets assume you
		have a RS485 bus and an IO-16 Bricklet connected to one of the slave
		stacks. You can now call this function every second, with a time parameter
		of two seconds and pin 0 set to high. Pin 0 will be high all the time. If now
		the RS485 connection is lost, then pin 0 will get low in at most two seconds.
		*/
		this.ipcon.sendRequest(this, BrickletIO16.FUNCTION_SET_PORT_MONOFLOP, [port, selectionMask, valueMask, time], 'c B B I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getPortMonoflop = function(port, pin, returnCallback, errorCallback) {
		/*
		Returns (for the given pin) the current value and the time as set by
		:func:`Set Port Monoflop` as well as the remaining time until the value flips.
		
		If the timer is not running currently, the remaining time will be returned
		as 0.
		*/
		this.ipcon.sendRequest(this, BrickletIO16.FUNCTION_GET_PORT_MONOFLOP, [port, pin], 'c B', 17, 'B I I', returnCallback, errorCallback, false, true);
	};
	this.setSelectedValues = function(port, selectionMask, valueMask, returnCallback, errorCallback) {
		/*
		Sets the output value (high or low) for a port ("a" or "b" with a bitmask,
		according to the selection mask. The bitmask is 8 bit long and a 1 in the
		bitmask means high and a 0 in the bitmask means low.
		
		For example: The parameters ('a', 192, 128) or ('a', 0b11000000, 0b10000000)
		will turn pin 7 high and pin 6 low on port A, pins 0-6 will remain untouched.
		
		Running monoflop timers for the selected pins will be aborted if this
		function is called.
		
		.. note::
		 This function does nothing for pins that are configured as input.
		 Pull-up resistors can be switched on with :func:`Set Port Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletIO16.FUNCTION_SET_SELECTED_VALUES, [port, selectionMask, valueMask], 'c B B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getEdgeCount = function(pin, resetCounter, returnCallback, errorCallback) {
		/*
		Returns the current value of the edge counter for the selected pin on port A.
		You can configure the edges that are counted with :func:`Set Edge Count Config`.
		
		If you set the reset counter to *true*, the count is set back to 0
		directly after it is read.
		
		.. versionadded:: 2.0.3$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletIO16.FUNCTION_GET_EDGE_COUNT, [pin, resetCounter], 'B ?', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setEdgeCountConfig = function(pin, edgeType, debounce, returnCallback, errorCallback) {
		/*
		Configures the edge counter for the selected pin of port A. Pins 0 and 1
		are available for edge counting.
		
		The edge type parameter configures if rising edges, falling edges or
		both are counted if the pin is configured for input. Possible edge types are:
		
		* 0 = rising
		* 1 = falling
		* 2 = both
		
		Configuring an edge counter resets its value to 0.
		
		If you don't know what any of this means, just leave it at default. The
		default configuration is very likely OK for you.
		
		.. versionadded:: 2.0.3$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletIO16.FUNCTION_SET_EDGE_COUNT_CONFIG, [pin, edgeType, debounce], 'B B B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getEdgeCountConfig = function(pin, returnCallback, errorCallback) {
		/*
		Returns the edge type and debounce time for the selected pin of port A as set by
		:func:`Set Edge Count Config`.
		
		.. versionadded:: 2.0.3$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletIO16.FUNCTION_GET_EDGE_COUNT_CONFIG, [pin], 'B', 10, 'B B', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletIO16.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletIO16;

},{"./Device":279,"./IPConnection":280}],189:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletIO16V2.DEVICE_IDENTIFIER = 2114;
BrickletIO16V2.DEVICE_DISPLAY_NAME = 'IO-16 Bricklet 2.0';
BrickletIO16V2.CALLBACK_INPUT_VALUE = 15;
BrickletIO16V2.CALLBACK_ALL_INPUT_VALUE = 16;
BrickletIO16V2.CALLBACK_MONOFLOP_DONE = 17;
BrickletIO16V2.FUNCTION_SET_VALUE = 1;
BrickletIO16V2.FUNCTION_GET_VALUE = 2;
BrickletIO16V2.FUNCTION_SET_SELECTED_VALUE = 3;
BrickletIO16V2.FUNCTION_SET_CONFIGURATION = 4;
BrickletIO16V2.FUNCTION_GET_CONFIGURATION = 5;
BrickletIO16V2.FUNCTION_SET_INPUT_VALUE_CALLBACK_CONFIGURATION = 6;
BrickletIO16V2.FUNCTION_GET_INPUT_VALUE_CALLBACK_CONFIGURATION = 7;
BrickletIO16V2.FUNCTION_SET_ALL_INPUT_VALUE_CALLBACK_CONFIGURATION = 8;
BrickletIO16V2.FUNCTION_GET_ALL_INPUT_VALUE_CALLBACK_CONFIGURATION = 9;
BrickletIO16V2.FUNCTION_SET_MONOFLOP = 10;
BrickletIO16V2.FUNCTION_GET_MONOFLOP = 11;
BrickletIO16V2.FUNCTION_GET_EDGE_COUNT = 12;
BrickletIO16V2.FUNCTION_SET_EDGE_COUNT_CONFIGURATION = 13;
BrickletIO16V2.FUNCTION_GET_EDGE_COUNT_CONFIGURATION = 14;
BrickletIO16V2.FUNCTION_GET_SPITFP_ERROR_COUNT = 234;
BrickletIO16V2.FUNCTION_SET_BOOTLOADER_MODE = 235;
BrickletIO16V2.FUNCTION_GET_BOOTLOADER_MODE = 236;
BrickletIO16V2.FUNCTION_SET_WRITE_FIRMWARE_POINTER = 237;
BrickletIO16V2.FUNCTION_WRITE_FIRMWARE = 238;
BrickletIO16V2.FUNCTION_SET_STATUS_LED_CONFIG = 239;
BrickletIO16V2.FUNCTION_GET_STATUS_LED_CONFIG = 240;
BrickletIO16V2.FUNCTION_GET_CHIP_TEMPERATURE = 242;
BrickletIO16V2.FUNCTION_RESET = 243;
BrickletIO16V2.FUNCTION_WRITE_UID = 248;
BrickletIO16V2.FUNCTION_READ_UID = 249;
BrickletIO16V2.FUNCTION_GET_IDENTITY = 255;
BrickletIO16V2.DIRECTION_IN = 'i';
BrickletIO16V2.DIRECTION_OUT = 'o';
BrickletIO16V2.EDGE_TYPE_RISING = 0;
BrickletIO16V2.EDGE_TYPE_FALLING = 1;
BrickletIO16V2.EDGE_TYPE_BOTH = 2;
BrickletIO16V2.BOOTLOADER_MODE_BOOTLOADER = 0;
BrickletIO16V2.BOOTLOADER_MODE_FIRMWARE = 1;
BrickletIO16V2.BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT = 2;
BrickletIO16V2.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT = 3;
BrickletIO16V2.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT = 4;
BrickletIO16V2.BOOTLOADER_STATUS_OK = 0;
BrickletIO16V2.BOOTLOADER_STATUS_INVALID_MODE = 1;
BrickletIO16V2.BOOTLOADER_STATUS_NO_CHANGE = 2;
BrickletIO16V2.BOOTLOADER_STATUS_ENTRY_FUNCTION_NOT_PRESENT = 3;
BrickletIO16V2.BOOTLOADER_STATUS_DEVICE_IDENTIFIER_INCORRECT = 4;
BrickletIO16V2.BOOTLOADER_STATUS_CRC_MISMATCH = 5;
BrickletIO16V2.STATUS_LED_CONFIG_OFF = 0;
BrickletIO16V2.STATUS_LED_CONFIG_ON = 1;
BrickletIO16V2.STATUS_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletIO16V2.STATUS_LED_CONFIG_SHOW_STATUS = 3;

function BrickletIO16V2(uid, ipcon) {
	//16-channel digital input/output

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletIO16V2.DEVICE_IDENTIFIER, BrickletIO16V2.DEVICE_DISPLAY_NAME);
	BrickletIO16V2.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickletIO16V2.FUNCTION_SET_VALUE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIO16V2.FUNCTION_GET_VALUE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIO16V2.FUNCTION_SET_SELECTED_VALUE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIO16V2.FUNCTION_SET_CONFIGURATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIO16V2.FUNCTION_GET_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIO16V2.FUNCTION_SET_INPUT_VALUE_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletIO16V2.FUNCTION_GET_INPUT_VALUE_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIO16V2.FUNCTION_SET_ALL_INPUT_VALUE_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletIO16V2.FUNCTION_GET_ALL_INPUT_VALUE_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIO16V2.FUNCTION_SET_MONOFLOP] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIO16V2.FUNCTION_GET_MONOFLOP] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIO16V2.FUNCTION_GET_EDGE_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIO16V2.FUNCTION_SET_EDGE_COUNT_CONFIGURATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIO16V2.FUNCTION_GET_EDGE_COUNT_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIO16V2.FUNCTION_GET_SPITFP_ERROR_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIO16V2.FUNCTION_SET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIO16V2.FUNCTION_GET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIO16V2.FUNCTION_SET_WRITE_FIRMWARE_POINTER] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIO16V2.FUNCTION_WRITE_FIRMWARE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIO16V2.FUNCTION_SET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIO16V2.FUNCTION_GET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIO16V2.FUNCTION_GET_CHIP_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIO16V2.FUNCTION_RESET] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIO16V2.FUNCTION_WRITE_UID] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIO16V2.FUNCTION_READ_UID] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIO16V2.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletIO16V2.CALLBACK_INPUT_VALUE] = [11, 'B ? ?'];
	this.callbackFormats[BrickletIO16V2.CALLBACK_ALL_INPUT_VALUE] = [12, '?16 ?16'];
	this.callbackFormats[BrickletIO16V2.CALLBACK_MONOFLOP_DONE] = [10, 'B ?'];



	this.setValue = function(value, returnCallback, errorCallback) {
		/*
		Sets the output value of all sixteen channels. A value of *true* or *false* outputs
		logic 1 or logic 0 respectively on the corresponding channel.
		
		Use :func:`Set Selected Value` to change only one output channel state.
		
		For example: (True, True, False, False, ..., False) will turn the channels 0-1
		high and the channels 2-15 low.
		
		All running monoflop timers will be aborted if this function is called.
		
		.. note::
		 This function does nothing for channels that are configured as input. Pull-up
		 resistors can be switched on with :func:`Set Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletIO16V2.FUNCTION_SET_VALUE, [value], '?16', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getValue = function(returnCallback, errorCallback) {
		/*
		Returns the logic levels that are currently measured on the channels.
		This function works if the channel is configured as input as well as if it is
		configured as output.
		*/
		this.ipcon.sendRequest(this, BrickletIO16V2.FUNCTION_GET_VALUE, [], '', 10, '?16', returnCallback, errorCallback, false, true);
	};
	this.setSelectedValue = function(channel, value, returnCallback, errorCallback) {
		/*
		Sets the output value of a specific channel without affecting the other channels.
		
		A running monoflop timer for the specific channel will be aborted if this
		function is called.
		
		.. note::
		 This function does nothing for channels that are configured as input. Pull-up
		 resistors can be switched on with :func:`Set Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletIO16V2.FUNCTION_SET_SELECTED_VALUE, [channel, value], 'B ?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.setConfiguration = function(channel, direction, value, returnCallback, errorCallback) {
		/*
		Configures the value and direction of a specific channel. Possible directions
		are 'i' and 'o' for input and output.
		
		If the direction is configured as output, the value is either high or low
		(set as *true* or *false*).
		
		If the direction is configured as input, the value is either pull-up or
		default (set as *true* or *false*).
		
		For example:
		
		* (0, 'i', true) will set channel-0 as input pull-up.
		* (1, 'i', false) will set channel-1 as input default (floating if nothing is connected).
		* (2, 'o', true) will set channel-2 as output high.
		* (3, 'o', false) will set channel-3 as output low.
		
		A running monoflop timer for the specific channel will be aborted if this
		function is called.
		*/
		this.ipcon.sendRequest(this, BrickletIO16V2.FUNCTION_SET_CONFIGURATION, [channel, direction, value], 'B c ?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getConfiguration = function(channel, returnCallback, errorCallback) {
		/*
		Returns the channel configuration as set by :func:`Set Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletIO16V2.FUNCTION_GET_CONFIGURATION, [channel], 'B', 10, 'c ?', returnCallback, errorCallback, false, true);
	};
	this.setInputValueCallbackConfiguration = function(channel, period, valueHasToChange, returnCallback, errorCallback) {
		/*
		This callback can be configured per channel.
		
		The period is the period with which the :cb:`Input Value`
		callback is triggered periodically. A value of 0 turns the callback off.
		
		If the `value has to change`-parameter is set to true, the callback is only
		triggered after the value has changed. If the value didn't change within the
		period, the callback is triggered immediately on change.
		
		If it is set to false, the callback is continuously triggered with the period,
		independent of the value.
		*/
		this.ipcon.sendRequest(this, BrickletIO16V2.FUNCTION_SET_INPUT_VALUE_CALLBACK_CONFIGURATION, [channel, period, valueHasToChange], 'B I ?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getInputValueCallbackConfiguration = function(channel, returnCallback, errorCallback) {
		/*
		Returns the callback configuration as set by
		:func:`Set Input Value Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletIO16V2.FUNCTION_GET_INPUT_VALUE_CALLBACK_CONFIGURATION, [channel], 'B', 13, 'I ?', returnCallback, errorCallback, false, true);
	};
	this.setAllInputValueCallbackConfiguration = function(period, valueHasToChange, returnCallback, errorCallback) {
		/*
		The period is the period with which the :cb:`All Input Value`
		callback is triggered periodically. A value of 0 turns the callback off.
		
		If the `value has to change`-parameter is set to true, the callback is only
		triggered after the value has changed. If the value didn't change within the
		period, the callback is triggered immediately on change.
		
		If it is set to false, the callback is continuously triggered with the period,
		independent of the value.
		*/
		this.ipcon.sendRequest(this, BrickletIO16V2.FUNCTION_SET_ALL_INPUT_VALUE_CALLBACK_CONFIGURATION, [period, valueHasToChange], 'I ?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getAllInputValueCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the callback configuration as set by
		:func:`Set All Input Value Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletIO16V2.FUNCTION_GET_ALL_INPUT_VALUE_CALLBACK_CONFIGURATION, [], '', 13, 'I ?', returnCallback, errorCallback, false, true);
	};
	this.setMonoflop = function(channel, value, time, returnCallback, errorCallback) {
		/*
		Configures a monoflop of the specified channel.
		
		The second parameter is the desired value of the specified
		channel. A *true* means relay closed and a *false* means relay open.
		
		The third parameter indicates the time that the channels should hold
		the value.
		
		If this function is called with the parameters (0, 1, 1500) channel 0 will
		close and in 1.5s channel 0 will open again
		
		A monoflop can be used as a fail-safe mechanism. For example: Lets assume you
		have a RS485 bus and a IO-16 Bricklet 2.0 connected to one of
		the slave stacks. You can now call this function every second, with a time
		parameter of two seconds and channel 0 closed. Channel 0 will be closed all the
		time. If now the RS485 connection is lost, then channel 0 will be opened in at
		most two seconds.
		*/
		this.ipcon.sendRequest(this, BrickletIO16V2.FUNCTION_SET_MONOFLOP, [channel, value, time], 'B ? I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getMonoflop = function(channel, returnCallback, errorCallback) {
		/*
		Returns (for the given channel) the current value and the time as set by
		:func:`Set Monoflop` as well as the remaining time until the value flips.
		
		If the timer is not running currently, the remaining time will be returned
		as 0.
		*/
		this.ipcon.sendRequest(this, BrickletIO16V2.FUNCTION_GET_MONOFLOP, [channel], 'B', 17, '? I I', returnCallback, errorCallback, false, true);
	};
	this.getEdgeCount = function(channel, resetCounter, returnCallback, errorCallback) {
		/*
		Returns the current value of the edge counter for the selected channel. You can
		configure the edges that are counted with :func:`Set Edge Count Configuration`.
		
		If you set the reset counter to *true*, the count is set back to 0
		directly after it is read.
		*/
		this.ipcon.sendRequest(this, BrickletIO16V2.FUNCTION_GET_EDGE_COUNT, [channel, resetCounter], 'B ?', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setEdgeCountConfiguration = function(channel, edgeType, debounce, returnCallback, errorCallback) {
		/*
		Configures the edge counter for a specific channel.
		
		The edge type parameter configures if rising edges, falling edges or
		both are counted if the channel is configured for input. Possible edge types are:
		
		* 0 = rising
		* 1 = falling
		* 2 = both
		
		Configuring an edge counter resets its value to 0.
		
		If you don't know what any of this means, just leave it at default. The
		default configuration is very likely OK for you.
		*/
		this.ipcon.sendRequest(this, BrickletIO16V2.FUNCTION_SET_EDGE_COUNT_CONFIGURATION, [channel, edgeType, debounce], 'B B B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getEdgeCountConfiguration = function(channel, returnCallback, errorCallback) {
		/*
		Returns the edge type and debounce time for the selected channel as set by
		:func:`Set Edge Count Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletIO16V2.FUNCTION_GET_EDGE_COUNT_CONFIGURATION, [channel], 'B', 10, 'B B', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPErrorCount = function(returnCallback, errorCallback) {
		/*
		Returns the error count for the communication between Brick and Bricklet.
		
		The errors are divided into
		
		* ACK checksum errors,
		* message checksum errors,
		* framing errors and
		* overflow errors.
		
		The errors counts are for errors that occur on the Bricklet side. All
		Bricks have a similar function that returns the errors on the Brick side.
		*/
		this.ipcon.sendRequest(this, BrickletIO16V2.FUNCTION_GET_SPITFP_ERROR_COUNT, [], '', 24, 'I I I I', returnCallback, errorCallback, false, true);
	};
	this.setBootloaderMode = function(mode, returnCallback, errorCallback) {
		/*
		Sets the bootloader mode and returns the status after the requested
		mode change was instigated.
		
		You can change from bootloader mode to firmware mode and vice versa. A change
		from bootloader mode to firmware mode will only take place if the entry function,
		device identifier and CRC are present and correct.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletIO16V2.FUNCTION_SET_BOOTLOADER_MODE, [mode], 'B', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getBootloaderMode = function(returnCallback, errorCallback) {
		/*
		Returns the current bootloader mode, see :func:`Set Bootloader Mode`.
		*/
		this.ipcon.sendRequest(this, BrickletIO16V2.FUNCTION_GET_BOOTLOADER_MODE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setWriteFirmwarePointer = function(pointer, returnCallback, errorCallback) {
		/*
		Sets the firmware pointer for :func:`Write Firmware`. The pointer has
		to be increased by chunks of size 64. The data is written to flash
		every 4 chunks (which equals to one page of size 256).
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletIO16V2.FUNCTION_SET_WRITE_FIRMWARE_POINTER, [pointer], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeFirmware = function(data, returnCallback, errorCallback) {
		/*
		Writes 64 Bytes of firmware at the position as written by
		:func:`Set Write Firmware Pointer` before. The firmware is written
		to flash every 4 chunks.
		
		You can only write firmware in bootloader mode.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletIO16V2.FUNCTION_WRITE_FIRMWARE, [data], 'B64', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setStatusLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Sets the status LED configuration. By default the LED shows
		communication traffic between Brick and Bricklet, it flickers once
		for every 10 received data packets.
		
		You can also turn the LED permanently on/off or show a heartbeat.
		
		If the Bricklet is in bootloader mode, the LED is will show heartbeat by default.
		*/
		this.ipcon.sendRequest(this, BrickletIO16V2.FUNCTION_SET_STATUS_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getStatusLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Status LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletIO16V2.FUNCTION_GET_STATUS_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getChipTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature as measured inside the microcontroller. The
		value returned is not the ambient temperature!
		
		The temperature is only proportional to the real temperature and it has bad
		accuracy. Practically it is only useful as an indicator for
		temperature changes.
		*/
		this.ipcon.sendRequest(this, BrickletIO16V2.FUNCTION_GET_CHIP_TEMPERATURE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.reset = function(returnCallback, errorCallback) {
		/*
		Calling this function will reset the Bricklet. All configurations
		will be lost.
		
		After a reset you have to create new device objects,
		calling functions on the existing ones will result in
		undefined behavior!
		*/
		this.ipcon.sendRequest(this, BrickletIO16V2.FUNCTION_RESET, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeUID = function(uid, returnCallback, errorCallback) {
		/*
		Writes a new UID into flash. If you want to set a new UID
		you have to decode the Base58 encoded UID string into an
		integer first.
		
		We recommend that you use Brick Viewer to change the UID.
		*/
		this.ipcon.sendRequest(this, BrickletIO16V2.FUNCTION_WRITE_UID, [uid], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.readUID = function(returnCallback, errorCallback) {
		/*
		Returns the current UID as an integer. Encode as
		Base58 to get the usual string version.
		*/
		this.ipcon.sendRequest(this, BrickletIO16V2.FUNCTION_READ_UID, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletIO16V2.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletIO16V2;

},{"./Device":279,"./IPConnection":280}],190:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletIO4.DEVICE_IDENTIFIER = 29;
BrickletIO4.DEVICE_DISPLAY_NAME = 'IO-4 Bricklet';
BrickletIO4.CALLBACK_INTERRUPT = 9;
BrickletIO4.CALLBACK_MONOFLOP_DONE = 12;
BrickletIO4.FUNCTION_SET_VALUE = 1;
BrickletIO4.FUNCTION_GET_VALUE = 2;
BrickletIO4.FUNCTION_SET_CONFIGURATION = 3;
BrickletIO4.FUNCTION_GET_CONFIGURATION = 4;
BrickletIO4.FUNCTION_SET_DEBOUNCE_PERIOD = 5;
BrickletIO4.FUNCTION_GET_DEBOUNCE_PERIOD = 6;
BrickletIO4.FUNCTION_SET_INTERRUPT = 7;
BrickletIO4.FUNCTION_GET_INTERRUPT = 8;
BrickletIO4.FUNCTION_SET_MONOFLOP = 10;
BrickletIO4.FUNCTION_GET_MONOFLOP = 11;
BrickletIO4.FUNCTION_SET_SELECTED_VALUES = 13;
BrickletIO4.FUNCTION_GET_EDGE_COUNT = 14;
BrickletIO4.FUNCTION_SET_EDGE_COUNT_CONFIG = 15;
BrickletIO4.FUNCTION_GET_EDGE_COUNT_CONFIG = 16;
BrickletIO4.FUNCTION_GET_IDENTITY = 255;
BrickletIO4.DIRECTION_IN = 'i';
BrickletIO4.DIRECTION_OUT = 'o';
BrickletIO4.EDGE_TYPE_RISING = 0;
BrickletIO4.EDGE_TYPE_FALLING = 1;
BrickletIO4.EDGE_TYPE_BOTH = 2;

function BrickletIO4(uid, ipcon) {
	//4-channel digital input/output

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletIO4.DEVICE_IDENTIFIER, BrickletIO4.DEVICE_DISPLAY_NAME);
	BrickletIO4.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 1];
	this.responseExpected[BrickletIO4.FUNCTION_SET_VALUE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIO4.FUNCTION_GET_VALUE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIO4.FUNCTION_SET_CONFIGURATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIO4.FUNCTION_GET_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIO4.FUNCTION_SET_DEBOUNCE_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletIO4.FUNCTION_GET_DEBOUNCE_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIO4.FUNCTION_SET_INTERRUPT] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletIO4.FUNCTION_GET_INTERRUPT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIO4.FUNCTION_SET_MONOFLOP] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIO4.FUNCTION_GET_MONOFLOP] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIO4.FUNCTION_SET_SELECTED_VALUES] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIO4.FUNCTION_GET_EDGE_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIO4.FUNCTION_SET_EDGE_COUNT_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIO4.FUNCTION_GET_EDGE_COUNT_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIO4.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletIO4.CALLBACK_INTERRUPT] = [10, 'B B'];
	this.callbackFormats[BrickletIO4.CALLBACK_MONOFLOP_DONE] = [10, 'B B'];



	this.setValue = function(valueMask, returnCallback, errorCallback) {
		/*
		Sets the output value (high or low) with a bitmask (4bit). A 1 in the bitmask
		means high and a 0 in the bitmask means low.
		
		For example: The value 3 or 0b0011 will turn the pins 0-1 high and the
		pins 2-3 low.
		
		All running monoflop timers will be aborted if this function is called.
		
		.. note::
		 This function does nothing for pins that are configured as input.
		 Pull-up resistors can be switched on with :func:`Set Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletIO4.FUNCTION_SET_VALUE, [valueMask], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getValue = function(returnCallback, errorCallback) {
		/*
		Returns a bitmask of the values that are currently measured.
		This function works if the pin is configured to input
		as well as if it is configured to output.
		*/
		this.ipcon.sendRequest(this, BrickletIO4.FUNCTION_GET_VALUE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setConfiguration = function(selectionMask, direction, value, returnCallback, errorCallback) {
		/*
		Configures the value and direction of the specified pins. Possible directions
		are 'i' and 'o' for input and output.
		
		If the direction is configured as output, the value is either high or low
		(set as *true* or *false*).
		
		If the direction is configured as input, the value is either pull-up or
		default (set as *true* or *false*).
		
		For example:
		
		* (15, 'i', true) or (0b1111, 'i', true) will set all pins of as input pull-up.
		* (8, 'i', false) or (0b1000, 'i', false) will set pin 3 of as input default (floating if nothing is connected).
		* (3, 'o', false) or (0b0011, 'o', false) will set pins 0 and 1 as output low.
		* (4, 'o', true) or (0b0100, 'o', true) will set pin 2 of as output high.
		
		Running monoflop timers for the specified pins will be aborted if this
		function is called.
		*/
		this.ipcon.sendRequest(this, BrickletIO4.FUNCTION_SET_CONFIGURATION, [selectionMask, direction, value], 'B c ?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns a value bitmask and a direction bitmask. A 1 in the direction bitmask
		means input and a 0 in the bitmask means output.
		
		For example: A return value of (3, 5) or (0b0011, 0b0101) for direction and
		value means that:
		
		* pin 0 is configured as input pull-up,
		* pin 1 is configured as input default,
		* pin 2 is configured as output high and
		* pin 3 is are configured as output low.
		*/
		this.ipcon.sendRequest(this, BrickletIO4.FUNCTION_GET_CONFIGURATION, [], '', 10, 'B B', returnCallback, errorCallback, false, true);
	};
	this.setDebouncePeriod = function(debounce, returnCallback, errorCallback) {
		/*
		Sets the debounce period of the :cb:`Interrupt` callback.
		
		For example: If you set this value to 100, you will get the interrupt
		maximal every 100ms. This is necessary if something that bounces is
		connected to the IO-4 Bricklet, such as a button.
		*/
		this.ipcon.sendRequest(this, BrickletIO4.FUNCTION_SET_DEBOUNCE_PERIOD, [debounce], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getDebouncePeriod = function(returnCallback, errorCallback) {
		/*
		Returns the debounce period as set by :func:`Set Debounce Period`.
		*/
		this.ipcon.sendRequest(this, BrickletIO4.FUNCTION_GET_DEBOUNCE_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setInterrupt = function(interruptMask, returnCallback, errorCallback) {
		/*
		Sets the pins on which an interrupt is activated with a bitmask.
		Interrupts are triggered on changes of the voltage level of the pin,
		i.e. changes from high to low and low to high.
		
		For example: An interrupt bitmask of 10 or 0b1010 will enable the interrupt for
		pins 1 and 3.
		
		The interrupt is delivered with the :cb:`Interrupt` callback.
		*/
		this.ipcon.sendRequest(this, BrickletIO4.FUNCTION_SET_INTERRUPT, [interruptMask], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getInterrupt = function(returnCallback, errorCallback) {
		/*
		Returns the interrupt bitmask as set by :func:`Set Interrupt`.
		*/
		this.ipcon.sendRequest(this, BrickletIO4.FUNCTION_GET_INTERRUPT, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setMonoflop = function(selectionMask, valueMask, time, returnCallback, errorCallback) {
		/*
		Configures a monoflop of the pins specified by the first parameter as 4 bit
		long bitmask. The specified pins must be configured for output. Non-output
		pins will be ignored.
		
		The second parameter is a bitmask with the desired value of the specified
		output pins. A 1 in the bitmask means high and a 0 in the bitmask means low.
		
		The third parameter indicates the time that the pins should hold
		the value.
		
		If this function is called with the parameters (9, 1, 1500) or
		(0b1001, 0b0001, 1500): Pin 0 will get high and pin 3 will get low. In 1.5s pin
		0 will get low and pin 3 will get high again.
		
		A monoflop can be used as a fail-safe mechanism. For example: Lets assume you
		have a RS485 bus and an IO-4 Bricklet connected to one of the slave
		stacks. You can now call this function every second, with a time parameter
		of two seconds and pin 0 set to high. Pin 0 will be high all the time. If now
		the RS485 connection is lost, then pin 0 will get low in at most two seconds.
		*/
		this.ipcon.sendRequest(this, BrickletIO4.FUNCTION_SET_MONOFLOP, [selectionMask, valueMask, time], 'B B I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getMonoflop = function(pin, returnCallback, errorCallback) {
		/*
		Returns (for the given pin) the current value and the time as set by
		:func:`Set Monoflop` as well as the remaining time until the value flips.
		
		If the timer is not running currently, the remaining time will be returned
		as 0.
		*/
		this.ipcon.sendRequest(this, BrickletIO4.FUNCTION_GET_MONOFLOP, [pin], 'B', 17, 'B I I', returnCallback, errorCallback, false, true);
	};
	this.setSelectedValues = function(selectionMask, valueMask, returnCallback, errorCallback) {
		/*
		Sets the output value (high or low) with a bitmask, according to
		the selection mask. The bitmask is 4 bit long, *true* refers to high
		and *false* refers to low.
		
		For example: The parameters (9, 4) or (0b0110, 0b0100) will turn
		pin 1 low and pin 2 high, pin 0 and 3 will remain untouched.
		
		Running monoflop timers for the selected pins will be aborted if this
		function is called.
		
		.. note::
		 This function does nothing for pins that are configured as input.
		 Pull-up resistors can be switched on with :func:`Set Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletIO4.FUNCTION_SET_SELECTED_VALUES, [selectionMask, valueMask], 'B B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getEdgeCount = function(pin, resetCounter, returnCallback, errorCallback) {
		/*
		Returns the current value of the edge counter for the selected pin. You can
		configure the edges that are counted with :func:`Set Edge Count Config`.
		
		If you set the reset counter to *true*, the count is set back to 0
		directly after it is read.
		
		.. versionadded:: 2.0.1$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletIO4.FUNCTION_GET_EDGE_COUNT, [pin, resetCounter], 'B ?', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setEdgeCountConfig = function(selectionMask, edgeType, debounce, returnCallback, errorCallback) {
		/*
		Configures the edge counter for the selected pins.
		
		The edge type parameter configures if rising edges, falling edges or
		both are counted if the pin is configured for input. Possible edge types are:
		
		* 0 = rising (default)
		* 1 = falling
		* 2 = both
		
		Configuring an edge counter resets its value to 0.
		
		If you don't know what any of this means, just leave it at default. The
		default configuration is very likely OK for you.
		
		.. versionadded:: 2.0.1$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletIO4.FUNCTION_SET_EDGE_COUNT_CONFIG, [selectionMask, edgeType, debounce], 'B B B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getEdgeCountConfig = function(pin, returnCallback, errorCallback) {
		/*
		Returns the edge type and debounce time for the selected pin as set by
		:func:`Set Edge Count Config`.
		
		.. versionadded:: 2.0.1$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletIO4.FUNCTION_GET_EDGE_COUNT_CONFIG, [pin], 'B', 10, 'B B', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletIO4.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletIO4;

},{"./Device":279,"./IPConnection":280}],191:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletIO4V2.DEVICE_IDENTIFIER = 2111;
BrickletIO4V2.DEVICE_DISPLAY_NAME = 'IO-4 Bricklet 2.0';
BrickletIO4V2.CALLBACK_INPUT_VALUE = 17;
BrickletIO4V2.CALLBACK_ALL_INPUT_VALUE = 18;
BrickletIO4V2.CALLBACK_MONOFLOP_DONE = 19;
BrickletIO4V2.FUNCTION_SET_VALUE = 1;
BrickletIO4V2.FUNCTION_GET_VALUE = 2;
BrickletIO4V2.FUNCTION_SET_SELECTED_VALUE = 3;
BrickletIO4V2.FUNCTION_SET_CONFIGURATION = 4;
BrickletIO4V2.FUNCTION_GET_CONFIGURATION = 5;
BrickletIO4V2.FUNCTION_SET_INPUT_VALUE_CALLBACK_CONFIGURATION = 6;
BrickletIO4V2.FUNCTION_GET_INPUT_VALUE_CALLBACK_CONFIGURATION = 7;
BrickletIO4V2.FUNCTION_SET_ALL_INPUT_VALUE_CALLBACK_CONFIGURATION = 8;
BrickletIO4V2.FUNCTION_GET_ALL_INPUT_VALUE_CALLBACK_CONFIGURATION = 9;
BrickletIO4V2.FUNCTION_SET_MONOFLOP = 10;
BrickletIO4V2.FUNCTION_GET_MONOFLOP = 11;
BrickletIO4V2.FUNCTION_GET_EDGE_COUNT = 12;
BrickletIO4V2.FUNCTION_SET_EDGE_COUNT_CONFIGURATION = 13;
BrickletIO4V2.FUNCTION_GET_EDGE_COUNT_CONFIGURATION = 14;
BrickletIO4V2.FUNCTION_SET_PWM_CONFIGURATION = 15;
BrickletIO4V2.FUNCTION_GET_PWM_CONFIGURATION = 16;
BrickletIO4V2.FUNCTION_GET_SPITFP_ERROR_COUNT = 234;
BrickletIO4V2.FUNCTION_SET_BOOTLOADER_MODE = 235;
BrickletIO4V2.FUNCTION_GET_BOOTLOADER_MODE = 236;
BrickletIO4V2.FUNCTION_SET_WRITE_FIRMWARE_POINTER = 237;
BrickletIO4V2.FUNCTION_WRITE_FIRMWARE = 238;
BrickletIO4V2.FUNCTION_SET_STATUS_LED_CONFIG = 239;
BrickletIO4V2.FUNCTION_GET_STATUS_LED_CONFIG = 240;
BrickletIO4V2.FUNCTION_GET_CHIP_TEMPERATURE = 242;
BrickletIO4V2.FUNCTION_RESET = 243;
BrickletIO4V2.FUNCTION_WRITE_UID = 248;
BrickletIO4V2.FUNCTION_READ_UID = 249;
BrickletIO4V2.FUNCTION_GET_IDENTITY = 255;
BrickletIO4V2.DIRECTION_IN = 'i';
BrickletIO4V2.DIRECTION_OUT = 'o';
BrickletIO4V2.EDGE_TYPE_RISING = 0;
BrickletIO4V2.EDGE_TYPE_FALLING = 1;
BrickletIO4V2.EDGE_TYPE_BOTH = 2;
BrickletIO4V2.BOOTLOADER_MODE_BOOTLOADER = 0;
BrickletIO4V2.BOOTLOADER_MODE_FIRMWARE = 1;
BrickletIO4V2.BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT = 2;
BrickletIO4V2.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT = 3;
BrickletIO4V2.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT = 4;
BrickletIO4V2.BOOTLOADER_STATUS_OK = 0;
BrickletIO4V2.BOOTLOADER_STATUS_INVALID_MODE = 1;
BrickletIO4V2.BOOTLOADER_STATUS_NO_CHANGE = 2;
BrickletIO4V2.BOOTLOADER_STATUS_ENTRY_FUNCTION_NOT_PRESENT = 3;
BrickletIO4V2.BOOTLOADER_STATUS_DEVICE_IDENTIFIER_INCORRECT = 4;
BrickletIO4V2.BOOTLOADER_STATUS_CRC_MISMATCH = 5;
BrickletIO4V2.STATUS_LED_CONFIG_OFF = 0;
BrickletIO4V2.STATUS_LED_CONFIG_ON = 1;
BrickletIO4V2.STATUS_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletIO4V2.STATUS_LED_CONFIG_SHOW_STATUS = 3;

function BrickletIO4V2(uid, ipcon) {
	//4-channel digital input/output

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletIO4V2.DEVICE_IDENTIFIER, BrickletIO4V2.DEVICE_DISPLAY_NAME);
	BrickletIO4V2.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickletIO4V2.FUNCTION_SET_VALUE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIO4V2.FUNCTION_GET_VALUE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIO4V2.FUNCTION_SET_SELECTED_VALUE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIO4V2.FUNCTION_SET_CONFIGURATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIO4V2.FUNCTION_GET_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIO4V2.FUNCTION_SET_INPUT_VALUE_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletIO4V2.FUNCTION_GET_INPUT_VALUE_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIO4V2.FUNCTION_SET_ALL_INPUT_VALUE_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletIO4V2.FUNCTION_GET_ALL_INPUT_VALUE_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIO4V2.FUNCTION_SET_MONOFLOP] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIO4V2.FUNCTION_GET_MONOFLOP] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIO4V2.FUNCTION_GET_EDGE_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIO4V2.FUNCTION_SET_EDGE_COUNT_CONFIGURATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIO4V2.FUNCTION_GET_EDGE_COUNT_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIO4V2.FUNCTION_SET_PWM_CONFIGURATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIO4V2.FUNCTION_GET_PWM_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIO4V2.FUNCTION_GET_SPITFP_ERROR_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIO4V2.FUNCTION_SET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIO4V2.FUNCTION_GET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIO4V2.FUNCTION_SET_WRITE_FIRMWARE_POINTER] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIO4V2.FUNCTION_WRITE_FIRMWARE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIO4V2.FUNCTION_SET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIO4V2.FUNCTION_GET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIO4V2.FUNCTION_GET_CHIP_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIO4V2.FUNCTION_RESET] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIO4V2.FUNCTION_WRITE_UID] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIO4V2.FUNCTION_READ_UID] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIO4V2.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletIO4V2.CALLBACK_INPUT_VALUE] = [11, 'B ? ?'];
	this.callbackFormats[BrickletIO4V2.CALLBACK_ALL_INPUT_VALUE] = [10, '?4 ?4'];
	this.callbackFormats[BrickletIO4V2.CALLBACK_MONOFLOP_DONE] = [10, 'B ?'];



	this.setValue = function(value, returnCallback, errorCallback) {
		/*
		Sets the output value of all four channels. A value of *true* or *false* outputs
		logic 1 or logic 0 respectively on the corresponding channel.
		
		Use :func:`Set Selected Value` to change only one output channel state.
		
		For example: (True, True, False, False) will turn the channels 0-1 high and the
		channels 2-3 low.
		
		All running monoflop timers and PWMs will be aborted if this function is called.
		
		.. note::
		 This function does nothing for channels that are configured as input. Pull-up
		 resistors can be switched on with :func:`Set Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletIO4V2.FUNCTION_SET_VALUE, [value], '?4', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getValue = function(returnCallback, errorCallback) {
		/*
		Returns the logic levels that are currently measured on the channels.
		This function works if the channel is configured as input as well as if it is
		configured as output.
		*/
		this.ipcon.sendRequest(this, BrickletIO4V2.FUNCTION_GET_VALUE, [], '', 9, '?4', returnCallback, errorCallback, false, true);
	};
	this.setSelectedValue = function(channel, value, returnCallback, errorCallback) {
		/*
		Sets the output value of a specific channel without affecting the other channels.
		
		A running monoflop timer or PWM for the specific channel will be aborted if this
		function is called.
		
		.. note::
		 This function does nothing for channels that are configured as input. Pull-up
		 resistors can be switched on with :func:`Set Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletIO4V2.FUNCTION_SET_SELECTED_VALUE, [channel, value], 'B ?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.setConfiguration = function(channel, direction, value, returnCallback, errorCallback) {
		/*
		Configures the value and direction of a specific channel. Possible directions
		are 'i' and 'o' for input and output.
		
		If the direction is configured as output, the value is either high or low
		(set as *true* or *false*).
		
		If the direction is configured as input, the value is either pull-up or
		default (set as *true* or *false*).
		
		For example:
		
		* (0, 'i', true) will set channel 0 as input pull-up.
		* (1, 'i', false) will set channel 1 as input default (floating if nothing is connected).
		* (2, 'o', true) will set channel 2 as output high.
		* (3, 'o', false) will set channel 3 as output low.
		
		A running monoflop timer or PWM for the specific channel will be aborted if this
		function is called.
		*/
		this.ipcon.sendRequest(this, BrickletIO4V2.FUNCTION_SET_CONFIGURATION, [channel, direction, value], 'B c ?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getConfiguration = function(channel, returnCallback, errorCallback) {
		/*
		Returns the channel configuration as set by :func:`Set Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletIO4V2.FUNCTION_GET_CONFIGURATION, [channel], 'B', 10, 'c ?', returnCallback, errorCallback, false, true);
	};
	this.setInputValueCallbackConfiguration = function(channel, period, valueHasToChange, returnCallback, errorCallback) {
		/*
		This callback can be configured per channel.
		
		The period is the period with which the :cb:`Input Value`
		callback is triggered periodically. A value of 0 turns the callback off.
		
		If the `value has to change`-parameter is set to true, the callback is only
		triggered after the value has changed. If the value didn't change within the
		period, the callback is triggered immediately on change.
		
		If it is set to false, the callback is continuously triggered with the period,
		independent of the value.
		*/
		this.ipcon.sendRequest(this, BrickletIO4V2.FUNCTION_SET_INPUT_VALUE_CALLBACK_CONFIGURATION, [channel, period, valueHasToChange], 'B I ?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getInputValueCallbackConfiguration = function(channel, returnCallback, errorCallback) {
		/*
		Returns the callback configuration for the given channel as set by
		:func:`Set Input Value Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletIO4V2.FUNCTION_GET_INPUT_VALUE_CALLBACK_CONFIGURATION, [channel], 'B', 13, 'I ?', returnCallback, errorCallback, false, true);
	};
	this.setAllInputValueCallbackConfiguration = function(period, valueHasToChange, returnCallback, errorCallback) {
		/*
		The period is the period with which the :cb:`All Input Value`
		callback is triggered periodically. A value of 0 turns the callback off.
		
		If the `value has to change`-parameter is set to true, the callback is only
		triggered after the value has changed. If the value didn't change within the
		period, the callback is triggered immediately on change.
		
		If it is set to false, the callback is continuously triggered with the period,
		independent of the value.
		*/
		this.ipcon.sendRequest(this, BrickletIO4V2.FUNCTION_SET_ALL_INPUT_VALUE_CALLBACK_CONFIGURATION, [period, valueHasToChange], 'I ?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getAllInputValueCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the callback configuration as set by
		:func:`Set All Input Value Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletIO4V2.FUNCTION_GET_ALL_INPUT_VALUE_CALLBACK_CONFIGURATION, [], '', 13, 'I ?', returnCallback, errorCallback, false, true);
	};
	this.setMonoflop = function(channel, value, time, returnCallback, errorCallback) {
		/*
		The first parameter is the desired state of the channel (*true* means output *high*
		and *false* means output *low*). The second parameter indicates the time that
		the channel should hold the state.
		
		If this function is called with the parameters (true, 1500):
		The channel will turn on and in 1.5s it will turn off again.
		
		A PWM for the selected channel will be aborted if this function is called.
		
		A monoflop can be used as a failsafe mechanism. For example: Lets assume you
		have a RS485 bus and a IO-4 Bricklet 2.0 is connected to one of the slave
		stacks. You can now call this function every second, with a time parameter
		of two seconds. The channel will be *high* all the time. If now the RS485
		connection is lost, the channel will turn *low* in at most two seconds.
		*/
		this.ipcon.sendRequest(this, BrickletIO4V2.FUNCTION_SET_MONOFLOP, [channel, value, time], 'B ? I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getMonoflop = function(channel, returnCallback, errorCallback) {
		/*
		Returns (for the given channel) the current value and the time as set by
		:func:`Set Monoflop` as well as the remaining time until the value flips.
		
		If the timer is not running currently, the remaining time will be returned
		as 0.
		*/
		this.ipcon.sendRequest(this, BrickletIO4V2.FUNCTION_GET_MONOFLOP, [channel], 'B', 17, '? I I', returnCallback, errorCallback, false, true);
	};
	this.getEdgeCount = function(channel, resetCounter, returnCallback, errorCallback) {
		/*
		Returns the current value of the edge counter for the selected channel. You can
		configure the edges that are counted with :func:`Set Edge Count Configuration`.
		
		If you set the reset counter to *true*, the count is set back to 0
		directly after it is read.
		
		.. note::
		 Calling this function is only allowed for channels configured as input.
		*/
		this.ipcon.sendRequest(this, BrickletIO4V2.FUNCTION_GET_EDGE_COUNT, [channel, resetCounter], 'B ?', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setEdgeCountConfiguration = function(channel, edgeType, debounce, returnCallback, errorCallback) {
		/*
		Configures the edge counter for a specific channel.
		
		The edge type parameter configures if rising edges, falling edges or
		both are counted if the channel is configured for input. Possible edge types are:
		
		* 0 = rising
		* 1 = falling
		* 2 = both
		
		Configuring an edge counter resets its value to 0.
		
		If you don't know what any of this means, just leave it at default. The
		default configuration is very likely OK for you.
		
		.. note::
		 Calling this function is only allowed for channels configured as input.
		*/
		this.ipcon.sendRequest(this, BrickletIO4V2.FUNCTION_SET_EDGE_COUNT_CONFIGURATION, [channel, edgeType, debounce], 'B B B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getEdgeCountConfiguration = function(channel, returnCallback, errorCallback) {
		/*
		Returns the edge type and debounce time for the selected channel as set by
		:func:`Set Edge Count Configuration`.
		
		.. note::
		 Calling this function is only allowed for channels configured as input.
		*/
		this.ipcon.sendRequest(this, BrickletIO4V2.FUNCTION_GET_EDGE_COUNT_CONFIGURATION, [channel], 'B', 10, 'B B', returnCallback, errorCallback, false, true);
	};
	this.setPWMConfiguration = function(channel, frequency, dutyCycle, returnCallback, errorCallback) {
		/*
		Activates a PWM for the given channel.
		
		You need to set the channel to output before you call this function, otherwise it will
		report an invalid parameter error. To turn the PWM off again, you can set the frequency to 0 or any other
		function that changes a value of the channel (e.g. :func:`Set Selected Value`).
		
		A running monoflop timer for the given channel will be aborted if this function
		is called.
		*/
		this.ipcon.sendRequest(this, BrickletIO4V2.FUNCTION_SET_PWM_CONFIGURATION, [channel, frequency, dutyCycle], 'B I H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getPWMConfiguration = function(channel, returnCallback, errorCallback) {
		/*
		Returns the PWM configuration as set by :func:`Set PWM Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletIO4V2.FUNCTION_GET_PWM_CONFIGURATION, [channel], 'B', 14, 'I H', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPErrorCount = function(returnCallback, errorCallback) {
		/*
		Returns the error count for the communication between Brick and Bricklet.
		
		The errors are divided into
		
		* ACK checksum errors,
		* message checksum errors,
		* framing errors and
		* overflow errors.
		
		The errors counts are for errors that occur on the Bricklet side. All
		Bricks have a similar function that returns the errors on the Brick side.
		*/
		this.ipcon.sendRequest(this, BrickletIO4V2.FUNCTION_GET_SPITFP_ERROR_COUNT, [], '', 24, 'I I I I', returnCallback, errorCallback, false, true);
	};
	this.setBootloaderMode = function(mode, returnCallback, errorCallback) {
		/*
		Sets the bootloader mode and returns the status after the requested
		mode change was instigated.
		
		You can change from bootloader mode to firmware mode and vice versa. A change
		from bootloader mode to firmware mode will only take place if the entry function,
		device identifier and CRC are present and correct.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletIO4V2.FUNCTION_SET_BOOTLOADER_MODE, [mode], 'B', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getBootloaderMode = function(returnCallback, errorCallback) {
		/*
		Returns the current bootloader mode, see :func:`Set Bootloader Mode`.
		*/
		this.ipcon.sendRequest(this, BrickletIO4V2.FUNCTION_GET_BOOTLOADER_MODE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setWriteFirmwarePointer = function(pointer, returnCallback, errorCallback) {
		/*
		Sets the firmware pointer for :func:`Write Firmware`. The pointer has
		to be increased by chunks of size 64. The data is written to flash
		every 4 chunks (which equals to one page of size 256).
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletIO4V2.FUNCTION_SET_WRITE_FIRMWARE_POINTER, [pointer], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeFirmware = function(data, returnCallback, errorCallback) {
		/*
		Writes 64 Bytes of firmware at the position as written by
		:func:`Set Write Firmware Pointer` before. The firmware is written
		to flash every 4 chunks.
		
		You can only write firmware in bootloader mode.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletIO4V2.FUNCTION_WRITE_FIRMWARE, [data], 'B64', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setStatusLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Sets the status LED configuration. By default the LED shows
		communication traffic between Brick and Bricklet, it flickers once
		for every 10 received data packets.
		
		You can also turn the LED permanently on/off or show a heartbeat.
		
		If the Bricklet is in bootloader mode, the LED is will show heartbeat by default.
		*/
		this.ipcon.sendRequest(this, BrickletIO4V2.FUNCTION_SET_STATUS_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getStatusLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Status LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletIO4V2.FUNCTION_GET_STATUS_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getChipTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature as measured inside the microcontroller. The
		value returned is not the ambient temperature!
		
		The temperature is only proportional to the real temperature and it has bad
		accuracy. Practically it is only useful as an indicator for
		temperature changes.
		*/
		this.ipcon.sendRequest(this, BrickletIO4V2.FUNCTION_GET_CHIP_TEMPERATURE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.reset = function(returnCallback, errorCallback) {
		/*
		Calling this function will reset the Bricklet. All configurations
		will be lost.
		
		After a reset you have to create new device objects,
		calling functions on the existing ones will result in
		undefined behavior!
		*/
		this.ipcon.sendRequest(this, BrickletIO4V2.FUNCTION_RESET, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeUID = function(uid, returnCallback, errorCallback) {
		/*
		Writes a new UID into flash. If you want to set a new UID
		you have to decode the Base58 encoded UID string into an
		integer first.
		
		We recommend that you use Brick Viewer to change the UID.
		*/
		this.ipcon.sendRequest(this, BrickletIO4V2.FUNCTION_WRITE_UID, [uid], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.readUID = function(returnCallback, errorCallback) {
		/*
		Returns the current UID as an integer. Encode as
		Base58 to get the usual string version.
		*/
		this.ipcon.sendRequest(this, BrickletIO4V2.FUNCTION_READ_UID, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletIO4V2.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletIO4V2;

},{"./Device":279,"./IPConnection":280}],192:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletIndustrialAnalogOut.DEVICE_IDENTIFIER = 258;
BrickletIndustrialAnalogOut.DEVICE_DISPLAY_NAME = 'Industrial Analog Out Bricklet';
BrickletIndustrialAnalogOut.FUNCTION_ENABLE = 1;
BrickletIndustrialAnalogOut.FUNCTION_DISABLE = 2;
BrickletIndustrialAnalogOut.FUNCTION_IS_ENABLED = 3;
BrickletIndustrialAnalogOut.FUNCTION_SET_VOLTAGE = 4;
BrickletIndustrialAnalogOut.FUNCTION_GET_VOLTAGE = 5;
BrickletIndustrialAnalogOut.FUNCTION_SET_CURRENT = 6;
BrickletIndustrialAnalogOut.FUNCTION_GET_CURRENT = 7;
BrickletIndustrialAnalogOut.FUNCTION_SET_CONFIGURATION = 8;
BrickletIndustrialAnalogOut.FUNCTION_GET_CONFIGURATION = 9;
BrickletIndustrialAnalogOut.FUNCTION_GET_IDENTITY = 255;
BrickletIndustrialAnalogOut.VOLTAGE_RANGE_0_TO_5V = 0;
BrickletIndustrialAnalogOut.VOLTAGE_RANGE_0_TO_10V = 1;
BrickletIndustrialAnalogOut.CURRENT_RANGE_4_TO_20MA = 0;
BrickletIndustrialAnalogOut.CURRENT_RANGE_0_TO_20MA = 1;
BrickletIndustrialAnalogOut.CURRENT_RANGE_0_TO_24MA = 2;

function BrickletIndustrialAnalogOut(uid, ipcon) {
	//Generates configurable DC voltage and current, 0V to 10V and 4mA to 20mA

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletIndustrialAnalogOut.DEVICE_IDENTIFIER, BrickletIndustrialAnalogOut.DEVICE_DISPLAY_NAME);
	BrickletIndustrialAnalogOut.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickletIndustrialAnalogOut.FUNCTION_ENABLE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialAnalogOut.FUNCTION_DISABLE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialAnalogOut.FUNCTION_IS_ENABLED] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialAnalogOut.FUNCTION_SET_VOLTAGE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialAnalogOut.FUNCTION_GET_VOLTAGE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialAnalogOut.FUNCTION_SET_CURRENT] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialAnalogOut.FUNCTION_GET_CURRENT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialAnalogOut.FUNCTION_SET_CONFIGURATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialAnalogOut.FUNCTION_GET_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialAnalogOut.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;



	this.enable = function(returnCallback, errorCallback) {
		/*
		Enables the output of voltage and current.
		
		The default is disabled.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialAnalogOut.FUNCTION_ENABLE, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.disable = function(returnCallback, errorCallback) {
		/*
		Disables the output of voltage and current.
		
		The default is disabled.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialAnalogOut.FUNCTION_DISABLE, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.isEnabled = function(returnCallback, errorCallback) {
		/*
		Returns *true* if output of voltage and current is enabled, *false* otherwise.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialAnalogOut.FUNCTION_IS_ENABLED, [], '', 9, '?', returnCallback, errorCallback, false, true);
	};
	this.setVoltage = function(voltage, returnCallback, errorCallback) {
		/*
		Sets the output voltage.
		
		The output voltage and output current are linked. Changing the output voltage
		also changes the output current.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialAnalogOut.FUNCTION_SET_VOLTAGE, [voltage], 'H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getVoltage = function(returnCallback, errorCallback) {
		/*
		Returns the voltage as set by :func:`Set Voltage`.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialAnalogOut.FUNCTION_GET_VOLTAGE, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.setCurrent = function(current, returnCallback, errorCallback) {
		/*
		Sets the output current.
		
		The output current and output voltage are linked. Changing the output current
		also changes the output voltage.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialAnalogOut.FUNCTION_SET_CURRENT, [current], 'H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getCurrent = function(returnCallback, errorCallback) {
		/*
		Returns the current as set by :func:`Set Current`.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialAnalogOut.FUNCTION_GET_CURRENT, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.setConfiguration = function(voltageRange, currentRange, returnCallback, errorCallback) {
		/*
		Configures the voltage and current range.
		
		Possible voltage ranges are:
		
		* 0V to 5V
		* 0V to 10V
		
		Possible current ranges are:
		
		* 4mA to 20mA
		* 0mA to 20mA
		* 0mA to 24mA
		
		The resolution will always be 12 bit. This means, that the
		precision is higher with a smaller range.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialAnalogOut.FUNCTION_SET_CONFIGURATION, [voltageRange, currentRange], 'B B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialAnalogOut.FUNCTION_GET_CONFIGURATION, [], '', 10, 'B B', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialAnalogOut.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletIndustrialAnalogOut;

},{"./Device":279,"./IPConnection":280}],193:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletIndustrialAnalogOutV2.DEVICE_IDENTIFIER = 2116;
BrickletIndustrialAnalogOutV2.DEVICE_DISPLAY_NAME = 'Industrial Analog Out Bricklet 2.0';
BrickletIndustrialAnalogOutV2.FUNCTION_SET_ENABLED = 1;
BrickletIndustrialAnalogOutV2.FUNCTION_GET_ENABLED = 2;
BrickletIndustrialAnalogOutV2.FUNCTION_SET_VOLTAGE = 3;
BrickletIndustrialAnalogOutV2.FUNCTION_GET_VOLTAGE = 4;
BrickletIndustrialAnalogOutV2.FUNCTION_SET_CURRENT = 5;
BrickletIndustrialAnalogOutV2.FUNCTION_GET_CURRENT = 6;
BrickletIndustrialAnalogOutV2.FUNCTION_SET_CONFIGURATION = 7;
BrickletIndustrialAnalogOutV2.FUNCTION_GET_CONFIGURATION = 8;
BrickletIndustrialAnalogOutV2.FUNCTION_SET_OUT_LED_CONFIG = 9;
BrickletIndustrialAnalogOutV2.FUNCTION_GET_OUT_LED_CONFIG = 10;
BrickletIndustrialAnalogOutV2.FUNCTION_SET_OUT_LED_STATUS_CONFIG = 11;
BrickletIndustrialAnalogOutV2.FUNCTION_GET_OUT_LED_STATUS_CONFIG = 12;
BrickletIndustrialAnalogOutV2.FUNCTION_GET_SPITFP_ERROR_COUNT = 234;
BrickletIndustrialAnalogOutV2.FUNCTION_SET_BOOTLOADER_MODE = 235;
BrickletIndustrialAnalogOutV2.FUNCTION_GET_BOOTLOADER_MODE = 236;
BrickletIndustrialAnalogOutV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER = 237;
BrickletIndustrialAnalogOutV2.FUNCTION_WRITE_FIRMWARE = 238;
BrickletIndustrialAnalogOutV2.FUNCTION_SET_STATUS_LED_CONFIG = 239;
BrickletIndustrialAnalogOutV2.FUNCTION_GET_STATUS_LED_CONFIG = 240;
BrickletIndustrialAnalogOutV2.FUNCTION_GET_CHIP_TEMPERATURE = 242;
BrickletIndustrialAnalogOutV2.FUNCTION_RESET = 243;
BrickletIndustrialAnalogOutV2.FUNCTION_WRITE_UID = 248;
BrickletIndustrialAnalogOutV2.FUNCTION_READ_UID = 249;
BrickletIndustrialAnalogOutV2.FUNCTION_GET_IDENTITY = 255;
BrickletIndustrialAnalogOutV2.VOLTAGE_RANGE_0_TO_5V = 0;
BrickletIndustrialAnalogOutV2.VOLTAGE_RANGE_0_TO_10V = 1;
BrickletIndustrialAnalogOutV2.CURRENT_RANGE_4_TO_20MA = 0;
BrickletIndustrialAnalogOutV2.CURRENT_RANGE_0_TO_20MA = 1;
BrickletIndustrialAnalogOutV2.CURRENT_RANGE_0_TO_24MA = 2;
BrickletIndustrialAnalogOutV2.OUT_LED_CONFIG_OFF = 0;
BrickletIndustrialAnalogOutV2.OUT_LED_CONFIG_ON = 1;
BrickletIndustrialAnalogOutV2.OUT_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletIndustrialAnalogOutV2.OUT_LED_CONFIG_SHOW_OUT_STATUS = 3;
BrickletIndustrialAnalogOutV2.OUT_LED_STATUS_CONFIG_THRESHOLD = 0;
BrickletIndustrialAnalogOutV2.OUT_LED_STATUS_CONFIG_INTENSITY = 1;
BrickletIndustrialAnalogOutV2.BOOTLOADER_MODE_BOOTLOADER = 0;
BrickletIndustrialAnalogOutV2.BOOTLOADER_MODE_FIRMWARE = 1;
BrickletIndustrialAnalogOutV2.BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT = 2;
BrickletIndustrialAnalogOutV2.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT = 3;
BrickletIndustrialAnalogOutV2.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT = 4;
BrickletIndustrialAnalogOutV2.BOOTLOADER_STATUS_OK = 0;
BrickletIndustrialAnalogOutV2.BOOTLOADER_STATUS_INVALID_MODE = 1;
BrickletIndustrialAnalogOutV2.BOOTLOADER_STATUS_NO_CHANGE = 2;
BrickletIndustrialAnalogOutV2.BOOTLOADER_STATUS_ENTRY_FUNCTION_NOT_PRESENT = 3;
BrickletIndustrialAnalogOutV2.BOOTLOADER_STATUS_DEVICE_IDENTIFIER_INCORRECT = 4;
BrickletIndustrialAnalogOutV2.BOOTLOADER_STATUS_CRC_MISMATCH = 5;
BrickletIndustrialAnalogOutV2.STATUS_LED_CONFIG_OFF = 0;
BrickletIndustrialAnalogOutV2.STATUS_LED_CONFIG_ON = 1;
BrickletIndustrialAnalogOutV2.STATUS_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletIndustrialAnalogOutV2.STATUS_LED_CONFIG_SHOW_STATUS = 3;

function BrickletIndustrialAnalogOutV2(uid, ipcon) {
	//Generates configurable DC voltage and current, 0V to 10V and 4mA to 20mA

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletIndustrialAnalogOutV2.DEVICE_IDENTIFIER, BrickletIndustrialAnalogOutV2.DEVICE_DISPLAY_NAME);
	BrickletIndustrialAnalogOutV2.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickletIndustrialAnalogOutV2.FUNCTION_SET_ENABLED] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialAnalogOutV2.FUNCTION_GET_ENABLED] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialAnalogOutV2.FUNCTION_SET_VOLTAGE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialAnalogOutV2.FUNCTION_GET_VOLTAGE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialAnalogOutV2.FUNCTION_SET_CURRENT] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialAnalogOutV2.FUNCTION_GET_CURRENT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialAnalogOutV2.FUNCTION_SET_CONFIGURATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialAnalogOutV2.FUNCTION_GET_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialAnalogOutV2.FUNCTION_SET_OUT_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialAnalogOutV2.FUNCTION_GET_OUT_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialAnalogOutV2.FUNCTION_SET_OUT_LED_STATUS_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialAnalogOutV2.FUNCTION_GET_OUT_LED_STATUS_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialAnalogOutV2.FUNCTION_GET_SPITFP_ERROR_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialAnalogOutV2.FUNCTION_SET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialAnalogOutV2.FUNCTION_GET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialAnalogOutV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialAnalogOutV2.FUNCTION_WRITE_FIRMWARE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialAnalogOutV2.FUNCTION_SET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialAnalogOutV2.FUNCTION_GET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialAnalogOutV2.FUNCTION_GET_CHIP_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialAnalogOutV2.FUNCTION_RESET] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialAnalogOutV2.FUNCTION_WRITE_UID] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialAnalogOutV2.FUNCTION_READ_UID] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialAnalogOutV2.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;



	this.setEnabled = function(enabled, returnCallback, errorCallback) {
		/*
		Enables/disables the output of voltage and current.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialAnalogOutV2.FUNCTION_SET_ENABLED, [enabled], '?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getEnabled = function(returnCallback, errorCallback) {
		/*
		Returns *true* if output of voltage and current is enabled, *false* otherwise.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialAnalogOutV2.FUNCTION_GET_ENABLED, [], '', 9, '?', returnCallback, errorCallback, false, true);
	};
	this.setVoltage = function(voltage, returnCallback, errorCallback) {
		/*
		Sets the output voltage.
		
		The output voltage and output current are linked. Changing the output voltage
		also changes the output current.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialAnalogOutV2.FUNCTION_SET_VOLTAGE, [voltage], 'H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getVoltage = function(returnCallback, errorCallback) {
		/*
		Returns the voltage as set by :func:`Set Voltage`.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialAnalogOutV2.FUNCTION_GET_VOLTAGE, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.setCurrent = function(current, returnCallback, errorCallback) {
		/*
		Sets the output current.
		
		The output current and output voltage are linked. Changing the output current
		also changes the output voltage.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialAnalogOutV2.FUNCTION_SET_CURRENT, [current], 'H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getCurrent = function(returnCallback, errorCallback) {
		/*
		Returns the current as set by :func:`Set Current`.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialAnalogOutV2.FUNCTION_GET_CURRENT, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.setConfiguration = function(voltageRange, currentRange, returnCallback, errorCallback) {
		/*
		Configures the voltage and current range.
		
		Possible voltage ranges are:
		
		* 0V to 5V
		* 0V to 10V
		
		Possible current ranges are:
		
		* 4mA to 20mA
		* 0mA to 20mA
		* 0mA to 24mA
		
		The resolution will always be 12 bit. This means, that the
		precision is higher with a smaller range.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialAnalogOutV2.FUNCTION_SET_CONFIGURATION, [voltageRange, currentRange], 'B B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialAnalogOutV2.FUNCTION_GET_CONFIGURATION, [], '', 10, 'B B', returnCallback, errorCallback, false, true);
	};
	this.setOutLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		You can turn the Out LED off, on or show a
		heartbeat. You can also set the LED to "Out Status". In this mode the
		LED can either be turned on with a pre-defined threshold or the intensity
		of the LED can change with the output value (voltage or current).
		
		You can configure the channel status behavior with :func:`Set Out LED Status Config`.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialAnalogOutV2.FUNCTION_SET_OUT_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getOutLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the Out LED configuration as set by :func:`Set Out LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialAnalogOutV2.FUNCTION_GET_OUT_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setOutLEDStatusConfig = function(min, max, config, returnCallback, errorCallback) {
		/*
		Sets the Out LED status config. This config is used if the Out LED is
		configured as "Out Status", see :func:`Set Out LED Config`.
		
		For each channel you can choose between threshold and intensity mode.
		
		In threshold mode you can define a positive or a negative threshold.
		For a positive threshold set the "min" parameter to the threshold value in mV or
		µA above which the LED should turn on and set the "max" parameter to 0. Example:
		If you set a positive threshold of 5V, the LED will turn on as soon as the
		output value exceeds 5V and turn off again if it goes below 5V.
		For a negative threshold set the "max" parameter to the threshold value in mV or
		µA below which the LED should turn on and set the "min" parameter to 0. Example:
		If you set a negative threshold of 5V, the LED will turn on as soon as the
		output value goes below 5V and the LED will turn off when the output value
		exceeds 5V.
		
		In intensity mode you can define a range mV or µA that is used to scale the brightness
		of the LED. Example with min=2V, max=8V: The LED is off at 2V and below, on at
		8V and above and the brightness is linearly scaled between the values 2V and 8V.
		If the min value is greater than the max value, the LED brightness is scaled the
		other way around.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialAnalogOutV2.FUNCTION_SET_OUT_LED_STATUS_CONFIG, [min, max, config], 'H H B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getOutLEDStatusConfig = function(returnCallback, errorCallback) {
		/*
		Returns the Out LED status configuration as set by :func:`Set Out LED Status Config`.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialAnalogOutV2.FUNCTION_GET_OUT_LED_STATUS_CONFIG, [], '', 13, 'H H B', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPErrorCount = function(returnCallback, errorCallback) {
		/*
		Returns the error count for the communication between Brick and Bricklet.
		
		The errors are divided into
		
		* ACK checksum errors,
		* message checksum errors,
		* framing errors and
		* overflow errors.
		
		The errors counts are for errors that occur on the Bricklet side. All
		Bricks have a similar function that returns the errors on the Brick side.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialAnalogOutV2.FUNCTION_GET_SPITFP_ERROR_COUNT, [], '', 24, 'I I I I', returnCallback, errorCallback, false, true);
	};
	this.setBootloaderMode = function(mode, returnCallback, errorCallback) {
		/*
		Sets the bootloader mode and returns the status after the requested
		mode change was instigated.
		
		You can change from bootloader mode to firmware mode and vice versa. A change
		from bootloader mode to firmware mode will only take place if the entry function,
		device identifier and CRC are present and correct.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialAnalogOutV2.FUNCTION_SET_BOOTLOADER_MODE, [mode], 'B', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getBootloaderMode = function(returnCallback, errorCallback) {
		/*
		Returns the current bootloader mode, see :func:`Set Bootloader Mode`.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialAnalogOutV2.FUNCTION_GET_BOOTLOADER_MODE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setWriteFirmwarePointer = function(pointer, returnCallback, errorCallback) {
		/*
		Sets the firmware pointer for :func:`Write Firmware`. The pointer has
		to be increased by chunks of size 64. The data is written to flash
		every 4 chunks (which equals to one page of size 256).
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialAnalogOutV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER, [pointer], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeFirmware = function(data, returnCallback, errorCallback) {
		/*
		Writes 64 Bytes of firmware at the position as written by
		:func:`Set Write Firmware Pointer` before. The firmware is written
		to flash every 4 chunks.
		
		You can only write firmware in bootloader mode.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialAnalogOutV2.FUNCTION_WRITE_FIRMWARE, [data], 'B64', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setStatusLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Sets the status LED configuration. By default the LED shows
		communication traffic between Brick and Bricklet, it flickers once
		for every 10 received data packets.
		
		You can also turn the LED permanently on/off or show a heartbeat.
		
		If the Bricklet is in bootloader mode, the LED is will show heartbeat by default.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialAnalogOutV2.FUNCTION_SET_STATUS_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getStatusLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Status LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialAnalogOutV2.FUNCTION_GET_STATUS_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getChipTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature as measured inside the microcontroller. The
		value returned is not the ambient temperature!
		
		The temperature is only proportional to the real temperature and it has bad
		accuracy. Practically it is only useful as an indicator for
		temperature changes.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialAnalogOutV2.FUNCTION_GET_CHIP_TEMPERATURE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.reset = function(returnCallback, errorCallback) {
		/*
		Calling this function will reset the Bricklet. All configurations
		will be lost.
		
		After a reset you have to create new device objects,
		calling functions on the existing ones will result in
		undefined behavior!
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialAnalogOutV2.FUNCTION_RESET, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeUID = function(uid, returnCallback, errorCallback) {
		/*
		Writes a new UID into flash. If you want to set a new UID
		you have to decode the Base58 encoded UID string into an
		integer first.
		
		We recommend that you use Brick Viewer to change the UID.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialAnalogOutV2.FUNCTION_WRITE_UID, [uid], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.readUID = function(returnCallback, errorCallback) {
		/*
		Returns the current UID as an integer. Encode as
		Base58 to get the usual string version.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialAnalogOutV2.FUNCTION_READ_UID, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialAnalogOutV2.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletIndustrialAnalogOutV2;

},{"./Device":279,"./IPConnection":280}],194:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletIndustrialCounter.DEVICE_IDENTIFIER = 293;
BrickletIndustrialCounter.DEVICE_DISPLAY_NAME = 'Industrial Counter Bricklet';
BrickletIndustrialCounter.CALLBACK_ALL_COUNTER = 19;
BrickletIndustrialCounter.CALLBACK_ALL_SIGNAL_DATA = 20;
BrickletIndustrialCounter.FUNCTION_GET_COUNTER = 1;
BrickletIndustrialCounter.FUNCTION_GET_ALL_COUNTER = 2;
BrickletIndustrialCounter.FUNCTION_SET_COUNTER = 3;
BrickletIndustrialCounter.FUNCTION_SET_ALL_COUNTER = 4;
BrickletIndustrialCounter.FUNCTION_GET_SIGNAL_DATA = 5;
BrickletIndustrialCounter.FUNCTION_GET_ALL_SIGNAL_DATA = 6;
BrickletIndustrialCounter.FUNCTION_SET_COUNTER_ACTIVE = 7;
BrickletIndustrialCounter.FUNCTION_SET_ALL_COUNTER_ACTIVE = 8;
BrickletIndustrialCounter.FUNCTION_GET_COUNTER_ACTIVE = 9;
BrickletIndustrialCounter.FUNCTION_GET_ALL_COUNTER_ACTIVE = 10;
BrickletIndustrialCounter.FUNCTION_SET_COUNTER_CONFIGURATION = 11;
BrickletIndustrialCounter.FUNCTION_GET_COUNTER_CONFIGURATION = 12;
BrickletIndustrialCounter.FUNCTION_SET_ALL_COUNTER_CALLBACK_CONFIGURATION = 13;
BrickletIndustrialCounter.FUNCTION_GET_ALL_COUNTER_CALLBACK_CONFIGURATION = 14;
BrickletIndustrialCounter.FUNCTION_SET_ALL_SIGNAL_DATA_CALLBACK_CONFIGURATION = 15;
BrickletIndustrialCounter.FUNCTION_GET_ALL_SIGNAL_DATA_CALLBACK_CONFIGURATION = 16;
BrickletIndustrialCounter.FUNCTION_SET_CHANNEL_LED_CONFIG = 17;
BrickletIndustrialCounter.FUNCTION_GET_CHANNEL_LED_CONFIG = 18;
BrickletIndustrialCounter.FUNCTION_GET_SPITFP_ERROR_COUNT = 234;
BrickletIndustrialCounter.FUNCTION_SET_BOOTLOADER_MODE = 235;
BrickletIndustrialCounter.FUNCTION_GET_BOOTLOADER_MODE = 236;
BrickletIndustrialCounter.FUNCTION_SET_WRITE_FIRMWARE_POINTER = 237;
BrickletIndustrialCounter.FUNCTION_WRITE_FIRMWARE = 238;
BrickletIndustrialCounter.FUNCTION_SET_STATUS_LED_CONFIG = 239;
BrickletIndustrialCounter.FUNCTION_GET_STATUS_LED_CONFIG = 240;
BrickletIndustrialCounter.FUNCTION_GET_CHIP_TEMPERATURE = 242;
BrickletIndustrialCounter.FUNCTION_RESET = 243;
BrickletIndustrialCounter.FUNCTION_WRITE_UID = 248;
BrickletIndustrialCounter.FUNCTION_READ_UID = 249;
BrickletIndustrialCounter.FUNCTION_GET_IDENTITY = 255;
BrickletIndustrialCounter.CHANNEL_0 = 0;
BrickletIndustrialCounter.CHANNEL_1 = 1;
BrickletIndustrialCounter.CHANNEL_2 = 2;
BrickletIndustrialCounter.CHANNEL_3 = 3;
BrickletIndustrialCounter.COUNT_EDGE_RISING = 0;
BrickletIndustrialCounter.COUNT_EDGE_FALLING = 1;
BrickletIndustrialCounter.COUNT_EDGE_BOTH = 2;
BrickletIndustrialCounter.COUNT_DIRECTION_UP = 0;
BrickletIndustrialCounter.COUNT_DIRECTION_DOWN = 1;
BrickletIndustrialCounter.COUNT_DIRECTION_EXTERNAL_UP = 2;
BrickletIndustrialCounter.COUNT_DIRECTION_EXTERNAL_DOWN = 3;
BrickletIndustrialCounter.DUTY_CYCLE_PRESCALER_1 = 0;
BrickletIndustrialCounter.DUTY_CYCLE_PRESCALER_2 = 1;
BrickletIndustrialCounter.DUTY_CYCLE_PRESCALER_4 = 2;
BrickletIndustrialCounter.DUTY_CYCLE_PRESCALER_8 = 3;
BrickletIndustrialCounter.DUTY_CYCLE_PRESCALER_16 = 4;
BrickletIndustrialCounter.DUTY_CYCLE_PRESCALER_32 = 5;
BrickletIndustrialCounter.DUTY_CYCLE_PRESCALER_64 = 6;
BrickletIndustrialCounter.DUTY_CYCLE_PRESCALER_128 = 7;
BrickletIndustrialCounter.DUTY_CYCLE_PRESCALER_256 = 8;
BrickletIndustrialCounter.DUTY_CYCLE_PRESCALER_512 = 9;
BrickletIndustrialCounter.DUTY_CYCLE_PRESCALER_1024 = 10;
BrickletIndustrialCounter.DUTY_CYCLE_PRESCALER_2048 = 11;
BrickletIndustrialCounter.DUTY_CYCLE_PRESCALER_4096 = 12;
BrickletIndustrialCounter.DUTY_CYCLE_PRESCALER_8192 = 13;
BrickletIndustrialCounter.DUTY_CYCLE_PRESCALER_16384 = 14;
BrickletIndustrialCounter.DUTY_CYCLE_PRESCALER_32768 = 15;
BrickletIndustrialCounter.FREQUENCY_INTEGRATION_TIME_128_MS = 0;
BrickletIndustrialCounter.FREQUENCY_INTEGRATION_TIME_256_MS = 1;
BrickletIndustrialCounter.FREQUENCY_INTEGRATION_TIME_512_MS = 2;
BrickletIndustrialCounter.FREQUENCY_INTEGRATION_TIME_1024_MS = 3;
BrickletIndustrialCounter.FREQUENCY_INTEGRATION_TIME_2048_MS = 4;
BrickletIndustrialCounter.FREQUENCY_INTEGRATION_TIME_4096_MS = 5;
BrickletIndustrialCounter.FREQUENCY_INTEGRATION_TIME_8192_MS = 6;
BrickletIndustrialCounter.FREQUENCY_INTEGRATION_TIME_16384_MS = 7;
BrickletIndustrialCounter.FREQUENCY_INTEGRATION_TIME_32768_MS = 8;
BrickletIndustrialCounter.CHANNEL_LED_CONFIG_OFF = 0;
BrickletIndustrialCounter.CHANNEL_LED_CONFIG_ON = 1;
BrickletIndustrialCounter.CHANNEL_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletIndustrialCounter.CHANNEL_LED_CONFIG_SHOW_CHANNEL_STATUS = 3;
BrickletIndustrialCounter.BOOTLOADER_MODE_BOOTLOADER = 0;
BrickletIndustrialCounter.BOOTLOADER_MODE_FIRMWARE = 1;
BrickletIndustrialCounter.BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT = 2;
BrickletIndustrialCounter.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT = 3;
BrickletIndustrialCounter.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT = 4;
BrickletIndustrialCounter.BOOTLOADER_STATUS_OK = 0;
BrickletIndustrialCounter.BOOTLOADER_STATUS_INVALID_MODE = 1;
BrickletIndustrialCounter.BOOTLOADER_STATUS_NO_CHANGE = 2;
BrickletIndustrialCounter.BOOTLOADER_STATUS_ENTRY_FUNCTION_NOT_PRESENT = 3;
BrickletIndustrialCounter.BOOTLOADER_STATUS_DEVICE_IDENTIFIER_INCORRECT = 4;
BrickletIndustrialCounter.BOOTLOADER_STATUS_CRC_MISMATCH = 5;
BrickletIndustrialCounter.STATUS_LED_CONFIG_OFF = 0;
BrickletIndustrialCounter.STATUS_LED_CONFIG_ON = 1;
BrickletIndustrialCounter.STATUS_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletIndustrialCounter.STATUS_LED_CONFIG_SHOW_STATUS = 3;

function BrickletIndustrialCounter(uid, ipcon) {
	//4 channel counter up to 4MHz

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletIndustrialCounter.DEVICE_IDENTIFIER, BrickletIndustrialCounter.DEVICE_DISPLAY_NAME);
	BrickletIndustrialCounter.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickletIndustrialCounter.FUNCTION_GET_COUNTER] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialCounter.FUNCTION_GET_ALL_COUNTER] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialCounter.FUNCTION_SET_COUNTER] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialCounter.FUNCTION_SET_ALL_COUNTER] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialCounter.FUNCTION_GET_SIGNAL_DATA] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialCounter.FUNCTION_GET_ALL_SIGNAL_DATA] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialCounter.FUNCTION_SET_COUNTER_ACTIVE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialCounter.FUNCTION_SET_ALL_COUNTER_ACTIVE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialCounter.FUNCTION_GET_COUNTER_ACTIVE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialCounter.FUNCTION_GET_ALL_COUNTER_ACTIVE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialCounter.FUNCTION_SET_COUNTER_CONFIGURATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialCounter.FUNCTION_GET_COUNTER_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialCounter.FUNCTION_SET_ALL_COUNTER_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletIndustrialCounter.FUNCTION_GET_ALL_COUNTER_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialCounter.FUNCTION_SET_ALL_SIGNAL_DATA_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletIndustrialCounter.FUNCTION_GET_ALL_SIGNAL_DATA_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialCounter.FUNCTION_SET_CHANNEL_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialCounter.FUNCTION_GET_CHANNEL_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialCounter.FUNCTION_GET_SPITFP_ERROR_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialCounter.FUNCTION_SET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialCounter.FUNCTION_GET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialCounter.FUNCTION_SET_WRITE_FIRMWARE_POINTER] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialCounter.FUNCTION_WRITE_FIRMWARE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialCounter.FUNCTION_SET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialCounter.FUNCTION_GET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialCounter.FUNCTION_GET_CHIP_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialCounter.FUNCTION_RESET] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialCounter.FUNCTION_WRITE_UID] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialCounter.FUNCTION_READ_UID] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialCounter.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletIndustrialCounter.CALLBACK_ALL_COUNTER] = [40, 'q4'];
	this.callbackFormats[BrickletIndustrialCounter.CALLBACK_ALL_SIGNAL_DATA] = [65, 'H4 Q4 I4 ?4'];



	this.getCounter = function(channel, returnCallback, errorCallback) {
		/*
		Returns the current counter value for the given channel.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialCounter.FUNCTION_GET_COUNTER, [channel], 'B', 16, 'q', returnCallback, errorCallback, false, true);
	};
	this.getAllCounter = function(returnCallback, errorCallback) {
		/*
		Returns the current counter values for all four channels.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialCounter.FUNCTION_GET_ALL_COUNTER, [], '', 40, 'q4', returnCallback, errorCallback, false, true);
	};
	this.setCounter = function(channel, counter, returnCallback, errorCallback) {
		/*
		Sets the counter value for the given channel.
		
		The default value for the counters on startup is 0.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialCounter.FUNCTION_SET_COUNTER, [channel, counter], 'B q', 0, '', returnCallback, errorCallback, false, true);
	};
	this.setAllCounter = function(counter, returnCallback, errorCallback) {
		/*
		Sets the counter values for all four channels.
		
		The default value for the counters on startup is 0.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialCounter.FUNCTION_SET_ALL_COUNTER, [counter], 'q4', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getSignalData = function(channel, returnCallback, errorCallback) {
		/*
		Returns the signal data (duty cycle, period, frequency and value) for the
		given channel.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialCounter.FUNCTION_GET_SIGNAL_DATA, [channel], 'B', 23, 'H Q I ?', returnCallback, errorCallback, false, true);
	};
	this.getAllSignalData = function(returnCallback, errorCallback) {
		/*
		Returns the signal data (duty cycle, period, frequency and value) for all four
		channels.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialCounter.FUNCTION_GET_ALL_SIGNAL_DATA, [], '', 65, 'H4 Q4 I4 ?4', returnCallback, errorCallback, false, true);
	};
	this.setCounterActive = function(channel, active, returnCallback, errorCallback) {
		/*
		Activates/deactivates the counter of the given channel.
		
		true = activate, false = deactivate.
		
		By default all channels are activated.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialCounter.FUNCTION_SET_COUNTER_ACTIVE, [channel, active], 'B ?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.setAllCounterActive = function(active, returnCallback, errorCallback) {
		/*
		Activates/deactivates the counter of all four channels.
		
		true = activate, false = deactivate.
		
		By default all channels are activated.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialCounter.FUNCTION_SET_ALL_COUNTER_ACTIVE, [active], '?4', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getCounterActive = function(channel, returnCallback, errorCallback) {
		/*
		Returns the activation state of the given channel.
		
		true = activated, false = deactivated.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialCounter.FUNCTION_GET_COUNTER_ACTIVE, [channel], 'B', 9, '?', returnCallback, errorCallback, false, true);
	};
	this.getAllCounterActive = function(returnCallback, errorCallback) {
		/*
		Returns the activation state of all four channels.
		
		true = activated, false = deactivated.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialCounter.FUNCTION_GET_ALL_COUNTER_ACTIVE, [], '', 9, '?4', returnCallback, errorCallback, false, true);
	};
	this.setCounterConfiguration = function(channel, countEdge, countDirection, dutyCyclePrescaler, frequencyIntegrationTime, returnCallback, errorCallback) {
		/*
		Sets the counter configuration for the given channel.
		
		* Count Edge: Counter can count on rising, falling or both edges.
		* Count Direction: Counter can count up or down. You can also use
		  another channel as direction input, see
		  `here <https://www.tinkerforge.com/en/doc/Hardware/Bricklets/Industrial_Counter.html#external-count-direction>`__
		  for details.
		* Duty Cycle Prescaler: Sets a divider for the internal clock. See
		  `here <https://www.tinkerforge.com/en/doc/Hardware/Bricklets/Industrial_Counter.html#duty-cycle-prescaler-and-frequency-integration-time>`__
		  for details.
		* Frequency Integration Time: Sets the integration time for the
		  frequency measurement. See
		  `here <https://www.tinkerforge.com/en/doc/Hardware/Bricklets/Industrial_Counter.html#duty-cycle-prescaler-and-frequency-integration-time>`__
		  for details.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialCounter.FUNCTION_SET_COUNTER_CONFIGURATION, [channel, countEdge, countDirection, dutyCyclePrescaler, frequencyIntegrationTime], 'B B B B B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getCounterConfiguration = function(channel, returnCallback, errorCallback) {
		/*
		Returns the counter configuration as set by :func:`Set Counter Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialCounter.FUNCTION_GET_COUNTER_CONFIGURATION, [channel], 'B', 12, 'B B B B', returnCallback, errorCallback, false, true);
	};
	this.setAllCounterCallbackConfiguration = function(period, valueHasToChange, returnCallback, errorCallback) {
		/*
		The period is the period with which the :cb:`All Counter`
		callback is triggered periodically. A value of 0 turns the callback off.
		
		If the `value has to change`-parameter is set to true, the callback is only
		triggered after the value has changed. If the value didn't change within the
		period, the callback is triggered immediately on change.
		
		If it is set to false, the callback is continuously triggered with the period,
		independent of the value.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialCounter.FUNCTION_SET_ALL_COUNTER_CALLBACK_CONFIGURATION, [period, valueHasToChange], 'I ?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getAllCounterCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the callback configuration as set by
		:func:`Set All Counter Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialCounter.FUNCTION_GET_ALL_COUNTER_CALLBACK_CONFIGURATION, [], '', 13, 'I ?', returnCallback, errorCallback, false, true);
	};
	this.setAllSignalDataCallbackConfiguration = function(period, valueHasToChange, returnCallback, errorCallback) {
		/*
		The period is the period with which the :cb:`All Signal Data`
		callback is triggered periodically. A value of 0 turns the callback off.
		
		If the `value has to change`-parameter is set to true, the callback is only
		triggered after the value has changed. If the value didn't change within the
		period, the callback is triggered immediately on change.
		
		If it is set to false, the callback is continuously triggered with the period,
		independent of the value.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialCounter.FUNCTION_SET_ALL_SIGNAL_DATA_CALLBACK_CONFIGURATION, [period, valueHasToChange], 'I ?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getAllSignalDataCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the callback configuration as set by
		:func:`Set All Signal Data Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialCounter.FUNCTION_GET_ALL_SIGNAL_DATA_CALLBACK_CONFIGURATION, [], '', 13, 'I ?', returnCallback, errorCallback, false, true);
	};
	this.setChannelLEDConfig = function(channel, config, returnCallback, errorCallback) {
		/*
		Each channel has a corresponding LED. You can turn the LED off, on or show a
		heartbeat. You can also set the LED to "Channel Status". In this mode the
		LED is on if the channel is high and off otherwise.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialCounter.FUNCTION_SET_CHANNEL_LED_CONFIG, [channel, config], 'B B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getChannelLEDConfig = function(channel, returnCallback, errorCallback) {
		/*
		Returns the channel LED configuration as set by :func:`Set Channel LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialCounter.FUNCTION_GET_CHANNEL_LED_CONFIG, [channel], 'B', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPErrorCount = function(returnCallback, errorCallback) {
		/*
		Returns the error count for the communication between Brick and Bricklet.
		
		The errors are divided into
		
		* ACK checksum errors,
		* message checksum errors,
		* framing errors and
		* overflow errors.
		
		The errors counts are for errors that occur on the Bricklet side. All
		Bricks have a similar function that returns the errors on the Brick side.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialCounter.FUNCTION_GET_SPITFP_ERROR_COUNT, [], '', 24, 'I I I I', returnCallback, errorCallback, false, true);
	};
	this.setBootloaderMode = function(mode, returnCallback, errorCallback) {
		/*
		Sets the bootloader mode and returns the status after the requested
		mode change was instigated.
		
		You can change from bootloader mode to firmware mode and vice versa. A change
		from bootloader mode to firmware mode will only take place if the entry function,
		device identifier and CRC are present and correct.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialCounter.FUNCTION_SET_BOOTLOADER_MODE, [mode], 'B', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getBootloaderMode = function(returnCallback, errorCallback) {
		/*
		Returns the current bootloader mode, see :func:`Set Bootloader Mode`.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialCounter.FUNCTION_GET_BOOTLOADER_MODE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setWriteFirmwarePointer = function(pointer, returnCallback, errorCallback) {
		/*
		Sets the firmware pointer for :func:`Write Firmware`. The pointer has
		to be increased by chunks of size 64. The data is written to flash
		every 4 chunks (which equals to one page of size 256).
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialCounter.FUNCTION_SET_WRITE_FIRMWARE_POINTER, [pointer], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeFirmware = function(data, returnCallback, errorCallback) {
		/*
		Writes 64 Bytes of firmware at the position as written by
		:func:`Set Write Firmware Pointer` before. The firmware is written
		to flash every 4 chunks.
		
		You can only write firmware in bootloader mode.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialCounter.FUNCTION_WRITE_FIRMWARE, [data], 'B64', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setStatusLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Sets the status LED configuration. By default the LED shows
		communication traffic between Brick and Bricklet, it flickers once
		for every 10 received data packets.
		
		You can also turn the LED permanently on/off or show a heartbeat.
		
		If the Bricklet is in bootloader mode, the LED is will show heartbeat by default.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialCounter.FUNCTION_SET_STATUS_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getStatusLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Status LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialCounter.FUNCTION_GET_STATUS_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getChipTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature as measured inside the microcontroller. The
		value returned is not the ambient temperature!
		
		The temperature is only proportional to the real temperature and it has bad
		accuracy. Practically it is only useful as an indicator for
		temperature changes.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialCounter.FUNCTION_GET_CHIP_TEMPERATURE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.reset = function(returnCallback, errorCallback) {
		/*
		Calling this function will reset the Bricklet. All configurations
		will be lost.
		
		After a reset you have to create new device objects,
		calling functions on the existing ones will result in
		undefined behavior!
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialCounter.FUNCTION_RESET, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeUID = function(uid, returnCallback, errorCallback) {
		/*
		Writes a new UID into flash. If you want to set a new UID
		you have to decode the Base58 encoded UID string into an
		integer first.
		
		We recommend that you use Brick Viewer to change the UID.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialCounter.FUNCTION_WRITE_UID, [uid], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.readUID = function(returnCallback, errorCallback) {
		/*
		Returns the current UID as an integer. Encode as
		Base58 to get the usual string version.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialCounter.FUNCTION_READ_UID, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialCounter.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletIndustrialCounter;

},{"./Device":279,"./IPConnection":280}],195:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletIndustrialDigitalIn4.DEVICE_IDENTIFIER = 223;
BrickletIndustrialDigitalIn4.DEVICE_DISPLAY_NAME = 'Industrial Digital In 4 Bricklet';
BrickletIndustrialDigitalIn4.CALLBACK_INTERRUPT = 9;
BrickletIndustrialDigitalIn4.FUNCTION_GET_VALUE = 1;
BrickletIndustrialDigitalIn4.FUNCTION_SET_GROUP = 2;
BrickletIndustrialDigitalIn4.FUNCTION_GET_GROUP = 3;
BrickletIndustrialDigitalIn4.FUNCTION_GET_AVAILABLE_FOR_GROUP = 4;
BrickletIndustrialDigitalIn4.FUNCTION_SET_DEBOUNCE_PERIOD = 5;
BrickletIndustrialDigitalIn4.FUNCTION_GET_DEBOUNCE_PERIOD = 6;
BrickletIndustrialDigitalIn4.FUNCTION_SET_INTERRUPT = 7;
BrickletIndustrialDigitalIn4.FUNCTION_GET_INTERRUPT = 8;
BrickletIndustrialDigitalIn4.FUNCTION_GET_EDGE_COUNT = 10;
BrickletIndustrialDigitalIn4.FUNCTION_SET_EDGE_COUNT_CONFIG = 11;
BrickletIndustrialDigitalIn4.FUNCTION_GET_EDGE_COUNT_CONFIG = 12;
BrickletIndustrialDigitalIn4.FUNCTION_GET_IDENTITY = 255;
BrickletIndustrialDigitalIn4.EDGE_TYPE_RISING = 0;
BrickletIndustrialDigitalIn4.EDGE_TYPE_FALLING = 1;
BrickletIndustrialDigitalIn4.EDGE_TYPE_BOTH = 2;

function BrickletIndustrialDigitalIn4(uid, ipcon) {
	//4 galvanically isolated digital inputs

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletIndustrialDigitalIn4.DEVICE_IDENTIFIER, BrickletIndustrialDigitalIn4.DEVICE_DISPLAY_NAME);
	BrickletIndustrialDigitalIn4.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 1];
	this.responseExpected[BrickletIndustrialDigitalIn4.FUNCTION_GET_VALUE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDigitalIn4.FUNCTION_SET_GROUP] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialDigitalIn4.FUNCTION_GET_GROUP] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDigitalIn4.FUNCTION_GET_AVAILABLE_FOR_GROUP] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDigitalIn4.FUNCTION_SET_DEBOUNCE_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletIndustrialDigitalIn4.FUNCTION_GET_DEBOUNCE_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDigitalIn4.FUNCTION_SET_INTERRUPT] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletIndustrialDigitalIn4.FUNCTION_GET_INTERRUPT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDigitalIn4.FUNCTION_GET_EDGE_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDigitalIn4.FUNCTION_SET_EDGE_COUNT_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialDigitalIn4.FUNCTION_GET_EDGE_COUNT_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDigitalIn4.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletIndustrialDigitalIn4.CALLBACK_INTERRUPT] = [12, 'H H'];



	this.getValue = function(returnCallback, errorCallback) {
		/*
		Returns the input value with a bitmask. The bitmask is 16bit long, *true*
		refers to high and *false* refers to low.
		
		For example: The value 3 or 0b0011 means that pins 0-1 are high and the other
		pins are low.
		
		If no groups are used (see :func:`Set Group`), the pins correspond to the
		markings on the IndustrialDigital In 4 Bricklet.
		
		If groups are used, the pins correspond to the element in the group.
		Element 1 in the group will get pins 0-3, element 2 pins 4-7, element 3
		pins 8-11 and element 4 pins 12-15.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDigitalIn4.FUNCTION_GET_VALUE, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.setGroup = function(group, returnCallback, errorCallback) {
		/*
		Sets a group of Digital In 4 Bricklets that should work together. You can
		find Bricklets that can be grouped together with :func:`Get Available For Group`.
		
		The group consists of 4 elements. Element 1 in the group will get pins 0-3,
		element 2 pins 4-7, element 3 pins 8-11 and element 4 pins 12-15.
		
		Each element can either be one of the ports ('a' to 'd') or 'n' if it should
		not be used.
		
		For example: If you have two Digital In 4 Bricklets connected to port A and
		port B respectively, you could call with ``['a', 'b', 'n', 'n']``.
		
		Now the pins on the Digital In 4 on port A are assigned to 0-3 and the
		pins on the Digital In 4 on port B are assigned to 4-7. It is now possible
		to call :func:`Get Value` and read out two Bricklets at the same time.
		
		Changing the group configuration resets all edge counter configurations
		and values.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDigitalIn4.FUNCTION_SET_GROUP, [group], 'c4', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getGroup = function(returnCallback, errorCallback) {
		/*
		Returns the group as set by :func:`Set Group`
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDigitalIn4.FUNCTION_GET_GROUP, [], '', 12, 'c4', returnCallback, errorCallback, false, true);
	};
	this.getAvailableForGroup = function(returnCallback, errorCallback) {
		/*
		Returns a bitmask of ports that are available for grouping. For example the
		value 5 or 0b0101 means: Port A and port C are connected to Bricklets that
		can be grouped together.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDigitalIn4.FUNCTION_GET_AVAILABLE_FOR_GROUP, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setDebouncePeriod = function(debounce, returnCallback, errorCallback) {
		/*
		Sets the debounce period of the :cb:`Interrupt` callback.
		
		For example: If you set this value to 100, you will get the interrupt
		maximal every 100ms. This is necessary if something that bounces is
		connected to the Digital In 4 Bricklet, such as a button.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDigitalIn4.FUNCTION_SET_DEBOUNCE_PERIOD, [debounce], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getDebouncePeriod = function(returnCallback, errorCallback) {
		/*
		Returns the debounce period as set by :func:`Set Debounce Period`.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDigitalIn4.FUNCTION_GET_DEBOUNCE_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setInterrupt = function(interruptMask, returnCallback, errorCallback) {
		/*
		Sets the pins on which an interrupt is activated with a bitmask.
		Interrupts are triggered on changes of the voltage level of the pin,
		i.e. changes from high to low and low to high.
		
		For example: An interrupt bitmask of 9 or 0b1001 will enable the interrupt for
		pins 0 and 3.
		
		The interrupts use the grouping as set by :func:`Set Group`.
		
		The interrupt is delivered with the :cb:`Interrupt` callback.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDigitalIn4.FUNCTION_SET_INTERRUPT, [interruptMask], 'H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getInterrupt = function(returnCallback, errorCallback) {
		/*
		Returns the interrupt bitmask as set by :func:`Set Interrupt`.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDigitalIn4.FUNCTION_GET_INTERRUPT, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.getEdgeCount = function(pin, resetCounter, returnCallback, errorCallback) {
		/*
		Returns the current value of the edge counter for the selected pin. You can
		configure the edges that are counted with :func:`Set Edge Count Config`.
		
		If you set the reset counter to *true*, the count is set back to 0
		directly after it is read.
		
		The edge counters use the grouping as set by :func:`Set Group`.
		
		.. versionadded:: 2.0.1$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDigitalIn4.FUNCTION_GET_EDGE_COUNT, [pin, resetCounter], 'B ?', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setEdgeCountConfig = function(selectionMask, edgeType, debounce, returnCallback, errorCallback) {
		/*
		Configures the edge counter for the selected pins. A bitmask of 9 or 0b1001 will
		enable the edge counter for pins 0 and 3.
		
		The edge type parameter configures if rising edges, falling edges or
		both are counted if the pin is configured for input. Possible edge types are:
		
		* 0 = rising
		* 1 = falling
		* 2 = both
		
		Configuring an edge counter resets its value to 0.
		
		If you don't know what any of this means, just leave it at default. The
		default configuration is very likely OK for you.
		
		The edge counters use the grouping as set by :func:`Set Group`.
		
		.. versionadded:: 2.0.1$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDigitalIn4.FUNCTION_SET_EDGE_COUNT_CONFIG, [selectionMask, edgeType, debounce], 'H B B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getEdgeCountConfig = function(pin, returnCallback, errorCallback) {
		/*
		Returns the edge type and debounce time for the selected pin as set by
		:func:`Set Edge Count Config`.
		
		.. versionadded:: 2.0.1$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDigitalIn4.FUNCTION_GET_EDGE_COUNT_CONFIG, [pin], 'B', 10, 'B B', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDigitalIn4.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletIndustrialDigitalIn4;

},{"./Device":279,"./IPConnection":280}],196:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletIndustrialDigitalIn4V2.DEVICE_IDENTIFIER = 2100;
BrickletIndustrialDigitalIn4V2.DEVICE_DISPLAY_NAME = 'Industrial Digital In 4 Bricklet 2.0';
BrickletIndustrialDigitalIn4V2.CALLBACK_VALUE = 11;
BrickletIndustrialDigitalIn4V2.CALLBACK_ALL_VALUE = 12;
BrickletIndustrialDigitalIn4V2.FUNCTION_GET_VALUE = 1;
BrickletIndustrialDigitalIn4V2.FUNCTION_SET_VALUE_CALLBACK_CONFIGURATION = 2;
BrickletIndustrialDigitalIn4V2.FUNCTION_GET_VALUE_CALLBACK_CONFIGURATION = 3;
BrickletIndustrialDigitalIn4V2.FUNCTION_SET_ALL_VALUE_CALLBACK_CONFIGURATION = 4;
BrickletIndustrialDigitalIn4V2.FUNCTION_GET_ALL_VALUE_CALLBACK_CONFIGURATION = 5;
BrickletIndustrialDigitalIn4V2.FUNCTION_GET_EDGE_COUNT = 6;
BrickletIndustrialDigitalIn4V2.FUNCTION_SET_EDGE_COUNT_CONFIGURATION = 7;
BrickletIndustrialDigitalIn4V2.FUNCTION_GET_EDGE_COUNT_CONFIGURATION = 8;
BrickletIndustrialDigitalIn4V2.FUNCTION_SET_CHANNEL_LED_CONFIG = 9;
BrickletIndustrialDigitalIn4V2.FUNCTION_GET_CHANNEL_LED_CONFIG = 10;
BrickletIndustrialDigitalIn4V2.FUNCTION_GET_SPITFP_ERROR_COUNT = 234;
BrickletIndustrialDigitalIn4V2.FUNCTION_SET_BOOTLOADER_MODE = 235;
BrickletIndustrialDigitalIn4V2.FUNCTION_GET_BOOTLOADER_MODE = 236;
BrickletIndustrialDigitalIn4V2.FUNCTION_SET_WRITE_FIRMWARE_POINTER = 237;
BrickletIndustrialDigitalIn4V2.FUNCTION_WRITE_FIRMWARE = 238;
BrickletIndustrialDigitalIn4V2.FUNCTION_SET_STATUS_LED_CONFIG = 239;
BrickletIndustrialDigitalIn4V2.FUNCTION_GET_STATUS_LED_CONFIG = 240;
BrickletIndustrialDigitalIn4V2.FUNCTION_GET_CHIP_TEMPERATURE = 242;
BrickletIndustrialDigitalIn4V2.FUNCTION_RESET = 243;
BrickletIndustrialDigitalIn4V2.FUNCTION_WRITE_UID = 248;
BrickletIndustrialDigitalIn4V2.FUNCTION_READ_UID = 249;
BrickletIndustrialDigitalIn4V2.FUNCTION_GET_IDENTITY = 255;
BrickletIndustrialDigitalIn4V2.CHANNEL_0 = 0;
BrickletIndustrialDigitalIn4V2.CHANNEL_1 = 1;
BrickletIndustrialDigitalIn4V2.CHANNEL_2 = 2;
BrickletIndustrialDigitalIn4V2.CHANNEL_3 = 3;
BrickletIndustrialDigitalIn4V2.EDGE_TYPE_RISING = 0;
BrickletIndustrialDigitalIn4V2.EDGE_TYPE_FALLING = 1;
BrickletIndustrialDigitalIn4V2.EDGE_TYPE_BOTH = 2;
BrickletIndustrialDigitalIn4V2.CHANNEL_LED_CONFIG_OFF = 0;
BrickletIndustrialDigitalIn4V2.CHANNEL_LED_CONFIG_ON = 1;
BrickletIndustrialDigitalIn4V2.CHANNEL_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletIndustrialDigitalIn4V2.CHANNEL_LED_CONFIG_SHOW_CHANNEL_STATUS = 3;
BrickletIndustrialDigitalIn4V2.BOOTLOADER_MODE_BOOTLOADER = 0;
BrickletIndustrialDigitalIn4V2.BOOTLOADER_MODE_FIRMWARE = 1;
BrickletIndustrialDigitalIn4V2.BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT = 2;
BrickletIndustrialDigitalIn4V2.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT = 3;
BrickletIndustrialDigitalIn4V2.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT = 4;
BrickletIndustrialDigitalIn4V2.BOOTLOADER_STATUS_OK = 0;
BrickletIndustrialDigitalIn4V2.BOOTLOADER_STATUS_INVALID_MODE = 1;
BrickletIndustrialDigitalIn4V2.BOOTLOADER_STATUS_NO_CHANGE = 2;
BrickletIndustrialDigitalIn4V2.BOOTLOADER_STATUS_ENTRY_FUNCTION_NOT_PRESENT = 3;
BrickletIndustrialDigitalIn4V2.BOOTLOADER_STATUS_DEVICE_IDENTIFIER_INCORRECT = 4;
BrickletIndustrialDigitalIn4V2.BOOTLOADER_STATUS_CRC_MISMATCH = 5;
BrickletIndustrialDigitalIn4V2.STATUS_LED_CONFIG_OFF = 0;
BrickletIndustrialDigitalIn4V2.STATUS_LED_CONFIG_ON = 1;
BrickletIndustrialDigitalIn4V2.STATUS_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletIndustrialDigitalIn4V2.STATUS_LED_CONFIG_SHOW_STATUS = 3;

function BrickletIndustrialDigitalIn4V2(uid, ipcon) {
	//4 galvanically isolated digital inputs

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletIndustrialDigitalIn4V2.DEVICE_IDENTIFIER, BrickletIndustrialDigitalIn4V2.DEVICE_DISPLAY_NAME);
	BrickletIndustrialDigitalIn4V2.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickletIndustrialDigitalIn4V2.FUNCTION_GET_VALUE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDigitalIn4V2.FUNCTION_SET_VALUE_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletIndustrialDigitalIn4V2.FUNCTION_GET_VALUE_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDigitalIn4V2.FUNCTION_SET_ALL_VALUE_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletIndustrialDigitalIn4V2.FUNCTION_GET_ALL_VALUE_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDigitalIn4V2.FUNCTION_GET_EDGE_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDigitalIn4V2.FUNCTION_SET_EDGE_COUNT_CONFIGURATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialDigitalIn4V2.FUNCTION_GET_EDGE_COUNT_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDigitalIn4V2.FUNCTION_SET_CHANNEL_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialDigitalIn4V2.FUNCTION_GET_CHANNEL_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDigitalIn4V2.FUNCTION_GET_SPITFP_ERROR_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDigitalIn4V2.FUNCTION_SET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDigitalIn4V2.FUNCTION_GET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDigitalIn4V2.FUNCTION_SET_WRITE_FIRMWARE_POINTER] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialDigitalIn4V2.FUNCTION_WRITE_FIRMWARE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDigitalIn4V2.FUNCTION_SET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialDigitalIn4V2.FUNCTION_GET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDigitalIn4V2.FUNCTION_GET_CHIP_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDigitalIn4V2.FUNCTION_RESET] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialDigitalIn4V2.FUNCTION_WRITE_UID] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialDigitalIn4V2.FUNCTION_READ_UID] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDigitalIn4V2.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletIndustrialDigitalIn4V2.CALLBACK_VALUE] = [11, 'B ? ?'];
	this.callbackFormats[BrickletIndustrialDigitalIn4V2.CALLBACK_ALL_VALUE] = [10, '?4 ?4'];



	this.getValue = function(returnCallback, errorCallback) {
		/*
		Returns the input value as bools, *true* refers to high and *false* refers to low.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDigitalIn4V2.FUNCTION_GET_VALUE, [], '', 9, '?4', returnCallback, errorCallback, false, true);
	};
	this.setValueCallbackConfiguration = function(channel, period, valueHasToChange, returnCallback, errorCallback) {
		/*
		This callback can be configured per channel.
		
		The period is the period with which the :cb:`Value`
		callback is triggered periodically. A value of 0 turns the callback off.
		
		If the `value has to change`-parameter is set to true, the callback is only
		triggered after the value has changed. If the value didn't change within the
		period, the callback is triggered immediately on change.
		
		If it is set to false, the callback is continuously triggered with the period,
		independent of the value.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDigitalIn4V2.FUNCTION_SET_VALUE_CALLBACK_CONFIGURATION, [channel, period, valueHasToChange], 'B I ?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getValueCallbackConfiguration = function(channel, returnCallback, errorCallback) {
		/*
		Returns the callback configuration for the given channel as set by
		:func:`Set Value Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDigitalIn4V2.FUNCTION_GET_VALUE_CALLBACK_CONFIGURATION, [channel], 'B', 13, 'I ?', returnCallback, errorCallback, false, true);
	};
	this.setAllValueCallbackConfiguration = function(period, valueHasToChange, returnCallback, errorCallback) {
		/*
		The period is the period with which the :cb:`All Value`
		callback is triggered periodically. A value of 0 turns the callback off.
		
		If the `value has to change`-parameter is set to true, the callback is only
		triggered after the value has changed. If the value didn't change within the
		period, the callback is triggered immediately on change.
		
		If it is set to false, the callback is continuously triggered with the period,
		independent of the value.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDigitalIn4V2.FUNCTION_SET_ALL_VALUE_CALLBACK_CONFIGURATION, [period, valueHasToChange], 'I ?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getAllValueCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the callback configuration as set by
		:func:`Set All Value Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDigitalIn4V2.FUNCTION_GET_ALL_VALUE_CALLBACK_CONFIGURATION, [], '', 13, 'I ?', returnCallback, errorCallback, false, true);
	};
	this.getEdgeCount = function(channel, resetCounter, returnCallback, errorCallback) {
		/*
		Returns the current value of the edge counter for the selected channel. You can
		configure the edges that are counted with :func:`Set Edge Count Configuration`.
		
		If you set the reset counter to *true*, the count is set back to 0
		directly after it is read.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDigitalIn4V2.FUNCTION_GET_EDGE_COUNT, [channel, resetCounter], 'B ?', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setEdgeCountConfiguration = function(channel, edgeType, debounce, returnCallback, errorCallback) {
		/*
		Configures the edge counter for a specific channel.
		
		The edge type parameter configures if rising edges, falling edges or both are
		counted. Possible edge types are:
		
		* 0 = rising
		* 1 = falling
		* 2 = both
		
		Configuring an edge counter resets its value to 0.
		
		If you don't know what any of this means, just leave it at default. The
		default configuration is very likely OK for you.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDigitalIn4V2.FUNCTION_SET_EDGE_COUNT_CONFIGURATION, [channel, edgeType, debounce], 'B B B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getEdgeCountConfiguration = function(channel, returnCallback, errorCallback) {
		/*
		Returns the edge type and debounce time for the selected channel as set by
		:func:`Set Edge Count Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDigitalIn4V2.FUNCTION_GET_EDGE_COUNT_CONFIGURATION, [channel], 'B', 10, 'B B', returnCallback, errorCallback, false, true);
	};
	this.setChannelLEDConfig = function(channel, config, returnCallback, errorCallback) {
		/*
		Each channel has a corresponding LED. You can turn the LED off, on or show a
		heartbeat. You can also set the LED to "Channel Status". In this mode the
		LED is on if the channel is high and off otherwise.
		
		By default all channel LEDs are configured as "Channel Status".
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDigitalIn4V2.FUNCTION_SET_CHANNEL_LED_CONFIG, [channel, config], 'B B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getChannelLEDConfig = function(channel, returnCallback, errorCallback) {
		/*
		Returns the channel LED configuration as set by :func:`Set Channel LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDigitalIn4V2.FUNCTION_GET_CHANNEL_LED_CONFIG, [channel], 'B', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPErrorCount = function(returnCallback, errorCallback) {
		/*
		Returns the error count for the communication between Brick and Bricklet.
		
		The errors are divided into
		
		* ACK checksum errors,
		* message checksum errors,
		* framing errors and
		* overflow errors.
		
		The errors counts are for errors that occur on the Bricklet side. All
		Bricks have a similar function that returns the errors on the Brick side.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDigitalIn4V2.FUNCTION_GET_SPITFP_ERROR_COUNT, [], '', 24, 'I I I I', returnCallback, errorCallback, false, true);
	};
	this.setBootloaderMode = function(mode, returnCallback, errorCallback) {
		/*
		Sets the bootloader mode and returns the status after the requested
		mode change was instigated.
		
		You can change from bootloader mode to firmware mode and vice versa. A change
		from bootloader mode to firmware mode will only take place if the entry function,
		device identifier and CRC are present and correct.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDigitalIn4V2.FUNCTION_SET_BOOTLOADER_MODE, [mode], 'B', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getBootloaderMode = function(returnCallback, errorCallback) {
		/*
		Returns the current bootloader mode, see :func:`Set Bootloader Mode`.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDigitalIn4V2.FUNCTION_GET_BOOTLOADER_MODE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setWriteFirmwarePointer = function(pointer, returnCallback, errorCallback) {
		/*
		Sets the firmware pointer for :func:`Write Firmware`. The pointer has
		to be increased by chunks of size 64. The data is written to flash
		every 4 chunks (which equals to one page of size 256).
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDigitalIn4V2.FUNCTION_SET_WRITE_FIRMWARE_POINTER, [pointer], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeFirmware = function(data, returnCallback, errorCallback) {
		/*
		Writes 64 Bytes of firmware at the position as written by
		:func:`Set Write Firmware Pointer` before. The firmware is written
		to flash every 4 chunks.
		
		You can only write firmware in bootloader mode.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDigitalIn4V2.FUNCTION_WRITE_FIRMWARE, [data], 'B64', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setStatusLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Sets the status LED configuration. By default the LED shows
		communication traffic between Brick and Bricklet, it flickers once
		for every 10 received data packets.
		
		You can also turn the LED permanently on/off or show a heartbeat.
		
		If the Bricklet is in bootloader mode, the LED is will show heartbeat by default.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDigitalIn4V2.FUNCTION_SET_STATUS_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getStatusLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Status LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDigitalIn4V2.FUNCTION_GET_STATUS_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getChipTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature as measured inside the microcontroller. The
		value returned is not the ambient temperature!
		
		The temperature is only proportional to the real temperature and it has bad
		accuracy. Practically it is only useful as an indicator for
		temperature changes.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDigitalIn4V2.FUNCTION_GET_CHIP_TEMPERATURE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.reset = function(returnCallback, errorCallback) {
		/*
		Calling this function will reset the Bricklet. All configurations
		will be lost.
		
		After a reset you have to create new device objects,
		calling functions on the existing ones will result in
		undefined behavior!
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDigitalIn4V2.FUNCTION_RESET, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeUID = function(uid, returnCallback, errorCallback) {
		/*
		Writes a new UID into flash. If you want to set a new UID
		you have to decode the Base58 encoded UID string into an
		integer first.
		
		We recommend that you use Brick Viewer to change the UID.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDigitalIn4V2.FUNCTION_WRITE_UID, [uid], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.readUID = function(returnCallback, errorCallback) {
		/*
		Returns the current UID as an integer. Encode as
		Base58 to get the usual string version.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDigitalIn4V2.FUNCTION_READ_UID, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDigitalIn4V2.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletIndustrialDigitalIn4V2;

},{"./Device":279,"./IPConnection":280}],197:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletIndustrialDigitalOut4.DEVICE_IDENTIFIER = 224;
BrickletIndustrialDigitalOut4.DEVICE_DISPLAY_NAME = 'Industrial Digital Out 4 Bricklet';
BrickletIndustrialDigitalOut4.CALLBACK_MONOFLOP_DONE = 8;
BrickletIndustrialDigitalOut4.FUNCTION_SET_VALUE = 1;
BrickletIndustrialDigitalOut4.FUNCTION_GET_VALUE = 2;
BrickletIndustrialDigitalOut4.FUNCTION_SET_MONOFLOP = 3;
BrickletIndustrialDigitalOut4.FUNCTION_GET_MONOFLOP = 4;
BrickletIndustrialDigitalOut4.FUNCTION_SET_GROUP = 5;
BrickletIndustrialDigitalOut4.FUNCTION_GET_GROUP = 6;
BrickletIndustrialDigitalOut4.FUNCTION_GET_AVAILABLE_FOR_GROUP = 7;
BrickletIndustrialDigitalOut4.FUNCTION_SET_SELECTED_VALUES = 9;
BrickletIndustrialDigitalOut4.FUNCTION_GET_IDENTITY = 255;

function BrickletIndustrialDigitalOut4(uid, ipcon) {
	//4 galvanically isolated digital outputs

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletIndustrialDigitalOut4.DEVICE_IDENTIFIER, BrickletIndustrialDigitalOut4.DEVICE_DISPLAY_NAME);
	BrickletIndustrialDigitalOut4.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickletIndustrialDigitalOut4.FUNCTION_SET_VALUE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialDigitalOut4.FUNCTION_GET_VALUE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDigitalOut4.FUNCTION_SET_MONOFLOP] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialDigitalOut4.FUNCTION_GET_MONOFLOP] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDigitalOut4.FUNCTION_SET_GROUP] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialDigitalOut4.FUNCTION_GET_GROUP] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDigitalOut4.FUNCTION_GET_AVAILABLE_FOR_GROUP] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDigitalOut4.FUNCTION_SET_SELECTED_VALUES] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialDigitalOut4.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletIndustrialDigitalOut4.CALLBACK_MONOFLOP_DONE] = [12, 'H H'];



	this.setValue = function(valueMask, returnCallback, errorCallback) {
		/*
		Sets the output value with a bitmask (16bit). A 1 in the bitmask means high
		and a 0 in the bitmask means low.
		
		For example: The value 3 or 0b0011 will turn pins 0-1 high and the other pins
		low.
		
		If no groups are used (see :func:`Set Group`), the pins correspond to the
		markings on the Industrial Digital Out 4 Bricklet.
		
		If groups are used, the pins correspond to the element in the group.
		Element 1 in the group will get pins 0-3, element 2 pins 4-7, element 3
		pins 8-11 and element 4 pins 12-15.
		
		All running monoflop timers will be aborted if this function is called.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDigitalOut4.FUNCTION_SET_VALUE, [valueMask], 'H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getValue = function(returnCallback, errorCallback) {
		/*
		Returns the bitmask as set by :func:`Set Value`.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDigitalOut4.FUNCTION_GET_VALUE, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.setMonoflop = function(selectionMask, valueMask, time, returnCallback, errorCallback) {
		/*
		Configures a monoflop of the pins specified by the first parameter
		bitmask.
		
		The second parameter is a bitmask with the desired value of the specified
		pins. A 1 in the bitmask means high and a 0 in the bitmask means low.
		
		The third parameter indicates the time that the pins should hold
		the value.
		
		If this function is called with the parameters (9, 1, 1500) or
		(0b1001, 0b0001, 1500): Pin 0 will get high and pin 3 will get low. In 1.5s
		pin 0 will get low and pin 3 will get high again.
		
		A monoflop can be used as a fail-safe mechanism. For example: Lets assume you
		have a RS485 bus and a Digital Out 4 Bricklet connected to one of the slave
		stacks. You can now call this function every second, with a time parameter
		of two seconds and pin 0 high. Pin 0 will be high all the time. If now
		the RS485 connection is lost, then pin 0 will turn low in at most two seconds.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDigitalOut4.FUNCTION_SET_MONOFLOP, [selectionMask, valueMask, time], 'H H I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getMonoflop = function(pin, returnCallback, errorCallback) {
		/*
		Returns (for the given pin) the current value and the time as set by
		:func:`Set Monoflop` as well as the remaining time until the value flips.
		
		If the timer is not running currently, the remaining time will be returned
		as 0.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDigitalOut4.FUNCTION_GET_MONOFLOP, [pin], 'B', 18, 'H I I', returnCallback, errorCallback, false, true);
	};
	this.setGroup = function(group, returnCallback, errorCallback) {
		/*
		Sets a group of Digital Out 4 Bricklets that should work together. You can
		find Bricklets that can be grouped together with :func:`Get Available For Group`.
		
		The group consists of 4 elements. Element 1 in the group will get pins 0-3,
		element 2 pins 4-7, element 3 pins 8-11 and element 4 pins 12-15.
		
		Each element can either be one of the ports ('a' to 'd') or 'n' if it should
		not be used.
		
		For example: If you have two Digital Out 4 Bricklets connected to port A and
		port B respectively, you could call with ``['a', 'b', 'n', 'n']``.
		
		Now the pins on the Digital Out 4 on port A are assigned to 0-3 and the
		pins on the Digital Out 4 on port B are assigned to 4-7. It is now possible
		to call :func:`Set Value` and control two Bricklets at the same time.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDigitalOut4.FUNCTION_SET_GROUP, [group], 'c4', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getGroup = function(returnCallback, errorCallback) {
		/*
		Returns the group as set by :func:`Set Group`
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDigitalOut4.FUNCTION_GET_GROUP, [], '', 12, 'c4', returnCallback, errorCallback, false, true);
	};
	this.getAvailableForGroup = function(returnCallback, errorCallback) {
		/*
		Returns a bitmask of ports that are available for grouping. For example the
		value 5 or 0b0101 means: Port A and port C are connected to Bricklets that
		can be grouped together.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDigitalOut4.FUNCTION_GET_AVAILABLE_FOR_GROUP, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setSelectedValues = function(selectionMask, valueMask, returnCallback, errorCallback) {
		/*
		Sets the output value with a bitmask, according to the selection mask.
		The bitmask is 16 bit long, *true* refers to high and *false* refers to
		low.
		
		For example: The values (3, 1) or (0b0011, 0b0001) will turn pin 0 high, pin 1
		low the other pins remain untouched.
		
		If no groups are used (see :func:`Set Group`), the pins correspond to the
		markings on the Industrial Digital Out 4 Bricklet.
		
		If groups are used, the pins correspond to the element in the group.
		Element 1 in the group will get pins 0-3, element 2 pins 4-7, element 3
		pins 8-11 and element 4 pins 12-15.
		
		Running monoflop timers for the selected pins will be aborted if this function
		is called.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDigitalOut4.FUNCTION_SET_SELECTED_VALUES, [selectionMask, valueMask], 'H H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDigitalOut4.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletIndustrialDigitalOut4;

},{"./Device":279,"./IPConnection":280}],198:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletIndustrialDigitalOut4V2.DEVICE_IDENTIFIER = 2124;
BrickletIndustrialDigitalOut4V2.DEVICE_DISPLAY_NAME = 'Industrial Digital Out 4 Bricklet 2.0';
BrickletIndustrialDigitalOut4V2.CALLBACK_MONOFLOP_DONE = 6;
BrickletIndustrialDigitalOut4V2.FUNCTION_SET_VALUE = 1;
BrickletIndustrialDigitalOut4V2.FUNCTION_GET_VALUE = 2;
BrickletIndustrialDigitalOut4V2.FUNCTION_SET_SELECTED_VALUE = 3;
BrickletIndustrialDigitalOut4V2.FUNCTION_SET_MONOFLOP = 4;
BrickletIndustrialDigitalOut4V2.FUNCTION_GET_MONOFLOP = 5;
BrickletIndustrialDigitalOut4V2.FUNCTION_SET_CHANNEL_LED_CONFIG = 7;
BrickletIndustrialDigitalOut4V2.FUNCTION_GET_CHANNEL_LED_CONFIG = 8;
BrickletIndustrialDigitalOut4V2.FUNCTION_SET_PWM_CONFIGURATION = 9;
BrickletIndustrialDigitalOut4V2.FUNCTION_GET_PWM_CONFIGURATION = 10;
BrickletIndustrialDigitalOut4V2.FUNCTION_GET_SPITFP_ERROR_COUNT = 234;
BrickletIndustrialDigitalOut4V2.FUNCTION_SET_BOOTLOADER_MODE = 235;
BrickletIndustrialDigitalOut4V2.FUNCTION_GET_BOOTLOADER_MODE = 236;
BrickletIndustrialDigitalOut4V2.FUNCTION_SET_WRITE_FIRMWARE_POINTER = 237;
BrickletIndustrialDigitalOut4V2.FUNCTION_WRITE_FIRMWARE = 238;
BrickletIndustrialDigitalOut4V2.FUNCTION_SET_STATUS_LED_CONFIG = 239;
BrickletIndustrialDigitalOut4V2.FUNCTION_GET_STATUS_LED_CONFIG = 240;
BrickletIndustrialDigitalOut4V2.FUNCTION_GET_CHIP_TEMPERATURE = 242;
BrickletIndustrialDigitalOut4V2.FUNCTION_RESET = 243;
BrickletIndustrialDigitalOut4V2.FUNCTION_WRITE_UID = 248;
BrickletIndustrialDigitalOut4V2.FUNCTION_READ_UID = 249;
BrickletIndustrialDigitalOut4V2.FUNCTION_GET_IDENTITY = 255;
BrickletIndustrialDigitalOut4V2.CHANNEL_LED_CONFIG_OFF = 0;
BrickletIndustrialDigitalOut4V2.CHANNEL_LED_CONFIG_ON = 1;
BrickletIndustrialDigitalOut4V2.CHANNEL_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletIndustrialDigitalOut4V2.CHANNEL_LED_CONFIG_SHOW_CHANNEL_STATUS = 3;
BrickletIndustrialDigitalOut4V2.BOOTLOADER_MODE_BOOTLOADER = 0;
BrickletIndustrialDigitalOut4V2.BOOTLOADER_MODE_FIRMWARE = 1;
BrickletIndustrialDigitalOut4V2.BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT = 2;
BrickletIndustrialDigitalOut4V2.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT = 3;
BrickletIndustrialDigitalOut4V2.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT = 4;
BrickletIndustrialDigitalOut4V2.BOOTLOADER_STATUS_OK = 0;
BrickletIndustrialDigitalOut4V2.BOOTLOADER_STATUS_INVALID_MODE = 1;
BrickletIndustrialDigitalOut4V2.BOOTLOADER_STATUS_NO_CHANGE = 2;
BrickletIndustrialDigitalOut4V2.BOOTLOADER_STATUS_ENTRY_FUNCTION_NOT_PRESENT = 3;
BrickletIndustrialDigitalOut4V2.BOOTLOADER_STATUS_DEVICE_IDENTIFIER_INCORRECT = 4;
BrickletIndustrialDigitalOut4V2.BOOTLOADER_STATUS_CRC_MISMATCH = 5;
BrickletIndustrialDigitalOut4V2.STATUS_LED_CONFIG_OFF = 0;
BrickletIndustrialDigitalOut4V2.STATUS_LED_CONFIG_ON = 1;
BrickletIndustrialDigitalOut4V2.STATUS_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletIndustrialDigitalOut4V2.STATUS_LED_CONFIG_SHOW_STATUS = 3;

function BrickletIndustrialDigitalOut4V2(uid, ipcon) {
	//4 galvanically isolated digital outputs

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletIndustrialDigitalOut4V2.DEVICE_IDENTIFIER, BrickletIndustrialDigitalOut4V2.DEVICE_DISPLAY_NAME);
	BrickletIndustrialDigitalOut4V2.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickletIndustrialDigitalOut4V2.FUNCTION_SET_VALUE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialDigitalOut4V2.FUNCTION_GET_VALUE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDigitalOut4V2.FUNCTION_SET_SELECTED_VALUE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialDigitalOut4V2.FUNCTION_SET_MONOFLOP] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialDigitalOut4V2.FUNCTION_GET_MONOFLOP] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDigitalOut4V2.FUNCTION_SET_CHANNEL_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialDigitalOut4V2.FUNCTION_GET_CHANNEL_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDigitalOut4V2.FUNCTION_SET_PWM_CONFIGURATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialDigitalOut4V2.FUNCTION_GET_PWM_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDigitalOut4V2.FUNCTION_GET_SPITFP_ERROR_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDigitalOut4V2.FUNCTION_SET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDigitalOut4V2.FUNCTION_GET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDigitalOut4V2.FUNCTION_SET_WRITE_FIRMWARE_POINTER] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialDigitalOut4V2.FUNCTION_WRITE_FIRMWARE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDigitalOut4V2.FUNCTION_SET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialDigitalOut4V2.FUNCTION_GET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDigitalOut4V2.FUNCTION_GET_CHIP_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDigitalOut4V2.FUNCTION_RESET] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialDigitalOut4V2.FUNCTION_WRITE_UID] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialDigitalOut4V2.FUNCTION_READ_UID] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDigitalOut4V2.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletIndustrialDigitalOut4V2.CALLBACK_MONOFLOP_DONE] = [10, 'B ?'];



	this.setValue = function(value, returnCallback, errorCallback) {
		/*
		Sets the output value of all four channels. A value of *true* or *false* outputs
		logic 1 or logic 0 respectively on the corresponding channel.
		
		Use :func:`Set Selected Value` to change only one output channel state.
		
		All running monoflop timers and PWMs will be aborted if this function is called.
		
		For example: (True, True, False, False) will turn the channels 0-1 high and the
		channels 2-3 low.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDigitalOut4V2.FUNCTION_SET_VALUE, [value], '?4', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getValue = function(returnCallback, errorCallback) {
		/*
		Returns the logic levels that are currently output on the channels.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDigitalOut4V2.FUNCTION_GET_VALUE, [], '', 9, '?4', returnCallback, errorCallback, false, true);
	};
	this.setSelectedValue = function(channel, value, returnCallback, errorCallback) {
		/*
		Sets the output value of a specific channel without affecting the other channels.
		
		A running monoflop timer or PWM for the specified channel will be aborted if this
		function is called.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDigitalOut4V2.FUNCTION_SET_SELECTED_VALUE, [channel, value], 'B ?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.setMonoflop = function(channel, value, time, returnCallback, errorCallback) {
		/*
		The first parameter is the desired state of the channel (*true* means output *high*
		and *false* means output *low*). The second parameter indicates the time that
		the channel should hold the state.
		
		If this function is called with the parameters (true, 1500):
		The channel will turn on and in 1.5s it will turn off again.
		
		A PWM for the selected channel will be aborted if this function is called.
		
		A monoflop can be used as a failsafe mechanism. For example: Lets assume you
		have a RS485 bus and a IO-4 Bricklet is connected to one of the slave
		stacks. You can now call this function every second, with a time parameter
		of two seconds. The channel will be *high* all the time. If now the RS485
		connection is lost, the channel will turn *low* in at most two seconds.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDigitalOut4V2.FUNCTION_SET_MONOFLOP, [channel, value, time], 'B ? I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getMonoflop = function(channel, returnCallback, errorCallback) {
		/*
		Returns (for the given channel) the current value and the time as set by
		:func:`Set Monoflop` as well as the remaining time until the value flips.
		
		If the timer is not running currently, the remaining time will be returned
		as 0.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDigitalOut4V2.FUNCTION_GET_MONOFLOP, [channel], 'B', 17, '? I I', returnCallback, errorCallback, false, true);
	};
	this.setChannelLEDConfig = function(channel, config, returnCallback, errorCallback) {
		/*
		Each channel has a corresponding LED. You can turn the LED off, on or show a
		heartbeat. You can also set the LED to "Channel Status". In this mode the
		LED is on if the channel is high and off otherwise.
		
		By default all channel LEDs are configured as "Channel Status".
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDigitalOut4V2.FUNCTION_SET_CHANNEL_LED_CONFIG, [channel, config], 'B B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getChannelLEDConfig = function(channel, returnCallback, errorCallback) {
		/*
		Returns the channel LED configuration as set by :func:`Set Channel LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDigitalOut4V2.FUNCTION_GET_CHANNEL_LED_CONFIG, [channel], 'B', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setPWMConfiguration = function(channel, frequency, dutyCycle, returnCallback, errorCallback) {
		/*
		Activates a PWM for the given channel.
		
		To turn the PWM off again, you can set the frequency to 0 or any other
		function that changes a value of the channel (e.g. :func:`Set Selected Value`).
		
		The optocoupler of the Industrial Digital
		Out 4 Bricklet 2.0 has a rise time and fall time of 11.5us (each) at 24V. So the maximum
		useful frequency value is about 400000 (40kHz).
		
		A running monoflop timer for the given channel will be aborted if this function
		is called.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDigitalOut4V2.FUNCTION_SET_PWM_CONFIGURATION, [channel, frequency, dutyCycle], 'B I H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getPWMConfiguration = function(channel, returnCallback, errorCallback) {
		/*
		Returns the PWM configuration as set by :func:`Set PWM Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDigitalOut4V2.FUNCTION_GET_PWM_CONFIGURATION, [channel], 'B', 14, 'I H', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPErrorCount = function(returnCallback, errorCallback) {
		/*
		Returns the error count for the communication between Brick and Bricklet.
		
		The errors are divided into
		
		* ACK checksum errors,
		* message checksum errors,
		* framing errors and
		* overflow errors.
		
		The errors counts are for errors that occur on the Bricklet side. All
		Bricks have a similar function that returns the errors on the Brick side.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDigitalOut4V2.FUNCTION_GET_SPITFP_ERROR_COUNT, [], '', 24, 'I I I I', returnCallback, errorCallback, false, true);
	};
	this.setBootloaderMode = function(mode, returnCallback, errorCallback) {
		/*
		Sets the bootloader mode and returns the status after the requested
		mode change was instigated.
		
		You can change from bootloader mode to firmware mode and vice versa. A change
		from bootloader mode to firmware mode will only take place if the entry function,
		device identifier and CRC are present and correct.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDigitalOut4V2.FUNCTION_SET_BOOTLOADER_MODE, [mode], 'B', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getBootloaderMode = function(returnCallback, errorCallback) {
		/*
		Returns the current bootloader mode, see :func:`Set Bootloader Mode`.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDigitalOut4V2.FUNCTION_GET_BOOTLOADER_MODE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setWriteFirmwarePointer = function(pointer, returnCallback, errorCallback) {
		/*
		Sets the firmware pointer for :func:`Write Firmware`. The pointer has
		to be increased by chunks of size 64. The data is written to flash
		every 4 chunks (which equals to one page of size 256).
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDigitalOut4V2.FUNCTION_SET_WRITE_FIRMWARE_POINTER, [pointer], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeFirmware = function(data, returnCallback, errorCallback) {
		/*
		Writes 64 Bytes of firmware at the position as written by
		:func:`Set Write Firmware Pointer` before. The firmware is written
		to flash every 4 chunks.
		
		You can only write firmware in bootloader mode.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDigitalOut4V2.FUNCTION_WRITE_FIRMWARE, [data], 'B64', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setStatusLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Sets the status LED configuration. By default the LED shows
		communication traffic between Brick and Bricklet, it flickers once
		for every 10 received data packets.
		
		You can also turn the LED permanently on/off or show a heartbeat.
		
		If the Bricklet is in bootloader mode, the LED is will show heartbeat by default.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDigitalOut4V2.FUNCTION_SET_STATUS_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getStatusLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Status LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDigitalOut4V2.FUNCTION_GET_STATUS_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getChipTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature as measured inside the microcontroller. The
		value returned is not the ambient temperature!
		
		The temperature is only proportional to the real temperature and it has bad
		accuracy. Practically it is only useful as an indicator for
		temperature changes.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDigitalOut4V2.FUNCTION_GET_CHIP_TEMPERATURE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.reset = function(returnCallback, errorCallback) {
		/*
		Calling this function will reset the Bricklet. All configurations
		will be lost.
		
		After a reset you have to create new device objects,
		calling functions on the existing ones will result in
		undefined behavior!
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDigitalOut4V2.FUNCTION_RESET, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeUID = function(uid, returnCallback, errorCallback) {
		/*
		Writes a new UID into flash. If you want to set a new UID
		you have to decode the Base58 encoded UID string into an
		integer first.
		
		We recommend that you use Brick Viewer to change the UID.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDigitalOut4V2.FUNCTION_WRITE_UID, [uid], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.readUID = function(returnCallback, errorCallback) {
		/*
		Returns the current UID as an integer. Encode as
		Base58 to get the usual string version.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDigitalOut4V2.FUNCTION_READ_UID, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDigitalOut4V2.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletIndustrialDigitalOut4V2;

},{"./Device":279,"./IPConnection":280}],199:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletIndustrialDual020mA.DEVICE_IDENTIFIER = 228;
BrickletIndustrialDual020mA.DEVICE_DISPLAY_NAME = 'Industrial Dual 0-20mA Bricklet';
BrickletIndustrialDual020mA.CALLBACK_CURRENT = 10;
BrickletIndustrialDual020mA.CALLBACK_CURRENT_REACHED = 11;
BrickletIndustrialDual020mA.FUNCTION_GET_CURRENT = 1;
BrickletIndustrialDual020mA.FUNCTION_SET_CURRENT_CALLBACK_PERIOD = 2;
BrickletIndustrialDual020mA.FUNCTION_GET_CURRENT_CALLBACK_PERIOD = 3;
BrickletIndustrialDual020mA.FUNCTION_SET_CURRENT_CALLBACK_THRESHOLD = 4;
BrickletIndustrialDual020mA.FUNCTION_GET_CURRENT_CALLBACK_THRESHOLD = 5;
BrickletIndustrialDual020mA.FUNCTION_SET_DEBOUNCE_PERIOD = 6;
BrickletIndustrialDual020mA.FUNCTION_GET_DEBOUNCE_PERIOD = 7;
BrickletIndustrialDual020mA.FUNCTION_SET_SAMPLE_RATE = 8;
BrickletIndustrialDual020mA.FUNCTION_GET_SAMPLE_RATE = 9;
BrickletIndustrialDual020mA.FUNCTION_GET_IDENTITY = 255;
BrickletIndustrialDual020mA.THRESHOLD_OPTION_OFF = 'x';
BrickletIndustrialDual020mA.THRESHOLD_OPTION_OUTSIDE = 'o';
BrickletIndustrialDual020mA.THRESHOLD_OPTION_INSIDE = 'i';
BrickletIndustrialDual020mA.THRESHOLD_OPTION_SMALLER = '<';
BrickletIndustrialDual020mA.THRESHOLD_OPTION_GREATER = '>';
BrickletIndustrialDual020mA.SAMPLE_RATE_240_SPS = 0;
BrickletIndustrialDual020mA.SAMPLE_RATE_60_SPS = 1;
BrickletIndustrialDual020mA.SAMPLE_RATE_15_SPS = 2;
BrickletIndustrialDual020mA.SAMPLE_RATE_4_SPS = 3;

function BrickletIndustrialDual020mA(uid, ipcon) {
	//Measures two DC currents between 0mA and 20mA (IEC 60381-1)

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletIndustrialDual020mA.DEVICE_IDENTIFIER, BrickletIndustrialDual020mA.DEVICE_DISPLAY_NAME);
	BrickletIndustrialDual020mA.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickletIndustrialDual020mA.FUNCTION_GET_CURRENT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDual020mA.FUNCTION_SET_CURRENT_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletIndustrialDual020mA.FUNCTION_GET_CURRENT_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDual020mA.FUNCTION_SET_CURRENT_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletIndustrialDual020mA.FUNCTION_GET_CURRENT_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDual020mA.FUNCTION_SET_DEBOUNCE_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletIndustrialDual020mA.FUNCTION_GET_DEBOUNCE_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDual020mA.FUNCTION_SET_SAMPLE_RATE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialDual020mA.FUNCTION_GET_SAMPLE_RATE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDual020mA.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletIndustrialDual020mA.CALLBACK_CURRENT] = [13, 'B i'];
	this.callbackFormats[BrickletIndustrialDual020mA.CALLBACK_CURRENT_REACHED] = [13, 'B i'];



	this.getCurrent = function(sensor, returnCallback, errorCallback) {
		/*
		Returns the current of the specified sensor.
		
		It is possible to detect if an IEC 60381-1 compatible sensor is connected
		and if it works properly.
		
		If the returned current is below 4mA, there is likely no sensor connected
		or the sensor may be defect. If the returned current is over 20mA, there might
		be a short circuit or the sensor may be defect.
		
		If you want to get the current periodically, it is recommended to use the
		:cb:`Current` callback and set the period with
		:func:`Set Current Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDual020mA.FUNCTION_GET_CURRENT, [sensor], 'B', 12, 'i', returnCallback, errorCallback, false, true);
	};
	this.setCurrentCallbackPeriod = function(sensor, period, returnCallback, errorCallback) {
		/*
		Sets the period with which the :cb:`Current` callback is triggered
		periodically for the given sensor. A value of 0 turns the callback off.
		
		The :cb:`Current` callback is only triggered if the current has changed since the
		last triggering.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDual020mA.FUNCTION_SET_CURRENT_CALLBACK_PERIOD, [sensor, period], 'B I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getCurrentCallbackPeriod = function(sensor, returnCallback, errorCallback) {
		/*
		Returns the period as set by :func:`Set Current Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDual020mA.FUNCTION_GET_CURRENT_CALLBACK_PERIOD, [sensor], 'B', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setCurrentCallbackThreshold = function(sensor, option, min, max, returnCallback, errorCallback) {
		/*
		Sets the thresholds for the :cb:`Current Reached` callback for the given
		sensor.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Callback is turned off"
		 "'o'",    "Callback is triggered when the current is *outside* the min and max values"
		 "'i'",    "Callback is triggered when the current is *inside* the min and max values"
		 "'<'",    "Callback is triggered when the current is smaller than the min value (max is ignored)"
		 "'>'",    "Callback is triggered when the current is greater than the min value (max is ignored)"
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDual020mA.FUNCTION_SET_CURRENT_CALLBACK_THRESHOLD, [sensor, option, min, max], 'B c i i', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getCurrentCallbackThreshold = function(sensor, returnCallback, errorCallback) {
		/*
		Returns the threshold as set by :func:`Set Current Callback Threshold`.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDual020mA.FUNCTION_GET_CURRENT_CALLBACK_THRESHOLD, [sensor], 'B', 17, 'c i i', returnCallback, errorCallback, false, true);
	};
	this.setDebouncePeriod = function(debounce, returnCallback, errorCallback) {
		/*
		Sets the period with which the threshold callback
		
		* :cb:`Current Reached`
		
		is triggered, if the threshold
		
		* :func:`Set Current Callback Threshold`
		
		keeps being reached.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDual020mA.FUNCTION_SET_DEBOUNCE_PERIOD, [debounce], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getDebouncePeriod = function(returnCallback, errorCallback) {
		/*
		Returns the debounce period as set by :func:`Set Debounce Period`.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDual020mA.FUNCTION_GET_DEBOUNCE_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setSampleRate = function(rate, returnCallback, errorCallback) {
		/*
		Sets the sample rate to either 240, 60, 15 or 4 samples per second.
		The resolution for the rates is 12, 14, 16 and 18 bit respectively.
		
		.. csv-table::
		 :header: "Value", "Description"
		 :widths: 10, 100
		
		 "0",    "240 samples per second, 12 bit resolution"
		 "1",    "60 samples per second, 14 bit resolution"
		 "2",    "15 samples per second, 16 bit resolution"
		 "3",    "4 samples per second, 18 bit resolution"
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDual020mA.FUNCTION_SET_SAMPLE_RATE, [rate], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getSampleRate = function(returnCallback, errorCallback) {
		/*
		Returns the sample rate as set by :func:`Set Sample Rate`.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDual020mA.FUNCTION_GET_SAMPLE_RATE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDual020mA.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletIndustrialDual020mA;

},{"./Device":279,"./IPConnection":280}],200:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletIndustrialDual020mAV2.DEVICE_IDENTIFIER = 2120;
BrickletIndustrialDual020mAV2.DEVICE_DISPLAY_NAME = 'Industrial Dual 0-20mA Bricklet 2.0';
BrickletIndustrialDual020mAV2.CALLBACK_CURRENT = 4;
BrickletIndustrialDual020mAV2.FUNCTION_GET_CURRENT = 1;
BrickletIndustrialDual020mAV2.FUNCTION_SET_CURRENT_CALLBACK_CONFIGURATION = 2;
BrickletIndustrialDual020mAV2.FUNCTION_GET_CURRENT_CALLBACK_CONFIGURATION = 3;
BrickletIndustrialDual020mAV2.FUNCTION_SET_SAMPLE_RATE = 5;
BrickletIndustrialDual020mAV2.FUNCTION_GET_SAMPLE_RATE = 6;
BrickletIndustrialDual020mAV2.FUNCTION_SET_GAIN = 7;
BrickletIndustrialDual020mAV2.FUNCTION_GET_GAIN = 8;
BrickletIndustrialDual020mAV2.FUNCTION_SET_CHANNEL_LED_CONFIG = 9;
BrickletIndustrialDual020mAV2.FUNCTION_GET_CHANNEL_LED_CONFIG = 10;
BrickletIndustrialDual020mAV2.FUNCTION_SET_CHANNEL_LED_STATUS_CONFIG = 11;
BrickletIndustrialDual020mAV2.FUNCTION_GET_CHANNEL_LED_STATUS_CONFIG = 12;
BrickletIndustrialDual020mAV2.FUNCTION_GET_SPITFP_ERROR_COUNT = 234;
BrickletIndustrialDual020mAV2.FUNCTION_SET_BOOTLOADER_MODE = 235;
BrickletIndustrialDual020mAV2.FUNCTION_GET_BOOTLOADER_MODE = 236;
BrickletIndustrialDual020mAV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER = 237;
BrickletIndustrialDual020mAV2.FUNCTION_WRITE_FIRMWARE = 238;
BrickletIndustrialDual020mAV2.FUNCTION_SET_STATUS_LED_CONFIG = 239;
BrickletIndustrialDual020mAV2.FUNCTION_GET_STATUS_LED_CONFIG = 240;
BrickletIndustrialDual020mAV2.FUNCTION_GET_CHIP_TEMPERATURE = 242;
BrickletIndustrialDual020mAV2.FUNCTION_RESET = 243;
BrickletIndustrialDual020mAV2.FUNCTION_WRITE_UID = 248;
BrickletIndustrialDual020mAV2.FUNCTION_READ_UID = 249;
BrickletIndustrialDual020mAV2.FUNCTION_GET_IDENTITY = 255;
BrickletIndustrialDual020mAV2.THRESHOLD_OPTION_OFF = 'x';
BrickletIndustrialDual020mAV2.THRESHOLD_OPTION_OUTSIDE = 'o';
BrickletIndustrialDual020mAV2.THRESHOLD_OPTION_INSIDE = 'i';
BrickletIndustrialDual020mAV2.THRESHOLD_OPTION_SMALLER = '<';
BrickletIndustrialDual020mAV2.THRESHOLD_OPTION_GREATER = '>';
BrickletIndustrialDual020mAV2.SAMPLE_RATE_240_SPS = 0;
BrickletIndustrialDual020mAV2.SAMPLE_RATE_60_SPS = 1;
BrickletIndustrialDual020mAV2.SAMPLE_RATE_15_SPS = 2;
BrickletIndustrialDual020mAV2.SAMPLE_RATE_4_SPS = 3;
BrickletIndustrialDual020mAV2.GAIN_1X = 0;
BrickletIndustrialDual020mAV2.GAIN_2X = 1;
BrickletIndustrialDual020mAV2.GAIN_4X = 2;
BrickletIndustrialDual020mAV2.GAIN_8X = 3;
BrickletIndustrialDual020mAV2.CHANNEL_LED_CONFIG_OFF = 0;
BrickletIndustrialDual020mAV2.CHANNEL_LED_CONFIG_ON = 1;
BrickletIndustrialDual020mAV2.CHANNEL_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletIndustrialDual020mAV2.CHANNEL_LED_CONFIG_SHOW_CHANNEL_STATUS = 3;
BrickletIndustrialDual020mAV2.CHANNEL_LED_STATUS_CONFIG_THRESHOLD = 0;
BrickletIndustrialDual020mAV2.CHANNEL_LED_STATUS_CONFIG_INTENSITY = 1;
BrickletIndustrialDual020mAV2.BOOTLOADER_MODE_BOOTLOADER = 0;
BrickletIndustrialDual020mAV2.BOOTLOADER_MODE_FIRMWARE = 1;
BrickletIndustrialDual020mAV2.BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT = 2;
BrickletIndustrialDual020mAV2.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT = 3;
BrickletIndustrialDual020mAV2.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT = 4;
BrickletIndustrialDual020mAV2.BOOTLOADER_STATUS_OK = 0;
BrickletIndustrialDual020mAV2.BOOTLOADER_STATUS_INVALID_MODE = 1;
BrickletIndustrialDual020mAV2.BOOTLOADER_STATUS_NO_CHANGE = 2;
BrickletIndustrialDual020mAV2.BOOTLOADER_STATUS_ENTRY_FUNCTION_NOT_PRESENT = 3;
BrickletIndustrialDual020mAV2.BOOTLOADER_STATUS_DEVICE_IDENTIFIER_INCORRECT = 4;
BrickletIndustrialDual020mAV2.BOOTLOADER_STATUS_CRC_MISMATCH = 5;
BrickletIndustrialDual020mAV2.STATUS_LED_CONFIG_OFF = 0;
BrickletIndustrialDual020mAV2.STATUS_LED_CONFIG_ON = 1;
BrickletIndustrialDual020mAV2.STATUS_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletIndustrialDual020mAV2.STATUS_LED_CONFIG_SHOW_STATUS = 3;

function BrickletIndustrialDual020mAV2(uid, ipcon) {
	//Measures two DC currents between 0mA and 20mA (IEC 60381-1)

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletIndustrialDual020mAV2.DEVICE_IDENTIFIER, BrickletIndustrialDual020mAV2.DEVICE_DISPLAY_NAME);
	BrickletIndustrialDual020mAV2.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickletIndustrialDual020mAV2.FUNCTION_GET_CURRENT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDual020mAV2.FUNCTION_SET_CURRENT_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletIndustrialDual020mAV2.FUNCTION_GET_CURRENT_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDual020mAV2.FUNCTION_SET_SAMPLE_RATE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialDual020mAV2.FUNCTION_GET_SAMPLE_RATE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDual020mAV2.FUNCTION_SET_GAIN] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialDual020mAV2.FUNCTION_GET_GAIN] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDual020mAV2.FUNCTION_SET_CHANNEL_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialDual020mAV2.FUNCTION_GET_CHANNEL_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDual020mAV2.FUNCTION_SET_CHANNEL_LED_STATUS_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialDual020mAV2.FUNCTION_GET_CHANNEL_LED_STATUS_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDual020mAV2.FUNCTION_GET_SPITFP_ERROR_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDual020mAV2.FUNCTION_SET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDual020mAV2.FUNCTION_GET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDual020mAV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialDual020mAV2.FUNCTION_WRITE_FIRMWARE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDual020mAV2.FUNCTION_SET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialDual020mAV2.FUNCTION_GET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDual020mAV2.FUNCTION_GET_CHIP_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDual020mAV2.FUNCTION_RESET] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialDual020mAV2.FUNCTION_WRITE_UID] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialDual020mAV2.FUNCTION_READ_UID] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDual020mAV2.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletIndustrialDual020mAV2.CALLBACK_CURRENT] = [13, 'B i'];



	this.getCurrent = function(channel, returnCallback, errorCallback) {
		/*
		Returns the current of the specified channel.
		
		It is possible to detect if an IEC 60381-1 compatible sensor is connected
		and if it works probably.
		
		If the returned current is below 4mA, there is likely no sensor connected
		or the connected sensor is defective. If the returned current is over 20mA,
		there might be a short circuit or the sensor is defective.
		
		
		If you want to get the value periodically, it is recommended to use the
		:cb:`Current` callback. You can set the callback configuration
		with :func:`Set Current Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDual020mAV2.FUNCTION_GET_CURRENT, [channel], 'B', 12, 'i', returnCallback, errorCallback, false, true);
	};
	this.setCurrentCallbackConfiguration = function(channel, period, valueHasToChange, option, min, max, returnCallback, errorCallback) {
		/*
		The period is the period with which the :cb:`Current` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		If the `value has to change`-parameter is set to true, the callback is only
		triggered after the value has changed. If the value didn't change
		within the period, the callback is triggered immediately on change.
		
		If it is set to false, the callback is continuously triggered with the period,
		independent of the value.
		
		It is furthermore possible to constrain the callback with thresholds.
		
		The `option`-parameter together with min/max sets a threshold for the :cb:`Current` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Threshold is turned off"
		 "'o'",    "Threshold is triggered when the value is *outside* the min and max values"
		 "'i'",    "Threshold is triggered when the value is *inside* or equal to the min and max values"
		 "'<'",    "Threshold is triggered when the value is smaller than the min value (max is ignored)"
		 "'>'",    "Threshold is triggered when the value is greater than the min value (max is ignored)"
		
		If the option is set to 'x' (threshold turned off) the callback is triggered with the fixed period.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDual020mAV2.FUNCTION_SET_CURRENT_CALLBACK_CONFIGURATION, [channel, period, valueHasToChange, option, min, max], 'B I ? c i i', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getCurrentCallbackConfiguration = function(channel, returnCallback, errorCallback) {
		/*
		Returns the callback configuration as set by :func:`Set Current Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDual020mAV2.FUNCTION_GET_CURRENT_CALLBACK_CONFIGURATION, [channel], 'B', 22, 'I ? c i i', returnCallback, errorCallback, false, true);
	};
	this.setSampleRate = function(rate, returnCallback, errorCallback) {
		/*
		Sets the sample rate to either 240, 60, 15 or 4 samples per second.
		The resolution for the rates is 12, 14, 16 and 18 bit respectively.
		
		.. csv-table::
		 :header: "Value", "Description"
		 :widths: 10, 100
		
		 "0",    "240 samples per second, 12 bit resolution"
		 "1",    "60 samples per second, 14 bit resolution"
		 "2",    "15 samples per second, 16 bit resolution"
		 "3",    "4 samples per second, 18 bit resolution"
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDual020mAV2.FUNCTION_SET_SAMPLE_RATE, [rate], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getSampleRate = function(returnCallback, errorCallback) {
		/*
		Returns the sample rate as set by :func:`Set Sample Rate`.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDual020mAV2.FUNCTION_GET_SAMPLE_RATE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setGain = function(gain, returnCallback, errorCallback) {
		/*
		Sets a gain between 1x and 8x. If you want to measure a very small current,
		you can increase the gain to get some more resolution.
		
		Example: If you measure 0.5mA with a gain of 8x the return value will be
		4mA.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDual020mAV2.FUNCTION_SET_GAIN, [gain], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getGain = function(returnCallback, errorCallback) {
		/*
		Returns the gain as set by :func:`Set Gain`.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDual020mAV2.FUNCTION_GET_GAIN, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setChannelLEDConfig = function(channel, config, returnCallback, errorCallback) {
		/*
		Each channel has a corresponding LED. You can turn the LED off, on or show a
		heartbeat. You can also set the LED to "Channel Status". In this mode the
		LED can either be turned on with a pre-defined threshold or the intensity
		of the LED can change with the measured value.
		
		You can configure the channel status behavior with :func:`Set Channel LED Status Config`.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDual020mAV2.FUNCTION_SET_CHANNEL_LED_CONFIG, [channel, config], 'B B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getChannelLEDConfig = function(channel, returnCallback, errorCallback) {
		/*
		Returns the channel LED configuration as set by :func:`Set Channel LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDual020mAV2.FUNCTION_GET_CHANNEL_LED_CONFIG, [channel], 'B', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setChannelLEDStatusConfig = function(channel, min, max, config, returnCallback, errorCallback) {
		/*
		Sets the channel LED status config. This config is used if the channel LED is
		configured as "Channel Status", see :func:`Set Channel LED Config`.
		
		For each channel you can choose between threshold and intensity mode.
		
		In threshold mode you can define a positive or a negative threshold.
		For a positive threshold set the "min" parameter to the threshold value in nA
		above which the LED should turn on and set the "max" parameter to 0. Example:
		If you set a positive threshold of 10mA, the LED will turn on as soon as the
		current exceeds 10mA and turn off again if it goes below 10mA.
		For a negative threshold set the "max" parameter to the threshold value in nA
		below which the LED should turn on and set the "min" parameter to 0. Example:
		If you set a negative threshold of 10mA, the LED will turn on as soon as the
		current goes below 10mA and the LED will turn off when the current exceeds 10mA.
		
		In intensity mode you can define a range in nA that is used to scale the brightness
		of the LED. Example with min=4mA and max=20mA: The LED is off at 4mA and below,
		on at 20mA and above and the brightness is linearly scaled between the values
		4mA and 20mA. If the min value is greater than the max value, the LED brightness
		is scaled the other way around.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDual020mAV2.FUNCTION_SET_CHANNEL_LED_STATUS_CONFIG, [channel, min, max, config], 'B i i B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getChannelLEDStatusConfig = function(channel, returnCallback, errorCallback) {
		/*
		Returns the channel LED status configuration as set by
		:func:`Set Channel LED Status Config`.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDual020mAV2.FUNCTION_GET_CHANNEL_LED_STATUS_CONFIG, [channel], 'B', 17, 'i i B', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPErrorCount = function(returnCallback, errorCallback) {
		/*
		Returns the error count for the communication between Brick and Bricklet.
		
		The errors are divided into
		
		* ACK checksum errors,
		* message checksum errors,
		* framing errors and
		* overflow errors.
		
		The errors counts are for errors that occur on the Bricklet side. All
		Bricks have a similar function that returns the errors on the Brick side.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDual020mAV2.FUNCTION_GET_SPITFP_ERROR_COUNT, [], '', 24, 'I I I I', returnCallback, errorCallback, false, true);
	};
	this.setBootloaderMode = function(mode, returnCallback, errorCallback) {
		/*
		Sets the bootloader mode and returns the status after the requested
		mode change was instigated.
		
		You can change from bootloader mode to firmware mode and vice versa. A change
		from bootloader mode to firmware mode will only take place if the entry function,
		device identifier and CRC are present and correct.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDual020mAV2.FUNCTION_SET_BOOTLOADER_MODE, [mode], 'B', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getBootloaderMode = function(returnCallback, errorCallback) {
		/*
		Returns the current bootloader mode, see :func:`Set Bootloader Mode`.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDual020mAV2.FUNCTION_GET_BOOTLOADER_MODE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setWriteFirmwarePointer = function(pointer, returnCallback, errorCallback) {
		/*
		Sets the firmware pointer for :func:`Write Firmware`. The pointer has
		to be increased by chunks of size 64. The data is written to flash
		every 4 chunks (which equals to one page of size 256).
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDual020mAV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER, [pointer], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeFirmware = function(data, returnCallback, errorCallback) {
		/*
		Writes 64 Bytes of firmware at the position as written by
		:func:`Set Write Firmware Pointer` before. The firmware is written
		to flash every 4 chunks.
		
		You can only write firmware in bootloader mode.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDual020mAV2.FUNCTION_WRITE_FIRMWARE, [data], 'B64', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setStatusLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Sets the status LED configuration. By default the LED shows
		communication traffic between Brick and Bricklet, it flickers once
		for every 10 received data packets.
		
		You can also turn the LED permanently on/off or show a heartbeat.
		
		If the Bricklet is in bootloader mode, the LED is will show heartbeat by default.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDual020mAV2.FUNCTION_SET_STATUS_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getStatusLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Status LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDual020mAV2.FUNCTION_GET_STATUS_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getChipTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature as measured inside the microcontroller. The
		value returned is not the ambient temperature!
		
		The temperature is only proportional to the real temperature and it has bad
		accuracy. Practically it is only useful as an indicator for
		temperature changes.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDual020mAV2.FUNCTION_GET_CHIP_TEMPERATURE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.reset = function(returnCallback, errorCallback) {
		/*
		Calling this function will reset the Bricklet. All configurations
		will be lost.
		
		After a reset you have to create new device objects,
		calling functions on the existing ones will result in
		undefined behavior!
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDual020mAV2.FUNCTION_RESET, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeUID = function(uid, returnCallback, errorCallback) {
		/*
		Writes a new UID into flash. If you want to set a new UID
		you have to decode the Base58 encoded UID string into an
		integer first.
		
		We recommend that you use Brick Viewer to change the UID.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDual020mAV2.FUNCTION_WRITE_UID, [uid], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.readUID = function(returnCallback, errorCallback) {
		/*
		Returns the current UID as an integer. Encode as
		Base58 to get the usual string version.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDual020mAV2.FUNCTION_READ_UID, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDual020mAV2.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletIndustrialDual020mAV2;

},{"./Device":279,"./IPConnection":280}],201:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletIndustrialDualACRelay.DEVICE_IDENTIFIER = 2162;
BrickletIndustrialDualACRelay.DEVICE_DISPLAY_NAME = 'Industrial Dual AC Relay Bricklet';
BrickletIndustrialDualACRelay.CALLBACK_MONOFLOP_DONE = 7;
BrickletIndustrialDualACRelay.FUNCTION_SET_VALUE = 1;
BrickletIndustrialDualACRelay.FUNCTION_GET_VALUE = 2;
BrickletIndustrialDualACRelay.FUNCTION_SET_CHANNEL_LED_CONFIG = 3;
BrickletIndustrialDualACRelay.FUNCTION_GET_CHANNEL_LED_CONFIG = 4;
BrickletIndustrialDualACRelay.FUNCTION_SET_MONOFLOP = 5;
BrickletIndustrialDualACRelay.FUNCTION_GET_MONOFLOP = 6;
BrickletIndustrialDualACRelay.FUNCTION_SET_SELECTED_VALUE = 8;
BrickletIndustrialDualACRelay.FUNCTION_GET_SPITFP_ERROR_COUNT = 234;
BrickletIndustrialDualACRelay.FUNCTION_SET_BOOTLOADER_MODE = 235;
BrickletIndustrialDualACRelay.FUNCTION_GET_BOOTLOADER_MODE = 236;
BrickletIndustrialDualACRelay.FUNCTION_SET_WRITE_FIRMWARE_POINTER = 237;
BrickletIndustrialDualACRelay.FUNCTION_WRITE_FIRMWARE = 238;
BrickletIndustrialDualACRelay.FUNCTION_SET_STATUS_LED_CONFIG = 239;
BrickletIndustrialDualACRelay.FUNCTION_GET_STATUS_LED_CONFIG = 240;
BrickletIndustrialDualACRelay.FUNCTION_GET_CHIP_TEMPERATURE = 242;
BrickletIndustrialDualACRelay.FUNCTION_RESET = 243;
BrickletIndustrialDualACRelay.FUNCTION_WRITE_UID = 248;
BrickletIndustrialDualACRelay.FUNCTION_READ_UID = 249;
BrickletIndustrialDualACRelay.FUNCTION_GET_IDENTITY = 255;
BrickletIndustrialDualACRelay.CHANNEL_LED_CONFIG_OFF = 0;
BrickletIndustrialDualACRelay.CHANNEL_LED_CONFIG_ON = 1;
BrickletIndustrialDualACRelay.CHANNEL_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletIndustrialDualACRelay.CHANNEL_LED_CONFIG_SHOW_CHANNEL_STATUS = 3;
BrickletIndustrialDualACRelay.BOOTLOADER_MODE_BOOTLOADER = 0;
BrickletIndustrialDualACRelay.BOOTLOADER_MODE_FIRMWARE = 1;
BrickletIndustrialDualACRelay.BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT = 2;
BrickletIndustrialDualACRelay.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT = 3;
BrickletIndustrialDualACRelay.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT = 4;
BrickletIndustrialDualACRelay.BOOTLOADER_STATUS_OK = 0;
BrickletIndustrialDualACRelay.BOOTLOADER_STATUS_INVALID_MODE = 1;
BrickletIndustrialDualACRelay.BOOTLOADER_STATUS_NO_CHANGE = 2;
BrickletIndustrialDualACRelay.BOOTLOADER_STATUS_ENTRY_FUNCTION_NOT_PRESENT = 3;
BrickletIndustrialDualACRelay.BOOTLOADER_STATUS_DEVICE_IDENTIFIER_INCORRECT = 4;
BrickletIndustrialDualACRelay.BOOTLOADER_STATUS_CRC_MISMATCH = 5;
BrickletIndustrialDualACRelay.STATUS_LED_CONFIG_OFF = 0;
BrickletIndustrialDualACRelay.STATUS_LED_CONFIG_ON = 1;
BrickletIndustrialDualACRelay.STATUS_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletIndustrialDualACRelay.STATUS_LED_CONFIG_SHOW_STATUS = 3;

function BrickletIndustrialDualACRelay(uid, ipcon) {
	//Two relays to switch AC devices

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletIndustrialDualACRelay.DEVICE_IDENTIFIER, BrickletIndustrialDualACRelay.DEVICE_DISPLAY_NAME);
	BrickletIndustrialDualACRelay.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickletIndustrialDualACRelay.FUNCTION_SET_VALUE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialDualACRelay.FUNCTION_GET_VALUE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDualACRelay.FUNCTION_SET_CHANNEL_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialDualACRelay.FUNCTION_GET_CHANNEL_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDualACRelay.FUNCTION_SET_MONOFLOP] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialDualACRelay.FUNCTION_GET_MONOFLOP] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDualACRelay.FUNCTION_SET_SELECTED_VALUE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialDualACRelay.FUNCTION_GET_SPITFP_ERROR_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDualACRelay.FUNCTION_SET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDualACRelay.FUNCTION_GET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDualACRelay.FUNCTION_SET_WRITE_FIRMWARE_POINTER] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialDualACRelay.FUNCTION_WRITE_FIRMWARE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDualACRelay.FUNCTION_SET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialDualACRelay.FUNCTION_GET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDualACRelay.FUNCTION_GET_CHIP_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDualACRelay.FUNCTION_RESET] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialDualACRelay.FUNCTION_WRITE_UID] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialDualACRelay.FUNCTION_READ_UID] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDualACRelay.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletIndustrialDualACRelay.CALLBACK_MONOFLOP_DONE] = [10, 'B ?'];



	this.setValue = function(channel0, channel1, returnCallback, errorCallback) {
		/*
		Sets the state of the relays, *true* means on and *false* means off.
		For example: (true, false) turns relay 0 on and relay 1 off.
		
		If you just want to set one of the relays and don't know the current state
		of the other relay, you can get the state with :func:`Get Value` or you
		can use :func:`Set Selected Value`.
		
		All running monoflop timers will be aborted if this function is called.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDualACRelay.FUNCTION_SET_VALUE, [channel0, channel1], '? ?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getValue = function(returnCallback, errorCallback) {
		/*
		Returns the state of the relays, *true* means on and *false* means off.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDualACRelay.FUNCTION_GET_VALUE, [], '', 10, '? ?', returnCallback, errorCallback, false, true);
	};
	this.setChannelLEDConfig = function(channel, config, returnCallback, errorCallback) {
		/*
		Each channel has a corresponding LED. You can turn the LED off, on or show a
		heartbeat. You can also set the LED to "Channel Status". In this mode the
		LED is on if the channel is high and off otherwise.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDualACRelay.FUNCTION_SET_CHANNEL_LED_CONFIG, [channel, config], 'B B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getChannelLEDConfig = function(channel, returnCallback, errorCallback) {
		/*
		Returns the channel LED configuration as set by :func:`Set Channel LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDualACRelay.FUNCTION_GET_CHANNEL_LED_CONFIG, [channel], 'B', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setMonoflop = function(channel, value, time, returnCallback, errorCallback) {
		/*
		The first parameter can be 0 or 1 (relay 0 or relay 1). The second parameter
		is the desired state of the relay (*true* means on and *false* means off).
		The third parameter indicates the time that the relay should hold
		the state.
		
		If this function is called with the parameters (1, true, 1500):
		Relay 1 will turn on and in 1.5s it will turn off again.
		
		A monoflop can be used as a failsafe mechanism. For example: Lets assume you
		have a RS485 bus and a Industrial Dual AC Relay Bricklet connected to one of the
		slave stacks. You can now call this function every second, with a time parameter
		of two seconds. The relay will be on all the time. If now the RS485
		connection is lost, the relay will turn off in at most two seconds.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDualACRelay.FUNCTION_SET_MONOFLOP, [channel, value, time], 'B ? I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getMonoflop = function(channel, returnCallback, errorCallback) {
		/*
		Returns (for the given relay) the current state and the time as set by
		:func:`Set Monoflop` as well as the remaining time until the state flips.
		
		If the timer is not running currently, the remaining time will be returned
		as 0.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDualACRelay.FUNCTION_GET_MONOFLOP, [channel], 'B', 17, '? I I', returnCallback, errorCallback, false, true);
	};
	this.setSelectedValue = function(channel, value, returnCallback, errorCallback) {
		/*
		Sets the state of the selected relay, *true* means on and *false*
		means off.
		
		A running monoflop timer for the selected relay will be aborted if this function
		is called.
		
		The other relay remains untouched.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDualACRelay.FUNCTION_SET_SELECTED_VALUE, [channel, value], 'B ?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPErrorCount = function(returnCallback, errorCallback) {
		/*
		Returns the error count for the communication between Brick and Bricklet.
		
		The errors are divided into
		
		* ACK checksum errors,
		* message checksum errors,
		* framing errors and
		* overflow errors.
		
		The errors counts are for errors that occur on the Bricklet side. All
		Bricks have a similar function that returns the errors on the Brick side.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDualACRelay.FUNCTION_GET_SPITFP_ERROR_COUNT, [], '', 24, 'I I I I', returnCallback, errorCallback, false, true);
	};
	this.setBootloaderMode = function(mode, returnCallback, errorCallback) {
		/*
		Sets the bootloader mode and returns the status after the requested
		mode change was instigated.
		
		You can change from bootloader mode to firmware mode and vice versa. A change
		from bootloader mode to firmware mode will only take place if the entry function,
		device identifier and CRC are present and correct.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDualACRelay.FUNCTION_SET_BOOTLOADER_MODE, [mode], 'B', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getBootloaderMode = function(returnCallback, errorCallback) {
		/*
		Returns the current bootloader mode, see :func:`Set Bootloader Mode`.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDualACRelay.FUNCTION_GET_BOOTLOADER_MODE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setWriteFirmwarePointer = function(pointer, returnCallback, errorCallback) {
		/*
		Sets the firmware pointer for :func:`Write Firmware`. The pointer has
		to be increased by chunks of size 64. The data is written to flash
		every 4 chunks (which equals to one page of size 256).
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDualACRelay.FUNCTION_SET_WRITE_FIRMWARE_POINTER, [pointer], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeFirmware = function(data, returnCallback, errorCallback) {
		/*
		Writes 64 Bytes of firmware at the position as written by
		:func:`Set Write Firmware Pointer` before. The firmware is written
		to flash every 4 chunks.
		
		You can only write firmware in bootloader mode.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDualACRelay.FUNCTION_WRITE_FIRMWARE, [data], 'B64', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setStatusLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Sets the status LED configuration. By default the LED shows
		communication traffic between Brick and Bricklet, it flickers once
		for every 10 received data packets.
		
		You can also turn the LED permanently on/off or show a heartbeat.
		
		If the Bricklet is in bootloader mode, the LED is will show heartbeat by default.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDualACRelay.FUNCTION_SET_STATUS_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getStatusLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Status LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDualACRelay.FUNCTION_GET_STATUS_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getChipTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature as measured inside the microcontroller. The
		value returned is not the ambient temperature!
		
		The temperature is only proportional to the real temperature and it has bad
		accuracy. Practically it is only useful as an indicator for
		temperature changes.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDualACRelay.FUNCTION_GET_CHIP_TEMPERATURE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.reset = function(returnCallback, errorCallback) {
		/*
		Calling this function will reset the Bricklet. All configurations
		will be lost.
		
		After a reset you have to create new device objects,
		calling functions on the existing ones will result in
		undefined behavior!
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDualACRelay.FUNCTION_RESET, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeUID = function(uid, returnCallback, errorCallback) {
		/*
		Writes a new UID into flash. If you want to set a new UID
		you have to decode the Base58 encoded UID string into an
		integer first.
		
		We recommend that you use Brick Viewer to change the UID.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDualACRelay.FUNCTION_WRITE_UID, [uid], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.readUID = function(returnCallback, errorCallback) {
		/*
		Returns the current UID as an integer. Encode as
		Base58 to get the usual string version.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDualACRelay.FUNCTION_READ_UID, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDualACRelay.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletIndustrialDualACRelay;

},{"./Device":279,"./IPConnection":280}],202:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletIndustrialDualAnalogIn.DEVICE_IDENTIFIER = 249;
BrickletIndustrialDualAnalogIn.DEVICE_DISPLAY_NAME = 'Industrial Dual Analog In Bricklet';
BrickletIndustrialDualAnalogIn.CALLBACK_VOLTAGE = 13;
BrickletIndustrialDualAnalogIn.CALLBACK_VOLTAGE_REACHED = 14;
BrickletIndustrialDualAnalogIn.FUNCTION_GET_VOLTAGE = 1;
BrickletIndustrialDualAnalogIn.FUNCTION_SET_VOLTAGE_CALLBACK_PERIOD = 2;
BrickletIndustrialDualAnalogIn.FUNCTION_GET_VOLTAGE_CALLBACK_PERIOD = 3;
BrickletIndustrialDualAnalogIn.FUNCTION_SET_VOLTAGE_CALLBACK_THRESHOLD = 4;
BrickletIndustrialDualAnalogIn.FUNCTION_GET_VOLTAGE_CALLBACK_THRESHOLD = 5;
BrickletIndustrialDualAnalogIn.FUNCTION_SET_DEBOUNCE_PERIOD = 6;
BrickletIndustrialDualAnalogIn.FUNCTION_GET_DEBOUNCE_PERIOD = 7;
BrickletIndustrialDualAnalogIn.FUNCTION_SET_SAMPLE_RATE = 8;
BrickletIndustrialDualAnalogIn.FUNCTION_GET_SAMPLE_RATE = 9;
BrickletIndustrialDualAnalogIn.FUNCTION_SET_CALIBRATION = 10;
BrickletIndustrialDualAnalogIn.FUNCTION_GET_CALIBRATION = 11;
BrickletIndustrialDualAnalogIn.FUNCTION_GET_ADC_VALUES = 12;
BrickletIndustrialDualAnalogIn.FUNCTION_GET_IDENTITY = 255;
BrickletIndustrialDualAnalogIn.THRESHOLD_OPTION_OFF = 'x';
BrickletIndustrialDualAnalogIn.THRESHOLD_OPTION_OUTSIDE = 'o';
BrickletIndustrialDualAnalogIn.THRESHOLD_OPTION_INSIDE = 'i';
BrickletIndustrialDualAnalogIn.THRESHOLD_OPTION_SMALLER = '<';
BrickletIndustrialDualAnalogIn.THRESHOLD_OPTION_GREATER = '>';
BrickletIndustrialDualAnalogIn.SAMPLE_RATE_976_SPS = 0;
BrickletIndustrialDualAnalogIn.SAMPLE_RATE_488_SPS = 1;
BrickletIndustrialDualAnalogIn.SAMPLE_RATE_244_SPS = 2;
BrickletIndustrialDualAnalogIn.SAMPLE_RATE_122_SPS = 3;
BrickletIndustrialDualAnalogIn.SAMPLE_RATE_61_SPS = 4;
BrickletIndustrialDualAnalogIn.SAMPLE_RATE_4_SPS = 5;
BrickletIndustrialDualAnalogIn.SAMPLE_RATE_2_SPS = 6;
BrickletIndustrialDualAnalogIn.SAMPLE_RATE_1_SPS = 7;

function BrickletIndustrialDualAnalogIn(uid, ipcon) {
	//Measures two DC voltages between -35V and +35V with 24bit resolution each

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletIndustrialDualAnalogIn.DEVICE_IDENTIFIER, BrickletIndustrialDualAnalogIn.DEVICE_DISPLAY_NAME);
	BrickletIndustrialDualAnalogIn.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickletIndustrialDualAnalogIn.FUNCTION_GET_VOLTAGE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDualAnalogIn.FUNCTION_SET_VOLTAGE_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletIndustrialDualAnalogIn.FUNCTION_GET_VOLTAGE_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDualAnalogIn.FUNCTION_SET_VOLTAGE_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletIndustrialDualAnalogIn.FUNCTION_GET_VOLTAGE_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDualAnalogIn.FUNCTION_SET_DEBOUNCE_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletIndustrialDualAnalogIn.FUNCTION_GET_DEBOUNCE_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDualAnalogIn.FUNCTION_SET_SAMPLE_RATE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialDualAnalogIn.FUNCTION_GET_SAMPLE_RATE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDualAnalogIn.FUNCTION_SET_CALIBRATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialDualAnalogIn.FUNCTION_GET_CALIBRATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDualAnalogIn.FUNCTION_GET_ADC_VALUES] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDualAnalogIn.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletIndustrialDualAnalogIn.CALLBACK_VOLTAGE] = [13, 'B i'];
	this.callbackFormats[BrickletIndustrialDualAnalogIn.CALLBACK_VOLTAGE_REACHED] = [13, 'B i'];



	this.getVoltage = function(channel, returnCallback, errorCallback) {
		/*
		Returns the voltage for the given channel.
		
		If you want to get the voltage periodically, it is recommended to use the
		:cb:`Voltage` callback and set the period with
		:func:`Set Voltage Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDualAnalogIn.FUNCTION_GET_VOLTAGE, [channel], 'B', 12, 'i', returnCallback, errorCallback, false, true);
	};
	this.setVoltageCallbackPeriod = function(channel, period, returnCallback, errorCallback) {
		/*
		Sets the period with which the :cb:`Voltage` callback is triggered
		periodically for the given channel. A value of 0 turns the callback off.
		
		The :cb:`Voltage` callback is only triggered if the voltage has changed since the
		last triggering.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDualAnalogIn.FUNCTION_SET_VOLTAGE_CALLBACK_PERIOD, [channel, period], 'B I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getVoltageCallbackPeriod = function(channel, returnCallback, errorCallback) {
		/*
		Returns the period as set by :func:`Set Voltage Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDualAnalogIn.FUNCTION_GET_VOLTAGE_CALLBACK_PERIOD, [channel], 'B', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setVoltageCallbackThreshold = function(channel, option, min, max, returnCallback, errorCallback) {
		/*
		Sets the thresholds for the :cb:`Voltage Reached` callback for the given
		channel.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Callback is turned off"
		 "'o'",    "Callback is triggered when the voltage is *outside* the min and max values"
		 "'i'",    "Callback is triggered when the voltage is *inside* the min and max values"
		 "'<'",    "Callback is triggered when the voltage is smaller than the min value (max is ignored)"
		 "'>'",    "Callback is triggered when the voltage is greater than the min value (max is ignored)"
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDualAnalogIn.FUNCTION_SET_VOLTAGE_CALLBACK_THRESHOLD, [channel, option, min, max], 'B c i i', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getVoltageCallbackThreshold = function(channel, returnCallback, errorCallback) {
		/*
		Returns the threshold as set by :func:`Set Voltage Callback Threshold`.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDualAnalogIn.FUNCTION_GET_VOLTAGE_CALLBACK_THRESHOLD, [channel], 'B', 17, 'c i i', returnCallback, errorCallback, false, true);
	};
	this.setDebouncePeriod = function(debounce, returnCallback, errorCallback) {
		/*
		Sets the period with which the threshold callback
		
		* :cb:`Voltage Reached`
		
		is triggered, if the threshold
		
		* :func:`Set Voltage Callback Threshold`
		
		keeps being reached.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDualAnalogIn.FUNCTION_SET_DEBOUNCE_PERIOD, [debounce], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getDebouncePeriod = function(returnCallback, errorCallback) {
		/*
		Returns the debounce period as set by :func:`Set Debounce Period`.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDualAnalogIn.FUNCTION_GET_DEBOUNCE_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setSampleRate = function(rate, returnCallback, errorCallback) {
		/*
		Sets the sample rate. The sample rate can be between 1 sample per second
		and 976 samples per second. Decreasing the sample rate will also decrease the
		noise on the data.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDualAnalogIn.FUNCTION_SET_SAMPLE_RATE, [rate], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getSampleRate = function(returnCallback, errorCallback) {
		/*
		Returns the sample rate as set by :func:`Set Sample Rate`.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDualAnalogIn.FUNCTION_GET_SAMPLE_RATE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setCalibration = function(offset, gain, returnCallback, errorCallback) {
		/*
		Sets offset and gain of MCP3911 internal calibration registers.
		
		See MCP3911 datasheet 7.7 and 7.8. The Industrial Dual Analog In Bricklet
		is already factory calibrated by Tinkerforge. It should not be necessary
		for you to use this function
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDualAnalogIn.FUNCTION_SET_CALIBRATION, [offset, gain], 'i2 i2', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getCalibration = function(returnCallback, errorCallback) {
		/*
		Returns the calibration as set by :func:`Set Calibration`.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDualAnalogIn.FUNCTION_GET_CALIBRATION, [], '', 24, 'i2 i2', returnCallback, errorCallback, false, true);
	};
	this.getADCValues = function(returnCallback, errorCallback) {
		/*
		Returns the ADC values as given by the MCP3911 IC. This function
		is needed for proper calibration, see :func:`Set Calibration`.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDualAnalogIn.FUNCTION_GET_ADC_VALUES, [], '', 16, 'i2', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDualAnalogIn.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletIndustrialDualAnalogIn;

},{"./Device":279,"./IPConnection":280}],203:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletIndustrialDualAnalogInV2.DEVICE_IDENTIFIER = 2121;
BrickletIndustrialDualAnalogInV2.DEVICE_DISPLAY_NAME = 'Industrial Dual Analog In Bricklet 2.0';
BrickletIndustrialDualAnalogInV2.CALLBACK_VOLTAGE = 4;
BrickletIndustrialDualAnalogInV2.CALLBACK_ALL_VOLTAGES = 17;
BrickletIndustrialDualAnalogInV2.FUNCTION_GET_VOLTAGE = 1;
BrickletIndustrialDualAnalogInV2.FUNCTION_SET_VOLTAGE_CALLBACK_CONFIGURATION = 2;
BrickletIndustrialDualAnalogInV2.FUNCTION_GET_VOLTAGE_CALLBACK_CONFIGURATION = 3;
BrickletIndustrialDualAnalogInV2.FUNCTION_SET_SAMPLE_RATE = 5;
BrickletIndustrialDualAnalogInV2.FUNCTION_GET_SAMPLE_RATE = 6;
BrickletIndustrialDualAnalogInV2.FUNCTION_SET_CALIBRATION = 7;
BrickletIndustrialDualAnalogInV2.FUNCTION_GET_CALIBRATION = 8;
BrickletIndustrialDualAnalogInV2.FUNCTION_GET_ADC_VALUES = 9;
BrickletIndustrialDualAnalogInV2.FUNCTION_SET_CHANNEL_LED_CONFIG = 10;
BrickletIndustrialDualAnalogInV2.FUNCTION_GET_CHANNEL_LED_CONFIG = 11;
BrickletIndustrialDualAnalogInV2.FUNCTION_SET_CHANNEL_LED_STATUS_CONFIG = 12;
BrickletIndustrialDualAnalogInV2.FUNCTION_GET_CHANNEL_LED_STATUS_CONFIG = 13;
BrickletIndustrialDualAnalogInV2.FUNCTION_GET_ALL_VOLTAGES = 14;
BrickletIndustrialDualAnalogInV2.FUNCTION_SET_ALL_VOLTAGES_CALLBACK_CONFIGURATION = 15;
BrickletIndustrialDualAnalogInV2.FUNCTION_GET_ALL_VOLTAGES_CALLBACK_CONFIGURATION = 16;
BrickletIndustrialDualAnalogInV2.FUNCTION_GET_SPITFP_ERROR_COUNT = 234;
BrickletIndustrialDualAnalogInV2.FUNCTION_SET_BOOTLOADER_MODE = 235;
BrickletIndustrialDualAnalogInV2.FUNCTION_GET_BOOTLOADER_MODE = 236;
BrickletIndustrialDualAnalogInV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER = 237;
BrickletIndustrialDualAnalogInV2.FUNCTION_WRITE_FIRMWARE = 238;
BrickletIndustrialDualAnalogInV2.FUNCTION_SET_STATUS_LED_CONFIG = 239;
BrickletIndustrialDualAnalogInV2.FUNCTION_GET_STATUS_LED_CONFIG = 240;
BrickletIndustrialDualAnalogInV2.FUNCTION_GET_CHIP_TEMPERATURE = 242;
BrickletIndustrialDualAnalogInV2.FUNCTION_RESET = 243;
BrickletIndustrialDualAnalogInV2.FUNCTION_WRITE_UID = 248;
BrickletIndustrialDualAnalogInV2.FUNCTION_READ_UID = 249;
BrickletIndustrialDualAnalogInV2.FUNCTION_GET_IDENTITY = 255;
BrickletIndustrialDualAnalogInV2.THRESHOLD_OPTION_OFF = 'x';
BrickletIndustrialDualAnalogInV2.THRESHOLD_OPTION_OUTSIDE = 'o';
BrickletIndustrialDualAnalogInV2.THRESHOLD_OPTION_INSIDE = 'i';
BrickletIndustrialDualAnalogInV2.THRESHOLD_OPTION_SMALLER = '<';
BrickletIndustrialDualAnalogInV2.THRESHOLD_OPTION_GREATER = '>';
BrickletIndustrialDualAnalogInV2.SAMPLE_RATE_976_SPS = 0;
BrickletIndustrialDualAnalogInV2.SAMPLE_RATE_488_SPS = 1;
BrickletIndustrialDualAnalogInV2.SAMPLE_RATE_244_SPS = 2;
BrickletIndustrialDualAnalogInV2.SAMPLE_RATE_122_SPS = 3;
BrickletIndustrialDualAnalogInV2.SAMPLE_RATE_61_SPS = 4;
BrickletIndustrialDualAnalogInV2.SAMPLE_RATE_4_SPS = 5;
BrickletIndustrialDualAnalogInV2.SAMPLE_RATE_2_SPS = 6;
BrickletIndustrialDualAnalogInV2.SAMPLE_RATE_1_SPS = 7;
BrickletIndustrialDualAnalogInV2.CHANNEL_LED_CONFIG_OFF = 0;
BrickletIndustrialDualAnalogInV2.CHANNEL_LED_CONFIG_ON = 1;
BrickletIndustrialDualAnalogInV2.CHANNEL_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletIndustrialDualAnalogInV2.CHANNEL_LED_CONFIG_SHOW_CHANNEL_STATUS = 3;
BrickletIndustrialDualAnalogInV2.CHANNEL_LED_STATUS_CONFIG_THRESHOLD = 0;
BrickletIndustrialDualAnalogInV2.CHANNEL_LED_STATUS_CONFIG_INTENSITY = 1;
BrickletIndustrialDualAnalogInV2.BOOTLOADER_MODE_BOOTLOADER = 0;
BrickletIndustrialDualAnalogInV2.BOOTLOADER_MODE_FIRMWARE = 1;
BrickletIndustrialDualAnalogInV2.BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT = 2;
BrickletIndustrialDualAnalogInV2.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT = 3;
BrickletIndustrialDualAnalogInV2.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT = 4;
BrickletIndustrialDualAnalogInV2.BOOTLOADER_STATUS_OK = 0;
BrickletIndustrialDualAnalogInV2.BOOTLOADER_STATUS_INVALID_MODE = 1;
BrickletIndustrialDualAnalogInV2.BOOTLOADER_STATUS_NO_CHANGE = 2;
BrickletIndustrialDualAnalogInV2.BOOTLOADER_STATUS_ENTRY_FUNCTION_NOT_PRESENT = 3;
BrickletIndustrialDualAnalogInV2.BOOTLOADER_STATUS_DEVICE_IDENTIFIER_INCORRECT = 4;
BrickletIndustrialDualAnalogInV2.BOOTLOADER_STATUS_CRC_MISMATCH = 5;
BrickletIndustrialDualAnalogInV2.STATUS_LED_CONFIG_OFF = 0;
BrickletIndustrialDualAnalogInV2.STATUS_LED_CONFIG_ON = 1;
BrickletIndustrialDualAnalogInV2.STATUS_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletIndustrialDualAnalogInV2.STATUS_LED_CONFIG_SHOW_STATUS = 3;

function BrickletIndustrialDualAnalogInV2(uid, ipcon) {
	//Measures two DC voltages between -35V and +35V with 24bit resolution each

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletIndustrialDualAnalogInV2.DEVICE_IDENTIFIER, BrickletIndustrialDualAnalogInV2.DEVICE_DISPLAY_NAME);
	BrickletIndustrialDualAnalogInV2.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 1];
	this.responseExpected[BrickletIndustrialDualAnalogInV2.FUNCTION_GET_VOLTAGE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDualAnalogInV2.FUNCTION_SET_VOLTAGE_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletIndustrialDualAnalogInV2.FUNCTION_GET_VOLTAGE_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDualAnalogInV2.FUNCTION_SET_SAMPLE_RATE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialDualAnalogInV2.FUNCTION_GET_SAMPLE_RATE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDualAnalogInV2.FUNCTION_SET_CALIBRATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialDualAnalogInV2.FUNCTION_GET_CALIBRATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDualAnalogInV2.FUNCTION_GET_ADC_VALUES] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDualAnalogInV2.FUNCTION_SET_CHANNEL_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialDualAnalogInV2.FUNCTION_GET_CHANNEL_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDualAnalogInV2.FUNCTION_SET_CHANNEL_LED_STATUS_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialDualAnalogInV2.FUNCTION_GET_CHANNEL_LED_STATUS_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDualAnalogInV2.FUNCTION_GET_ALL_VOLTAGES] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDualAnalogInV2.FUNCTION_SET_ALL_VOLTAGES_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletIndustrialDualAnalogInV2.FUNCTION_GET_ALL_VOLTAGES_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDualAnalogInV2.FUNCTION_GET_SPITFP_ERROR_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDualAnalogInV2.FUNCTION_SET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDualAnalogInV2.FUNCTION_GET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDualAnalogInV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialDualAnalogInV2.FUNCTION_WRITE_FIRMWARE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDualAnalogInV2.FUNCTION_SET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialDualAnalogInV2.FUNCTION_GET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDualAnalogInV2.FUNCTION_GET_CHIP_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDualAnalogInV2.FUNCTION_RESET] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialDualAnalogInV2.FUNCTION_WRITE_UID] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialDualAnalogInV2.FUNCTION_READ_UID] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDualAnalogInV2.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletIndustrialDualAnalogInV2.CALLBACK_VOLTAGE] = [13, 'B i'];
	this.callbackFormats[BrickletIndustrialDualAnalogInV2.CALLBACK_ALL_VOLTAGES] = [16, 'i2'];



	this.getVoltage = function(channel, returnCallback, errorCallback) {
		/*
		Returns the voltage for the given channel.
		
		
		If you want to get the value periodically, it is recommended to use the
		:cb:`Voltage` callback. You can set the callback configuration
		with :func:`Set Voltage Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDualAnalogInV2.FUNCTION_GET_VOLTAGE, [channel], 'B', 12, 'i', returnCallback, errorCallback, false, true);
	};
	this.setVoltageCallbackConfiguration = function(channel, period, valueHasToChange, option, min, max, returnCallback, errorCallback) {
		/*
		The period is the period with which the :cb:`Voltage` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		If the `value has to change`-parameter is set to true, the callback is only
		triggered after the value has changed. If the value didn't change
		within the period, the callback is triggered immediately on change.
		
		If it is set to false, the callback is continuously triggered with the period,
		independent of the value.
		
		It is furthermore possible to constrain the callback with thresholds.
		
		The `option`-parameter together with min/max sets a threshold for the :cb:`Voltage` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Threshold is turned off"
		 "'o'",    "Threshold is triggered when the value is *outside* the min and max values"
		 "'i'",    "Threshold is triggered when the value is *inside* or equal to the min and max values"
		 "'<'",    "Threshold is triggered when the value is smaller than the min value (max is ignored)"
		 "'>'",    "Threshold is triggered when the value is greater than the min value (max is ignored)"
		
		If the option is set to 'x' (threshold turned off) the callback is triggered with the fixed period.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDualAnalogInV2.FUNCTION_SET_VOLTAGE_CALLBACK_CONFIGURATION, [channel, period, valueHasToChange, option, min, max], 'B I ? c i i', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getVoltageCallbackConfiguration = function(channel, returnCallback, errorCallback) {
		/*
		Returns the callback configuration as set by :func:`Set Voltage Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDualAnalogInV2.FUNCTION_GET_VOLTAGE_CALLBACK_CONFIGURATION, [channel], 'B', 22, 'I ? c i i', returnCallback, errorCallback, false, true);
	};
	this.setSampleRate = function(rate, returnCallback, errorCallback) {
		/*
		Sets the sample rate. The sample rate can be between 1 sample per second
		and 976 samples per second. Decreasing the sample rate will also decrease the
		noise on the data.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDualAnalogInV2.FUNCTION_SET_SAMPLE_RATE, [rate], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getSampleRate = function(returnCallback, errorCallback) {
		/*
		Returns the sample rate as set by :func:`Set Sample Rate`.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDualAnalogInV2.FUNCTION_GET_SAMPLE_RATE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setCalibration = function(offset, gain, returnCallback, errorCallback) {
		/*
		Sets offset and gain of MCP3911 internal calibration registers.
		
		See MCP3911 datasheet 7.7 and 7.8. The Industrial Dual Analog In Bricklet 2.0
		is already factory calibrated by Tinkerforge. It should not be necessary
		for you to use this function
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDualAnalogInV2.FUNCTION_SET_CALIBRATION, [offset, gain], 'i2 i2', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getCalibration = function(returnCallback, errorCallback) {
		/*
		Returns the calibration as set by :func:`Set Calibration`.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDualAnalogInV2.FUNCTION_GET_CALIBRATION, [], '', 24, 'i2 i2', returnCallback, errorCallback, false, true);
	};
	this.getADCValues = function(returnCallback, errorCallback) {
		/*
		Returns the ADC values as given by the MCP3911 IC. This function
		is needed for proper calibration, see :func:`Set Calibration`.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDualAnalogInV2.FUNCTION_GET_ADC_VALUES, [], '', 16, 'i2', returnCallback, errorCallback, false, true);
	};
	this.setChannelLEDConfig = function(channel, config, returnCallback, errorCallback) {
		/*
		Each channel has a corresponding LED. You can turn the LED off, on or show a
		heartbeat. You can also set the LED to "Channel Status". In this mode the
		LED can either be turned on with a pre-defined threshold or the intensity
		of the LED can change with the measured value.
		
		You can configure the channel status behavior with :func:`Set Channel LED Status Config`.
		
		By default all channel LEDs are configured as "Channel Status".
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDualAnalogInV2.FUNCTION_SET_CHANNEL_LED_CONFIG, [channel, config], 'B B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getChannelLEDConfig = function(channel, returnCallback, errorCallback) {
		/*
		Returns the channel LED configuration as set by :func:`Set Channel LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDualAnalogInV2.FUNCTION_GET_CHANNEL_LED_CONFIG, [channel], 'B', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setChannelLEDStatusConfig = function(channel, min, max, config, returnCallback, errorCallback) {
		/*
		Sets the channel LED status config. This config is used if the channel LED is
		configured as "Channel Status", see :func:`Set Channel LED Config`.
		
		For each channel you can choose between threshold and intensity mode.
		
		In threshold mode you can define a positive or a negative threshold.
		For a positive threshold set the "min" parameter to the threshold value in mV
		above which the LED should turn on and set the "max" parameter to 0. Example:
		If you set a positive threshold of 10V, the LED will turn on as soon as the
		voltage exceeds 10V and turn off again if it goes below 10V.
		For a negative threshold set the "max" parameter to the threshold value in mV
		below which the LED should turn on and set the "min" parameter to 0. Example:
		If you set a negative threshold of 10V, the LED will turn on as soon as the
		voltage goes below 10V and the LED will turn off when the voltage exceeds 10V.
		
		In intensity mode you can define a range in mV that is used to scale the brightness
		of the LED. Example with min=4V, max=20V: The LED is off at 4V, on at 20V
		and the brightness is linearly scaled between the values 4V and 20V. If the
		min value is greater than the max value, the LED brightness is scaled the other
		way around.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDualAnalogInV2.FUNCTION_SET_CHANNEL_LED_STATUS_CONFIG, [channel, min, max, config], 'B i i B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getChannelLEDStatusConfig = function(channel, returnCallback, errorCallback) {
		/*
		Returns the channel LED status configuration as set by
		:func:`Set Channel LED Status Config`.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDualAnalogInV2.FUNCTION_GET_CHANNEL_LED_STATUS_CONFIG, [channel], 'B', 17, 'i i B', returnCallback, errorCallback, false, true);
	};
	this.getAllVoltages = function(returnCallback, errorCallback) {
		/*
		Returns the voltages for all channels.
		
		If you want to get the value periodically, it is recommended to use the
		:cb:`All Voltages` callback. You can set the callback configuration
		with :func:`Set All Voltages Callback Configuration`.
		
		.. versionadded:: 2.0.6$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDualAnalogInV2.FUNCTION_GET_ALL_VOLTAGES, [], '', 16, 'i2', returnCallback, errorCallback, false, true);
	};
	this.setAllVoltagesCallbackConfiguration = function(period, valueHasToChange, returnCallback, errorCallback) {
		/*
		The period is the period with which the :cb:`All Voltages`
		callback is triggered periodically. A value of 0 turns the callback off.
		
		If the `value has to change`-parameter is set to true, the callback is only
		triggered after at least one of the values has changed. If the values didn't
		change within the period, the callback is triggered immediately on change.
		
		If it is set to false, the callback is continuously triggered with the period,
		independent of the value.
		
		.. versionadded:: 2.0.6$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDualAnalogInV2.FUNCTION_SET_ALL_VOLTAGES_CALLBACK_CONFIGURATION, [period, valueHasToChange], 'I ?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getAllVoltagesCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the callback configuration as set by
		:func:`Set All Voltages Callback Configuration`.
		
		.. versionadded:: 2.0.6$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDualAnalogInV2.FUNCTION_GET_ALL_VOLTAGES_CALLBACK_CONFIGURATION, [], '', 13, 'I ?', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPErrorCount = function(returnCallback, errorCallback) {
		/*
		Returns the error count for the communication between Brick and Bricklet.
		
		The errors are divided into
		
		* ACK checksum errors,
		* message checksum errors,
		* framing errors and
		* overflow errors.
		
		The errors counts are for errors that occur on the Bricklet side. All
		Bricks have a similar function that returns the errors on the Brick side.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDualAnalogInV2.FUNCTION_GET_SPITFP_ERROR_COUNT, [], '', 24, 'I I I I', returnCallback, errorCallback, false, true);
	};
	this.setBootloaderMode = function(mode, returnCallback, errorCallback) {
		/*
		Sets the bootloader mode and returns the status after the requested
		mode change was instigated.
		
		You can change from bootloader mode to firmware mode and vice versa. A change
		from bootloader mode to firmware mode will only take place if the entry function,
		device identifier and CRC are present and correct.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDualAnalogInV2.FUNCTION_SET_BOOTLOADER_MODE, [mode], 'B', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getBootloaderMode = function(returnCallback, errorCallback) {
		/*
		Returns the current bootloader mode, see :func:`Set Bootloader Mode`.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDualAnalogInV2.FUNCTION_GET_BOOTLOADER_MODE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setWriteFirmwarePointer = function(pointer, returnCallback, errorCallback) {
		/*
		Sets the firmware pointer for :func:`Write Firmware`. The pointer has
		to be increased by chunks of size 64. The data is written to flash
		every 4 chunks (which equals to one page of size 256).
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDualAnalogInV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER, [pointer], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeFirmware = function(data, returnCallback, errorCallback) {
		/*
		Writes 64 Bytes of firmware at the position as written by
		:func:`Set Write Firmware Pointer` before. The firmware is written
		to flash every 4 chunks.
		
		You can only write firmware in bootloader mode.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDualAnalogInV2.FUNCTION_WRITE_FIRMWARE, [data], 'B64', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setStatusLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Sets the status LED configuration. By default the LED shows
		communication traffic between Brick and Bricklet, it flickers once
		for every 10 received data packets.
		
		You can also turn the LED permanently on/off or show a heartbeat.
		
		If the Bricklet is in bootloader mode, the LED is will show heartbeat by default.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDualAnalogInV2.FUNCTION_SET_STATUS_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getStatusLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Status LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDualAnalogInV2.FUNCTION_GET_STATUS_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getChipTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature as measured inside the microcontroller. The
		value returned is not the ambient temperature!
		
		The temperature is only proportional to the real temperature and it has bad
		accuracy. Practically it is only useful as an indicator for
		temperature changes.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDualAnalogInV2.FUNCTION_GET_CHIP_TEMPERATURE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.reset = function(returnCallback, errorCallback) {
		/*
		Calling this function will reset the Bricklet. All configurations
		will be lost.
		
		After a reset you have to create new device objects,
		calling functions on the existing ones will result in
		undefined behavior!
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDualAnalogInV2.FUNCTION_RESET, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeUID = function(uid, returnCallback, errorCallback) {
		/*
		Writes a new UID into flash. If you want to set a new UID
		you have to decode the Base58 encoded UID string into an
		integer first.
		
		We recommend that you use Brick Viewer to change the UID.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDualAnalogInV2.FUNCTION_WRITE_UID, [uid], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.readUID = function(returnCallback, errorCallback) {
		/*
		Returns the current UID as an integer. Encode as
		Base58 to get the usual string version.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDualAnalogInV2.FUNCTION_READ_UID, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDualAnalogInV2.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletIndustrialDualAnalogInV2;

},{"./Device":279,"./IPConnection":280}],204:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletIndustrialDualRelay.DEVICE_IDENTIFIER = 284;
BrickletIndustrialDualRelay.DEVICE_DISPLAY_NAME = 'Industrial Dual Relay Bricklet';
BrickletIndustrialDualRelay.CALLBACK_MONOFLOP_DONE = 5;
BrickletIndustrialDualRelay.FUNCTION_SET_VALUE = 1;
BrickletIndustrialDualRelay.FUNCTION_GET_VALUE = 2;
BrickletIndustrialDualRelay.FUNCTION_SET_MONOFLOP = 3;
BrickletIndustrialDualRelay.FUNCTION_GET_MONOFLOP = 4;
BrickletIndustrialDualRelay.FUNCTION_SET_SELECTED_VALUE = 6;
BrickletIndustrialDualRelay.FUNCTION_GET_SPITFP_ERROR_COUNT = 234;
BrickletIndustrialDualRelay.FUNCTION_SET_BOOTLOADER_MODE = 235;
BrickletIndustrialDualRelay.FUNCTION_GET_BOOTLOADER_MODE = 236;
BrickletIndustrialDualRelay.FUNCTION_SET_WRITE_FIRMWARE_POINTER = 237;
BrickletIndustrialDualRelay.FUNCTION_WRITE_FIRMWARE = 238;
BrickletIndustrialDualRelay.FUNCTION_SET_STATUS_LED_CONFIG = 239;
BrickletIndustrialDualRelay.FUNCTION_GET_STATUS_LED_CONFIG = 240;
BrickletIndustrialDualRelay.FUNCTION_GET_CHIP_TEMPERATURE = 242;
BrickletIndustrialDualRelay.FUNCTION_RESET = 243;
BrickletIndustrialDualRelay.FUNCTION_WRITE_UID = 248;
BrickletIndustrialDualRelay.FUNCTION_READ_UID = 249;
BrickletIndustrialDualRelay.FUNCTION_GET_IDENTITY = 255;
BrickletIndustrialDualRelay.BOOTLOADER_MODE_BOOTLOADER = 0;
BrickletIndustrialDualRelay.BOOTLOADER_MODE_FIRMWARE = 1;
BrickletIndustrialDualRelay.BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT = 2;
BrickletIndustrialDualRelay.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT = 3;
BrickletIndustrialDualRelay.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT = 4;
BrickletIndustrialDualRelay.BOOTLOADER_STATUS_OK = 0;
BrickletIndustrialDualRelay.BOOTLOADER_STATUS_INVALID_MODE = 1;
BrickletIndustrialDualRelay.BOOTLOADER_STATUS_NO_CHANGE = 2;
BrickletIndustrialDualRelay.BOOTLOADER_STATUS_ENTRY_FUNCTION_NOT_PRESENT = 3;
BrickletIndustrialDualRelay.BOOTLOADER_STATUS_DEVICE_IDENTIFIER_INCORRECT = 4;
BrickletIndustrialDualRelay.BOOTLOADER_STATUS_CRC_MISMATCH = 5;
BrickletIndustrialDualRelay.STATUS_LED_CONFIG_OFF = 0;
BrickletIndustrialDualRelay.STATUS_LED_CONFIG_ON = 1;
BrickletIndustrialDualRelay.STATUS_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletIndustrialDualRelay.STATUS_LED_CONFIG_SHOW_STATUS = 3;

function BrickletIndustrialDualRelay(uid, ipcon) {
	//Two relays to switch AC/DC devices

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletIndustrialDualRelay.DEVICE_IDENTIFIER, BrickletIndustrialDualRelay.DEVICE_DISPLAY_NAME);
	BrickletIndustrialDualRelay.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickletIndustrialDualRelay.FUNCTION_SET_VALUE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialDualRelay.FUNCTION_GET_VALUE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDualRelay.FUNCTION_SET_MONOFLOP] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialDualRelay.FUNCTION_GET_MONOFLOP] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDualRelay.FUNCTION_SET_SELECTED_VALUE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialDualRelay.FUNCTION_GET_SPITFP_ERROR_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDualRelay.FUNCTION_SET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDualRelay.FUNCTION_GET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDualRelay.FUNCTION_SET_WRITE_FIRMWARE_POINTER] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialDualRelay.FUNCTION_WRITE_FIRMWARE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDualRelay.FUNCTION_SET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialDualRelay.FUNCTION_GET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDualRelay.FUNCTION_GET_CHIP_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDualRelay.FUNCTION_RESET] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialDualRelay.FUNCTION_WRITE_UID] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialDualRelay.FUNCTION_READ_UID] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialDualRelay.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletIndustrialDualRelay.CALLBACK_MONOFLOP_DONE] = [10, 'B ?'];



	this.setValue = function(channel0, channel1, returnCallback, errorCallback) {
		/*
		Sets the state of the relays, *true* means on and *false* means off.
		For example: (true, false) turns relay 0 on and relay 1 off.
		
		If you just want to set one of the relays and don't know the current state
		of the other relay, you can get the state with :func:`Get Value` or you
		can use :func:`Set Selected Value`.
		
		All running monoflop timers will be aborted if this function is called.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDualRelay.FUNCTION_SET_VALUE, [channel0, channel1], '? ?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getValue = function(returnCallback, errorCallback) {
		/*
		Returns the state of the relays, *true* means on and *false* means off.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDualRelay.FUNCTION_GET_VALUE, [], '', 10, '? ?', returnCallback, errorCallback, false, true);
	};
	this.setMonoflop = function(channel, value, time, returnCallback, errorCallback) {
		/*
		The first parameter can be 0 or 1 (relay 0 or relay 1). The second parameter
		is the desired state of the relay (*true* means on and *false* means off).
		The third parameter indicates the time that the relay should hold
		the state.
		
		If this function is called with the parameters (1, true, 1500):
		Relay 1 will turn on and in 1.5s it will turn off again.
		
		A monoflop can be used as a failsafe mechanism. For example: Lets assume you
		have a RS485 bus and a Industrial Dual Relay Bricklet connected to one of the
		slave stacks. You can now call this function every second, with a time parameter
		of two seconds. The relay will be on all the time. If now the RS485
		connection is lost, the relay will turn off in at most two seconds.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDualRelay.FUNCTION_SET_MONOFLOP, [channel, value, time], 'B ? I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getMonoflop = function(channel, returnCallback, errorCallback) {
		/*
		Returns (for the given relay) the current state and the time as set by
		:func:`Set Monoflop` as well as the remaining time until the state flips.
		
		If the timer is not running currently, the remaining time will be returned
		as 0.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDualRelay.FUNCTION_GET_MONOFLOP, [channel], 'B', 17, '? I I', returnCallback, errorCallback, false, true);
	};
	this.setSelectedValue = function(channel, value, returnCallback, errorCallback) {
		/*
		Sets the state of the selected relay, *true* means on and *false*
		means off.
		
		A running monoflop timer for the selected relay will be aborted if this function
		is called.
		
		The other relay remains untouched.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDualRelay.FUNCTION_SET_SELECTED_VALUE, [channel, value], 'B ?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPErrorCount = function(returnCallback, errorCallback) {
		/*
		Returns the error count for the communication between Brick and Bricklet.
		
		The errors are divided into
		
		* ACK checksum errors,
		* message checksum errors,
		* framing errors and
		* overflow errors.
		
		The errors counts are for errors that occur on the Bricklet side. All
		Bricks have a similar function that returns the errors on the Brick side.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDualRelay.FUNCTION_GET_SPITFP_ERROR_COUNT, [], '', 24, 'I I I I', returnCallback, errorCallback, false, true);
	};
	this.setBootloaderMode = function(mode, returnCallback, errorCallback) {
		/*
		Sets the bootloader mode and returns the status after the requested
		mode change was instigated.
		
		You can change from bootloader mode to firmware mode and vice versa. A change
		from bootloader mode to firmware mode will only take place if the entry function,
		device identifier and CRC are present and correct.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDualRelay.FUNCTION_SET_BOOTLOADER_MODE, [mode], 'B', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getBootloaderMode = function(returnCallback, errorCallback) {
		/*
		Returns the current bootloader mode, see :func:`Set Bootloader Mode`.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDualRelay.FUNCTION_GET_BOOTLOADER_MODE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setWriteFirmwarePointer = function(pointer, returnCallback, errorCallback) {
		/*
		Sets the firmware pointer for :func:`Write Firmware`. The pointer has
		to be increased by chunks of size 64. The data is written to flash
		every 4 chunks (which equals to one page of size 256).
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDualRelay.FUNCTION_SET_WRITE_FIRMWARE_POINTER, [pointer], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeFirmware = function(data, returnCallback, errorCallback) {
		/*
		Writes 64 Bytes of firmware at the position as written by
		:func:`Set Write Firmware Pointer` before. The firmware is written
		to flash every 4 chunks.
		
		You can only write firmware in bootloader mode.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDualRelay.FUNCTION_WRITE_FIRMWARE, [data], 'B64', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setStatusLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Sets the status LED configuration. By default the LED shows
		communication traffic between Brick and Bricklet, it flickers once
		for every 10 received data packets.
		
		You can also turn the LED permanently on/off or show a heartbeat.
		
		If the Bricklet is in bootloader mode, the LED is will show heartbeat by default.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDualRelay.FUNCTION_SET_STATUS_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getStatusLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Status LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDualRelay.FUNCTION_GET_STATUS_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getChipTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature as measured inside the microcontroller. The
		value returned is not the ambient temperature!
		
		The temperature is only proportional to the real temperature and it has bad
		accuracy. Practically it is only useful as an indicator for
		temperature changes.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDualRelay.FUNCTION_GET_CHIP_TEMPERATURE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.reset = function(returnCallback, errorCallback) {
		/*
		Calling this function will reset the Bricklet. All configurations
		will be lost.
		
		After a reset you have to create new device objects,
		calling functions on the existing ones will result in
		undefined behavior!
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDualRelay.FUNCTION_RESET, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeUID = function(uid, returnCallback, errorCallback) {
		/*
		Writes a new UID into flash. If you want to set a new UID
		you have to decode the Base58 encoded UID string into an
		integer first.
		
		We recommend that you use Brick Viewer to change the UID.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDualRelay.FUNCTION_WRITE_UID, [uid], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.readUID = function(returnCallback, errorCallback) {
		/*
		Returns the current UID as an integer. Encode as
		Base58 to get the usual string version.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDualRelay.FUNCTION_READ_UID, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialDualRelay.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletIndustrialDualRelay;

},{"./Device":279,"./IPConnection":280}],205:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletIndustrialQuadRelay.DEVICE_IDENTIFIER = 225;
BrickletIndustrialQuadRelay.DEVICE_DISPLAY_NAME = 'Industrial Quad Relay Bricklet';
BrickletIndustrialQuadRelay.CALLBACK_MONOFLOP_DONE = 8;
BrickletIndustrialQuadRelay.FUNCTION_SET_VALUE = 1;
BrickletIndustrialQuadRelay.FUNCTION_GET_VALUE = 2;
BrickletIndustrialQuadRelay.FUNCTION_SET_MONOFLOP = 3;
BrickletIndustrialQuadRelay.FUNCTION_GET_MONOFLOP = 4;
BrickletIndustrialQuadRelay.FUNCTION_SET_GROUP = 5;
BrickletIndustrialQuadRelay.FUNCTION_GET_GROUP = 6;
BrickletIndustrialQuadRelay.FUNCTION_GET_AVAILABLE_FOR_GROUP = 7;
BrickletIndustrialQuadRelay.FUNCTION_SET_SELECTED_VALUES = 9;
BrickletIndustrialQuadRelay.FUNCTION_GET_IDENTITY = 255;

function BrickletIndustrialQuadRelay(uid, ipcon) {
	//4 galvanically isolated solid state relays

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletIndustrialQuadRelay.DEVICE_IDENTIFIER, BrickletIndustrialQuadRelay.DEVICE_DISPLAY_NAME);
	BrickletIndustrialQuadRelay.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickletIndustrialQuadRelay.FUNCTION_SET_VALUE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialQuadRelay.FUNCTION_GET_VALUE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialQuadRelay.FUNCTION_SET_MONOFLOP] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialQuadRelay.FUNCTION_GET_MONOFLOP] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialQuadRelay.FUNCTION_SET_GROUP] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialQuadRelay.FUNCTION_GET_GROUP] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialQuadRelay.FUNCTION_GET_AVAILABLE_FOR_GROUP] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialQuadRelay.FUNCTION_SET_SELECTED_VALUES] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialQuadRelay.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletIndustrialQuadRelay.CALLBACK_MONOFLOP_DONE] = [12, 'H H'];



	this.setValue = function(valueMask, returnCallback, errorCallback) {
		/*
		Sets the output value with a bitmask (16bit). A 1 in the bitmask means relay
		closed and a 0 means relay open.
		
		For example: The value 3 or 0b0011 will close the relay of pins 0-1 and open
		the other pins.
		
		If no groups are used (see :func:`Set Group`), the pins correspond to the
		markings on the Industrial Quad Relay Bricklet.
		
		If groups are used, the pins correspond to the element in the group.
		Element 1 in the group will get pins 0-3, element 2 pins 4-7, element 3
		pins 8-11 and element 4 pins 12-15.
		
		All running monoflop timers will be aborted if this function is called.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialQuadRelay.FUNCTION_SET_VALUE, [valueMask], 'H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getValue = function(returnCallback, errorCallback) {
		/*
		Returns the bitmask as set by :func:`Set Value`.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialQuadRelay.FUNCTION_GET_VALUE, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.setMonoflop = function(selectionMask, valueMask, time, returnCallback, errorCallback) {
		/*
		Configures a monoflop of the pins specified by the first parameter
		bitmask.
		
		The second parameter is a bitmask with the desired value of the specified
		pins. A 1 in the bitmask means relay closed and a 0 means relay open.
		
		The third parameter indicates the time that the pins should hold
		the value.
		
		If this function is called with the parameters (9, 1, 1500) or
		(0b1001, 0b0001, 1500): Pin 0 will close and pin 3 will open. In 1.5s pin 0
		will open and pin 3 will close again.
		
		A monoflop can be used as a fail-safe mechanism. For example: Lets assume you
		have a RS485 bus and a Quad Relay Bricklet connected to one of the slave
		stacks. You can now call this function every second, with a time parameter
		of two seconds and pin 0 closed. Pin 0 will be closed all the time. If now
		the RS485 connection is lost, then pin 0 will be opened in at most two seconds.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialQuadRelay.FUNCTION_SET_MONOFLOP, [selectionMask, valueMask, time], 'H H I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getMonoflop = function(pin, returnCallback, errorCallback) {
		/*
		Returns (for the given pin) the current value and the time as set by
		:func:`Set Monoflop` as well as the remaining time until the value flips.
		
		If the timer is not running currently, the remaining time will be returned
		as 0.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialQuadRelay.FUNCTION_GET_MONOFLOP, [pin], 'B', 18, 'H I I', returnCallback, errorCallback, false, true);
	};
	this.setGroup = function(group, returnCallback, errorCallback) {
		/*
		Sets a group of Quad Relay Bricklets that should work together. You can
		find Bricklets that can be grouped together with :func:`Get Available For Group`.
		
		The group consists of 4 elements. Element 1 in the group will get pins 0-3,
		element 2 pins 4-7, element 3 pins 8-11 and element 4 pins 12-15.
		
		Each element can either be one of the ports ('a' to 'd') or 'n' if it should
		not be used.
		
		For example: If you have two Quad Relay Bricklets connected to port A and
		port B respectively, you could call with ``['a', 'b', 'n', 'n']``.
		
		Now the pins on the Quad Relay on port A are assigned to 0-3 and the
		pins on the Quad Relay on port B are assigned to 4-7. It is now possible
		to call :func:`Set Value` and control two Bricklets at the same time.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialQuadRelay.FUNCTION_SET_GROUP, [group], 'c4', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getGroup = function(returnCallback, errorCallback) {
		/*
		Returns the group as set by :func:`Set Group`
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialQuadRelay.FUNCTION_GET_GROUP, [], '', 12, 'c4', returnCallback, errorCallback, false, true);
	};
	this.getAvailableForGroup = function(returnCallback, errorCallback) {
		/*
		Returns a bitmask of ports that are available for grouping. For example the
		value 5 or 0b0101 means: Port A and port C are connected to Bricklets that
		can be grouped together.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialQuadRelay.FUNCTION_GET_AVAILABLE_FOR_GROUP, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setSelectedValues = function(selectionMask, valueMask, returnCallback, errorCallback) {
		/*
		Sets the output value with a bitmask, according to the selection mask.
		The bitmask is 16 bit long, *true* refers to a closed relay and
		*false* refers to an open relay.
		
		For example: The values (3, 1) or (0b0011, 0b0001) will close the relay of
		pin 0, open the relay of pin 1 and leave the others untouched.
		
		If no groups are used (see :func:`Set Group`), the pins correspond to the
		markings on the Industrial Quad Relay Bricklet.
		
		If groups are used, the pins correspond to the element in the group.
		Element 1 in the group will get pins 0-3, element 2 pins 4-7, element 3
		pins 8-11 and element 4 pins 12-15.
		
		Running monoflop timers for the selected relays will be aborted if this function
		is called.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialQuadRelay.FUNCTION_SET_SELECTED_VALUES, [selectionMask, valueMask], 'H H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialQuadRelay.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletIndustrialQuadRelay;

},{"./Device":279,"./IPConnection":280}],206:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletIndustrialQuadRelayV2.DEVICE_IDENTIFIER = 2102;
BrickletIndustrialQuadRelayV2.DEVICE_DISPLAY_NAME = 'Industrial Quad Relay Bricklet 2.0';
BrickletIndustrialQuadRelayV2.CALLBACK_MONOFLOP_DONE = 8;
BrickletIndustrialQuadRelayV2.FUNCTION_SET_VALUE = 1;
BrickletIndustrialQuadRelayV2.FUNCTION_GET_VALUE = 2;
BrickletIndustrialQuadRelayV2.FUNCTION_SET_MONOFLOP = 3;
BrickletIndustrialQuadRelayV2.FUNCTION_GET_MONOFLOP = 4;
BrickletIndustrialQuadRelayV2.FUNCTION_SET_SELECTED_VALUE = 5;
BrickletIndustrialQuadRelayV2.FUNCTION_SET_CHANNEL_LED_CONFIG = 6;
BrickletIndustrialQuadRelayV2.FUNCTION_GET_CHANNEL_LED_CONFIG = 7;
BrickletIndustrialQuadRelayV2.FUNCTION_GET_SPITFP_ERROR_COUNT = 234;
BrickletIndustrialQuadRelayV2.FUNCTION_SET_BOOTLOADER_MODE = 235;
BrickletIndustrialQuadRelayV2.FUNCTION_GET_BOOTLOADER_MODE = 236;
BrickletIndustrialQuadRelayV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER = 237;
BrickletIndustrialQuadRelayV2.FUNCTION_WRITE_FIRMWARE = 238;
BrickletIndustrialQuadRelayV2.FUNCTION_SET_STATUS_LED_CONFIG = 239;
BrickletIndustrialQuadRelayV2.FUNCTION_GET_STATUS_LED_CONFIG = 240;
BrickletIndustrialQuadRelayV2.FUNCTION_GET_CHIP_TEMPERATURE = 242;
BrickletIndustrialQuadRelayV2.FUNCTION_RESET = 243;
BrickletIndustrialQuadRelayV2.FUNCTION_WRITE_UID = 248;
BrickletIndustrialQuadRelayV2.FUNCTION_READ_UID = 249;
BrickletIndustrialQuadRelayV2.FUNCTION_GET_IDENTITY = 255;
BrickletIndustrialQuadRelayV2.CHANNEL_LED_CONFIG_OFF = 0;
BrickletIndustrialQuadRelayV2.CHANNEL_LED_CONFIG_ON = 1;
BrickletIndustrialQuadRelayV2.CHANNEL_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletIndustrialQuadRelayV2.CHANNEL_LED_CONFIG_SHOW_CHANNEL_STATUS = 3;
BrickletIndustrialQuadRelayV2.BOOTLOADER_MODE_BOOTLOADER = 0;
BrickletIndustrialQuadRelayV2.BOOTLOADER_MODE_FIRMWARE = 1;
BrickletIndustrialQuadRelayV2.BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT = 2;
BrickletIndustrialQuadRelayV2.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT = 3;
BrickletIndustrialQuadRelayV2.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT = 4;
BrickletIndustrialQuadRelayV2.BOOTLOADER_STATUS_OK = 0;
BrickletIndustrialQuadRelayV2.BOOTLOADER_STATUS_INVALID_MODE = 1;
BrickletIndustrialQuadRelayV2.BOOTLOADER_STATUS_NO_CHANGE = 2;
BrickletIndustrialQuadRelayV2.BOOTLOADER_STATUS_ENTRY_FUNCTION_NOT_PRESENT = 3;
BrickletIndustrialQuadRelayV2.BOOTLOADER_STATUS_DEVICE_IDENTIFIER_INCORRECT = 4;
BrickletIndustrialQuadRelayV2.BOOTLOADER_STATUS_CRC_MISMATCH = 5;
BrickletIndustrialQuadRelayV2.STATUS_LED_CONFIG_OFF = 0;
BrickletIndustrialQuadRelayV2.STATUS_LED_CONFIG_ON = 1;
BrickletIndustrialQuadRelayV2.STATUS_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletIndustrialQuadRelayV2.STATUS_LED_CONFIG_SHOW_STATUS = 3;

function BrickletIndustrialQuadRelayV2(uid, ipcon) {
	//4 galvanically isolated solid state relays

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletIndustrialQuadRelayV2.DEVICE_IDENTIFIER, BrickletIndustrialQuadRelayV2.DEVICE_DISPLAY_NAME);
	BrickletIndustrialQuadRelayV2.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickletIndustrialQuadRelayV2.FUNCTION_SET_VALUE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialQuadRelayV2.FUNCTION_GET_VALUE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialQuadRelayV2.FUNCTION_SET_MONOFLOP] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialQuadRelayV2.FUNCTION_GET_MONOFLOP] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialQuadRelayV2.FUNCTION_SET_SELECTED_VALUE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialQuadRelayV2.FUNCTION_SET_CHANNEL_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialQuadRelayV2.FUNCTION_GET_CHANNEL_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialQuadRelayV2.FUNCTION_GET_SPITFP_ERROR_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialQuadRelayV2.FUNCTION_SET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialQuadRelayV2.FUNCTION_GET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialQuadRelayV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialQuadRelayV2.FUNCTION_WRITE_FIRMWARE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialQuadRelayV2.FUNCTION_SET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialQuadRelayV2.FUNCTION_GET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialQuadRelayV2.FUNCTION_GET_CHIP_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialQuadRelayV2.FUNCTION_RESET] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialQuadRelayV2.FUNCTION_WRITE_UID] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIndustrialQuadRelayV2.FUNCTION_READ_UID] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIndustrialQuadRelayV2.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletIndustrialQuadRelayV2.CALLBACK_MONOFLOP_DONE] = [10, 'B ?'];



	this.setValue = function(value, returnCallback, errorCallback) {
		/*
		Sets the value of all four relays. A value of *true* closes the
		relay and a value of *false* opens the relay.
		
		Use :func:`Set Selected Value` to only change one relay.
		
		All running monoflop timers will be aborted if this function is called.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialQuadRelayV2.FUNCTION_SET_VALUE, [value], '?4', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getValue = function(returnCallback, errorCallback) {
		/*
		Returns the values as set by :func:`Set Value`.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialQuadRelayV2.FUNCTION_GET_VALUE, [], '', 9, '?4', returnCallback, errorCallback, false, true);
	};
	this.setMonoflop = function(channel, value, time, returnCallback, errorCallback) {
		/*
		Configures a monoflop of the specified channel.
		
		The second parameter is the desired value of the specified
		channel. A *true* means relay closed and a *false* means relay open.
		
		The third parameter indicates the time that the channels should hold
		the value.
		
		If this function is called with the parameters (0, 1, 1500) channel 0 will
		close and in 1.5s channel 0 will open again
		
		A monoflop can be used as a fail-safe mechanism. For example: Lets assume you
		have a RS485 bus and a Industrial Quad Relay Bricklet 2.0 connected to one of
		the slave stacks. You can now call this function every second, with a time
		parameter of two seconds and channel 0 closed. Channel 0 will be closed all the
		time. If now the RS485 connection is lost, then channel 0 will be opened in at
		most two seconds.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialQuadRelayV2.FUNCTION_SET_MONOFLOP, [channel, value, time], 'B ? I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getMonoflop = function(channel, returnCallback, errorCallback) {
		/*
		Returns (for the given channel) the current value and the time as set by
		:func:`Set Monoflop` as well as the remaining time until the value flips.
		
		If the timer is not running currently, the remaining time will be returned
		as 0.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialQuadRelayV2.FUNCTION_GET_MONOFLOP, [channel], 'B', 17, '? I I', returnCallback, errorCallback, false, true);
	};
	this.setSelectedValue = function(channel, value, returnCallback, errorCallback) {
		/*
		Sets the output value of the specified channel without affecting the other
		channels.
		
		A running monoflop timer for the specified channel will be aborted if this
		function is called.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialQuadRelayV2.FUNCTION_SET_SELECTED_VALUE, [channel, value], 'B ?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.setChannelLEDConfig = function(channel, config, returnCallback, errorCallback) {
		/*
		Each channel has a corresponding LED. You can turn the LED off, on or show a
		heartbeat. You can also set the LED to "Channel Status". In this mode the
		LED is on if the channel is high and off otherwise.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialQuadRelayV2.FUNCTION_SET_CHANNEL_LED_CONFIG, [channel, config], 'B B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getChannelLEDConfig = function(channel, returnCallback, errorCallback) {
		/*
		Returns the channel LED configuration as set by :func:`Set Channel LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialQuadRelayV2.FUNCTION_GET_CHANNEL_LED_CONFIG, [channel], 'B', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPErrorCount = function(returnCallback, errorCallback) {
		/*
		Returns the error count for the communication between Brick and Bricklet.
		
		The errors are divided into
		
		* ACK checksum errors,
		* message checksum errors,
		* framing errors and
		* overflow errors.
		
		The errors counts are for errors that occur on the Bricklet side. All
		Bricks have a similar function that returns the errors on the Brick side.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialQuadRelayV2.FUNCTION_GET_SPITFP_ERROR_COUNT, [], '', 24, 'I I I I', returnCallback, errorCallback, false, true);
	};
	this.setBootloaderMode = function(mode, returnCallback, errorCallback) {
		/*
		Sets the bootloader mode and returns the status after the requested
		mode change was instigated.
		
		You can change from bootloader mode to firmware mode and vice versa. A change
		from bootloader mode to firmware mode will only take place if the entry function,
		device identifier and CRC are present and correct.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialQuadRelayV2.FUNCTION_SET_BOOTLOADER_MODE, [mode], 'B', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getBootloaderMode = function(returnCallback, errorCallback) {
		/*
		Returns the current bootloader mode, see :func:`Set Bootloader Mode`.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialQuadRelayV2.FUNCTION_GET_BOOTLOADER_MODE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setWriteFirmwarePointer = function(pointer, returnCallback, errorCallback) {
		/*
		Sets the firmware pointer for :func:`Write Firmware`. The pointer has
		to be increased by chunks of size 64. The data is written to flash
		every 4 chunks (which equals to one page of size 256).
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialQuadRelayV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER, [pointer], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeFirmware = function(data, returnCallback, errorCallback) {
		/*
		Writes 64 Bytes of firmware at the position as written by
		:func:`Set Write Firmware Pointer` before. The firmware is written
		to flash every 4 chunks.
		
		You can only write firmware in bootloader mode.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialQuadRelayV2.FUNCTION_WRITE_FIRMWARE, [data], 'B64', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setStatusLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Sets the status LED configuration. By default the LED shows
		communication traffic between Brick and Bricklet, it flickers once
		for every 10 received data packets.
		
		You can also turn the LED permanently on/off or show a heartbeat.
		
		If the Bricklet is in bootloader mode, the LED is will show heartbeat by default.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialQuadRelayV2.FUNCTION_SET_STATUS_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getStatusLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Status LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialQuadRelayV2.FUNCTION_GET_STATUS_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getChipTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature as measured inside the microcontroller. The
		value returned is not the ambient temperature!
		
		The temperature is only proportional to the real temperature and it has bad
		accuracy. Practically it is only useful as an indicator for
		temperature changes.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialQuadRelayV2.FUNCTION_GET_CHIP_TEMPERATURE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.reset = function(returnCallback, errorCallback) {
		/*
		Calling this function will reset the Bricklet. All configurations
		will be lost.
		
		After a reset you have to create new device objects,
		calling functions on the existing ones will result in
		undefined behavior!
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialQuadRelayV2.FUNCTION_RESET, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeUID = function(uid, returnCallback, errorCallback) {
		/*
		Writes a new UID into flash. If you want to set a new UID
		you have to decode the Base58 encoded UID string into an
		integer first.
		
		We recommend that you use Brick Viewer to change the UID.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialQuadRelayV2.FUNCTION_WRITE_UID, [uid], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.readUID = function(returnCallback, errorCallback) {
		/*
		Returns the current UID as an integer. Encode as
		Base58 to get the usual string version.
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialQuadRelayV2.FUNCTION_READ_UID, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletIndustrialQuadRelayV2.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletIndustrialQuadRelayV2;

},{"./Device":279,"./IPConnection":280}],207:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletIsolator.DEVICE_IDENTIFIER = 2122;
BrickletIsolator.DEVICE_DISPLAY_NAME = 'Isolator Bricklet';
BrickletIsolator.CALLBACK_STATISTICS = 9;
BrickletIsolator.FUNCTION_GET_STATISTICS = 1;
BrickletIsolator.FUNCTION_SET_SPITFP_BAUDRATE_CONFIG = 2;
BrickletIsolator.FUNCTION_GET_SPITFP_BAUDRATE_CONFIG = 3;
BrickletIsolator.FUNCTION_SET_SPITFP_BAUDRATE = 4;
BrickletIsolator.FUNCTION_GET_SPITFP_BAUDRATE = 5;
BrickletIsolator.FUNCTION_GET_ISOLATOR_SPITFP_ERROR_COUNT = 6;
BrickletIsolator.FUNCTION_SET_STATISTICS_CALLBACK_CONFIGURATION = 7;
BrickletIsolator.FUNCTION_GET_STATISTICS_CALLBACK_CONFIGURATION = 8;
BrickletIsolator.FUNCTION_GET_SPITFP_ERROR_COUNT = 234;
BrickletIsolator.FUNCTION_SET_BOOTLOADER_MODE = 235;
BrickletIsolator.FUNCTION_GET_BOOTLOADER_MODE = 236;
BrickletIsolator.FUNCTION_SET_WRITE_FIRMWARE_POINTER = 237;
BrickletIsolator.FUNCTION_WRITE_FIRMWARE = 238;
BrickletIsolator.FUNCTION_SET_STATUS_LED_CONFIG = 239;
BrickletIsolator.FUNCTION_GET_STATUS_LED_CONFIG = 240;
BrickletIsolator.FUNCTION_GET_CHIP_TEMPERATURE = 242;
BrickletIsolator.FUNCTION_RESET = 243;
BrickletIsolator.FUNCTION_WRITE_UID = 248;
BrickletIsolator.FUNCTION_READ_UID = 249;
BrickletIsolator.FUNCTION_GET_IDENTITY = 255;
BrickletIsolator.BOOTLOADER_MODE_BOOTLOADER = 0;
BrickletIsolator.BOOTLOADER_MODE_FIRMWARE = 1;
BrickletIsolator.BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT = 2;
BrickletIsolator.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT = 3;
BrickletIsolator.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT = 4;
BrickletIsolator.BOOTLOADER_STATUS_OK = 0;
BrickletIsolator.BOOTLOADER_STATUS_INVALID_MODE = 1;
BrickletIsolator.BOOTLOADER_STATUS_NO_CHANGE = 2;
BrickletIsolator.BOOTLOADER_STATUS_ENTRY_FUNCTION_NOT_PRESENT = 3;
BrickletIsolator.BOOTLOADER_STATUS_DEVICE_IDENTIFIER_INCORRECT = 4;
BrickletIsolator.BOOTLOADER_STATUS_CRC_MISMATCH = 5;
BrickletIsolator.STATUS_LED_CONFIG_OFF = 0;
BrickletIsolator.STATUS_LED_CONFIG_ON = 1;
BrickletIsolator.STATUS_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletIsolator.STATUS_LED_CONFIG_SHOW_STATUS = 3;

function BrickletIsolator(uid, ipcon) {
	//Galvanically isolates any Bricklet from any Brick

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletIsolator.DEVICE_IDENTIFIER, BrickletIsolator.DEVICE_DISPLAY_NAME);
	BrickletIsolator.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 1];
	this.responseExpected[BrickletIsolator.FUNCTION_GET_STATISTICS] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIsolator.FUNCTION_SET_SPITFP_BAUDRATE_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIsolator.FUNCTION_GET_SPITFP_BAUDRATE_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIsolator.FUNCTION_SET_SPITFP_BAUDRATE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIsolator.FUNCTION_GET_SPITFP_BAUDRATE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIsolator.FUNCTION_GET_ISOLATOR_SPITFP_ERROR_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIsolator.FUNCTION_SET_STATISTICS_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletIsolator.FUNCTION_GET_STATISTICS_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIsolator.FUNCTION_GET_SPITFP_ERROR_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIsolator.FUNCTION_SET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIsolator.FUNCTION_GET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIsolator.FUNCTION_SET_WRITE_FIRMWARE_POINTER] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIsolator.FUNCTION_WRITE_FIRMWARE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIsolator.FUNCTION_SET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIsolator.FUNCTION_GET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIsolator.FUNCTION_GET_CHIP_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIsolator.FUNCTION_RESET] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIsolator.FUNCTION_WRITE_UID] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletIsolator.FUNCTION_READ_UID] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletIsolator.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletIsolator.CALLBACK_STATISTICS] = [26, 'I I H s8'];



	this.getStatistics = function(returnCallback, errorCallback) {
		/*
		Returns statistics for the Isolator Bricklet.
		*/
		this.ipcon.sendRequest(this, BrickletIsolator.FUNCTION_GET_STATISTICS, [], '', 26, 'I I H s8', returnCallback, errorCallback, false, true);
	};
	this.setSPITFPBaudrateConfig = function(enableDynamicBaudrate, minimumDynamicBaudrate, returnCallback, errorCallback) {
		/*
		The SPITF protocol can be used with a dynamic baudrate. If the dynamic baudrate is
		enabled, the Isolator Bricklet will try to adapt the baudrate for the communication
		between Bricks and Bricklets according to the amount of data that is transferred.
		
		The baudrate for communication config between
		Brick and Isolator Bricklet can be set through the API of the Brick.
		
		The baudrate will be increased exponentially if lots of data is sent/received and
		decreased linearly if little data is sent/received.
		
		This lowers the baudrate in applications where little data is transferred (e.g.
		a weather station) and increases the robustness. If there is lots of data to transfer
		(e.g. Thermal Imaging Bricklet) it automatically increases the baudrate as needed.
		
		In cases where some data has to transferred as fast as possible every few seconds
		(e.g. RS485 Bricklet with a high baudrate but small payload) you may want to turn
		the dynamic baudrate off to get the highest possible performance.
		
		The maximum value of the baudrate can be set per port with the function
		:func:`Set SPITFP Baudrate`. If the dynamic baudrate is disabled, the baudrate
		as set by :func:`Set SPITFP Baudrate` will be used statically.
		*/
		this.ipcon.sendRequest(this, BrickletIsolator.FUNCTION_SET_SPITFP_BAUDRATE_CONFIG, [enableDynamicBaudrate, minimumDynamicBaudrate], '? I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPBaudrateConfig = function(returnCallback, errorCallback) {
		/*
		Returns the baudrate config, see :func:`Set SPITFP Baudrate Config`.
		*/
		this.ipcon.sendRequest(this, BrickletIsolator.FUNCTION_GET_SPITFP_BAUDRATE_CONFIG, [], '', 13, '? I', returnCallback, errorCallback, false, true);
	};
	this.setSPITFPBaudrate = function(baudrate, returnCallback, errorCallback) {
		/*
		Sets the baudrate for a the communication between Isolator Bricklet
		and the connected Bricklet. The baudrate for communication between
		Brick and Isolator Bricklet can be set through the API of the Brick.
		
		If you want to increase the throughput of Bricklets you can increase
		the baudrate. If you get a high error count because of high
		interference (see :func:`Get SPITFP Error Count`) you can decrease the
		baudrate.
		
		If the dynamic baudrate feature is enabled, the baudrate set by this
		function corresponds to the maximum baudrate (see :func:`Set SPITFP Baudrate Config`).
		
		Regulatory testing is done with the default baudrate. If CE compatibility
		or similar is necessary in your applications we recommend to not change
		the baudrate.
		*/
		this.ipcon.sendRequest(this, BrickletIsolator.FUNCTION_SET_SPITFP_BAUDRATE, [baudrate], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPBaudrate = function(returnCallback, errorCallback) {
		/*
		Returns the baudrate, see :func:`Set SPITFP Baudrate`.
		*/
		this.ipcon.sendRequest(this, BrickletIsolator.FUNCTION_GET_SPITFP_BAUDRATE, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getIsolatorSPITFPErrorCount = function(returnCallback, errorCallback) {
		/*
		Returns the error count for the communication between Isolator Bricklet and
		the connected Bricklet. Call :func:`Get SPITFP Error Count` to get the
		error count between Isolator Bricklet and Brick.
		
		The errors are divided into
		
		* ACK checksum errors,
		* message checksum errors,
		* framing errors and
		* overflow errors.
		*/
		this.ipcon.sendRequest(this, BrickletIsolator.FUNCTION_GET_ISOLATOR_SPITFP_ERROR_COUNT, [], '', 24, 'I I I I', returnCallback, errorCallback, false, true);
	};
	this.setStatisticsCallbackConfiguration = function(period, valueHasToChange, returnCallback, errorCallback) {
		/*
		The period is the period with which the :cb:`Statistics`
		callback is triggered periodically. A value of 0 turns the callback off.
		
		If the `value has to change`-parameter is set to true, the callback is only
		triggered after the value has changed. If the value didn't change within the
		period, the callback is triggered immediately on change.
		
		If it is set to false, the callback is continuously triggered with the period,
		independent of the value.
		
		.. versionadded:: 2.0.2$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletIsolator.FUNCTION_SET_STATISTICS_CALLBACK_CONFIGURATION, [period, valueHasToChange], 'I ?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getStatisticsCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the callback configuration as set by
		:func:`Set Statistics Callback Configuration`.
		
		.. versionadded:: 2.0.2$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletIsolator.FUNCTION_GET_STATISTICS_CALLBACK_CONFIGURATION, [], '', 13, 'I ?', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPErrorCount = function(returnCallback, errorCallback) {
		/*
		Returns the error count for the communication between Brick and Bricklet.
		
		The errors are divided into
		
		* ACK checksum errors,
		* message checksum errors,
		* framing errors and
		* overflow errors.
		
		The errors counts are for errors that occur on the Bricklet side. All
		Bricks have a similar function that returns the errors on the Brick side.
		*/
		this.ipcon.sendRequest(this, BrickletIsolator.FUNCTION_GET_SPITFP_ERROR_COUNT, [], '', 24, 'I I I I', returnCallback, errorCallback, false, true);
	};
	this.setBootloaderMode = function(mode, returnCallback, errorCallback) {
		/*
		Sets the bootloader mode and returns the status after the requested
		mode change was instigated.
		
		You can change from bootloader mode to firmware mode and vice versa. A change
		from bootloader mode to firmware mode will only take place if the entry function,
		device identifier and CRC are present and correct.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletIsolator.FUNCTION_SET_BOOTLOADER_MODE, [mode], 'B', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getBootloaderMode = function(returnCallback, errorCallback) {
		/*
		Returns the current bootloader mode, see :func:`Set Bootloader Mode`.
		*/
		this.ipcon.sendRequest(this, BrickletIsolator.FUNCTION_GET_BOOTLOADER_MODE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setWriteFirmwarePointer = function(pointer, returnCallback, errorCallback) {
		/*
		Sets the firmware pointer for :func:`Write Firmware`. The pointer has
		to be increased by chunks of size 64. The data is written to flash
		every 4 chunks (which equals to one page of size 256).
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletIsolator.FUNCTION_SET_WRITE_FIRMWARE_POINTER, [pointer], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeFirmware = function(data, returnCallback, errorCallback) {
		/*
		Writes 64 Bytes of firmware at the position as written by
		:func:`Set Write Firmware Pointer` before. The firmware is written
		to flash every 4 chunks.
		
		You can only write firmware in bootloader mode.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletIsolator.FUNCTION_WRITE_FIRMWARE, [data], 'B64', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setStatusLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Sets the status LED configuration. By default the LED shows
		communication traffic between Brick and Bricklet, it flickers once
		for every 10 received data packets.
		
		You can also turn the LED permanently on/off or show a heartbeat.
		
		If the Bricklet is in bootloader mode, the LED is will show heartbeat by default.
		*/
		this.ipcon.sendRequest(this, BrickletIsolator.FUNCTION_SET_STATUS_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getStatusLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Status LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletIsolator.FUNCTION_GET_STATUS_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getChipTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature as measured inside the microcontroller. The
		value returned is not the ambient temperature!
		
		The temperature is only proportional to the real temperature and it has bad
		accuracy. Practically it is only useful as an indicator for
		temperature changes.
		*/
		this.ipcon.sendRequest(this, BrickletIsolator.FUNCTION_GET_CHIP_TEMPERATURE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.reset = function(returnCallback, errorCallback) {
		/*
		Calling this function will reset the Bricklet. All configurations
		will be lost.
		
		After a reset you have to create new device objects,
		calling functions on the existing ones will result in
		undefined behavior!
		*/
		this.ipcon.sendRequest(this, BrickletIsolator.FUNCTION_RESET, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeUID = function(uid, returnCallback, errorCallback) {
		/*
		Writes a new UID into flash. If you want to set a new UID
		you have to decode the Base58 encoded UID string into an
		integer first.
		
		We recommend that you use Brick Viewer to change the UID.
		*/
		this.ipcon.sendRequest(this, BrickletIsolator.FUNCTION_WRITE_UID, [uid], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.readUID = function(returnCallback, errorCallback) {
		/*
		Returns the current UID as an integer. Encode as
		Base58 to get the usual string version.
		*/
		this.ipcon.sendRequest(this, BrickletIsolator.FUNCTION_READ_UID, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletIsolator.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletIsolator;

},{"./Device":279,"./IPConnection":280}],208:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletJoystick.DEVICE_IDENTIFIER = 210;
BrickletJoystick.DEVICE_DISPLAY_NAME = 'Joystick Bricklet';
BrickletJoystick.CALLBACK_POSITION = 15;
BrickletJoystick.CALLBACK_ANALOG_VALUE = 16;
BrickletJoystick.CALLBACK_POSITION_REACHED = 17;
BrickletJoystick.CALLBACK_ANALOG_VALUE_REACHED = 18;
BrickletJoystick.CALLBACK_PRESSED = 19;
BrickletJoystick.CALLBACK_RELEASED = 20;
BrickletJoystick.FUNCTION_GET_POSITION = 1;
BrickletJoystick.FUNCTION_IS_PRESSED = 2;
BrickletJoystick.FUNCTION_GET_ANALOG_VALUE = 3;
BrickletJoystick.FUNCTION_CALIBRATE = 4;
BrickletJoystick.FUNCTION_SET_POSITION_CALLBACK_PERIOD = 5;
BrickletJoystick.FUNCTION_GET_POSITION_CALLBACK_PERIOD = 6;
BrickletJoystick.FUNCTION_SET_ANALOG_VALUE_CALLBACK_PERIOD = 7;
BrickletJoystick.FUNCTION_GET_ANALOG_VALUE_CALLBACK_PERIOD = 8;
BrickletJoystick.FUNCTION_SET_POSITION_CALLBACK_THRESHOLD = 9;
BrickletJoystick.FUNCTION_GET_POSITION_CALLBACK_THRESHOLD = 10;
BrickletJoystick.FUNCTION_SET_ANALOG_VALUE_CALLBACK_THRESHOLD = 11;
BrickletJoystick.FUNCTION_GET_ANALOG_VALUE_CALLBACK_THRESHOLD = 12;
BrickletJoystick.FUNCTION_SET_DEBOUNCE_PERIOD = 13;
BrickletJoystick.FUNCTION_GET_DEBOUNCE_PERIOD = 14;
BrickletJoystick.FUNCTION_GET_IDENTITY = 255;
BrickletJoystick.THRESHOLD_OPTION_OFF = 'x';
BrickletJoystick.THRESHOLD_OPTION_OUTSIDE = 'o';
BrickletJoystick.THRESHOLD_OPTION_INSIDE = 'i';
BrickletJoystick.THRESHOLD_OPTION_SMALLER = '<';
BrickletJoystick.THRESHOLD_OPTION_GREATER = '>';

function BrickletJoystick(uid, ipcon) {
	//2-axis joystick with push-button

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletJoystick.DEVICE_IDENTIFIER, BrickletJoystick.DEVICE_DISPLAY_NAME);
	BrickletJoystick.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickletJoystick.FUNCTION_GET_POSITION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletJoystick.FUNCTION_IS_PRESSED] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletJoystick.FUNCTION_GET_ANALOG_VALUE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletJoystick.FUNCTION_CALIBRATE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletJoystick.FUNCTION_SET_POSITION_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletJoystick.FUNCTION_GET_POSITION_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletJoystick.FUNCTION_SET_ANALOG_VALUE_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletJoystick.FUNCTION_GET_ANALOG_VALUE_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletJoystick.FUNCTION_SET_POSITION_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletJoystick.FUNCTION_GET_POSITION_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletJoystick.FUNCTION_SET_ANALOG_VALUE_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletJoystick.FUNCTION_GET_ANALOG_VALUE_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletJoystick.FUNCTION_SET_DEBOUNCE_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletJoystick.FUNCTION_GET_DEBOUNCE_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletJoystick.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletJoystick.CALLBACK_POSITION] = [12, 'h h'];
	this.callbackFormats[BrickletJoystick.CALLBACK_ANALOG_VALUE] = [12, 'H H'];
	this.callbackFormats[BrickletJoystick.CALLBACK_POSITION_REACHED] = [12, 'h h'];
	this.callbackFormats[BrickletJoystick.CALLBACK_ANALOG_VALUE_REACHED] = [12, 'H H'];
	this.callbackFormats[BrickletJoystick.CALLBACK_PRESSED] = [8, ''];
	this.callbackFormats[BrickletJoystick.CALLBACK_RELEASED] = [8, ''];



	this.getPosition = function(returnCallback, errorCallback) {
		/*
		Returns the position of the joystick. The middle position of the joystick is x=0, y=0.
		The returned values are averaged and calibrated (see :func:`Calibrate`).
		
		If you want to get the position periodically, it is recommended to use the
		:cb:`Position` callback and set the period with
		:func:`Set Position Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletJoystick.FUNCTION_GET_POSITION, [], '', 12, 'h h', returnCallback, errorCallback, false, true);
	};
	this.isPressed = function(returnCallback, errorCallback) {
		/*
		Returns *true* if the button is pressed and *false* otherwise.
		
		It is recommended to use the :cb:`Pressed` and :cb:`Released` callbacks
		to handle the button.
		*/
		this.ipcon.sendRequest(this, BrickletJoystick.FUNCTION_IS_PRESSED, [], '', 9, '?', returnCallback, errorCallback, false, true);
	};
	this.getAnalogValue = function(returnCallback, errorCallback) {
		/*
		Returns the values as read by a 12-bit analog-to-digital converter.
		
		.. note::
		 The values returned by :func:`Get Position` are averaged over several samples
		 to yield less noise, while :func:`Get Analog Value` gives back raw
		 unfiltered analog values. The only reason to use :func:`Get Analog Value` is,
		 if you need the full resolution of the analog-to-digital converter.
		
		If you want the analog values periodically, it is recommended to use the
		:cb:`Analog Value` callback and set the period with
		:func:`Set Analog Value Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletJoystick.FUNCTION_GET_ANALOG_VALUE, [], '', 12, 'H H', returnCallback, errorCallback, false, true);
	};
	this.calibrate = function(returnCallback, errorCallback) {
		/*
		Calibrates the middle position of the joystick. If your Joystick Bricklet
		does not return x=0 and y=0 in the middle position, call this function
		while the joystick is standing still in the middle position.
		
		The resulting calibration will be saved on the EEPROM of the Joystick
		Bricklet, thus you only have to calibrate it once.
		*/
		this.ipcon.sendRequest(this, BrickletJoystick.FUNCTION_CALIBRATE, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.setPositionCallbackPeriod = function(period, returnCallback, errorCallback) {
		/*
		Sets the period with which the :cb:`Position` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		The :cb:`Position` callback is only triggered if the position has changed since the
		last triggering.
		*/
		this.ipcon.sendRequest(this, BrickletJoystick.FUNCTION_SET_POSITION_CALLBACK_PERIOD, [period], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getPositionCallbackPeriod = function(returnCallback, errorCallback) {
		/*
		Returns the period as set by :func:`Set Position Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletJoystick.FUNCTION_GET_POSITION_CALLBACK_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setAnalogValueCallbackPeriod = function(period, returnCallback, errorCallback) {
		/*
		Sets the period with which the :cb:`Analog Value` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		The :cb:`Analog Value` callback is only triggered if the analog values have
		changed since the last triggering.
		*/
		this.ipcon.sendRequest(this, BrickletJoystick.FUNCTION_SET_ANALOG_VALUE_CALLBACK_PERIOD, [period], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getAnalogValueCallbackPeriod = function(returnCallback, errorCallback) {
		/*
		Returns the period as set by :func:`Set Analog Value Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletJoystick.FUNCTION_GET_ANALOG_VALUE_CALLBACK_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setPositionCallbackThreshold = function(option, minX, maxX, minY, maxY, returnCallback, errorCallback) {
		/*
		Sets the thresholds for the :cb:`Position Reached` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Callback is turned off"
		 "'o'",    "Callback is triggered when the position is *outside* the min and max values"
		 "'i'",    "Callback is triggered when the position is *inside* the min and max values"
		 "'<'",    "Callback is triggered when the position is smaller than the min values (max is ignored)"
		 "'>'",    "Callback is triggered when the position is greater than the min values (max is ignored)"
		*/
		this.ipcon.sendRequest(this, BrickletJoystick.FUNCTION_SET_POSITION_CALLBACK_THRESHOLD, [option, minX, maxX, minY, maxY], 'c h h h h', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getPositionCallbackThreshold = function(returnCallback, errorCallback) {
		/*
		Returns the threshold as set by :func:`Set Position Callback Threshold`.
		*/
		this.ipcon.sendRequest(this, BrickletJoystick.FUNCTION_GET_POSITION_CALLBACK_THRESHOLD, [], '', 17, 'c h h h h', returnCallback, errorCallback, false, true);
	};
	this.setAnalogValueCallbackThreshold = function(option, minX, maxX, minY, maxY, returnCallback, errorCallback) {
		/*
		Sets the thresholds for the :cb:`Analog Value Reached` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Callback is turned off"
		 "'o'",    "Callback is triggered when the analog values are *outside* the min and max values"
		 "'i'",    "Callback is triggered when the analog values are *inside* the min and max values"
		 "'<'",    "Callback is triggered when the analog values are smaller than the min values (max is ignored)"
		 "'>'",    "Callback is triggered when the analog values are greater than the min values (max is ignored)"
		*/
		this.ipcon.sendRequest(this, BrickletJoystick.FUNCTION_SET_ANALOG_VALUE_CALLBACK_THRESHOLD, [option, minX, maxX, minY, maxY], 'c H H H H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getAnalogValueCallbackThreshold = function(returnCallback, errorCallback) {
		/*
		Returns the threshold as set by :func:`Set Analog Value Callback Threshold`.
		*/
		this.ipcon.sendRequest(this, BrickletJoystick.FUNCTION_GET_ANALOG_VALUE_CALLBACK_THRESHOLD, [], '', 17, 'c H H H H', returnCallback, errorCallback, false, true);
	};
	this.setDebouncePeriod = function(debounce, returnCallback, errorCallback) {
		/*
		Sets the period with which the threshold callbacks
		
		* :cb:`Position Reached`,
		* :cb:`Analog Value Reached`
		
		are triggered, if the thresholds
		
		* :func:`Set Position Callback Threshold`,
		* :func:`Set Analog Value Callback Threshold`
		
		keep being reached.
		*/
		this.ipcon.sendRequest(this, BrickletJoystick.FUNCTION_SET_DEBOUNCE_PERIOD, [debounce], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getDebouncePeriod = function(returnCallback, errorCallback) {
		/*
		Returns the debounce period as set by :func:`Set Debounce Period`.
		*/
		this.ipcon.sendRequest(this, BrickletJoystick.FUNCTION_GET_DEBOUNCE_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletJoystick.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletJoystick;

},{"./Device":279,"./IPConnection":280}],209:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletJoystickV2.DEVICE_IDENTIFIER = 2138;
BrickletJoystickV2.DEVICE_DISPLAY_NAME = 'Joystick Bricklet 2.0';
BrickletJoystickV2.CALLBACK_POSITION = 6;
BrickletJoystickV2.CALLBACK_PRESSED = 9;
BrickletJoystickV2.FUNCTION_GET_POSITION = 1;
BrickletJoystickV2.FUNCTION_IS_PRESSED = 2;
BrickletJoystickV2.FUNCTION_CALIBRATE = 3;
BrickletJoystickV2.FUNCTION_SET_POSITION_CALLBACK_CONFIGURATION = 4;
BrickletJoystickV2.FUNCTION_GET_POSITION_CALLBACK_CONFIGURATION = 5;
BrickletJoystickV2.FUNCTION_SET_PRESSED_CALLBACK_CONFIGURATION = 7;
BrickletJoystickV2.FUNCTION_GET_PRESSED_CALLBACK_CONFIGURATION = 8;
BrickletJoystickV2.FUNCTION_GET_SPITFP_ERROR_COUNT = 234;
BrickletJoystickV2.FUNCTION_SET_BOOTLOADER_MODE = 235;
BrickletJoystickV2.FUNCTION_GET_BOOTLOADER_MODE = 236;
BrickletJoystickV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER = 237;
BrickletJoystickV2.FUNCTION_WRITE_FIRMWARE = 238;
BrickletJoystickV2.FUNCTION_SET_STATUS_LED_CONFIG = 239;
BrickletJoystickV2.FUNCTION_GET_STATUS_LED_CONFIG = 240;
BrickletJoystickV2.FUNCTION_GET_CHIP_TEMPERATURE = 242;
BrickletJoystickV2.FUNCTION_RESET = 243;
BrickletJoystickV2.FUNCTION_WRITE_UID = 248;
BrickletJoystickV2.FUNCTION_READ_UID = 249;
BrickletJoystickV2.FUNCTION_GET_IDENTITY = 255;
BrickletJoystickV2.BOOTLOADER_MODE_BOOTLOADER = 0;
BrickletJoystickV2.BOOTLOADER_MODE_FIRMWARE = 1;
BrickletJoystickV2.BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT = 2;
BrickletJoystickV2.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT = 3;
BrickletJoystickV2.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT = 4;
BrickletJoystickV2.BOOTLOADER_STATUS_OK = 0;
BrickletJoystickV2.BOOTLOADER_STATUS_INVALID_MODE = 1;
BrickletJoystickV2.BOOTLOADER_STATUS_NO_CHANGE = 2;
BrickletJoystickV2.BOOTLOADER_STATUS_ENTRY_FUNCTION_NOT_PRESENT = 3;
BrickletJoystickV2.BOOTLOADER_STATUS_DEVICE_IDENTIFIER_INCORRECT = 4;
BrickletJoystickV2.BOOTLOADER_STATUS_CRC_MISMATCH = 5;
BrickletJoystickV2.STATUS_LED_CONFIG_OFF = 0;
BrickletJoystickV2.STATUS_LED_CONFIG_ON = 1;
BrickletJoystickV2.STATUS_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletJoystickV2.STATUS_LED_CONFIG_SHOW_STATUS = 3;

function BrickletJoystickV2(uid, ipcon) {
	//2-axis joystick with push-button

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletJoystickV2.DEVICE_IDENTIFIER, BrickletJoystickV2.DEVICE_DISPLAY_NAME);
	BrickletJoystickV2.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickletJoystickV2.FUNCTION_GET_POSITION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletJoystickV2.FUNCTION_IS_PRESSED] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletJoystickV2.FUNCTION_CALIBRATE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletJoystickV2.FUNCTION_SET_POSITION_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletJoystickV2.FUNCTION_GET_POSITION_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletJoystickV2.FUNCTION_SET_PRESSED_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletJoystickV2.FUNCTION_GET_PRESSED_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletJoystickV2.FUNCTION_GET_SPITFP_ERROR_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletJoystickV2.FUNCTION_SET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletJoystickV2.FUNCTION_GET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletJoystickV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletJoystickV2.FUNCTION_WRITE_FIRMWARE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletJoystickV2.FUNCTION_SET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletJoystickV2.FUNCTION_GET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletJoystickV2.FUNCTION_GET_CHIP_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletJoystickV2.FUNCTION_RESET] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletJoystickV2.FUNCTION_WRITE_UID] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletJoystickV2.FUNCTION_READ_UID] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletJoystickV2.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletJoystickV2.CALLBACK_POSITION] = [12, 'h h'];
	this.callbackFormats[BrickletJoystickV2.CALLBACK_PRESSED] = [9, '?'];



	this.getPosition = function(returnCallback, errorCallback) {
		/*
		Returns the position of the joystick. The middle position of the joystick is x=0, y=0.
		The returned values are averaged and calibrated (see :func:`Calibrate`).
		
		If you want to get the position periodically, it is recommended to use the
		:cb:`Position` callback and set the period with
		:func:`Set Position Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletJoystickV2.FUNCTION_GET_POSITION, [], '', 12, 'h h', returnCallback, errorCallback, false, true);
	};
	this.isPressed = function(returnCallback, errorCallback) {
		/*
		Returns *true* if the button is pressed and *false* otherwise.
		
		If you want to get the press-state periodically, it is recommended to use the
		:cb:`Pressed` callback and set the period with
		:func:`Set Pressed Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletJoystickV2.FUNCTION_IS_PRESSED, [], '', 9, '?', returnCallback, errorCallback, false, true);
	};
	this.calibrate = function(returnCallback, errorCallback) {
		/*
		Calibrates the middle position of the joystick. If your Joystick Bricklet 2.0
		does not return x=0 and y=0 in the middle position, call this function
		while the joystick is standing still in the middle position.
		
		The resulting calibration will be saved in non-volatile memory,
		thus you only have to calibrate it once.
		*/
		this.ipcon.sendRequest(this, BrickletJoystickV2.FUNCTION_CALIBRATE, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.setPositionCallbackConfiguration = function(period, valueHasToChange, returnCallback, errorCallback) {
		/*
		The period is the period with which the :cb:`Position`
		callback is triggered periodically. A value of 0 turns the callback off.
		
		If the `value has to change`-parameter is set to true, the callback is only
		triggered after at least one of the values has changed. If the values didn't
		change within the period, the callback is triggered immediately on change.
		
		If it is set to false, the callback is continuously triggered with the period,
		independent of the value.
		*/
		this.ipcon.sendRequest(this, BrickletJoystickV2.FUNCTION_SET_POSITION_CALLBACK_CONFIGURATION, [period, valueHasToChange], 'I ?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getPositionCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the callback configuration as set by
		:func:`Set Position Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletJoystickV2.FUNCTION_GET_POSITION_CALLBACK_CONFIGURATION, [], '', 13, 'I ?', returnCallback, errorCallback, false, true);
	};
	this.setPressedCallbackConfiguration = function(period, valueHasToChange, returnCallback, errorCallback) {
		/*
		The period is the period with which the :cb:`Pressed`
		callback is triggered periodically. A value of 0 turns the callback off.
		
		If the `value has to change`-parameter is set to true, the callback is only
		triggered after at least one of the values has changed. If the values didn't
		change within the period, the callback is triggered immediately on change.
		
		If it is set to false, the callback is continuously triggered with the period,
		independent of the value.
		*/
		this.ipcon.sendRequest(this, BrickletJoystickV2.FUNCTION_SET_PRESSED_CALLBACK_CONFIGURATION, [period, valueHasToChange], 'I ?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getPressedCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the callback configuration as set by
		:func:`Set Pressed Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletJoystickV2.FUNCTION_GET_PRESSED_CALLBACK_CONFIGURATION, [], '', 13, 'I ?', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPErrorCount = function(returnCallback, errorCallback) {
		/*
		Returns the error count for the communication between Brick and Bricklet.
		
		The errors are divided into
		
		* ACK checksum errors,
		* message checksum errors,
		* framing errors and
		* overflow errors.
		
		The errors counts are for errors that occur on the Bricklet side. All
		Bricks have a similar function that returns the errors on the Brick side.
		*/
		this.ipcon.sendRequest(this, BrickletJoystickV2.FUNCTION_GET_SPITFP_ERROR_COUNT, [], '', 24, 'I I I I', returnCallback, errorCallback, false, true);
	};
	this.setBootloaderMode = function(mode, returnCallback, errorCallback) {
		/*
		Sets the bootloader mode and returns the status after the requested
		mode change was instigated.
		
		You can change from bootloader mode to firmware mode and vice versa. A change
		from bootloader mode to firmware mode will only take place if the entry function,
		device identifier and CRC are present and correct.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletJoystickV2.FUNCTION_SET_BOOTLOADER_MODE, [mode], 'B', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getBootloaderMode = function(returnCallback, errorCallback) {
		/*
		Returns the current bootloader mode, see :func:`Set Bootloader Mode`.
		*/
		this.ipcon.sendRequest(this, BrickletJoystickV2.FUNCTION_GET_BOOTLOADER_MODE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setWriteFirmwarePointer = function(pointer, returnCallback, errorCallback) {
		/*
		Sets the firmware pointer for :func:`Write Firmware`. The pointer has
		to be increased by chunks of size 64. The data is written to flash
		every 4 chunks (which equals to one page of size 256).
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletJoystickV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER, [pointer], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeFirmware = function(data, returnCallback, errorCallback) {
		/*
		Writes 64 Bytes of firmware at the position as written by
		:func:`Set Write Firmware Pointer` before. The firmware is written
		to flash every 4 chunks.
		
		You can only write firmware in bootloader mode.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletJoystickV2.FUNCTION_WRITE_FIRMWARE, [data], 'B64', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setStatusLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Sets the status LED configuration. By default the LED shows
		communication traffic between Brick and Bricklet, it flickers once
		for every 10 received data packets.
		
		You can also turn the LED permanently on/off or show a heartbeat.
		
		If the Bricklet is in bootloader mode, the LED is will show heartbeat by default.
		*/
		this.ipcon.sendRequest(this, BrickletJoystickV2.FUNCTION_SET_STATUS_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getStatusLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Status LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletJoystickV2.FUNCTION_GET_STATUS_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getChipTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature as measured inside the microcontroller. The
		value returned is not the ambient temperature!
		
		The temperature is only proportional to the real temperature and it has bad
		accuracy. Practically it is only useful as an indicator for
		temperature changes.
		*/
		this.ipcon.sendRequest(this, BrickletJoystickV2.FUNCTION_GET_CHIP_TEMPERATURE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.reset = function(returnCallback, errorCallback) {
		/*
		Calling this function will reset the Bricklet. All configurations
		will be lost.
		
		After a reset you have to create new device objects,
		calling functions on the existing ones will result in
		undefined behavior!
		*/
		this.ipcon.sendRequest(this, BrickletJoystickV2.FUNCTION_RESET, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeUID = function(uid, returnCallback, errorCallback) {
		/*
		Writes a new UID into flash. If you want to set a new UID
		you have to decode the Base58 encoded UID string into an
		integer first.
		
		We recommend that you use Brick Viewer to change the UID.
		*/
		this.ipcon.sendRequest(this, BrickletJoystickV2.FUNCTION_WRITE_UID, [uid], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.readUID = function(returnCallback, errorCallback) {
		/*
		Returns the current UID as an integer. Encode as
		Base58 to get the usual string version.
		*/
		this.ipcon.sendRequest(this, BrickletJoystickV2.FUNCTION_READ_UID, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletJoystickV2.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletJoystickV2;

},{"./Device":279,"./IPConnection":280}],210:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletLCD128x64.DEVICE_IDENTIFIER = 298;
BrickletLCD128x64.DEVICE_DISPLAY_NAME = 'LCD 128x64 Bricklet';
BrickletLCD128x64.CALLBACK_TOUCH_POSITION = 11;
BrickletLCD128x64.CALLBACK_TOUCH_GESTURE = 15;
BrickletLCD128x64.CALLBACK_GUI_BUTTON_PRESSED = 25;
BrickletLCD128x64.CALLBACK_GUI_SLIDER_VALUE = 32;
BrickletLCD128x64.CALLBACK_GUI_TAB_SELECTED = 44;
BrickletLCD128x64.FUNCTION_WRITE_PIXELS_LOW_LEVEL = 1;
BrickletLCD128x64.FUNCTION_READ_PIXELS_LOW_LEVEL = 2;
BrickletLCD128x64.FUNCTION_CLEAR_DISPLAY = 3;
BrickletLCD128x64.FUNCTION_SET_DISPLAY_CONFIGURATION = 4;
BrickletLCD128x64.FUNCTION_GET_DISPLAY_CONFIGURATION = 5;
BrickletLCD128x64.FUNCTION_WRITE_LINE = 6;
BrickletLCD128x64.FUNCTION_DRAW_BUFFERED_FRAME = 7;
BrickletLCD128x64.FUNCTION_GET_TOUCH_POSITION = 8;
BrickletLCD128x64.FUNCTION_SET_TOUCH_POSITION_CALLBACK_CONFIGURATION = 9;
BrickletLCD128x64.FUNCTION_GET_TOUCH_POSITION_CALLBACK_CONFIGURATION = 10;
BrickletLCD128x64.FUNCTION_GET_TOUCH_GESTURE = 12;
BrickletLCD128x64.FUNCTION_SET_TOUCH_GESTURE_CALLBACK_CONFIGURATION = 13;
BrickletLCD128x64.FUNCTION_GET_TOUCH_GESTURE_CALLBACK_CONFIGURATION = 14;
BrickletLCD128x64.FUNCTION_DRAW_LINE = 16;
BrickletLCD128x64.FUNCTION_DRAW_BOX = 17;
BrickletLCD128x64.FUNCTION_DRAW_TEXT = 18;
BrickletLCD128x64.FUNCTION_SET_GUI_BUTTON = 19;
BrickletLCD128x64.FUNCTION_GET_GUI_BUTTON = 20;
BrickletLCD128x64.FUNCTION_REMOVE_GUI_BUTTON = 21;
BrickletLCD128x64.FUNCTION_SET_GUI_BUTTON_PRESSED_CALLBACK_CONFIGURATION = 22;
BrickletLCD128x64.FUNCTION_GET_GUI_BUTTON_PRESSED_CALLBACK_CONFIGURATION = 23;
BrickletLCD128x64.FUNCTION_GET_GUI_BUTTON_PRESSED = 24;
BrickletLCD128x64.FUNCTION_SET_GUI_SLIDER = 26;
BrickletLCD128x64.FUNCTION_GET_GUI_SLIDER = 27;
BrickletLCD128x64.FUNCTION_REMOVE_GUI_SLIDER = 28;
BrickletLCD128x64.FUNCTION_SET_GUI_SLIDER_VALUE_CALLBACK_CONFIGURATION = 29;
BrickletLCD128x64.FUNCTION_GET_GUI_SLIDER_VALUE_CALLBACK_CONFIGURATION = 30;
BrickletLCD128x64.FUNCTION_GET_GUI_SLIDER_VALUE = 31;
BrickletLCD128x64.FUNCTION_SET_GUI_TAB_CONFIGURATION = 33;
BrickletLCD128x64.FUNCTION_GET_GUI_TAB_CONFIGURATION = 34;
BrickletLCD128x64.FUNCTION_SET_GUI_TAB_TEXT = 35;
BrickletLCD128x64.FUNCTION_GET_GUI_TAB_TEXT = 36;
BrickletLCD128x64.FUNCTION_SET_GUI_TAB_ICON = 37;
BrickletLCD128x64.FUNCTION_GET_GUI_TAB_ICON = 38;
BrickletLCD128x64.FUNCTION_REMOVE_GUI_TAB = 39;
BrickletLCD128x64.FUNCTION_SET_GUI_TAB_SELECTED = 40;
BrickletLCD128x64.FUNCTION_SET_GUI_TAB_SELECTED_CALLBACK_CONFIGURATION = 41;
BrickletLCD128x64.FUNCTION_GET_GUI_TAB_SELECTED_CALLBACK_CONFIGURATION = 42;
BrickletLCD128x64.FUNCTION_GET_GUI_TAB_SELECTED = 43;
BrickletLCD128x64.FUNCTION_SET_GUI_GRAPH_CONFIGURATION = 45;
BrickletLCD128x64.FUNCTION_GET_GUI_GRAPH_CONFIGURATION = 46;
BrickletLCD128x64.FUNCTION_SET_GUI_GRAPH_DATA_LOW_LEVEL = 47;
BrickletLCD128x64.FUNCTION_GET_GUI_GRAPH_DATA_LOW_LEVEL = 48;
BrickletLCD128x64.FUNCTION_REMOVE_GUI_GRAPH = 49;
BrickletLCD128x64.FUNCTION_REMOVE_ALL_GUI = 50;
BrickletLCD128x64.FUNCTION_SET_TOUCH_LED_CONFIG = 51;
BrickletLCD128x64.FUNCTION_GET_TOUCH_LED_CONFIG = 52;
BrickletLCD128x64.FUNCTION_GET_SPITFP_ERROR_COUNT = 234;
BrickletLCD128x64.FUNCTION_SET_BOOTLOADER_MODE = 235;
BrickletLCD128x64.FUNCTION_GET_BOOTLOADER_MODE = 236;
BrickletLCD128x64.FUNCTION_SET_WRITE_FIRMWARE_POINTER = 237;
BrickletLCD128x64.FUNCTION_WRITE_FIRMWARE = 238;
BrickletLCD128x64.FUNCTION_SET_STATUS_LED_CONFIG = 239;
BrickletLCD128x64.FUNCTION_GET_STATUS_LED_CONFIG = 240;
BrickletLCD128x64.FUNCTION_GET_CHIP_TEMPERATURE = 242;
BrickletLCD128x64.FUNCTION_RESET = 243;
BrickletLCD128x64.FUNCTION_WRITE_UID = 248;
BrickletLCD128x64.FUNCTION_READ_UID = 249;
BrickletLCD128x64.FUNCTION_GET_IDENTITY = 255;
BrickletLCD128x64.GESTURE_LEFT_TO_RIGHT = 0;
BrickletLCD128x64.GESTURE_RIGHT_TO_LEFT = 1;
BrickletLCD128x64.GESTURE_TOP_TO_BOTTOM = 2;
BrickletLCD128x64.GESTURE_BOTTOM_TO_TOP = 3;
BrickletLCD128x64.COLOR_WHITE = false;
BrickletLCD128x64.COLOR_BLACK = true;
BrickletLCD128x64.FONT_6X8 = 0;
BrickletLCD128x64.FONT_6X16 = 1;
BrickletLCD128x64.FONT_6X24 = 2;
BrickletLCD128x64.FONT_6X32 = 3;
BrickletLCD128x64.FONT_12X16 = 4;
BrickletLCD128x64.FONT_12X24 = 5;
BrickletLCD128x64.FONT_12X32 = 6;
BrickletLCD128x64.FONT_18X24 = 7;
BrickletLCD128x64.FONT_18X32 = 8;
BrickletLCD128x64.FONT_24X32 = 9;
BrickletLCD128x64.DIRECTION_HORIZONTAL = 0;
BrickletLCD128x64.DIRECTION_VERTICAL = 1;
BrickletLCD128x64.CHANGE_TAB_ON_CLICK = 1;
BrickletLCD128x64.CHANGE_TAB_ON_SWIPE = 2;
BrickletLCD128x64.CHANGE_TAB_ON_CLICK_AND_SWIPE = 3;
BrickletLCD128x64.GRAPH_TYPE_DOT = 0;
BrickletLCD128x64.GRAPH_TYPE_LINE = 1;
BrickletLCD128x64.GRAPH_TYPE_BAR = 2;
BrickletLCD128x64.TOUCH_LED_CONFIG_OFF = 0;
BrickletLCD128x64.TOUCH_LED_CONFIG_ON = 1;
BrickletLCD128x64.TOUCH_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletLCD128x64.TOUCH_LED_CONFIG_SHOW_TOUCH = 3;
BrickletLCD128x64.BOOTLOADER_MODE_BOOTLOADER = 0;
BrickletLCD128x64.BOOTLOADER_MODE_FIRMWARE = 1;
BrickletLCD128x64.BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT = 2;
BrickletLCD128x64.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT = 3;
BrickletLCD128x64.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT = 4;
BrickletLCD128x64.BOOTLOADER_STATUS_OK = 0;
BrickletLCD128x64.BOOTLOADER_STATUS_INVALID_MODE = 1;
BrickletLCD128x64.BOOTLOADER_STATUS_NO_CHANGE = 2;
BrickletLCD128x64.BOOTLOADER_STATUS_ENTRY_FUNCTION_NOT_PRESENT = 3;
BrickletLCD128x64.BOOTLOADER_STATUS_DEVICE_IDENTIFIER_INCORRECT = 4;
BrickletLCD128x64.BOOTLOADER_STATUS_CRC_MISMATCH = 5;
BrickletLCD128x64.STATUS_LED_CONFIG_OFF = 0;
BrickletLCD128x64.STATUS_LED_CONFIG_ON = 1;
BrickletLCD128x64.STATUS_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletLCD128x64.STATUS_LED_CONFIG_SHOW_STATUS = 3;

function BrickletLCD128x64(uid, ipcon) {
	//7.1cm (2.8") display with 128x64 pixel and touch screen

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletLCD128x64.DEVICE_IDENTIFIER, BrickletLCD128x64.DEVICE_DISPLAY_NAME);
	BrickletLCD128x64.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 1];
	this.responseExpected[BrickletLCD128x64.FUNCTION_WRITE_PIXELS_LOW_LEVEL] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletLCD128x64.FUNCTION_READ_PIXELS_LOW_LEVEL] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLCD128x64.FUNCTION_CLEAR_DISPLAY] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletLCD128x64.FUNCTION_SET_DISPLAY_CONFIGURATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletLCD128x64.FUNCTION_GET_DISPLAY_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLCD128x64.FUNCTION_WRITE_LINE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletLCD128x64.FUNCTION_DRAW_BUFFERED_FRAME] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletLCD128x64.FUNCTION_GET_TOUCH_POSITION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLCD128x64.FUNCTION_SET_TOUCH_POSITION_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletLCD128x64.FUNCTION_GET_TOUCH_POSITION_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLCD128x64.FUNCTION_GET_TOUCH_GESTURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLCD128x64.FUNCTION_SET_TOUCH_GESTURE_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletLCD128x64.FUNCTION_GET_TOUCH_GESTURE_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLCD128x64.FUNCTION_DRAW_LINE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletLCD128x64.FUNCTION_DRAW_BOX] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletLCD128x64.FUNCTION_DRAW_TEXT] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletLCD128x64.FUNCTION_SET_GUI_BUTTON] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletLCD128x64.FUNCTION_GET_GUI_BUTTON] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLCD128x64.FUNCTION_REMOVE_GUI_BUTTON] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletLCD128x64.FUNCTION_SET_GUI_BUTTON_PRESSED_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletLCD128x64.FUNCTION_GET_GUI_BUTTON_PRESSED_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLCD128x64.FUNCTION_GET_GUI_BUTTON_PRESSED] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLCD128x64.FUNCTION_SET_GUI_SLIDER] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletLCD128x64.FUNCTION_GET_GUI_SLIDER] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLCD128x64.FUNCTION_REMOVE_GUI_SLIDER] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletLCD128x64.FUNCTION_SET_GUI_SLIDER_VALUE_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletLCD128x64.FUNCTION_GET_GUI_SLIDER_VALUE_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLCD128x64.FUNCTION_GET_GUI_SLIDER_VALUE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLCD128x64.FUNCTION_SET_GUI_TAB_CONFIGURATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletLCD128x64.FUNCTION_GET_GUI_TAB_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLCD128x64.FUNCTION_SET_GUI_TAB_TEXT] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletLCD128x64.FUNCTION_GET_GUI_TAB_TEXT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLCD128x64.FUNCTION_SET_GUI_TAB_ICON] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletLCD128x64.FUNCTION_GET_GUI_TAB_ICON] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLCD128x64.FUNCTION_REMOVE_GUI_TAB] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletLCD128x64.FUNCTION_SET_GUI_TAB_SELECTED] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletLCD128x64.FUNCTION_SET_GUI_TAB_SELECTED_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletLCD128x64.FUNCTION_GET_GUI_TAB_SELECTED_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLCD128x64.FUNCTION_GET_GUI_TAB_SELECTED] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLCD128x64.FUNCTION_SET_GUI_GRAPH_CONFIGURATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletLCD128x64.FUNCTION_GET_GUI_GRAPH_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLCD128x64.FUNCTION_SET_GUI_GRAPH_DATA_LOW_LEVEL] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletLCD128x64.FUNCTION_GET_GUI_GRAPH_DATA_LOW_LEVEL] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLCD128x64.FUNCTION_REMOVE_GUI_GRAPH] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletLCD128x64.FUNCTION_REMOVE_ALL_GUI] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletLCD128x64.FUNCTION_SET_TOUCH_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletLCD128x64.FUNCTION_GET_TOUCH_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLCD128x64.FUNCTION_GET_SPITFP_ERROR_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLCD128x64.FUNCTION_SET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLCD128x64.FUNCTION_GET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLCD128x64.FUNCTION_SET_WRITE_FIRMWARE_POINTER] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletLCD128x64.FUNCTION_WRITE_FIRMWARE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLCD128x64.FUNCTION_SET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletLCD128x64.FUNCTION_GET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLCD128x64.FUNCTION_GET_CHIP_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLCD128x64.FUNCTION_RESET] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletLCD128x64.FUNCTION_WRITE_UID] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletLCD128x64.FUNCTION_READ_UID] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLCD128x64.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletLCD128x64.CALLBACK_TOUCH_POSITION] = [18, 'H H H I'];
	this.callbackFormats[BrickletLCD128x64.CALLBACK_TOUCH_GESTURE] = [27, 'B I H H H H H I'];
	this.callbackFormats[BrickletLCD128x64.CALLBACK_GUI_BUTTON_PRESSED] = [10, 'B ?'];
	this.callbackFormats[BrickletLCD128x64.CALLBACK_GUI_SLIDER_VALUE] = [10, 'B B'];
	this.callbackFormats[BrickletLCD128x64.CALLBACK_GUI_TAB_SELECTED] = [9, 'b'];


	this.streamStateObjects[BrickletLCD128x64.FUNCTION_WRITE_PIXELS_LOW_LEVEL] = {
		'dataMapping': [],
		'dataMappingStreamIn': [null, null, null, null, 'streamLength', 'streamChunkOffset', 'streamChunkData'],
		'streamProperties': {
			'fixedLength': null,
			'singleChunk': false,
			'shortWrite': false
		},
		'responseProperties': {
			'running': false,
			'runningSubcall': false,
			'runningSubcallOOS': false,
			'waitingFirstChunk': true,
			'timeout': null,
			'data': [],
			'streamInChunkOffset': 0,
			'streamInChunkLength': 0,
			'streamInResponseEmpty': true,
			'streamInWritten': 0,
			'streamInLLParams': null,
			'responseHandler': null,
			'packFormatString': 'B B B B H H ?448',
			'unpackFormatString': '',
			'returnCB': null,
			'errorCB': null,
			'callQueue': []
		}
	};
	this.streamStateObjects[BrickletLCD128x64.FUNCTION_READ_PIXELS_LOW_LEVEL] = {
		'dataMapping': ['streamLength', 'streamChunkOffset', 'streamChunkData'],
		'dataMappingStreamIn': [],
		'streamProperties': {
			'fixedLength': null,
			'singleChunk': false,
			'shortWrite': false
		},
		'responseProperties': {
			'running': false,
			'runningSubcall': false,
			'runningSubcallOOS': false,
			'waitingFirstChunk': true,
			'timeout': null,
			'data': [],
			'streamInChunkOffset': 0,
			'streamInChunkLength': 0,
			'streamInResponseEmpty': true,
			'streamInWritten': 0,
			'streamInLLParams': null,
			'responseHandler': null,
			'packFormatString': 'B B B B',
			'unpackFormatString': 'H H ?480',
			'returnCB': null,
			'errorCB': null,
			'callQueue': []
		}
	};
	this.streamStateObjects[BrickletLCD128x64.FUNCTION_SET_GUI_GRAPH_DATA_LOW_LEVEL] = {
		'dataMapping': [],
		'dataMappingStreamIn': [null, 'streamLength', 'streamChunkOffset', 'streamChunkData'],
		'streamProperties': {
			'fixedLength': null,
			'singleChunk': false,
			'shortWrite': false
		},
		'responseProperties': {
			'running': false,
			'runningSubcall': false,
			'runningSubcallOOS': false,
			'waitingFirstChunk': true,
			'timeout': null,
			'data': [],
			'streamInChunkOffset': 0,
			'streamInChunkLength': 0,
			'streamInResponseEmpty': true,
			'streamInWritten': 0,
			'streamInLLParams': null,
			'responseHandler': null,
			'packFormatString': 'B H H B59',
			'unpackFormatString': '',
			'returnCB': null,
			'errorCB': null,
			'callQueue': []
		}
	};
	this.streamStateObjects[BrickletLCD128x64.FUNCTION_GET_GUI_GRAPH_DATA_LOW_LEVEL] = {
		'dataMapping': ['streamLength', 'streamChunkOffset', 'streamChunkData'],
		'dataMappingStreamIn': [],
		'streamProperties': {
			'fixedLength': null,
			'singleChunk': false,
			'shortWrite': false
		},
		'responseProperties': {
			'running': false,
			'runningSubcall': false,
			'runningSubcallOOS': false,
			'waitingFirstChunk': true,
			'timeout': null,
			'data': [],
			'streamInChunkOffset': 0,
			'streamInChunkLength': 0,
			'streamInResponseEmpty': true,
			'streamInWritten': 0,
			'streamInLLParams': null,
			'responseHandler': null,
			'packFormatString': 'B',
			'unpackFormatString': 'H H B59',
			'returnCB': null,
			'errorCB': null,
			'callQueue': []
		}
	};

	this.writePixelsLowLevel = function(xStart, yStart, xEnd, yEnd, pixelsLength, pixelsChunkOffset, pixelsChunkData, returnCallback, errorCallback) {
		/*
		Writes pixels to the specified window.
		
		The pixels are written into the window line by line top to bottom
		and each line is written from left to right.
		
		If automatic draw is enabled (default) the pixels are directly written to
		the screen. Only pixels that have actually changed are updated on the screen,
		the rest stays the same.
		
		If automatic draw is disabled the pixels are written to an internal buffer and
		the buffer is transferred to the display only after :func:`Draw Buffered Frame`
		is called. This can be used to avoid flicker when drawing a complex frame in
		multiple steps.
		
		Automatic draw can be configured with the :func:`Set Display Configuration`
		function.
		*/
		this.ipcon.sendRequest(this, BrickletLCD128x64.FUNCTION_WRITE_PIXELS_LOW_LEVEL, [xStart, yStart, xEnd, yEnd, pixelsLength, pixelsChunkOffset, pixelsChunkData], 'B B B B H H ?448', 0, '', returnCallback, errorCallback, false, true);
	};
	this.readPixelsLowLevel = function(xStart, yStart, xEnd, yEnd, returnCallback, errorCallback) {
		/*
		Reads pixels from the specified window.
		
		The pixels are read from the window line by line top to bottom
		and each line is read from left to right.
		
		If automatic draw is enabled (default) the pixels that are read are always the
		same that are shown on the display.
		
		If automatic draw is disabled the pixels are read from the internal buffer
		(see :func:`Draw Buffered Frame`).
		
		Automatic draw can be configured with the :func:`Set Display Configuration`
		function.
		*/
		this.ipcon.sendRequest(this, BrickletLCD128x64.FUNCTION_READ_PIXELS_LOW_LEVEL, [xStart, yStart, xEnd, yEnd], 'B B B B', 72, 'H H ?480', returnCallback, errorCallback, false, true);
	};
	this.clearDisplay = function(returnCallback, errorCallback) {
		/*
		Clears the complete content of the display.
		
		If automatic draw is enabled (default) the pixels are directly cleared.
		
		If automatic draw is disabled the the internal buffer is cleared and
		the buffer is transferred to the display only after :func:`Draw Buffered Frame`
		is called. This can be used to avoid flicker when drawing a complex frame in
		multiple steps.
		
		Automatic draw can be configured with the :func:`Set Display Configuration`
		function.
		*/
		this.ipcon.sendRequest(this, BrickletLCD128x64.FUNCTION_CLEAR_DISPLAY, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.setDisplayConfiguration = function(contrast, backlight, invert, automaticDraw, returnCallback, errorCallback) {
		/*
		Sets the configuration of the display.
		
		If automatic draw is set to *true*, the display is automatically updated with every
		call of :func:`Write Pixels` and :func:`Write Line`. If it is set to false, the
		changes are written into an internal buffer and only shown on the display after
		a call of :func:`Draw Buffered Frame`.
		*/
		this.ipcon.sendRequest(this, BrickletLCD128x64.FUNCTION_SET_DISPLAY_CONFIGURATION, [contrast, backlight, invert, automaticDraw], 'B B ? ?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getDisplayConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Display Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletLCD128x64.FUNCTION_GET_DISPLAY_CONFIGURATION, [], '', 12, 'B B ? ?', returnCallback, errorCallback, false, true);
	};
	this.writeLine = function(line, position, text, returnCallback, errorCallback) {
		/*
		Writes text to a specific line with a specific position.
		
		For example: (1, 10, "Hello") will write *Hello* in the middle of the
		second line of the display.
		
		The display uses a special 5x7 pixel charset. You can view the characters
		of the charset in Brick Viewer.
		
		If automatic draw is enabled (default) the text is directly written to
		the screen. Only pixels that have actually changed are updated on the screen,
		the rest stays the same.
		
		If automatic draw is disabled the text is written to an internal buffer and
		the buffer is transferred to the display only after :func:`Draw Buffered Frame`
		is called. This can be used to avoid flicker when drawing a complex frame in
		multiple steps.
		
		Automatic draw can be configured with the :func:`Set Display Configuration`
		function.
		
		This function is a 1:1 replacement for the function with the same name
		in the LCD 20x4 Bricklet. You can draw text at a specific pixel position
		and with different font sizes with the :func:`Draw Text` function.
		*/
		this.ipcon.sendRequest(this, BrickletLCD128x64.FUNCTION_WRITE_LINE, [line, position, text], 'B B s22', 0, '', returnCallback, errorCallback, false, true);
	};
	this.drawBufferedFrame = function(forceCompleteRedraw, returnCallback, errorCallback) {
		/*
		Draws the currently buffered frame. Normally each call of :func:`Write Pixels` and
		:func:`Write Line` draws directly onto the display. If you turn automatic draw off
		(:func:`Set Display Configuration`), the data is written in an internal buffer and
		only transferred to the display by calling this function. This can be used to
		avoid flicker when drawing a complex frame in multiple steps.
		
		Set the `force complete redraw` to *true* to redraw the whole display
		instead of only the changed parts. Normally it should not be necessary to set this to
		*true*. It may only become necessary in case of stuck pixels because of errors.
		*/
		this.ipcon.sendRequest(this, BrickletLCD128x64.FUNCTION_DRAW_BUFFERED_FRAME, [forceCompleteRedraw], '?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getTouchPosition = function(returnCallback, errorCallback) {
		/*
		Returns the last valid touch position:
		
		* Pressure: Amount of pressure applied by the user
		* X: Touch position on x-axis
		* Y: Touch position on y-axis
		* Age: Age of touch press (how long ago it was)
		*/
		this.ipcon.sendRequest(this, BrickletLCD128x64.FUNCTION_GET_TOUCH_POSITION, [], '', 18, 'H H H I', returnCallback, errorCallback, false, true);
	};
	this.setTouchPositionCallbackConfiguration = function(period, valueHasToChange, returnCallback, errorCallback) {
		/*
		The period is the period with which the :cb:`Touch Position` callback
		is triggered periodically. A value of 0 turns the callback off.
		
		If the `value has to change`-parameter is set to true, the callback is only
		triggered after the value has changed. If the value didn't change within the
		period, the callback is triggered immediately on change.
		
		If it is set to false, the callback is continuously triggered with the period,
		independent of the value.
		*/
		this.ipcon.sendRequest(this, BrickletLCD128x64.FUNCTION_SET_TOUCH_POSITION_CALLBACK_CONFIGURATION, [period, valueHasToChange], 'I ?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getTouchPositionCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the callback configuration as set by
		:func:`Set Touch Position Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletLCD128x64.FUNCTION_GET_TOUCH_POSITION_CALLBACK_CONFIGURATION, [], '', 13, 'I ?', returnCallback, errorCallback, false, true);
	};
	this.getTouchGesture = function(returnCallback, errorCallback) {
		/*
		Returns one of four touch gestures that can be automatically detected by the Bricklet.
		
		The gestures are swipes from left to right, right to left, top to bottom and bottom to top.
		
		Additionally to the gestures a vector with a start and end position of the gesture is
		provided. You can use this vector do determine a more exact location of the gesture (e.g.
		the swipe from top to bottom was on the left or right part of the screen).
		
		The age parameter corresponds to the age of gesture (how long ago it was).
		*/
		this.ipcon.sendRequest(this, BrickletLCD128x64.FUNCTION_GET_TOUCH_GESTURE, [], '', 27, 'B I H H H H H I', returnCallback, errorCallback, false, true);
	};
	this.setTouchGestureCallbackConfiguration = function(period, valueHasToChange, returnCallback, errorCallback) {
		/*
		The period is the period with which the :cb:`Touch Gesture` callback
		is triggered periodically. A value of 0 turns the callback off.
		
		If the `value has to change`-parameter is set to true, the callback is only
		triggered after the value has changed. If the value didn't change within the
		period, the callback is triggered immediately on change.
		
		If it is set to false, the callback is continuously triggered with the period,
		independent of the value.
		*/
		this.ipcon.sendRequest(this, BrickletLCD128x64.FUNCTION_SET_TOUCH_GESTURE_CALLBACK_CONFIGURATION, [period, valueHasToChange], 'I ?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getTouchGestureCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the callback configuration as set by
		:func:`Set Touch Gesture Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletLCD128x64.FUNCTION_GET_TOUCH_GESTURE_CALLBACK_CONFIGURATION, [], '', 13, 'I ?', returnCallback, errorCallback, false, true);
	};
	this.drawLine = function(positionXStart, positionYStart, positionXEnd, positionYEnd, color, returnCallback, errorCallback) {
		/*
		Draws a white or black line from (x, y)-start to (x, y)-end.
		
		.. versionadded:: 2.0.2$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletLCD128x64.FUNCTION_DRAW_LINE, [positionXStart, positionYStart, positionXEnd, positionYEnd, color], 'B B B B ?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.drawBox = function(positionXStart, positionYStart, positionXEnd, positionYEnd, fill, color, returnCallback, errorCallback) {
		/*
		Draws a white or black box from (x, y)-start to (x, y)-end.
		
		If you set fill to true, the box will be filled with the
		color. Otherwise only the outline will be drawn.
		
		.. versionadded:: 2.0.2$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletLCD128x64.FUNCTION_DRAW_BOX, [positionXStart, positionYStart, positionXEnd, positionYEnd, fill, color], 'B B B B ? ?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.drawText = function(positionX, positionY, font, color, text, returnCallback, errorCallback) {
		/*
		Draws a text at the pixel position (x, y).
		
		You can use one of 9 different font sizes and draw the text in white or black.
		
		.. versionadded:: 2.0.2$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletLCD128x64.FUNCTION_DRAW_TEXT, [positionX, positionY, font, color, text], 'B B B ? s22', 0, '', returnCallback, errorCallback, false, true);
	};
	this.setGUIButton = function(index, positionX, positionY, width, height, text, returnCallback, errorCallback) {
		/*
		Draws a clickable button at position (x, y) with the given text.
		
		You can use up to 12 buttons.
		
		The x position + width has to be within the range of 1 to 128 and the y
		position + height has to be within the range of 1 to 64.
		
		The minimum useful width/height of a button is 3.
		
		You can enable a callback for a button press with
		:func:`Set GUI Button Pressed Callback Configuration`. The callback will
		be triggered for press and release-events.
		
		The button is drawn in a separate GUI buffer and the button-frame will
		always stay on top of the graphics drawn with :func:`Write Pixels`. To
		remove the button use :func:`Remove GUI Button`.
		
		If you want an icon instead of text, you can draw the icon inside of the
		button with :func:`Write Pixels`.
		
		.. versionadded:: 2.0.2$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletLCD128x64.FUNCTION_SET_GUI_BUTTON, [index, positionX, positionY, width, height, text], 'B B B B B s16', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getGUIButton = function(index, returnCallback, errorCallback) {
		/*
		Returns the button properties for a given `Index` as set by :func:`Set GUI Button`.
		
		Additionally the `Active` parameter shows if a button is currently active/visible
		or not.
		
		.. versionadded:: 2.0.2$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletLCD128x64.FUNCTION_GET_GUI_BUTTON, [index], 'B', 29, '? B B B B s16', returnCallback, errorCallback, false, true);
	};
	this.removeGUIButton = function(index, returnCallback, errorCallback) {
		/*
		Removes the button with the given index.
		
		You can use index 255 to remove all buttons.
		
		.. versionadded:: 2.0.2$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletLCD128x64.FUNCTION_REMOVE_GUI_BUTTON, [index], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.setGUIButtonPressedCallbackConfiguration = function(period, valueHasToChange, returnCallback, errorCallback) {
		/*
		The period is the period with which the :cb:`GUI Button Pressed` callback
		is triggered periodically. A value of 0 turns the callback off.
		
		If the `value has to change`-parameter is set to true, the callback is only
		triggered after the value has changed. If the value didn't change within the
		period, the callback is triggered immediately on change.
		
		If it is set to false, the callback is continuously triggered with the period,
		independent of the value.
		
		.. versionadded:: 2.0.2$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletLCD128x64.FUNCTION_SET_GUI_BUTTON_PRESSED_CALLBACK_CONFIGURATION, [period, valueHasToChange], 'I ?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getGUIButtonPressedCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the callback configuration as set by
		:func:`Set GUI Button Pressed Callback Configuration`.
		
		.. versionadded:: 2.0.2$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletLCD128x64.FUNCTION_GET_GUI_BUTTON_PRESSED_CALLBACK_CONFIGURATION, [], '', 13, 'I ?', returnCallback, errorCallback, false, true);
	};
	this.getGUIButtonPressed = function(index, returnCallback, errorCallback) {
		/*
		Returns the state of the button for the given index.
		
		The state can either be pressed (true) or released (false).
		
		.. versionadded:: 2.0.2$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletLCD128x64.FUNCTION_GET_GUI_BUTTON_PRESSED, [index], 'B', 9, '?', returnCallback, errorCallback, false, true);
	};
	this.setGUISlider = function(index, positionX, positionY, length, direction, value, returnCallback, errorCallback) {
		/*
		Draws a slider at position (x, y) with the given length.
		
		You can use up to 6 sliders.
		
		If you use the horizontal direction, the x position + length has to be
		within the range of 1 to 128 and the y position has to be within
		the range of 0 to 46.
		
		If you use the vertical direction, the y position + length has to be
		within the range of 1 to 64 and the x position has to be within
		the range of 0 to 110.
		
		The minimum length of a slider is 8.
		
		The parameter value is the start-position of the slider, it can
		be between 0 and length-8.
		
		You can enable a callback for the slider value with
		:func:`Set GUI Slider Value Callback Configuration`.
		
		The slider is drawn in a separate GUI buffer and it will
		always stay on top of the graphics drawn with :func:`Write Pixels`. To
		remove the button use :func:`Remove GUI Slider`.
		
		.. versionadded:: 2.0.2$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletLCD128x64.FUNCTION_SET_GUI_SLIDER, [index, positionX, positionY, length, direction, value], 'B B B B B B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getGUISlider = function(index, returnCallback, errorCallback) {
		/*
		Returns the slider properties for a given `Index` as set by :func:`Set GUI Slider`.
		
		Additionally the `Active` parameter shows if a button is currently active/visible
		or not.
		
		.. versionadded:: 2.0.2$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletLCD128x64.FUNCTION_GET_GUI_SLIDER, [index], 'B', 14, '? B B B B B', returnCallback, errorCallback, false, true);
	};
	this.removeGUISlider = function(index, returnCallback, errorCallback) {
		/*
		Removes the slider with the given index.
		
		You can use index 255 to remove all slider.
		
		.. versionadded:: 2.0.2$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletLCD128x64.FUNCTION_REMOVE_GUI_SLIDER, [index], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.setGUISliderValueCallbackConfiguration = function(period, valueHasToChange, returnCallback, errorCallback) {
		/*
		The period is the period with which the :cb:`GUI Slider Value` callback
		is triggered periodically. A value of 0 turns the callback off.
		
		If the `value has to change`-parameter is set to true, the callback is only
		triggered after the value has changed. If the value didn't change within the
		period, the callback is triggered immediately on change.
		
		If it is set to false, the callback is continuously triggered with the period,
		independent of the value.
		
		.. versionadded:: 2.0.2$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletLCD128x64.FUNCTION_SET_GUI_SLIDER_VALUE_CALLBACK_CONFIGURATION, [period, valueHasToChange], 'I ?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getGUISliderValueCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the callback configuration as set by
		:func:`Set GUI Slider Value Callback Configuration`.
		
		.. versionadded:: 2.0.2$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletLCD128x64.FUNCTION_GET_GUI_SLIDER_VALUE_CALLBACK_CONFIGURATION, [], '', 13, 'I ?', returnCallback, errorCallback, false, true);
	};
	this.getGUISliderValue = function(index, returnCallback, errorCallback) {
		/*
		Returns the current slider value for the given index.
		
		.. versionadded:: 2.0.2$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletLCD128x64.FUNCTION_GET_GUI_SLIDER_VALUE, [index], 'B', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setGUITabConfiguration = function(changeTabConfig, clearGUI, returnCallback, errorCallback) {
		/*
		Sets the general configuration for tabs. You can configure the tabs to only
		accept clicks or only swipes (gesture left/right and right/left) or both.
		
		Additionally, if you set `Clear GUI` to true, all of the GUI elements (buttons,
		slider, graphs) will automatically be removed on every tab change.
		
		.. versionadded:: 2.0.2$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletLCD128x64.FUNCTION_SET_GUI_TAB_CONFIGURATION, [changeTabConfig, clearGUI], 'B ?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getGUITabConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the tab configuration as set by :func:`Set GUI Tab Configuration`.
		
		.. versionadded:: 2.0.2$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletLCD128x64.FUNCTION_GET_GUI_TAB_CONFIGURATION, [], '', 10, 'B ?', returnCallback, errorCallback, false, true);
	};
	this.setGUITabText = function(index, text, returnCallback, errorCallback) {
		/*
		Adds a text-tab with the given index.
		
		You can use up to 10 tabs.
		
		A text-tab with the same index as a icon-tab will overwrite the icon-tab.
		
		.. versionadded:: 2.0.2$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletLCD128x64.FUNCTION_SET_GUI_TAB_TEXT, [index, text], 'B s5', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getGUITabText = function(index, returnCallback, errorCallback) {
		/*
		Returns the text for a given index as set by :func:`Set GUI Tab Text`.
		
		Additionally the `Active` parameter shows if the tab is currently active/visible
		or not.
		
		.. versionadded:: 2.0.2$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletLCD128x64.FUNCTION_GET_GUI_TAB_TEXT, [index], 'B', 14, '? s5', returnCallback, errorCallback, false, true);
	};
	this.setGUITabIcon = function(index, icon, returnCallback, errorCallback) {
		/*
		Adds a icon-tab with the given index. The icon can have a width of 28 pixels
		with a height of 6 pixels. It is drawn line-by-line from left to right.
		
		You can use up to 10 tabs.
		
		A icon-tab with the same index as a text-tab will overwrite the text-tab.
		
		.. versionadded:: 2.0.2$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletLCD128x64.FUNCTION_SET_GUI_TAB_ICON, [index, icon], 'B ?168', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getGUITabIcon = function(index, returnCallback, errorCallback) {
		/*
		Returns the icon for a given index as set by :func:`Set GUI Tab Icon`.
		
		Additionally the `Active` parameter shows if the tab is currently active/visible
		or not.
		
		.. versionadded:: 2.0.2$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletLCD128x64.FUNCTION_GET_GUI_TAB_ICON, [index], 'B', 30, '? ?168', returnCallback, errorCallback, false, true);
	};
	this.removeGUITab = function(index, returnCallback, errorCallback) {
		/*
		Removes the tab with the given index.
		
		You can use index 255 to remove all tabs.
		
		.. versionadded:: 2.0.2$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletLCD128x64.FUNCTION_REMOVE_GUI_TAB, [index], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.setGUITabSelected = function(index, returnCallback, errorCallback) {
		/*
		Sets the tab with the given index as selected (drawn as selected on the display).
		
		.. versionadded:: 2.0.2$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletLCD128x64.FUNCTION_SET_GUI_TAB_SELECTED, [index], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.setGUITabSelectedCallbackConfiguration = function(period, valueHasToChange, returnCallback, errorCallback) {
		/*
		The period is the period with which the :cb:`GUI Tab Selected` callback
		is triggered periodically. A value of 0 turns the callback off.
		
		If the `value has to change`-parameter is set to true, the callback is only
		triggered after the value has changed. If the value didn't change within the
		period, the callback is triggered immediately on change.
		
		If it is set to false, the callback is continuously triggered with the period,
		independent of the value.
		
		.. versionadded:: 2.0.2$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletLCD128x64.FUNCTION_SET_GUI_TAB_SELECTED_CALLBACK_CONFIGURATION, [period, valueHasToChange], 'I ?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getGUITabSelectedCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the callback configuration as set by
		:func:`Set GUI Tab Selected Callback Configuration`.
		
		.. versionadded:: 2.0.2$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletLCD128x64.FUNCTION_GET_GUI_TAB_SELECTED_CALLBACK_CONFIGURATION, [], '', 13, 'I ?', returnCallback, errorCallback, false, true);
	};
	this.getGUITabSelected = function(returnCallback, errorCallback) {
		/*
		Returns the index of the currently selected tab.
		If there are not tabs, the returned index is -1.
		
		.. versionadded:: 2.0.2$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletLCD128x64.FUNCTION_GET_GUI_TAB_SELECTED, [], '', 9, 'b', returnCallback, errorCallback, false, true);
	};
	this.setGUIGraphConfiguration = function(index, graphType, positionX, positionY, width, height, textX, textY, returnCallback, errorCallback) {
		/*
		Sets the configuration for up to four graphs.
		
		The graph type can be dot-, line- or bar-graph.
		
		The x and y position are pixel positions.
		
		You can add a text for the x and y axis.
		The text is drawn at the inside of the graph and it can overwrite some
		of the graph data. If you need the text outside of the graph you can
		leave this text here empty and use :func:`Draw Text` to draw the caption
		outside of the graph.
		
		The data of the graph can be set and updated with :func:`Set GUI Graph Data`.
		
		The graph is drawn in a separate GUI buffer and the graph-frame and data will
		always stay on top of the graphics drawn with :func:`Write Pixels`. To
		remove the graph use :func:`Remove GUI Graph`.
		
		.. versionadded:: 2.0.2$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletLCD128x64.FUNCTION_SET_GUI_GRAPH_CONFIGURATION, [index, graphType, positionX, positionY, width, height, textX, textY], 'B B B B B B s4 s4', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getGUIGraphConfiguration = function(index, returnCallback, errorCallback) {
		/*
		Returns the graph properties for a given `Index` as set by :func:`Set GUI Graph Configuration`.
		
		Additionally the `Active` parameter shows if a graph is currently active/visible
		or not.
		
		.. versionadded:: 2.0.2$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletLCD128x64.FUNCTION_GET_GUI_GRAPH_CONFIGURATION, [index], 'B', 22, '? B B B B B s4 s4', returnCallback, errorCallback, false, true);
	};
	this.setGUIGraphDataLowLevel = function(index, dataLength, dataChunkOffset, dataChunkData, returnCallback, errorCallback) {
		/*
		Sets the data for a graph with the given index. You have to configure the graph with
		:func:`Set GUI Graph Configuration` before you can set the first data.
		
		The graph will show the first n values of the data that you set, where
		n is the width set with :func:`Set GUI Graph Configuration`. If you set
		less then n values it will show the rest of the values as zero.
		
		The maximum number of data-points you can set is 118 (which also corresponds to the
		maximum width of the graph).
		
		You have to scale your values to be between 0 and 255. 0 will be shown
		at the bottom of the graph and 255 at the top.
		
		.. versionadded:: 2.0.2$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletLCD128x64.FUNCTION_SET_GUI_GRAPH_DATA_LOW_LEVEL, [index, dataLength, dataChunkOffset, dataChunkData], 'B H H B59', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getGUIGraphDataLowLevel = function(index, returnCallback, errorCallback) {
		/*
		Returns the graph data for a given index as set by :func:`Set GUI Graph Data`.
		
		.. versionadded:: 2.0.2$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletLCD128x64.FUNCTION_GET_GUI_GRAPH_DATA_LOW_LEVEL, [index], 'B', 71, 'H H B59', returnCallback, errorCallback, false, true);
	};
	this.removeGUIGraph = function(index, returnCallback, errorCallback) {
		/*
		Removes the graph with the given index.
		
		You can use index 255 to remove all graphs.
		
		.. versionadded:: 2.0.2$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletLCD128x64.FUNCTION_REMOVE_GUI_GRAPH, [index], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.removeAllGUI = function(returnCallback, errorCallback) {
		/*
		Removes all GUI elements (buttons, slider, graphs, tabs).
		
		.. versionadded:: 2.0.2$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletLCD128x64.FUNCTION_REMOVE_ALL_GUI, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.setTouchLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Sets the touch LED configuration. By default the LED is on if the
		LCD is touched.
		
		You can also turn the LED permanently on/off or show a heartbeat.
		
		If the Bricklet is in bootloader mode, the LED is off.
		
		.. versionadded:: 2.0.2$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletLCD128x64.FUNCTION_SET_TOUCH_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getTouchLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Touch LED Config`
		
		.. versionadded:: 2.0.2$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletLCD128x64.FUNCTION_GET_TOUCH_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPErrorCount = function(returnCallback, errorCallback) {
		/*
		Returns the error count for the communication between Brick and Bricklet.
		
		The errors are divided into
		
		* ACK checksum errors,
		* message checksum errors,
		* framing errors and
		* overflow errors.
		
		The errors counts are for errors that occur on the Bricklet side. All
		Bricks have a similar function that returns the errors on the Brick side.
		*/
		this.ipcon.sendRequest(this, BrickletLCD128x64.FUNCTION_GET_SPITFP_ERROR_COUNT, [], '', 24, 'I I I I', returnCallback, errorCallback, false, true);
	};
	this.setBootloaderMode = function(mode, returnCallback, errorCallback) {
		/*
		Sets the bootloader mode and returns the status after the requested
		mode change was instigated.
		
		You can change from bootloader mode to firmware mode and vice versa. A change
		from bootloader mode to firmware mode will only take place if the entry function,
		device identifier and CRC are present and correct.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletLCD128x64.FUNCTION_SET_BOOTLOADER_MODE, [mode], 'B', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getBootloaderMode = function(returnCallback, errorCallback) {
		/*
		Returns the current bootloader mode, see :func:`Set Bootloader Mode`.
		*/
		this.ipcon.sendRequest(this, BrickletLCD128x64.FUNCTION_GET_BOOTLOADER_MODE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setWriteFirmwarePointer = function(pointer, returnCallback, errorCallback) {
		/*
		Sets the firmware pointer for :func:`Write Firmware`. The pointer has
		to be increased by chunks of size 64. The data is written to flash
		every 4 chunks (which equals to one page of size 256).
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletLCD128x64.FUNCTION_SET_WRITE_FIRMWARE_POINTER, [pointer], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeFirmware = function(data, returnCallback, errorCallback) {
		/*
		Writes 64 Bytes of firmware at the position as written by
		:func:`Set Write Firmware Pointer` before. The firmware is written
		to flash every 4 chunks.
		
		You can only write firmware in bootloader mode.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletLCD128x64.FUNCTION_WRITE_FIRMWARE, [data], 'B64', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setStatusLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Sets the status LED configuration. By default the LED shows
		communication traffic between Brick and Bricklet, it flickers once
		for every 10 received data packets.
		
		You can also turn the LED permanently on/off or show a heartbeat.
		
		If the Bricklet is in bootloader mode, the LED is will show heartbeat by default.
		*/
		this.ipcon.sendRequest(this, BrickletLCD128x64.FUNCTION_SET_STATUS_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getStatusLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Status LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletLCD128x64.FUNCTION_GET_STATUS_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getChipTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature as measured inside the microcontroller. The
		value returned is not the ambient temperature!
		
		The temperature is only proportional to the real temperature and it has bad
		accuracy. Practically it is only useful as an indicator for
		temperature changes.
		*/
		this.ipcon.sendRequest(this, BrickletLCD128x64.FUNCTION_GET_CHIP_TEMPERATURE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.reset = function(returnCallback, errorCallback) {
		/*
		Calling this function will reset the Bricklet. All configurations
		will be lost.
		
		After a reset you have to create new device objects,
		calling functions on the existing ones will result in
		undefined behavior!
		*/
		this.ipcon.sendRequest(this, BrickletLCD128x64.FUNCTION_RESET, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeUID = function(uid, returnCallback, errorCallback) {
		/*
		Writes a new UID into flash. If you want to set a new UID
		you have to decode the Base58 encoded UID string into an
		integer first.
		
		We recommend that you use Brick Viewer to change the UID.
		*/
		this.ipcon.sendRequest(this, BrickletLCD128x64.FUNCTION_WRITE_UID, [uid], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.readUID = function(returnCallback, errorCallback) {
		/*
		Returns the current UID as an integer. Encode as
		Base58 to get the usual string version.
		*/
		this.ipcon.sendRequest(this, BrickletLCD128x64.FUNCTION_READ_UID, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletLCD128x64.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};
	this.writePixels = function(xStart, yStart, xEnd, yEnd, pixels, returnCallback, errorCallback) {
		/*
		Writes pixels to the specified window.
		
		The pixels are written into the window line by line top to bottom
		and each line is written from left to right.
		
		If automatic draw is enabled (default) the pixels are directly written to
		the screen. Only pixels that have actually changed are updated on the screen,
		the rest stays the same.
		
		If automatic draw is disabled the pixels are written to an internal buffer and
		the buffer is transferred to the display only after :func:`Draw Buffered Frame`
		is called. This can be used to avoid flicker when drawing a complex frame in
		multiple steps.
		
		Automatic draw can be configured with the :func:`Set Display Configuration`
		function.
		*/

		var pixelsLength = 0;
		var pixelsChunkData = [];
		var pixelsChunkOffset = 0;
		var streamStateObject = this.streamStateObjects[1];

		if (pixels.length > 65535) {
			if (errorCallback !== null){
				errorCallback(IPConnection.ERROR_INVALID_PARAMETER);
			}

			this.resetStreamStateObject(streamStateObject);

			if (streamStateObject['responseProperties']['callQueue'].length > 0) {
				streamStateObject['responseProperties']['callQueue'].shift()(device);
			}

			return;
		}

		if (!this.getResponseExpected(1)) {
			if (streamStateObject['streamProperties']['fixedLength']) {
				pixelsLength = streamStateObject['streamProperties']['fixedLength'];
			}
			else {
				pixelsLength = pixels.length;
			}

			if (streamStateObject['streamProperties']['singleChunk']) {
				pixelsChunkData =
					this.ipcon.createChunkData(pixels, 0, 448, '\0');

				this.ipcon.sendRequest(this,
				                       BrickletLCD128x64.FUNCTION_WRITE_PIXELS_LOW_LEVEL,
				                       [xStart, yStart, xEnd, yEnd, pixelsLength, pixelsChunkOffset, pixelsChunkData],
				                       'B B B B H H ?448',
				                       0,
				                       '',
				                       returnCallback,
				                       errorCallback,
				                       false,
				                       true);
			}
			else {
				while (pixelsChunkOffset < pixels.length) {
					pixelsChunkData =
						this.ipcon.createChunkData(pixels, pixelsChunkOffset, 448, '\0');

					this.ipcon.sendRequest(this,
					                       BrickletLCD128x64.FUNCTION_WRITE_PIXELS_LOW_LEVEL,
					                       [xStart, yStart, xEnd, yEnd, pixelsLength, pixelsChunkOffset, pixelsChunkData],
					                       'B B B B H H ?448',
					                       0,
					                       '',
					                       returnCallback,
					                       errorCallback,
					                       false,
					                       true);

					pixelsChunkOffset += 448;
				}
			}

			if (returnCallback) {
				returnCallback();
			}
		}
		else {
			var responseHandler = null;
			var functionToQueue = null;

			if (streamStateObject['responseProperties']['responseHandler'] === null) {
				responseHandler = function (device, fid, packetResponse) {
					var result = [];
					var payload = null;
					var llvalues = null;
					var packetErrorFlag = 0;
					var rolesMappedData = [];
					var shortWriteWritten = -1;
					var streamStateObject = device.streamStateObjects[fid];
					var responseEmpty = streamStateObject['responseProperties']['streamInResponseEmpty'];
					var pixelsLength = 0;
					var pixelsChunkData = [];
					var pixelsChunkOffset = 0;

					function doNextLLCall() {
						pixelsLength = streamStateObject['responseProperties']['data'].length;
						pixelsChunkData =
							device.ipcon.createChunkData(streamStateObject['responseProperties']['data'],
							                             streamStateObject['responseProperties']['streamInChunkOffset'],
							                             streamStateObject['responseProperties']['streamInChunkLength'],
							                             '\0');
						pixelsChunkOffset = streamStateObject['responseProperties']['streamInChunkOffset'];

						for (var i = 0; i < streamStateObject['dataMappingStreamIn'].length; i++) {
							if (streamStateObject['dataMappingStreamIn'][i] === null) {
								continue;
							}

							if (streamStateObject['dataMappingStreamIn'][i].endsWith('Length')) {
								streamStateObject['responseProperties']['streamInLLParams'][i] = pixelsLength;
							}
							else if (streamStateObject['dataMappingStreamIn'][i].endsWith('Offset')) {
								streamStateObject['responseProperties']['streamInLLParams'][i] = pixelsChunkOffset;
							}
							else if (streamStateObject['dataMappingStreamIn'][i].endsWith('Data')) {
								streamStateObject['responseProperties']['streamInLLParams'][i] = pixelsChunkData;
							}
						}

						device.ipcon.sendRequest(device,
						                         BrickletLCD128x64.FUNCTION_WRITE_PIXELS_LOW_LEVEL,
						                         streamStateObject['responseProperties']['streamInLLParams'],
						                         'B B B B H H ?448',
						                         0,
						                         '',
						                         returnCallback,
						                         errorCallback,
						                         true,
						                         true);

						streamStateObject['responseProperties']['streamInChunkOffset'] += 448;
					}

					function handleStreamInDone() {
						if (streamStateObject['responseProperties']['returnCB']) {
							if (streamStateObject['streamProperties']['shortWrite']) {
								for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
									if (streamStateObject['dataMapping'][i].endsWith('Written')) {
										result[i] = streamStateObject['responseProperties']['streamInWritten'];
										break;
									}
								}
							}

							if (!responseEmpty) {
								streamStateObject['responseProperties']['returnCB'].apply(device, result);
							}
							else {
								streamStateObject['responseProperties']['returnCB'].apply(device);
							}
						}

						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}
					}

					if (!streamStateObject) {
						return;
					}

					packetErrorFlag = device.ipcon.getEFromPacket(packetResponse);

					if (packetErrorFlag !== 0) {
						if (streamStateObject['responseProperties']['errorCB'] !== undefined) {
							if (packetErrorFlag === 1) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_INVALID_PARAMETER);
							}
							else if (packetErrorFlag === 2) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_FUNCTION_NOT_SUPPORTED);
							}
							else {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_UNKNOWN_ERROR);
							}
						}

						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}

						return;
					}

					if (responseEmpty) {
						if (streamStateObject['streamProperties']['singleChunk']) {
							handleStreamInDone();

							return;
						}

						if (streamStateObject['responseProperties']['streamInChunkOffset'] < streamStateObject['responseProperties']['data'].length) {
							doNextLLCall();
						}
						else {
							handleStreamInDone();
						}
					}
					else {
						payload = device.ipcon.getPayloadFromPacket(packetResponse);
						llvalues = device.ipcon.unpack(payload,
						                               streamStateObject['responseProperties']['unpackFormatString']);

						if (!payload || !llvalues) {
							device.resetStreamStateObject(streamStateObject);

							if (streamStateObject['responseProperties']['callQueue'].length > 0) {
								streamStateObject['responseProperties']['callQueue'].shift()(device);
							}

							return;
						}

						for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
							result.push(llvalues[i]);
						}

						if (streamStateObject['streamProperties']['singleChunk']) {
							if (streamStateObject['responseProperties']['returnCB']) {
								streamStateObject['responseProperties']['returnCB'].apply(device, result);
							}

							device.resetStreamStateObject(streamStateObject);

							if (streamStateObject['responseProperties']['callQueue'].length > 0) {
								streamStateObject['responseProperties']['callQueue'].shift()(device);
							}

							return;
						}

						if (streamStateObject['streamProperties']['shortWrite']) {
							for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
								if (streamStateObject['dataMapping'][i].endsWith('Written')) {
									shortWriteWritten = llvalues[i];
									streamStateObject['responseProperties']['streamInWritten'] += shortWriteWritten;
									break;
								}
							}
							if ((shortWriteWritten !== -1) && (shortWriteWritten < 448)) {
								// Either last chunk or short write
								handleStreamInDone();
								return;
							}
						}

						if (streamStateObject['responseProperties']['streamInChunkOffset'] < streamStateObject['responseProperties']['data'].length) {
							doNextLLCall();
						}
						else {
							handleStreamInDone();
						}
					}
				};

				streamStateObject['responseProperties']['responseHandler'] = responseHandler;
			}

			if (!streamStateObject['responseProperties']['running']) {
				streamStateObject['responseProperties']['running'] = true;
				streamStateObject['responseProperties']['returnCB'] = returnCallback;
				streamStateObject['responseProperties']['errorCB'] = errorCallback;
				streamStateObject['responseProperties']['data'].length = 0;
				streamStateObject['responseProperties']['data'].push.apply(streamStateObject['responseProperties']['data'],
				                                                           pixels);

				if (streamStateObject['streamProperties']['fixedLength']) {
					pixelsLength = streamStateObject['streamProperties']['fixedLength'];
				}
				else {
					pixelsLength = pixels.length;
				}

				pixelsChunkOffset = 0;
				pixelsChunkData =
					this.ipcon.createChunkData(pixels, 0, 448, '\0');

				streamStateObject['responseProperties']['streamInChunkOffset'] = 448;
				streamStateObject['responseProperties']['streamInChunkLength'] = 448;
				streamStateObject['responseProperties']['streamInLLParams'] = [xStart, yStart, xEnd, yEnd, pixelsLength, pixelsChunkOffset, pixelsChunkData];

				this.ipcon.sendRequest(this,
				                       BrickletLCD128x64.FUNCTION_WRITE_PIXELS_LOW_LEVEL,
				                       [xStart, yStart, xEnd, yEnd, pixelsLength, pixelsChunkOffset, pixelsChunkData],
				                       'B B B B H H ?448',
				                       0,
				                       '',
				                       returnCallback,
				                       errorCallback,
				                       true,
				                       true);
			}
			else {
				functionToQueue = function (device) {
					device.writePixels.call(device, xStart, yStart, xEnd, yEnd, pixels, returnCallback, errorCallback);
				}

				streamStateObject['responseProperties']['callQueue'].push(functionToQueue);
			}
		}
	};

	this.readPixels = function(xStart, yStart, xEnd, yEnd, returnCallback, errorCallback) {
		/*
		Reads pixels from the specified window.
		
		The pixels are read from the window line by line top to bottom
		and each line is read from left to right.
		
		If automatic draw is enabled (default) the pixels that are read are always the
		same that are shown on the display.
		
		If automatic draw is disabled the pixels are read from the internal buffer
		(see :func:`Draw Buffered Frame`).
		
		Automatic draw can be configured with the :func:`Set Display Configuration`
		function.
		*/
		var responseHandler = null;
		var functionToQueue = null;
		var streamStateObject = this.streamStateObjects[2];
		if (streamStateObject['responseProperties']['responseHandler'] === null) {
			responseHandler = 
				function (device, fid, packetResponse) {
					var result = [];
					var llvalues = null;
					var packetErrorFlag = 0;
					var rolesMappedData = [];
					var pixelsLength = null;
					var pixelsChunkData = null;
					var pixelsOutOfSync = false;
					var streamStateObject = device.streamStateObjects[fid];
					var pixelsChunkOffset = null;
					var payload = device.ipcon.getPayloadFromPacket(packetResponse);

					packetErrorFlag = device.ipcon.getEFromPacket(packetResponse);

					if (packetErrorFlag !== 0) {
						if (streamStateObject['responseProperties']['errorCB'] !== undefined) {
							if (packetErrorFlag === 1) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_INVALID_PARAMETER);
							}
							else if (packetErrorFlag === 2) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_FUNCTION_NOT_SUPPORTED);
							}
							else {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_UNKNOWN_ERROR);
							}
						}

						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}

						return;
					}

					if (payload.length === 0) {
						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}

						return;
					}

					llvalues = device.ipcon.unpack(payload,
					                               streamStateObject['responseProperties']['unpackFormatString']);

					for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
						if (streamStateObject['dataMapping'][i] === 'streamChunkData') {
							pixelsChunkData = llvalues[i];
						}
						else if (streamStateObject['dataMapping'][i] === 'streamChunkOffset') {
							pixelsChunkOffset = llvalues[i];
						}
					}

					for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
						if (streamStateObject['dataMapping'][i] === 'streamLength') {
							pixelsLength = llvalues[i];
							break;
						}
					}

					function handleOOS() {
						if ((pixelsChunkOffset + 480) < pixelsLength) {
							streamStateObject['responseProperties']['runningSubcallOOS'] = true;
							device.ipcon.sendRequest(device, BrickletLCD128x64.FUNCTION_READ_PIXELS_LOW_LEVEL, [xStart, yStart, xEnd, yEnd], 'B B B B', 72, 'H H ?480', streamStateObject['responseProperties']['returnCB'], streamStateObject['responseProperties']['errorCB'], true, true);

							return;
						}

						if (streamStateObject['responseProperties']['errorCB']) {
							streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_STREAM_OUT_OF_SYNC);
						}

						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}
					}

					if (streamStateObject['responseProperties']['waitingFirstChunk']) {
						streamStateObject['responseProperties']['waitingFirstChunk'] = false;
						pixelsOutOfSync = (pixelsChunkOffset !== 0);
						streamStateObject['responseProperties']['data'] = pixelsChunkData;
					}

					if (!streamStateObject['responseProperties']['runningSubcallOOS']) {
						if (!streamStateObject['responseProperties']['runningSubcall']) {
							if (!pixelsOutOfSync &&
							    (streamStateObject['responseProperties']['data'].length < pixelsLength)) {
							        streamStateObject['responseProperties']['runningSubcall'] = true;
							        device.ipcon.sendRequest(device, BrickletLCD128x64.FUNCTION_READ_PIXELS_LOW_LEVEL, [xStart, yStart, xEnd, yEnd], 'B B B B', 72, 'H H ?480', streamStateObject['responseProperties']['returnCB'], streamStateObject['responseProperties']['errorCB'], true, true);

							        return;
							}
						}
						else {
							pixelsOutOfSync =
								(pixelsChunkOffset !== streamStateObject['responseProperties']['data'].length);

							if (!pixelsOutOfSync &&
								(streamStateObject['responseProperties']['data'].length < pixelsLength)) {
									streamStateObject['responseProperties']['data'] =
										streamStateObject['responseProperties']['data'].concat(pixelsChunkData);

									if (streamStateObject['responseProperties']['data'].length >= pixelsLength) {
										streamStateObject['responseProperties']['data'] =
											streamStateObject['responseProperties']['data'].splice(0, pixelsLength);
									}
									else {
										device.ipcon.sendRequest(device, BrickletLCD128x64.FUNCTION_READ_PIXELS_LOW_LEVEL, [xStart, yStart, xEnd, yEnd], 'B B B B', 72, 'H H ?480', streamStateObject['responseProperties']['returnCB'], streamStateObject['responseProperties']['errorCB'], true, true);

										return;
									}
							}
						}
					}
					else{
						handleOOS();

						return;
					}

					if (pixelsOutOfSync) { // Discard remaining stream to bring it back in-sync
						handleOOS();

						return;
					}

					if (streamStateObject['responseProperties']['returnCB']) {
						for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
							rolesMappedData.push({'role': streamStateObject['dataMapping'][i], 'llvalue': llvalues[i]});
						}

						for (var i = 0; i < rolesMappedData.length; i++) {
							if (rolesMappedData[i]['role'] === 'streamChunkData') {
								result.push(streamStateObject['responseProperties']['data'].splice(0, pixelsLength));
							}
							else if (rolesMappedData[i]['role'] === null) {
								result.push(rolesMappedData[i]['llvalue']);
							}
						}

						streamStateObject['responseProperties']['returnCB'].apply(device, result);
					}

					device.resetStreamStateObject(streamStateObject);

					if (streamStateObject['responseProperties']['callQueue'].length > 0) {
						streamStateObject['responseProperties']['callQueue'].shift()(device);
					}
					
				};

			streamStateObject['responseProperties']['responseHandler'] = responseHandler;
		}
		if (!streamStateObject['responseProperties']['running']) {
			streamStateObject['responseProperties']['running'] = true;
			streamStateObject['responseProperties']['returnCB'] = returnCallback;
			streamStateObject['responseProperties']['errorCB'] = errorCallback;
			this.ipcon.sendRequest(this,
			                       BrickletLCD128x64.FUNCTION_READ_PIXELS_LOW_LEVEL,
			                       [xStart, yStart, xEnd, yEnd],
			                       'B B B B',
			                       72,
			                       'H H ?480',
			                       returnCallback,
			                       errorCallback,
			                       true,
			                       true);
		}
		else {
			functionToQueue = function (device) {
				device.readPixels.call(device, xStart, yStart, xEnd, yEnd, returnCallback, errorCallback);
			}
			streamStateObject['responseProperties']['callQueue'].push(functionToQueue);
		}
	};
	this.setGUIGraphData = function(index, data, returnCallback, errorCallback) {
		/*
		Sets the data for a graph with the given index. You have to configure the graph with
		:func:`Set GUI Graph Configuration` before you can set the first data.
		
		The graph will show the first n values of the data that you set, where
		n is the width set with :func:`Set GUI Graph Configuration`. If you set
		less then n values it will show the rest of the values as zero.
		
		The maximum number of data-points you can set is 118 (which also corresponds to the
		maximum width of the graph).
		
		You have to scale your values to be between 0 and 255. 0 will be shown
		at the bottom of the graph and 255 at the top.
		
		.. versionadded:: 2.0.2$nbsp;(Plugin)
		*/

		var dataLength = 0;
		var dataChunkData = [];
		var dataChunkOffset = 0;
		var streamStateObject = this.streamStateObjects[47];

		if (data.length > 65535) {
			if (errorCallback !== null){
				errorCallback(IPConnection.ERROR_INVALID_PARAMETER);
			}

			this.resetStreamStateObject(streamStateObject);

			if (streamStateObject['responseProperties']['callQueue'].length > 0) {
				streamStateObject['responseProperties']['callQueue'].shift()(device);
			}

			return;
		}

		if (!this.getResponseExpected(47)) {
			if (streamStateObject['streamProperties']['fixedLength']) {
				dataLength = streamStateObject['streamProperties']['fixedLength'];
			}
			else {
				dataLength = data.length;
			}

			if (streamStateObject['streamProperties']['singleChunk']) {
				dataChunkData =
					this.ipcon.createChunkData(data, 0, 59, '\0');

				this.ipcon.sendRequest(this,
				                       BrickletLCD128x64.FUNCTION_SET_GUI_GRAPH_DATA_LOW_LEVEL,
				                       [index, dataLength, dataChunkOffset, dataChunkData],
				                       'B H H B59',
				                       0,
				                       '',
				                       returnCallback,
				                       errorCallback,
				                       false,
				                       true);
			}
			else {
				while (dataChunkOffset < data.length) {
					dataChunkData =
						this.ipcon.createChunkData(data, dataChunkOffset, 59, '\0');

					this.ipcon.sendRequest(this,
					                       BrickletLCD128x64.FUNCTION_SET_GUI_GRAPH_DATA_LOW_LEVEL,
					                       [index, dataLength, dataChunkOffset, dataChunkData],
					                       'B H H B59',
					                       0,
					                       '',
					                       returnCallback,
					                       errorCallback,
					                       false,
					                       true);

					dataChunkOffset += 59;
				}
			}

			if (returnCallback) {
				returnCallback();
			}
		}
		else {
			var responseHandler = null;
			var functionToQueue = null;

			if (streamStateObject['responseProperties']['responseHandler'] === null) {
				responseHandler = function (device, fid, packetResponse) {
					var result = [];
					var payload = null;
					var llvalues = null;
					var packetErrorFlag = 0;
					var rolesMappedData = [];
					var shortWriteWritten = -1;
					var streamStateObject = device.streamStateObjects[fid];
					var responseEmpty = streamStateObject['responseProperties']['streamInResponseEmpty'];
					var dataLength = 0;
					var dataChunkData = [];
					var dataChunkOffset = 0;

					function doNextLLCall() {
						dataLength = streamStateObject['responseProperties']['data'].length;
						dataChunkData =
							device.ipcon.createChunkData(streamStateObject['responseProperties']['data'],
							                             streamStateObject['responseProperties']['streamInChunkOffset'],
							                             streamStateObject['responseProperties']['streamInChunkLength'],
							                             '\0');
						dataChunkOffset = streamStateObject['responseProperties']['streamInChunkOffset'];

						for (var i = 0; i < streamStateObject['dataMappingStreamIn'].length; i++) {
							if (streamStateObject['dataMappingStreamIn'][i] === null) {
								continue;
							}

							if (streamStateObject['dataMappingStreamIn'][i].endsWith('Length')) {
								streamStateObject['responseProperties']['streamInLLParams'][i] = dataLength;
							}
							else if (streamStateObject['dataMappingStreamIn'][i].endsWith('Offset')) {
								streamStateObject['responseProperties']['streamInLLParams'][i] = dataChunkOffset;
							}
							else if (streamStateObject['dataMappingStreamIn'][i].endsWith('Data')) {
								streamStateObject['responseProperties']['streamInLLParams'][i] = dataChunkData;
							}
						}

						device.ipcon.sendRequest(device,
						                         BrickletLCD128x64.FUNCTION_SET_GUI_GRAPH_DATA_LOW_LEVEL,
						                         streamStateObject['responseProperties']['streamInLLParams'],
						                         'B H H B59',
						                         0,
						                         '',
						                         returnCallback,
						                         errorCallback,
						                         true,
						                         true);

						streamStateObject['responseProperties']['streamInChunkOffset'] += 59;
					}

					function handleStreamInDone() {
						if (streamStateObject['responseProperties']['returnCB']) {
							if (streamStateObject['streamProperties']['shortWrite']) {
								for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
									if (streamStateObject['dataMapping'][i].endsWith('Written')) {
										result[i] = streamStateObject['responseProperties']['streamInWritten'];
										break;
									}
								}
							}

							if (!responseEmpty) {
								streamStateObject['responseProperties']['returnCB'].apply(device, result);
							}
							else {
								streamStateObject['responseProperties']['returnCB'].apply(device);
							}
						}

						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}
					}

					if (!streamStateObject) {
						return;
					}

					packetErrorFlag = device.ipcon.getEFromPacket(packetResponse);

					if (packetErrorFlag !== 0) {
						if (streamStateObject['responseProperties']['errorCB'] !== undefined) {
							if (packetErrorFlag === 1) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_INVALID_PARAMETER);
							}
							else if (packetErrorFlag === 2) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_FUNCTION_NOT_SUPPORTED);
							}
							else {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_UNKNOWN_ERROR);
							}
						}

						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}

						return;
					}

					if (responseEmpty) {
						if (streamStateObject['streamProperties']['singleChunk']) {
							handleStreamInDone();

							return;
						}

						if (streamStateObject['responseProperties']['streamInChunkOffset'] < streamStateObject['responseProperties']['data'].length) {
							doNextLLCall();
						}
						else {
							handleStreamInDone();
						}
					}
					else {
						payload = device.ipcon.getPayloadFromPacket(packetResponse);
						llvalues = device.ipcon.unpack(payload,
						                               streamStateObject['responseProperties']['unpackFormatString']);

						if (!payload || !llvalues) {
							device.resetStreamStateObject(streamStateObject);

							if (streamStateObject['responseProperties']['callQueue'].length > 0) {
								streamStateObject['responseProperties']['callQueue'].shift()(device);
							}

							return;
						}

						for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
							result.push(llvalues[i]);
						}

						if (streamStateObject['streamProperties']['singleChunk']) {
							if (streamStateObject['responseProperties']['returnCB']) {
								streamStateObject['responseProperties']['returnCB'].apply(device, result);
							}

							device.resetStreamStateObject(streamStateObject);

							if (streamStateObject['responseProperties']['callQueue'].length > 0) {
								streamStateObject['responseProperties']['callQueue'].shift()(device);
							}

							return;
						}

						if (streamStateObject['streamProperties']['shortWrite']) {
							for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
								if (streamStateObject['dataMapping'][i].endsWith('Written')) {
									shortWriteWritten = llvalues[i];
									streamStateObject['responseProperties']['streamInWritten'] += shortWriteWritten;
									break;
								}
							}
							if ((shortWriteWritten !== -1) && (shortWriteWritten < 59)) {
								// Either last chunk or short write
								handleStreamInDone();
								return;
							}
						}

						if (streamStateObject['responseProperties']['streamInChunkOffset'] < streamStateObject['responseProperties']['data'].length) {
							doNextLLCall();
						}
						else {
							handleStreamInDone();
						}
					}
				};

				streamStateObject['responseProperties']['responseHandler'] = responseHandler;
			}

			if (!streamStateObject['responseProperties']['running']) {
				streamStateObject['responseProperties']['running'] = true;
				streamStateObject['responseProperties']['returnCB'] = returnCallback;
				streamStateObject['responseProperties']['errorCB'] = errorCallback;
				streamStateObject['responseProperties']['data'].length = 0;
				streamStateObject['responseProperties']['data'].push.apply(streamStateObject['responseProperties']['data'],
				                                                           data);

				if (streamStateObject['streamProperties']['fixedLength']) {
					dataLength = streamStateObject['streamProperties']['fixedLength'];
				}
				else {
					dataLength = data.length;
				}

				dataChunkOffset = 0;
				dataChunkData =
					this.ipcon.createChunkData(data, 0, 59, '\0');

				streamStateObject['responseProperties']['streamInChunkOffset'] = 59;
				streamStateObject['responseProperties']['streamInChunkLength'] = 59;
				streamStateObject['responseProperties']['streamInLLParams'] = [index, dataLength, dataChunkOffset, dataChunkData];

				this.ipcon.sendRequest(this,
				                       BrickletLCD128x64.FUNCTION_SET_GUI_GRAPH_DATA_LOW_LEVEL,
				                       [index, dataLength, dataChunkOffset, dataChunkData],
				                       'B H H B59',
				                       0,
				                       '',
				                       returnCallback,
				                       errorCallback,
				                       true,
				                       true);
			}
			else {
				functionToQueue = function (device) {
					device.setGUIGraphData.call(device, index, data, returnCallback, errorCallback);
				}

				streamStateObject['responseProperties']['callQueue'].push(functionToQueue);
			}
		}
	};

	this.getGUIGraphData = function(index, returnCallback, errorCallback) {
		/*
		Returns the graph data for a given index as set by :func:`Set GUI Graph Data`.
		
		.. versionadded:: 2.0.2$nbsp;(Plugin)
		*/
		var responseHandler = null;
		var functionToQueue = null;
		var streamStateObject = this.streamStateObjects[48];
		if (streamStateObject['responseProperties']['responseHandler'] === null) {
			responseHandler = 
				function (device, fid, packetResponse) {
					var result = [];
					var llvalues = null;
					var packetErrorFlag = 0;
					var rolesMappedData = [];
					var dataLength = null;
					var dataChunkData = null;
					var dataOutOfSync = false;
					var streamStateObject = device.streamStateObjects[fid];
					var dataChunkOffset = null;
					var payload = device.ipcon.getPayloadFromPacket(packetResponse);

					packetErrorFlag = device.ipcon.getEFromPacket(packetResponse);

					if (packetErrorFlag !== 0) {
						if (streamStateObject['responseProperties']['errorCB'] !== undefined) {
							if (packetErrorFlag === 1) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_INVALID_PARAMETER);
							}
							else if (packetErrorFlag === 2) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_FUNCTION_NOT_SUPPORTED);
							}
							else {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_UNKNOWN_ERROR);
							}
						}

						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}

						return;
					}

					if (payload.length === 0) {
						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}

						return;
					}

					llvalues = device.ipcon.unpack(payload,
					                               streamStateObject['responseProperties']['unpackFormatString']);

					for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
						if (streamStateObject['dataMapping'][i] === 'streamChunkData') {
							dataChunkData = llvalues[i];
						}
						else if (streamStateObject['dataMapping'][i] === 'streamChunkOffset') {
							dataChunkOffset = llvalues[i];
						}
					}

					for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
						if (streamStateObject['dataMapping'][i] === 'streamLength') {
							dataLength = llvalues[i];
							break;
						}
					}

					function handleOOS() {
						if ((dataChunkOffset + 59) < dataLength) {
							streamStateObject['responseProperties']['runningSubcallOOS'] = true;
							device.ipcon.sendRequest(device, BrickletLCD128x64.FUNCTION_GET_GUI_GRAPH_DATA_LOW_LEVEL, [index], 'B', 71, 'H H B59', streamStateObject['responseProperties']['returnCB'], streamStateObject['responseProperties']['errorCB'], true, true);

							return;
						}

						if (streamStateObject['responseProperties']['errorCB']) {
							streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_STREAM_OUT_OF_SYNC);
						}

						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}
					}

					if (streamStateObject['responseProperties']['waitingFirstChunk']) {
						streamStateObject['responseProperties']['waitingFirstChunk'] = false;
						dataOutOfSync = (dataChunkOffset !== 0);
						streamStateObject['responseProperties']['data'] = dataChunkData;
					}

					if (!streamStateObject['responseProperties']['runningSubcallOOS']) {
						if (!streamStateObject['responseProperties']['runningSubcall']) {
							if (!dataOutOfSync &&
							    (streamStateObject['responseProperties']['data'].length < dataLength)) {
							        streamStateObject['responseProperties']['runningSubcall'] = true;
							        device.ipcon.sendRequest(device, BrickletLCD128x64.FUNCTION_GET_GUI_GRAPH_DATA_LOW_LEVEL, [index], 'B', 71, 'H H B59', streamStateObject['responseProperties']['returnCB'], streamStateObject['responseProperties']['errorCB'], true, true);

							        return;
							}
						}
						else {
							dataOutOfSync =
								(dataChunkOffset !== streamStateObject['responseProperties']['data'].length);

							if (!dataOutOfSync &&
								(streamStateObject['responseProperties']['data'].length < dataLength)) {
									streamStateObject['responseProperties']['data'] =
										streamStateObject['responseProperties']['data'].concat(dataChunkData);

									if (streamStateObject['responseProperties']['data'].length >= dataLength) {
										streamStateObject['responseProperties']['data'] =
											streamStateObject['responseProperties']['data'].splice(0, dataLength);
									}
									else {
										device.ipcon.sendRequest(device, BrickletLCD128x64.FUNCTION_GET_GUI_GRAPH_DATA_LOW_LEVEL, [index], 'B', 71, 'H H B59', streamStateObject['responseProperties']['returnCB'], streamStateObject['responseProperties']['errorCB'], true, true);

										return;
									}
							}
						}
					}
					else{
						handleOOS();

						return;
					}

					if (dataOutOfSync) { // Discard remaining stream to bring it back in-sync
						handleOOS();

						return;
					}

					if (streamStateObject['responseProperties']['returnCB']) {
						for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
							rolesMappedData.push({'role': streamStateObject['dataMapping'][i], 'llvalue': llvalues[i]});
						}

						for (var i = 0; i < rolesMappedData.length; i++) {
							if (rolesMappedData[i]['role'] === 'streamChunkData') {
								result.push(streamStateObject['responseProperties']['data'].splice(0, dataLength));
							}
							else if (rolesMappedData[i]['role'] === null) {
								result.push(rolesMappedData[i]['llvalue']);
							}
						}

						streamStateObject['responseProperties']['returnCB'].apply(device, result);
					}

					device.resetStreamStateObject(streamStateObject);

					if (streamStateObject['responseProperties']['callQueue'].length > 0) {
						streamStateObject['responseProperties']['callQueue'].shift()(device);
					}
					
				};

			streamStateObject['responseProperties']['responseHandler'] = responseHandler;
		}
		if (!streamStateObject['responseProperties']['running']) {
			streamStateObject['responseProperties']['running'] = true;
			streamStateObject['responseProperties']['returnCB'] = returnCallback;
			streamStateObject['responseProperties']['errorCB'] = errorCallback;
			this.ipcon.sendRequest(this,
			                       BrickletLCD128x64.FUNCTION_GET_GUI_GRAPH_DATA_LOW_LEVEL,
			                       [index],
			                       'B',
			                       71,
			                       'H H B59',
			                       returnCallback,
			                       errorCallback,
			                       true,
			                       true);
		}
		else {
			functionToQueue = function (device) {
				device.getGUIGraphData.call(device, index, returnCallback, errorCallback);
			}
			streamStateObject['responseProperties']['callQueue'].push(functionToQueue);
		}
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletLCD128x64;

},{"./Device":279,"./IPConnection":280}],211:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletLCD16x2.DEVICE_IDENTIFIER = 211;
BrickletLCD16x2.DEVICE_DISPLAY_NAME = 'LCD 16x2 Bricklet';
BrickletLCD16x2.CALLBACK_BUTTON_PRESSED = 9;
BrickletLCD16x2.CALLBACK_BUTTON_RELEASED = 10;
BrickletLCD16x2.FUNCTION_WRITE_LINE = 1;
BrickletLCD16x2.FUNCTION_CLEAR_DISPLAY = 2;
BrickletLCD16x2.FUNCTION_BACKLIGHT_ON = 3;
BrickletLCD16x2.FUNCTION_BACKLIGHT_OFF = 4;
BrickletLCD16x2.FUNCTION_IS_BACKLIGHT_ON = 5;
BrickletLCD16x2.FUNCTION_SET_CONFIG = 6;
BrickletLCD16x2.FUNCTION_GET_CONFIG = 7;
BrickletLCD16x2.FUNCTION_IS_BUTTON_PRESSED = 8;
BrickletLCD16x2.FUNCTION_SET_CUSTOM_CHARACTER = 11;
BrickletLCD16x2.FUNCTION_GET_CUSTOM_CHARACTER = 12;
BrickletLCD16x2.FUNCTION_GET_IDENTITY = 255;

function BrickletLCD16x2(uid, ipcon) {
	//16x2 character alphanumeric display with blue backlight

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletLCD16x2.DEVICE_IDENTIFIER, BrickletLCD16x2.DEVICE_DISPLAY_NAME);
	BrickletLCD16x2.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 1];
	this.responseExpected[BrickletLCD16x2.FUNCTION_WRITE_LINE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletLCD16x2.FUNCTION_CLEAR_DISPLAY] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletLCD16x2.FUNCTION_BACKLIGHT_ON] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletLCD16x2.FUNCTION_BACKLIGHT_OFF] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletLCD16x2.FUNCTION_IS_BACKLIGHT_ON] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLCD16x2.FUNCTION_SET_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletLCD16x2.FUNCTION_GET_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLCD16x2.FUNCTION_IS_BUTTON_PRESSED] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLCD16x2.FUNCTION_SET_CUSTOM_CHARACTER] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletLCD16x2.FUNCTION_GET_CUSTOM_CHARACTER] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLCD16x2.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletLCD16x2.CALLBACK_BUTTON_PRESSED] = [9, 'B'];
	this.callbackFormats[BrickletLCD16x2.CALLBACK_BUTTON_RELEASED] = [9, 'B'];



	this.writeLine = function(line, position, text, returnCallback, errorCallback) {
		/*
		Writes text to a specific line with a specific position.
		The text can have a maximum of 16 characters.
		
		For example: (0, 5, "Hello") will write *Hello* in the middle of the
		first line of the display.
		
		The display uses a special charset that includes all ASCII characters except
		backslash and tilde. The LCD charset also includes several other non-ASCII characters, see
		the `charset specification <https://github.com/Tinkerforge/lcd-16x2-bricklet/raw/master/datasheets/standard_charset.pdf>`__
		for details. The Unicode example above shows how to specify non-ASCII characters
		and how to translate from Unicode to the LCD charset.
		*/
		this.ipcon.sendRequest(this, BrickletLCD16x2.FUNCTION_WRITE_LINE, [line, position, text], 'B B s16', 0, '', returnCallback, errorCallback, false, true);
	};
	this.clearDisplay = function(returnCallback, errorCallback) {
		/*
		Deletes all characters from the display.
		*/
		this.ipcon.sendRequest(this, BrickletLCD16x2.FUNCTION_CLEAR_DISPLAY, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.backlightOn = function(returnCallback, errorCallback) {
		/*
		Turns the backlight on.
		*/
		this.ipcon.sendRequest(this, BrickletLCD16x2.FUNCTION_BACKLIGHT_ON, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.backlightOff = function(returnCallback, errorCallback) {
		/*
		Turns the backlight off.
		*/
		this.ipcon.sendRequest(this, BrickletLCD16x2.FUNCTION_BACKLIGHT_OFF, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.isBacklightOn = function(returnCallback, errorCallback) {
		/*
		Returns *true* if the backlight is on and *false* otherwise.
		*/
		this.ipcon.sendRequest(this, BrickletLCD16x2.FUNCTION_IS_BACKLIGHT_ON, [], '', 9, '?', returnCallback, errorCallback, false, true);
	};
	this.setConfig = function(cursor, blinking, returnCallback, errorCallback) {
		/*
		Configures if the cursor (shown as "_") should be visible and if it
		should be blinking (shown as a blinking block). The cursor position
		is one character behind the the last text written with
		:func:`Write Line`.
		*/
		this.ipcon.sendRequest(this, BrickletLCD16x2.FUNCTION_SET_CONFIG, [cursor, blinking], '? ?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getConfig = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Config`.
		*/
		this.ipcon.sendRequest(this, BrickletLCD16x2.FUNCTION_GET_CONFIG, [], '', 10, '? ?', returnCallback, errorCallback, false, true);
	};
	this.isButtonPressed = function(button, returnCallback, errorCallback) {
		/*
		Returns *true* if the button is pressed.
		
		If you want to react on button presses and releases it is recommended to use the
		:cb:`Button Pressed` and :cb:`Button Released` callbacks.
		*/
		this.ipcon.sendRequest(this, BrickletLCD16x2.FUNCTION_IS_BUTTON_PRESSED, [button], 'B', 9, '?', returnCallback, errorCallback, false, true);
	};
	this.setCustomCharacter = function(index, character, returnCallback, errorCallback) {
		/*
		The LCD 16x2 Bricklet can store up to 8 custom characters. The characters
		consist of 5x8 pixels and can be addressed with the index 0-7. To describe
		the pixels, the first 5 bits of 8 bytes are used. For example, to make
		a custom character "H", you should transfer the following:
		
		* ``character[0] = 0b00010001`` (decimal value 17)
		* ``character[1] = 0b00010001`` (decimal value 17)
		* ``character[2] = 0b00010001`` (decimal value 17)
		* ``character[3] = 0b00011111`` (decimal value 31)
		* ``character[4] = 0b00010001`` (decimal value 17)
		* ``character[5] = 0b00010001`` (decimal value 17)
		* ``character[6] = 0b00010001`` (decimal value 17)
		* ``character[7] = 0b00000000`` (decimal value 0)
		
		The characters can later be written with :func:`Write Line` by using the
		characters with the byte representation 8 ("\\x08" or "\\u0008") to 15
		("\\x0F" or "\\u000F").
		
		You can play around with the custom characters in Brick Viewer since
		version 2.0.1.
		
		Custom characters are stored by the LCD in RAM, so they have to be set
		after each startup.
		
		.. versionadded:: 2.0.1$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletLCD16x2.FUNCTION_SET_CUSTOM_CHARACTER, [index, character], 'B B8', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getCustomCharacter = function(index, returnCallback, errorCallback) {
		/*
		Returns the custom character for a given index, as set with
		:func:`Set Custom Character`.
		
		.. versionadded:: 2.0.1$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletLCD16x2.FUNCTION_GET_CUSTOM_CHARACTER, [index], 'B', 16, 'B8', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletLCD16x2.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletLCD16x2;

},{"./Device":279,"./IPConnection":280}],212:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletLCD20x4.DEVICE_IDENTIFIER = 212;
BrickletLCD20x4.DEVICE_DISPLAY_NAME = 'LCD 20x4 Bricklet';
BrickletLCD20x4.CALLBACK_BUTTON_PRESSED = 9;
BrickletLCD20x4.CALLBACK_BUTTON_RELEASED = 10;
BrickletLCD20x4.FUNCTION_WRITE_LINE = 1;
BrickletLCD20x4.FUNCTION_CLEAR_DISPLAY = 2;
BrickletLCD20x4.FUNCTION_BACKLIGHT_ON = 3;
BrickletLCD20x4.FUNCTION_BACKLIGHT_OFF = 4;
BrickletLCD20x4.FUNCTION_IS_BACKLIGHT_ON = 5;
BrickletLCD20x4.FUNCTION_SET_CONFIG = 6;
BrickletLCD20x4.FUNCTION_GET_CONFIG = 7;
BrickletLCD20x4.FUNCTION_IS_BUTTON_PRESSED = 8;
BrickletLCD20x4.FUNCTION_SET_CUSTOM_CHARACTER = 11;
BrickletLCD20x4.FUNCTION_GET_CUSTOM_CHARACTER = 12;
BrickletLCD20x4.FUNCTION_SET_DEFAULT_TEXT = 13;
BrickletLCD20x4.FUNCTION_GET_DEFAULT_TEXT = 14;
BrickletLCD20x4.FUNCTION_SET_DEFAULT_TEXT_COUNTER = 15;
BrickletLCD20x4.FUNCTION_GET_DEFAULT_TEXT_COUNTER = 16;
BrickletLCD20x4.FUNCTION_GET_IDENTITY = 255;

function BrickletLCD20x4(uid, ipcon) {
	//20x4 character alphanumeric display with blue backlight

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletLCD20x4.DEVICE_IDENTIFIER, BrickletLCD20x4.DEVICE_DISPLAY_NAME);
	BrickletLCD20x4.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 2];
	this.responseExpected[BrickletLCD20x4.FUNCTION_WRITE_LINE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletLCD20x4.FUNCTION_CLEAR_DISPLAY] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletLCD20x4.FUNCTION_BACKLIGHT_ON] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletLCD20x4.FUNCTION_BACKLIGHT_OFF] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletLCD20x4.FUNCTION_IS_BACKLIGHT_ON] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLCD20x4.FUNCTION_SET_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletLCD20x4.FUNCTION_GET_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLCD20x4.FUNCTION_IS_BUTTON_PRESSED] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLCD20x4.FUNCTION_SET_CUSTOM_CHARACTER] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletLCD20x4.FUNCTION_GET_CUSTOM_CHARACTER] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLCD20x4.FUNCTION_SET_DEFAULT_TEXT] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletLCD20x4.FUNCTION_GET_DEFAULT_TEXT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLCD20x4.FUNCTION_SET_DEFAULT_TEXT_COUNTER] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletLCD20x4.FUNCTION_GET_DEFAULT_TEXT_COUNTER] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLCD20x4.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletLCD20x4.CALLBACK_BUTTON_PRESSED] = [9, 'B'];
	this.callbackFormats[BrickletLCD20x4.CALLBACK_BUTTON_RELEASED] = [9, 'B'];



	this.writeLine = function(line, position, text, returnCallback, errorCallback) {
		/*
		Writes text to a specific line with a specific position.
		The text can have a maximum of 20 characters.
		
		For example: (0, 7, "Hello") will write *Hello* in the middle of the
		first line of the display.
		
		The display uses a special charset that includes all ASCII characters except
		backslash and tilde. The LCD charset also includes several other non-ASCII characters, see
		the `charset specification <https://github.com/Tinkerforge/lcd-20x4-bricklet/raw/master/datasheets/standard_charset.pdf>`__
		for details. The Unicode example above shows how to specify non-ASCII characters
		and how to translate from Unicode to the LCD charset.
		*/
		this.ipcon.sendRequest(this, BrickletLCD20x4.FUNCTION_WRITE_LINE, [line, position, text], 'B B s20', 0, '', returnCallback, errorCallback, false, true);
	};
	this.clearDisplay = function(returnCallback, errorCallback) {
		/*
		Deletes all characters from the display.
		*/
		this.ipcon.sendRequest(this, BrickletLCD20x4.FUNCTION_CLEAR_DISPLAY, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.backlightOn = function(returnCallback, errorCallback) {
		/*
		Turns the backlight on.
		*/
		this.ipcon.sendRequest(this, BrickletLCD20x4.FUNCTION_BACKLIGHT_ON, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.backlightOff = function(returnCallback, errorCallback) {
		/*
		Turns the backlight off.
		*/
		this.ipcon.sendRequest(this, BrickletLCD20x4.FUNCTION_BACKLIGHT_OFF, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.isBacklightOn = function(returnCallback, errorCallback) {
		/*
		Returns *true* if the backlight is on and *false* otherwise.
		*/
		this.ipcon.sendRequest(this, BrickletLCD20x4.FUNCTION_IS_BACKLIGHT_ON, [], '', 9, '?', returnCallback, errorCallback, false, true);
	};
	this.setConfig = function(cursor, blinking, returnCallback, errorCallback) {
		/*
		Configures if the cursor (shown as "_") should be visible and if it
		should be blinking (shown as a blinking block). The cursor position
		is one character behind the the last text written with
		:func:`Write Line`.
		*/
		this.ipcon.sendRequest(this, BrickletLCD20x4.FUNCTION_SET_CONFIG, [cursor, blinking], '? ?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getConfig = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Config`.
		*/
		this.ipcon.sendRequest(this, BrickletLCD20x4.FUNCTION_GET_CONFIG, [], '', 10, '? ?', returnCallback, errorCallback, false, true);
	};
	this.isButtonPressed = function(button, returnCallback, errorCallback) {
		/*
		Returns *true* if the button (0 to 2 or 0 to 3 since hardware version 1.2)
		is pressed.
		
		If you want to react on button presses and releases it is recommended to use
		the :cb:`Button Pressed` and :cb:`Button Released` callbacks.
		*/
		this.ipcon.sendRequest(this, BrickletLCD20x4.FUNCTION_IS_BUTTON_PRESSED, [button], 'B', 9, '?', returnCallback, errorCallback, false, true);
	};
	this.setCustomCharacter = function(index, character, returnCallback, errorCallback) {
		/*
		The LCD 20x4 Bricklet can store up to 8 custom characters. The characters
		consist of 5x8 pixels and can be addressed with the index 0-7. To describe
		the pixels, the first 5 bits of 8 bytes are used. For example, to make
		a custom character "H", you should transfer the following:
		
		* ``character[0] = 0b00010001`` (decimal value 17)
		* ``character[1] = 0b00010001`` (decimal value 17)
		* ``character[2] = 0b00010001`` (decimal value 17)
		* ``character[3] = 0b00011111`` (decimal value 31)
		* ``character[4] = 0b00010001`` (decimal value 17)
		* ``character[5] = 0b00010001`` (decimal value 17)
		* ``character[6] = 0b00010001`` (decimal value 17)
		* ``character[7] = 0b00000000`` (decimal value 0)
		
		The characters can later be written with :func:`Write Line` by using the
		characters with the byte representation 8 ("\\x08" or "\\u0008") to 15
		("\\x0F" or "\\u000F").
		
		You can play around with the custom characters in Brick Viewer version
		since 2.0.1.
		
		Custom characters are stored by the LCD in RAM, so they have to be set
		after each startup.
		
		.. versionadded:: 2.0.1$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletLCD20x4.FUNCTION_SET_CUSTOM_CHARACTER, [index, character], 'B B8', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getCustomCharacter = function(index, returnCallback, errorCallback) {
		/*
		Returns the custom character for a given index, as set with
		:func:`Set Custom Character`.
		
		.. versionadded:: 2.0.1$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletLCD20x4.FUNCTION_GET_CUSTOM_CHARACTER, [index], 'B', 16, 'B8', returnCallback, errorCallback, false, true);
	};
	this.setDefaultText = function(line, text, returnCallback, errorCallback) {
		/*
		Sets the default text for lines 0-3. The max number of characters
		per line is 20.
		
		The default text is shown on the LCD, if the default text counter
		expires, see :func:`Set Default Text Counter`.
		
		.. versionadded:: 2.0.2$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletLCD20x4.FUNCTION_SET_DEFAULT_TEXT, [line, text], 'B s20', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getDefaultText = function(line, returnCallback, errorCallback) {
		/*
		Returns the default text for a given line (0-3) as set by
		:func:`Set Default Text`.
		
		.. versionadded:: 2.0.2$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletLCD20x4.FUNCTION_GET_DEFAULT_TEXT, [line], 'B', 28, 's20', returnCallback, errorCallback, false, true);
	};
	this.setDefaultTextCounter = function(counter, returnCallback, errorCallback) {
		/*
		Sets the default text counter. This counter is decremented each
		ms by the LCD firmware. If the counter reaches 0, the default text
		(see :func:`Set Default Text`) is shown on the LCD.
		
		This functionality can be used to show a default text if the controlling
		program crashes or the connection is interrupted.
		
		A possible approach is to call :func:`Set Default Text Counter` every
		minute with the parameter 1000*60*2 (2 minutes). In this case the
		default text will be shown no later than 2 minutes after the
		controlling program crashes.
		
		A negative counter turns the default text functionality off.
		
		.. versionadded:: 2.0.2$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletLCD20x4.FUNCTION_SET_DEFAULT_TEXT_COUNTER, [counter], 'i', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getDefaultTextCounter = function(returnCallback, errorCallback) {
		/*
		Returns the current value of the default text counter.
		
		.. versionadded:: 2.0.2$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletLCD20x4.FUNCTION_GET_DEFAULT_TEXT_COUNTER, [], '', 12, 'i', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletLCD20x4.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletLCD20x4;

},{"./Device":279,"./IPConnection":280}],213:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletLEDStrip.DEVICE_IDENTIFIER = 231;
BrickletLEDStrip.DEVICE_DISPLAY_NAME = 'LED Strip Bricklet';
BrickletLEDStrip.CALLBACK_FRAME_RENDERED = 6;
BrickletLEDStrip.FUNCTION_SET_RGB_VALUES = 1;
BrickletLEDStrip.FUNCTION_GET_RGB_VALUES = 2;
BrickletLEDStrip.FUNCTION_SET_FRAME_DURATION = 3;
BrickletLEDStrip.FUNCTION_GET_FRAME_DURATION = 4;
BrickletLEDStrip.FUNCTION_GET_SUPPLY_VOLTAGE = 5;
BrickletLEDStrip.FUNCTION_SET_CLOCK_FREQUENCY = 7;
BrickletLEDStrip.FUNCTION_GET_CLOCK_FREQUENCY = 8;
BrickletLEDStrip.FUNCTION_SET_CHIP_TYPE = 9;
BrickletLEDStrip.FUNCTION_GET_CHIP_TYPE = 10;
BrickletLEDStrip.FUNCTION_SET_RGBW_VALUES = 11;
BrickletLEDStrip.FUNCTION_GET_RGBW_VALUES = 12;
BrickletLEDStrip.FUNCTION_SET_CHANNEL_MAPPING = 13;
BrickletLEDStrip.FUNCTION_GET_CHANNEL_MAPPING = 14;
BrickletLEDStrip.FUNCTION_ENABLE_FRAME_RENDERED_CALLBACK = 15;
BrickletLEDStrip.FUNCTION_DISABLE_FRAME_RENDERED_CALLBACK = 16;
BrickletLEDStrip.FUNCTION_IS_FRAME_RENDERED_CALLBACK_ENABLED = 17;
BrickletLEDStrip.FUNCTION_GET_IDENTITY = 255;
BrickletLEDStrip.CHIP_TYPE_WS2801 = 2801;
BrickletLEDStrip.CHIP_TYPE_WS2811 = 2811;
BrickletLEDStrip.CHIP_TYPE_WS2812 = 2812;
BrickletLEDStrip.CHIP_TYPE_LPD8806 = 8806;
BrickletLEDStrip.CHIP_TYPE_APA102 = 102;
BrickletLEDStrip.CHANNEL_MAPPING_RGB = 6;
BrickletLEDStrip.CHANNEL_MAPPING_RBG = 9;
BrickletLEDStrip.CHANNEL_MAPPING_BRG = 33;
BrickletLEDStrip.CHANNEL_MAPPING_BGR = 36;
BrickletLEDStrip.CHANNEL_MAPPING_GRB = 18;
BrickletLEDStrip.CHANNEL_MAPPING_GBR = 24;
BrickletLEDStrip.CHANNEL_MAPPING_RGBW = 27;
BrickletLEDStrip.CHANNEL_MAPPING_RGWB = 30;
BrickletLEDStrip.CHANNEL_MAPPING_RBGW = 39;
BrickletLEDStrip.CHANNEL_MAPPING_RBWG = 45;
BrickletLEDStrip.CHANNEL_MAPPING_RWGB = 54;
BrickletLEDStrip.CHANNEL_MAPPING_RWBG = 57;
BrickletLEDStrip.CHANNEL_MAPPING_GRWB = 78;
BrickletLEDStrip.CHANNEL_MAPPING_GRBW = 75;
BrickletLEDStrip.CHANNEL_MAPPING_GBWR = 108;
BrickletLEDStrip.CHANNEL_MAPPING_GBRW = 99;
BrickletLEDStrip.CHANNEL_MAPPING_GWBR = 120;
BrickletLEDStrip.CHANNEL_MAPPING_GWRB = 114;
BrickletLEDStrip.CHANNEL_MAPPING_BRGW = 135;
BrickletLEDStrip.CHANNEL_MAPPING_BRWG = 141;
BrickletLEDStrip.CHANNEL_MAPPING_BGRW = 147;
BrickletLEDStrip.CHANNEL_MAPPING_BGWR = 156;
BrickletLEDStrip.CHANNEL_MAPPING_BWRG = 177;
BrickletLEDStrip.CHANNEL_MAPPING_BWGR = 180;
BrickletLEDStrip.CHANNEL_MAPPING_WRBG = 201;
BrickletLEDStrip.CHANNEL_MAPPING_WRGB = 198;
BrickletLEDStrip.CHANNEL_MAPPING_WGBR = 216;
BrickletLEDStrip.CHANNEL_MAPPING_WGRB = 210;
BrickletLEDStrip.CHANNEL_MAPPING_WBGR = 228;
BrickletLEDStrip.CHANNEL_MAPPING_WBRG = 225;

function BrickletLEDStrip(uid, ipcon) {
	//Controls up to 320 RGB LEDs

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletLEDStrip.DEVICE_IDENTIFIER, BrickletLEDStrip.DEVICE_DISPLAY_NAME);
	BrickletLEDStrip.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 3];
	this.responseExpected[BrickletLEDStrip.FUNCTION_SET_RGB_VALUES] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletLEDStrip.FUNCTION_GET_RGB_VALUES] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLEDStrip.FUNCTION_SET_FRAME_DURATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletLEDStrip.FUNCTION_GET_FRAME_DURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLEDStrip.FUNCTION_GET_SUPPLY_VOLTAGE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLEDStrip.FUNCTION_SET_CLOCK_FREQUENCY] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletLEDStrip.FUNCTION_GET_CLOCK_FREQUENCY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLEDStrip.FUNCTION_SET_CHIP_TYPE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletLEDStrip.FUNCTION_GET_CHIP_TYPE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLEDStrip.FUNCTION_SET_RGBW_VALUES] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletLEDStrip.FUNCTION_GET_RGBW_VALUES] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLEDStrip.FUNCTION_SET_CHANNEL_MAPPING] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletLEDStrip.FUNCTION_GET_CHANNEL_MAPPING] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLEDStrip.FUNCTION_ENABLE_FRAME_RENDERED_CALLBACK] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletLEDStrip.FUNCTION_DISABLE_FRAME_RENDERED_CALLBACK] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletLEDStrip.FUNCTION_IS_FRAME_RENDERED_CALLBACK_ENABLED] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLEDStrip.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletLEDStrip.CALLBACK_FRAME_RENDERED] = [10, 'H'];



	this.setRGBValues = function(index, length, r, g, b, returnCallback, errorCallback) {
		/*
		Sets *length* RGB values for the LEDs starting from *index*.
		
		To make the colors show correctly you need to configure the chip type
		(:func:`Set Chip Type`) and a 3-channel channel mapping (:func:`Set Channel Mapping`)
		according to the connected LEDs.
		
		Example: If you set
		
		* index to 5,
		* length to 3,
		* r to [255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
		* g to [0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] and
		* b to [0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
		
		the LED with index 5 will be red, 6 will be green and 7 will be blue.
		
		.. note:: Depending on the LED circuitry colors can be permuted.
		
		The colors will be transfered to actual LEDs when the next
		frame duration ends, see :func:`Set Frame Duration`.
		
		Generic approach:
		
		* Set the frame duration to a value that represents
		  the number of frames per second you want to achieve.
		* Set all of the LED colors for one frame.
		* Wait for the :cb:`Frame Rendered` callback.
		* Set all of the LED colors for next frame.
		* Wait for the :cb:`Frame Rendered` callback.
		* and so on.
		
		This approach ensures that you can change the LED colors with
		a fixed frame rate.
		
		The actual number of controllable LEDs depends on the number of free
		Bricklet ports. See :ref:`here <led_strip_bricklet_ram_constraints>` for more
		information. A call of :func:`Set RGB Values` with index + length above the
		bounds is ignored completely.
		*/
		this.ipcon.sendRequest(this, BrickletLEDStrip.FUNCTION_SET_RGB_VALUES, [index, length, r, g, b], 'H B B16 B16 B16', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getRGBValues = function(index, length, returnCallback, errorCallback) {
		/*
		Returns *length* R, G and B values starting from the
		given LED *index*.
		
		The values are the last values that were set by :func:`Set RGB Values`.
		*/
		this.ipcon.sendRequest(this, BrickletLEDStrip.FUNCTION_GET_RGB_VALUES, [index, length], 'H B', 56, 'B16 B16 B16', returnCallback, errorCallback, false, true);
	};
	this.setFrameDuration = function(duration, returnCallback, errorCallback) {
		/*
		Sets the frame duration.
		
		Example: If you want to achieve 20 frames per second, you should
		set the frame duration to 50ms (50ms * 20 = 1 second).
		
		For an explanation of the general approach see :func:`Set RGB Values`.
		*/
		this.ipcon.sendRequest(this, BrickletLEDStrip.FUNCTION_SET_FRAME_DURATION, [duration], 'H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getFrameDuration = function(returnCallback, errorCallback) {
		/*
		Returns the frame duration as set by :func:`Set Frame Duration`.
		*/
		this.ipcon.sendRequest(this, BrickletLEDStrip.FUNCTION_GET_FRAME_DURATION, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.getSupplyVoltage = function(returnCallback, errorCallback) {
		/*
		Returns the current supply voltage of the LEDs.
		*/
		this.ipcon.sendRequest(this, BrickletLEDStrip.FUNCTION_GET_SUPPLY_VOLTAGE, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.setClockFrequency = function(frequency, returnCallback, errorCallback) {
		/*
		Sets the frequency of the clock.
		
		The Bricklet will choose the nearest achievable frequency, which may
		be off by a few Hz. You can get the exact frequency that is used by
		calling :func:`Get Clock Frequency`.
		
		If you have problems with flickering LEDs, they may be bits flipping. You
		can fix this by either making the connection between the LEDs and the
		Bricklet shorter or by reducing the frequency.
		
		With a decreasing frequency your maximum frames per second will decrease
		too.
		
		.. note::
		 The frequency in firmware version 2.0.0 is fixed at 2MHz.
		
		.. versionadded:: 2.0.1$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletLEDStrip.FUNCTION_SET_CLOCK_FREQUENCY, [frequency], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getClockFrequency = function(returnCallback, errorCallback) {
		/*
		Returns the currently used clock frequency as set by :func:`Set Clock Frequency`.
		
		.. versionadded:: 2.0.1$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletLEDStrip.FUNCTION_GET_CLOCK_FREQUENCY, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setChipType = function(chip, returnCallback, errorCallback) {
		/*
		Sets the type of the LED driver chip. We currently support the chips
		
		* WS2801,
		* WS2811,
		* WS2812 / SK6812 / NeoPixel RGB,
		* SK6812RGBW / NeoPixel RGBW (Chip Type = WS2812),
		* LPD8806 and
		* APA102 / DotStar.
		
		.. versionadded:: 2.0.2$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletLEDStrip.FUNCTION_SET_CHIP_TYPE, [chip], 'H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getChipType = function(returnCallback, errorCallback) {
		/*
		Returns the currently used chip type as set by :func:`Set Chip Type`.
		
		.. versionadded:: 2.0.2$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletLEDStrip.FUNCTION_GET_CHIP_TYPE, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.setRGBWValues = function(index, length, r, g, b, w, returnCallback, errorCallback) {
		/*
		Sets *length* RGBW values for the LEDs starting from *index*.
		
		To make the colors show correctly you need to configure the chip type
		(:func:`Set Chip Type`) and a 4-channel channel mapping (:func:`Set Channel Mapping`)
		according to the connected LEDs.
		
		The maximum length is 12, the index goes from 0 to 239 and the rgbw values
		have 8 bits each.
		
		Example: If you set
		
		* index to 5,
		* length to 4,
		* r to [255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
		* g to [0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
		* b to [0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0] and
		* w to [0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0]
		
		the LED with index 5 will be red, 6 will be green, 7 will be blue and 8 will be white.
		
		.. note:: Depending on the LED circuitry colors can be permuted.
		
		The colors will be transfered to actual LEDs when the next
		frame duration ends, see :func:`Set Frame Duration`.
		
		Generic approach:
		
		* Set the frame duration to a value that represents
		  the number of frames per second you want to achieve.
		* Set all of the LED colors for one frame.
		* Wait for the :cb:`Frame Rendered` callback.
		* Set all of the LED colors for next frame.
		* Wait for the :cb:`Frame Rendered` callback.
		* and so on.
		
		This approach ensures that you can change the LED colors with
		a fixed frame rate.
		
		The actual number of controllable LEDs depends on the number of free
		Bricklet ports. See :ref:`here <led_strip_bricklet_ram_constraints>` for more
		information. A call of :func:`Set RGBW Values` with index + length above the
		bounds is ignored completely.
		
		The LPD8806 LED driver chips have 7-bit channels for RGB. Internally the LED
		Strip Bricklets divides the 8-bit values set using this function by 2 to make
		them 7-bit. Therefore, you can just use the normal value range (0-255) for
		LPD8806 LEDs.
		
		The brightness channel of the APA102 LED driver chips has 5-bit. Internally the
		LED Strip Bricklets divides the 8-bit values set using this function by 8 to make
		them 5-bit. Therefore, you can just use the normal value range (0-255) for
		the brightness channel of APA102 LEDs.
		
		.. versionadded:: 2.0.6$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletLEDStrip.FUNCTION_SET_RGBW_VALUES, [index, length, r, g, b, w], 'H B B12 B12 B12 B12', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getRGBWValues = function(index, length, returnCallback, errorCallback) {
		/*
		Returns *length* RGBW values starting from the given *index*.
		
		The values are the last values that were set by :func:`Set RGBW Values`.
		
		.. versionadded:: 2.0.6$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletLEDStrip.FUNCTION_GET_RGBW_VALUES, [index, length], 'H B', 56, 'B12 B12 B12 B12', returnCallback, errorCallback, false, true);
	};
	this.setChannelMapping = function(mapping, returnCallback, errorCallback) {
		/*
		Sets the channel mapping for the connected LEDs.
		
		:func:`Set RGB Values` and :func:`Set RGBW Values` take the data in RGB(W) order.
		But the connected LED driver chips might have their 3 or 4 channels in a
		different order. For example, the WS2801 chips typically use BGR order, the
		WS2812 chips typically use GRB order and the APA102 chips typically use WBGR
		order.
		
		The APA102 chips are special. They have three 8-bit channels for RGB
		and an additional 5-bit channel for the overall brightness of the RGB LED
		making them 4-channel chips. Internally the brightness channel is the first
		channel, therefore one of the Wxyz channel mappings should be used. Then
		the W channel controls the brightness.
		
		If a 3-channel mapping is selected then :func:`Set RGB Values` has to be used.
		Calling :func:`Set RGBW Values` with a 3-channel mapping will produce incorrect
		results. Vice-versa if a 4-channel mapping is selected then
		:func:`Set RGBW Values` has to be used. Calling :func:`Set RGB Values` with a
		4-channel mapping will produce incorrect results.
		
		.. versionadded:: 2.0.6$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletLEDStrip.FUNCTION_SET_CHANNEL_MAPPING, [mapping], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getChannelMapping = function(returnCallback, errorCallback) {
		/*
		Returns the currently used channel mapping as set by :func:`Set Channel Mapping`.
		
		.. versionadded:: 2.0.6$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletLEDStrip.FUNCTION_GET_CHANNEL_MAPPING, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.enableFrameRenderedCallback = function(returnCallback, errorCallback) {
		/*
		Enables the :cb:`Frame Rendered` callback.
		
		By default the callback is enabled.
		
		.. versionadded:: 2.0.6$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletLEDStrip.FUNCTION_ENABLE_FRAME_RENDERED_CALLBACK, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.disableFrameRenderedCallback = function(returnCallback, errorCallback) {
		/*
		Disables the :cb:`Frame Rendered` callback.
		
		By default the callback is enabled.
		
		.. versionadded:: 2.0.6$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletLEDStrip.FUNCTION_DISABLE_FRAME_RENDERED_CALLBACK, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.isFrameRenderedCallbackEnabled = function(returnCallback, errorCallback) {
		/*
		Returns *true* if the :cb:`Frame Rendered` callback is enabled, *false* otherwise.
		
		.. versionadded:: 2.0.6$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletLEDStrip.FUNCTION_IS_FRAME_RENDERED_CALLBACK_ENABLED, [], '', 9, '?', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletLEDStrip.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletLEDStrip;

},{"./Device":279,"./IPConnection":280}],214:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletLEDStripV2.DEVICE_IDENTIFIER = 2103;
BrickletLEDStripV2.DEVICE_DISPLAY_NAME = 'LED Strip Bricklet 2.0';
BrickletLEDStripV2.CALLBACK_FRAME_STARTED = 6;
BrickletLEDStripV2.FUNCTION_SET_LED_VALUES_LOW_LEVEL = 1;
BrickletLEDStripV2.FUNCTION_GET_LED_VALUES_LOW_LEVEL = 2;
BrickletLEDStripV2.FUNCTION_SET_FRAME_DURATION = 3;
BrickletLEDStripV2.FUNCTION_GET_FRAME_DURATION = 4;
BrickletLEDStripV2.FUNCTION_GET_SUPPLY_VOLTAGE = 5;
BrickletLEDStripV2.FUNCTION_SET_CLOCK_FREQUENCY = 7;
BrickletLEDStripV2.FUNCTION_GET_CLOCK_FREQUENCY = 8;
BrickletLEDStripV2.FUNCTION_SET_CHIP_TYPE = 9;
BrickletLEDStripV2.FUNCTION_GET_CHIP_TYPE = 10;
BrickletLEDStripV2.FUNCTION_SET_CHANNEL_MAPPING = 11;
BrickletLEDStripV2.FUNCTION_GET_CHANNEL_MAPPING = 12;
BrickletLEDStripV2.FUNCTION_SET_FRAME_STARTED_CALLBACK_CONFIGURATION = 13;
BrickletLEDStripV2.FUNCTION_GET_FRAME_STARTED_CALLBACK_CONFIGURATION = 14;
BrickletLEDStripV2.FUNCTION_GET_SPITFP_ERROR_COUNT = 234;
BrickletLEDStripV2.FUNCTION_SET_BOOTLOADER_MODE = 235;
BrickletLEDStripV2.FUNCTION_GET_BOOTLOADER_MODE = 236;
BrickletLEDStripV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER = 237;
BrickletLEDStripV2.FUNCTION_WRITE_FIRMWARE = 238;
BrickletLEDStripV2.FUNCTION_SET_STATUS_LED_CONFIG = 239;
BrickletLEDStripV2.FUNCTION_GET_STATUS_LED_CONFIG = 240;
BrickletLEDStripV2.FUNCTION_GET_CHIP_TEMPERATURE = 242;
BrickletLEDStripV2.FUNCTION_RESET = 243;
BrickletLEDStripV2.FUNCTION_WRITE_UID = 248;
BrickletLEDStripV2.FUNCTION_READ_UID = 249;
BrickletLEDStripV2.FUNCTION_GET_IDENTITY = 255;
BrickletLEDStripV2.CHIP_TYPE_WS2801 = 2801;
BrickletLEDStripV2.CHIP_TYPE_WS2811 = 2811;
BrickletLEDStripV2.CHIP_TYPE_WS2812 = 2812;
BrickletLEDStripV2.CHIP_TYPE_LPD8806 = 8806;
BrickletLEDStripV2.CHIP_TYPE_APA102 = 102;
BrickletLEDStripV2.CHANNEL_MAPPING_RGB = 6;
BrickletLEDStripV2.CHANNEL_MAPPING_RBG = 9;
BrickletLEDStripV2.CHANNEL_MAPPING_BRG = 33;
BrickletLEDStripV2.CHANNEL_MAPPING_BGR = 36;
BrickletLEDStripV2.CHANNEL_MAPPING_GRB = 18;
BrickletLEDStripV2.CHANNEL_MAPPING_GBR = 24;
BrickletLEDStripV2.CHANNEL_MAPPING_RGBW = 27;
BrickletLEDStripV2.CHANNEL_MAPPING_RGWB = 30;
BrickletLEDStripV2.CHANNEL_MAPPING_RBGW = 39;
BrickletLEDStripV2.CHANNEL_MAPPING_RBWG = 45;
BrickletLEDStripV2.CHANNEL_MAPPING_RWGB = 54;
BrickletLEDStripV2.CHANNEL_MAPPING_RWBG = 57;
BrickletLEDStripV2.CHANNEL_MAPPING_GRWB = 78;
BrickletLEDStripV2.CHANNEL_MAPPING_GRBW = 75;
BrickletLEDStripV2.CHANNEL_MAPPING_GBWR = 108;
BrickletLEDStripV2.CHANNEL_MAPPING_GBRW = 99;
BrickletLEDStripV2.CHANNEL_MAPPING_GWBR = 120;
BrickletLEDStripV2.CHANNEL_MAPPING_GWRB = 114;
BrickletLEDStripV2.CHANNEL_MAPPING_BRGW = 135;
BrickletLEDStripV2.CHANNEL_MAPPING_BRWG = 141;
BrickletLEDStripV2.CHANNEL_MAPPING_BGRW = 147;
BrickletLEDStripV2.CHANNEL_MAPPING_BGWR = 156;
BrickletLEDStripV2.CHANNEL_MAPPING_BWRG = 177;
BrickletLEDStripV2.CHANNEL_MAPPING_BWGR = 180;
BrickletLEDStripV2.CHANNEL_MAPPING_WRBG = 201;
BrickletLEDStripV2.CHANNEL_MAPPING_WRGB = 198;
BrickletLEDStripV2.CHANNEL_MAPPING_WGBR = 216;
BrickletLEDStripV2.CHANNEL_MAPPING_WGRB = 210;
BrickletLEDStripV2.CHANNEL_MAPPING_WBGR = 228;
BrickletLEDStripV2.CHANNEL_MAPPING_WBRG = 225;
BrickletLEDStripV2.BOOTLOADER_MODE_BOOTLOADER = 0;
BrickletLEDStripV2.BOOTLOADER_MODE_FIRMWARE = 1;
BrickletLEDStripV2.BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT = 2;
BrickletLEDStripV2.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT = 3;
BrickletLEDStripV2.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT = 4;
BrickletLEDStripV2.BOOTLOADER_STATUS_OK = 0;
BrickletLEDStripV2.BOOTLOADER_STATUS_INVALID_MODE = 1;
BrickletLEDStripV2.BOOTLOADER_STATUS_NO_CHANGE = 2;
BrickletLEDStripV2.BOOTLOADER_STATUS_ENTRY_FUNCTION_NOT_PRESENT = 3;
BrickletLEDStripV2.BOOTLOADER_STATUS_DEVICE_IDENTIFIER_INCORRECT = 4;
BrickletLEDStripV2.BOOTLOADER_STATUS_CRC_MISMATCH = 5;
BrickletLEDStripV2.STATUS_LED_CONFIG_OFF = 0;
BrickletLEDStripV2.STATUS_LED_CONFIG_ON = 1;
BrickletLEDStripV2.STATUS_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletLEDStripV2.STATUS_LED_CONFIG_SHOW_STATUS = 3;

function BrickletLEDStripV2(uid, ipcon) {
	//Controls up to 2048 RGB(W) LEDs

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletLEDStripV2.DEVICE_IDENTIFIER, BrickletLEDStripV2.DEVICE_DISPLAY_NAME);
	BrickletLEDStripV2.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickletLEDStripV2.FUNCTION_SET_LED_VALUES_LOW_LEVEL] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletLEDStripV2.FUNCTION_GET_LED_VALUES_LOW_LEVEL] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLEDStripV2.FUNCTION_SET_FRAME_DURATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletLEDStripV2.FUNCTION_GET_FRAME_DURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLEDStripV2.FUNCTION_GET_SUPPLY_VOLTAGE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLEDStripV2.FUNCTION_SET_CLOCK_FREQUENCY] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletLEDStripV2.FUNCTION_GET_CLOCK_FREQUENCY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLEDStripV2.FUNCTION_SET_CHIP_TYPE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletLEDStripV2.FUNCTION_GET_CHIP_TYPE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLEDStripV2.FUNCTION_SET_CHANNEL_MAPPING] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletLEDStripV2.FUNCTION_GET_CHANNEL_MAPPING] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLEDStripV2.FUNCTION_SET_FRAME_STARTED_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletLEDStripV2.FUNCTION_GET_FRAME_STARTED_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLEDStripV2.FUNCTION_GET_SPITFP_ERROR_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLEDStripV2.FUNCTION_SET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLEDStripV2.FUNCTION_GET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLEDStripV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletLEDStripV2.FUNCTION_WRITE_FIRMWARE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLEDStripV2.FUNCTION_SET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletLEDStripV2.FUNCTION_GET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLEDStripV2.FUNCTION_GET_CHIP_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLEDStripV2.FUNCTION_RESET] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletLEDStripV2.FUNCTION_WRITE_UID] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletLEDStripV2.FUNCTION_READ_UID] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLEDStripV2.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletLEDStripV2.CALLBACK_FRAME_STARTED] = [10, 'H'];


	this.streamStateObjects[BrickletLEDStripV2.FUNCTION_SET_LED_VALUES_LOW_LEVEL] = {
		'dataMapping': [],
		'dataMappingStreamIn': [null, 'streamLength', 'streamChunkOffset', 'streamChunkData'],
		'streamProperties': {
			'fixedLength': null,
			'singleChunk': false,
			'shortWrite': false
		},
		'responseProperties': {
			'running': false,
			'runningSubcall': false,
			'runningSubcallOOS': false,
			'waitingFirstChunk': true,
			'timeout': null,
			'data': [],
			'streamInChunkOffset': 0,
			'streamInChunkLength': 0,
			'streamInResponseEmpty': true,
			'streamInWritten': 0,
			'streamInLLParams': null,
			'responseHandler': null,
			'packFormatString': 'H H H B58',
			'unpackFormatString': '',
			'returnCB': null,
			'errorCB': null,
			'callQueue': []
		}
	};
	this.streamStateObjects[BrickletLEDStripV2.FUNCTION_GET_LED_VALUES_LOW_LEVEL] = {
		'dataMapping': ['streamLength', 'streamChunkOffset', 'streamChunkData'],
		'dataMappingStreamIn': [],
		'streamProperties': {
			'fixedLength': null,
			'singleChunk': false,
			'shortWrite': false
		},
		'responseProperties': {
			'running': false,
			'runningSubcall': false,
			'runningSubcallOOS': false,
			'waitingFirstChunk': true,
			'timeout': null,
			'data': [],
			'streamInChunkOffset': 0,
			'streamInChunkLength': 0,
			'streamInResponseEmpty': true,
			'streamInWritten': 0,
			'streamInLLParams': null,
			'responseHandler': null,
			'packFormatString': 'H H',
			'unpackFormatString': 'H H B60',
			'returnCB': null,
			'errorCB': null,
			'callQueue': []
		}
	};

	this.setLEDValuesLowLevel = function(index, valueLength, valueChunkOffset, valueChunkData, returnCallback, errorCallback) {
		/*
		Sets the RGB(W) values for the LEDs starting from *index*.
		You can set at most 2048 RGB values or 1536 RGBW values (6144 byte each).
		
		To make the colors show correctly you need to configure the chip type
		(see :func:`Set Chip Type`) and a channel mapping (see :func:`Set Channel Mapping`)
		according to the connected LEDs.
		
		If the channel mapping has 3 colors, you need to give the data in the sequence
		RGBRGBRGB... if the channel mapping has 4 colors you need to give data in the
		sequence RGBWRGBWRGBW...
		
		The data is double buffered and the colors will be transfered to the
		LEDs when the next frame duration ends (see :func:`Set Frame Duration`).
		
		Generic approach:
		
		* Set the frame duration to a value that represents the number of frames per
		  second you want to achieve.
		* Set all of the LED colors for one frame.
		* Wait for the :cb:`Frame Started` callback.
		* Set all of the LED colors for next frame.
		* Wait for the :cb:`Frame Started` callback.
		* And so on.
		
		This approach ensures that you can change the LED colors with a fixed frame rate.
		*/
		this.ipcon.sendRequest(this, BrickletLEDStripV2.FUNCTION_SET_LED_VALUES_LOW_LEVEL, [index, valueLength, valueChunkOffset, valueChunkData], 'H H H B58', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getLEDValuesLowLevel = function(index, length, returnCallback, errorCallback) {
		/*
		Returns *length* RGB(W) values starting from the
		given *index*.
		
		If the channel mapping has 3 colors, you will get the data in the sequence
		RGBRGBRGB... if the channel mapping has 4 colors you will get the data in the
		sequence RGBWRGBWRGBW...
		(assuming you start at an index divisible by 3 (RGB) or 4 (RGBW)).
		*/
		this.ipcon.sendRequest(this, BrickletLEDStripV2.FUNCTION_GET_LED_VALUES_LOW_LEVEL, [index, length], 'H H', 72, 'H H B60', returnCallback, errorCallback, false, true);
	};
	this.setFrameDuration = function(duration, returnCallback, errorCallback) {
		/*
		Sets the frame duration.
		
		Example: If you want to achieve 20 frames per second, you should
		set the frame duration to 50ms (50ms * 20 = 1 second).
		
		For an explanation of the general approach see :func:`Set LED Values`.
		
		Default value: 100ms (10 frames per second).
		*/
		this.ipcon.sendRequest(this, BrickletLEDStripV2.FUNCTION_SET_FRAME_DURATION, [duration], 'H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getFrameDuration = function(returnCallback, errorCallback) {
		/*
		Returns the frame duration as set by :func:`Set Frame Duration`.
		*/
		this.ipcon.sendRequest(this, BrickletLEDStripV2.FUNCTION_GET_FRAME_DURATION, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.getSupplyVoltage = function(returnCallback, errorCallback) {
		/*
		Returns the current supply voltage of the LEDs.
		*/
		this.ipcon.sendRequest(this, BrickletLEDStripV2.FUNCTION_GET_SUPPLY_VOLTAGE, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.setClockFrequency = function(frequency, returnCallback, errorCallback) {
		/*
		Sets the frequency of the clock.
		
		The Bricklet will choose the nearest achievable frequency, which may
		be off by a few Hz. You can get the exact frequency that is used by
		calling :func:`Get Clock Frequency`.
		
		If you have problems with flickering LEDs, they may be bits flipping. You
		can fix this by either making the connection between the LEDs and the
		Bricklet shorter or by reducing the frequency.
		
		With a decreasing frequency your maximum frames per second will decrease
		too.
		*/
		this.ipcon.sendRequest(this, BrickletLEDStripV2.FUNCTION_SET_CLOCK_FREQUENCY, [frequency], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getClockFrequency = function(returnCallback, errorCallback) {
		/*
		Returns the currently used clock frequency as set by :func:`Set Clock Frequency`.
		*/
		this.ipcon.sendRequest(this, BrickletLEDStripV2.FUNCTION_GET_CLOCK_FREQUENCY, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setChipType = function(chip, returnCallback, errorCallback) {
		/*
		Sets the type of the LED driver chip. We currently support the chips
		
		* WS2801,
		* WS2811,
		* WS2812 / SK6812 / NeoPixel RGB,
		* SK6812RGBW / NeoPixel RGBW (Chip Type = WS2812),
		* WS2813 / WS2815 (Chip Type = WS2812)
		* LPD8806 and
		* APA102 / DotStar.
		*/
		this.ipcon.sendRequest(this, BrickletLEDStripV2.FUNCTION_SET_CHIP_TYPE, [chip], 'H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getChipType = function(returnCallback, errorCallback) {
		/*
		Returns the currently used chip type as set by :func:`Set Chip Type`.
		*/
		this.ipcon.sendRequest(this, BrickletLEDStripV2.FUNCTION_GET_CHIP_TYPE, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.setChannelMapping = function(mapping, returnCallback, errorCallback) {
		/*
		Sets the channel mapping for the connected LEDs.
		
		If the mapping has 4 colors, the function :func:`Set LED Values` expects 4
		values per pixel and if the mapping has 3 colors it expects 3 values per pixel.
		
		The function always expects the order RGB(W). The connected LED driver chips
		might have their 3 or 4 channels in a different order. For example, the WS2801
		chips typically use BGR order, then WS2812 chips typically use GRB order and
		the APA102 chips typically use WBGR order.
		
		The APA102 chips are special. They have three 8-bit channels for RGB
		and an additional 5-bit channel for the overall brightness of the RGB LED
		making them 4-channel chips. Internally the brightness channel is the first
		channel, therefore one of the Wxyz channel mappings should be used. Then
		the W channel controls the brightness.
		*/
		this.ipcon.sendRequest(this, BrickletLEDStripV2.FUNCTION_SET_CHANNEL_MAPPING, [mapping], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getChannelMapping = function(returnCallback, errorCallback) {
		/*
		Returns the currently used channel mapping as set by :func:`Set Channel Mapping`.
		*/
		this.ipcon.sendRequest(this, BrickletLEDStripV2.FUNCTION_GET_CHANNEL_MAPPING, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setFrameStartedCallbackConfiguration = function(enable, returnCallback, errorCallback) {
		/*
		Enables/disables the :cb:`Frame Started` callback.
		*/
		this.ipcon.sendRequest(this, BrickletLEDStripV2.FUNCTION_SET_FRAME_STARTED_CALLBACK_CONFIGURATION, [enable], '?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getFrameStartedCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by
		:func:`Set Frame Started Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletLEDStripV2.FUNCTION_GET_FRAME_STARTED_CALLBACK_CONFIGURATION, [], '', 9, '?', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPErrorCount = function(returnCallback, errorCallback) {
		/*
		Returns the error count for the communication between Brick and Bricklet.
		
		The errors are divided into
		
		* ACK checksum errors,
		* message checksum errors,
		* framing errors and
		* overflow errors.
		
		The errors counts are for errors that occur on the Bricklet side. All
		Bricks have a similar function that returns the errors on the Brick side.
		*/
		this.ipcon.sendRequest(this, BrickletLEDStripV2.FUNCTION_GET_SPITFP_ERROR_COUNT, [], '', 24, 'I I I I', returnCallback, errorCallback, false, true);
	};
	this.setBootloaderMode = function(mode, returnCallback, errorCallback) {
		/*
		Sets the bootloader mode and returns the status after the requested
		mode change was instigated.
		
		You can change from bootloader mode to firmware mode and vice versa. A change
		from bootloader mode to firmware mode will only take place if the entry function,
		device identifier and CRC are present and correct.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletLEDStripV2.FUNCTION_SET_BOOTLOADER_MODE, [mode], 'B', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getBootloaderMode = function(returnCallback, errorCallback) {
		/*
		Returns the current bootloader mode, see :func:`Set Bootloader Mode`.
		*/
		this.ipcon.sendRequest(this, BrickletLEDStripV2.FUNCTION_GET_BOOTLOADER_MODE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setWriteFirmwarePointer = function(pointer, returnCallback, errorCallback) {
		/*
		Sets the firmware pointer for :func:`Write Firmware`. The pointer has
		to be increased by chunks of size 64. The data is written to flash
		every 4 chunks (which equals to one page of size 256).
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletLEDStripV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER, [pointer], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeFirmware = function(data, returnCallback, errorCallback) {
		/*
		Writes 64 Bytes of firmware at the position as written by
		:func:`Set Write Firmware Pointer` before. The firmware is written
		to flash every 4 chunks.
		
		You can only write firmware in bootloader mode.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletLEDStripV2.FUNCTION_WRITE_FIRMWARE, [data], 'B64', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setStatusLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Sets the status LED configuration. By default the LED shows
		communication traffic between Brick and Bricklet, it flickers once
		for every 10 received data packets.
		
		You can also turn the LED permanently on/off or show a heartbeat.
		
		If the Bricklet is in bootloader mode, the LED is will show heartbeat by default.
		*/
		this.ipcon.sendRequest(this, BrickletLEDStripV2.FUNCTION_SET_STATUS_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getStatusLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Status LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletLEDStripV2.FUNCTION_GET_STATUS_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getChipTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature as measured inside the microcontroller. The
		value returned is not the ambient temperature!
		
		The temperature is only proportional to the real temperature and it has bad
		accuracy. Practically it is only useful as an indicator for
		temperature changes.
		*/
		this.ipcon.sendRequest(this, BrickletLEDStripV2.FUNCTION_GET_CHIP_TEMPERATURE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.reset = function(returnCallback, errorCallback) {
		/*
		Calling this function will reset the Bricklet. All configurations
		will be lost.
		
		After a reset you have to create new device objects,
		calling functions on the existing ones will result in
		undefined behavior!
		*/
		this.ipcon.sendRequest(this, BrickletLEDStripV2.FUNCTION_RESET, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeUID = function(uid, returnCallback, errorCallback) {
		/*
		Writes a new UID into flash. If you want to set a new UID
		you have to decode the Base58 encoded UID string into an
		integer first.
		
		We recommend that you use Brick Viewer to change the UID.
		*/
		this.ipcon.sendRequest(this, BrickletLEDStripV2.FUNCTION_WRITE_UID, [uid], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.readUID = function(returnCallback, errorCallback) {
		/*
		Returns the current UID as an integer. Encode as
		Base58 to get the usual string version.
		*/
		this.ipcon.sendRequest(this, BrickletLEDStripV2.FUNCTION_READ_UID, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletLEDStripV2.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};
	this.setLEDValues = function(index, value, returnCallback, errorCallback) {
		/*
		Sets the RGB(W) values for the LEDs starting from *index*.
		You can set at most 2048 RGB values or 1536 RGBW values (6144 byte each).
		
		To make the colors show correctly you need to configure the chip type
		(see :func:`Set Chip Type`) and a channel mapping (see :func:`Set Channel Mapping`)
		according to the connected LEDs.
		
		If the channel mapping has 3 colors, you need to give the data in the sequence
		RGBRGBRGB... if the channel mapping has 4 colors you need to give data in the
		sequence RGBWRGBWRGBW...
		
		The data is double buffered and the colors will be transfered to the
		LEDs when the next frame duration ends (see :func:`Set Frame Duration`).
		
		Generic approach:
		
		* Set the frame duration to a value that represents the number of frames per
		  second you want to achieve.
		* Set all of the LED colors for one frame.
		* Wait for the :cb:`Frame Started` callback.
		* Set all of the LED colors for next frame.
		* Wait for the :cb:`Frame Started` callback.
		* And so on.
		
		This approach ensures that you can change the LED colors with a fixed frame rate.
		*/

		var valueLength = 0;
		var valueChunkData = [];
		var valueChunkOffset = 0;
		var streamStateObject = this.streamStateObjects[1];

		if (value.length > 65535) {
			if (errorCallback !== null){
				errorCallback(IPConnection.ERROR_INVALID_PARAMETER);
			}

			this.resetStreamStateObject(streamStateObject);

			if (streamStateObject['responseProperties']['callQueue'].length > 0) {
				streamStateObject['responseProperties']['callQueue'].shift()(device);
			}

			return;
		}

		if (!this.getResponseExpected(1)) {
			if (streamStateObject['streamProperties']['fixedLength']) {
				valueLength = streamStateObject['streamProperties']['fixedLength'];
			}
			else {
				valueLength = value.length;
			}

			if (streamStateObject['streamProperties']['singleChunk']) {
				valueChunkData =
					this.ipcon.createChunkData(value, 0, 58, '\0');

				this.ipcon.sendRequest(this,
				                       BrickletLEDStripV2.FUNCTION_SET_LED_VALUES_LOW_LEVEL,
				                       [index, valueLength, valueChunkOffset, valueChunkData],
				                       'H H H B58',
				                       0,
				                       '',
				                       returnCallback,
				                       errorCallback,
				                       false,
				                       true);
			}
			else {
				while (valueChunkOffset < value.length) {
					valueChunkData =
						this.ipcon.createChunkData(value, valueChunkOffset, 58, '\0');

					this.ipcon.sendRequest(this,
					                       BrickletLEDStripV2.FUNCTION_SET_LED_VALUES_LOW_LEVEL,
					                       [index, valueLength, valueChunkOffset, valueChunkData],
					                       'H H H B58',
					                       0,
					                       '',
					                       returnCallback,
					                       errorCallback,
					                       false,
					                       true);

					valueChunkOffset += 58;
				}
			}

			if (returnCallback) {
				returnCallback();
			}
		}
		else {
			var responseHandler = null;
			var functionToQueue = null;

			if (streamStateObject['responseProperties']['responseHandler'] === null) {
				responseHandler = function (device, fid, packetResponse) {
					var result = [];
					var payload = null;
					var llvalues = null;
					var packetErrorFlag = 0;
					var rolesMappedData = [];
					var shortWriteWritten = -1;
					var streamStateObject = device.streamStateObjects[fid];
					var responseEmpty = streamStateObject['responseProperties']['streamInResponseEmpty'];
					var valueLength = 0;
					var valueChunkData = [];
					var valueChunkOffset = 0;

					function doNextLLCall() {
						valueLength = streamStateObject['responseProperties']['data'].length;
						valueChunkData =
							device.ipcon.createChunkData(streamStateObject['responseProperties']['data'],
							                             streamStateObject['responseProperties']['streamInChunkOffset'],
							                             streamStateObject['responseProperties']['streamInChunkLength'],
							                             '\0');
						valueChunkOffset = streamStateObject['responseProperties']['streamInChunkOffset'];

						for (var i = 0; i < streamStateObject['dataMappingStreamIn'].length; i++) {
							if (streamStateObject['dataMappingStreamIn'][i] === null) {
								continue;
							}

							if (streamStateObject['dataMappingStreamIn'][i].endsWith('Length')) {
								streamStateObject['responseProperties']['streamInLLParams'][i] = valueLength;
							}
							else if (streamStateObject['dataMappingStreamIn'][i].endsWith('Offset')) {
								streamStateObject['responseProperties']['streamInLLParams'][i] = valueChunkOffset;
							}
							else if (streamStateObject['dataMappingStreamIn'][i].endsWith('Data')) {
								streamStateObject['responseProperties']['streamInLLParams'][i] = valueChunkData;
							}
						}

						device.ipcon.sendRequest(device,
						                         BrickletLEDStripV2.FUNCTION_SET_LED_VALUES_LOW_LEVEL,
						                         streamStateObject['responseProperties']['streamInLLParams'],
						                         'H H H B58',
						                         0,
						                         '',
						                         returnCallback,
						                         errorCallback,
						                         true,
						                         true);

						streamStateObject['responseProperties']['streamInChunkOffset'] += 58;
					}

					function handleStreamInDone() {
						if (streamStateObject['responseProperties']['returnCB']) {
							if (streamStateObject['streamProperties']['shortWrite']) {
								for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
									if (streamStateObject['dataMapping'][i].endsWith('Written')) {
										result[i] = streamStateObject['responseProperties']['streamInWritten'];
										break;
									}
								}
							}

							if (!responseEmpty) {
								streamStateObject['responseProperties']['returnCB'].apply(device, result);
							}
							else {
								streamStateObject['responseProperties']['returnCB'].apply(device);
							}
						}

						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}
					}

					if (!streamStateObject) {
						return;
					}

					packetErrorFlag = device.ipcon.getEFromPacket(packetResponse);

					if (packetErrorFlag !== 0) {
						if (streamStateObject['responseProperties']['errorCB'] !== undefined) {
							if (packetErrorFlag === 1) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_INVALID_PARAMETER);
							}
							else if (packetErrorFlag === 2) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_FUNCTION_NOT_SUPPORTED);
							}
							else {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_UNKNOWN_ERROR);
							}
						}

						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}

						return;
					}

					if (responseEmpty) {
						if (streamStateObject['streamProperties']['singleChunk']) {
							handleStreamInDone();

							return;
						}

						if (streamStateObject['responseProperties']['streamInChunkOffset'] < streamStateObject['responseProperties']['data'].length) {
							doNextLLCall();
						}
						else {
							handleStreamInDone();
						}
					}
					else {
						payload = device.ipcon.getPayloadFromPacket(packetResponse);
						llvalues = device.ipcon.unpack(payload,
						                               streamStateObject['responseProperties']['unpackFormatString']);

						if (!payload || !llvalues) {
							device.resetStreamStateObject(streamStateObject);

							if (streamStateObject['responseProperties']['callQueue'].length > 0) {
								streamStateObject['responseProperties']['callQueue'].shift()(device);
							}

							return;
						}

						for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
							result.push(llvalues[i]);
						}

						if (streamStateObject['streamProperties']['singleChunk']) {
							if (streamStateObject['responseProperties']['returnCB']) {
								streamStateObject['responseProperties']['returnCB'].apply(device, result);
							}

							device.resetStreamStateObject(streamStateObject);

							if (streamStateObject['responseProperties']['callQueue'].length > 0) {
								streamStateObject['responseProperties']['callQueue'].shift()(device);
							}

							return;
						}

						if (streamStateObject['streamProperties']['shortWrite']) {
							for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
								if (streamStateObject['dataMapping'][i].endsWith('Written')) {
									shortWriteWritten = llvalues[i];
									streamStateObject['responseProperties']['streamInWritten'] += shortWriteWritten;
									break;
								}
							}
							if ((shortWriteWritten !== -1) && (shortWriteWritten < 58)) {
								// Either last chunk or short write
								handleStreamInDone();
								return;
							}
						}

						if (streamStateObject['responseProperties']['streamInChunkOffset'] < streamStateObject['responseProperties']['data'].length) {
							doNextLLCall();
						}
						else {
							handleStreamInDone();
						}
					}
				};

				streamStateObject['responseProperties']['responseHandler'] = responseHandler;
			}

			if (!streamStateObject['responseProperties']['running']) {
				streamStateObject['responseProperties']['running'] = true;
				streamStateObject['responseProperties']['returnCB'] = returnCallback;
				streamStateObject['responseProperties']['errorCB'] = errorCallback;
				streamStateObject['responseProperties']['data'].length = 0;
				streamStateObject['responseProperties']['data'].push.apply(streamStateObject['responseProperties']['data'],
				                                                           value);

				if (streamStateObject['streamProperties']['fixedLength']) {
					valueLength = streamStateObject['streamProperties']['fixedLength'];
				}
				else {
					valueLength = value.length;
				}

				valueChunkOffset = 0;
				valueChunkData =
					this.ipcon.createChunkData(value, 0, 58, '\0');

				streamStateObject['responseProperties']['streamInChunkOffset'] = 58;
				streamStateObject['responseProperties']['streamInChunkLength'] = 58;
				streamStateObject['responseProperties']['streamInLLParams'] = [index, valueLength, valueChunkOffset, valueChunkData];

				this.ipcon.sendRequest(this,
				                       BrickletLEDStripV2.FUNCTION_SET_LED_VALUES_LOW_LEVEL,
				                       [index, valueLength, valueChunkOffset, valueChunkData],
				                       'H H H B58',
				                       0,
				                       '',
				                       returnCallback,
				                       errorCallback,
				                       true,
				                       true);
			}
			else {
				functionToQueue = function (device) {
					device.setLEDValues.call(device, index, value, returnCallback, errorCallback);
				}

				streamStateObject['responseProperties']['callQueue'].push(functionToQueue);
			}
		}
	};

	this.getLEDValues = function(index, length, returnCallback, errorCallback) {
		/*
		Returns *length* RGB(W) values starting from the
		given *index*.
		
		If the channel mapping has 3 colors, you will get the data in the sequence
		RGBRGBRGB... if the channel mapping has 4 colors you will get the data in the
		sequence RGBWRGBWRGBW...
		(assuming you start at an index divisible by 3 (RGB) or 4 (RGBW)).
		*/
		var responseHandler = null;
		var functionToQueue = null;
		var streamStateObject = this.streamStateObjects[2];
		if (streamStateObject['responseProperties']['responseHandler'] === null) {
			responseHandler = 
				function (device, fid, packetResponse) {
					var result = [];
					var llvalues = null;
					var packetErrorFlag = 0;
					var rolesMappedData = [];
					var valueLength = null;
					var valueChunkData = null;
					var valueOutOfSync = false;
					var streamStateObject = device.streamStateObjects[fid];
					var valueChunkOffset = null;
					var payload = device.ipcon.getPayloadFromPacket(packetResponse);

					packetErrorFlag = device.ipcon.getEFromPacket(packetResponse);

					if (packetErrorFlag !== 0) {
						if (streamStateObject['responseProperties']['errorCB'] !== undefined) {
							if (packetErrorFlag === 1) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_INVALID_PARAMETER);
							}
							else if (packetErrorFlag === 2) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_FUNCTION_NOT_SUPPORTED);
							}
							else {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_UNKNOWN_ERROR);
							}
						}

						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}

						return;
					}

					if (payload.length === 0) {
						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}

						return;
					}

					llvalues = device.ipcon.unpack(payload,
					                               streamStateObject['responseProperties']['unpackFormatString']);

					for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
						if (streamStateObject['dataMapping'][i] === 'streamChunkData') {
							valueChunkData = llvalues[i];
						}
						else if (streamStateObject['dataMapping'][i] === 'streamChunkOffset') {
							valueChunkOffset = llvalues[i];
						}
					}

					for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
						if (streamStateObject['dataMapping'][i] === 'streamLength') {
							valueLength = llvalues[i];
							break;
						}
					}

					function handleOOS() {
						if ((valueChunkOffset + 60) < valueLength) {
							streamStateObject['responseProperties']['runningSubcallOOS'] = true;
							device.ipcon.sendRequest(device, BrickletLEDStripV2.FUNCTION_GET_LED_VALUES_LOW_LEVEL, [index, length], 'H H', 72, 'H H B60', streamStateObject['responseProperties']['returnCB'], streamStateObject['responseProperties']['errorCB'], true, true);

							return;
						}

						if (streamStateObject['responseProperties']['errorCB']) {
							streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_STREAM_OUT_OF_SYNC);
						}

						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}
					}

					if (streamStateObject['responseProperties']['waitingFirstChunk']) {
						streamStateObject['responseProperties']['waitingFirstChunk'] = false;
						valueOutOfSync = (valueChunkOffset !== 0);
						streamStateObject['responseProperties']['data'] = valueChunkData;
					}

					if (!streamStateObject['responseProperties']['runningSubcallOOS']) {
						if (!streamStateObject['responseProperties']['runningSubcall']) {
							if (!valueOutOfSync &&
							    (streamStateObject['responseProperties']['data'].length < valueLength)) {
							        streamStateObject['responseProperties']['runningSubcall'] = true;
							        device.ipcon.sendRequest(device, BrickletLEDStripV2.FUNCTION_GET_LED_VALUES_LOW_LEVEL, [index, length], 'H H', 72, 'H H B60', streamStateObject['responseProperties']['returnCB'], streamStateObject['responseProperties']['errorCB'], true, true);

							        return;
							}
						}
						else {
							valueOutOfSync =
								(valueChunkOffset !== streamStateObject['responseProperties']['data'].length);

							if (!valueOutOfSync &&
								(streamStateObject['responseProperties']['data'].length < valueLength)) {
									streamStateObject['responseProperties']['data'] =
										streamStateObject['responseProperties']['data'].concat(valueChunkData);

									if (streamStateObject['responseProperties']['data'].length >= valueLength) {
										streamStateObject['responseProperties']['data'] =
											streamStateObject['responseProperties']['data'].splice(0, valueLength);
									}
									else {
										device.ipcon.sendRequest(device, BrickletLEDStripV2.FUNCTION_GET_LED_VALUES_LOW_LEVEL, [index, length], 'H H', 72, 'H H B60', streamStateObject['responseProperties']['returnCB'], streamStateObject['responseProperties']['errorCB'], true, true);

										return;
									}
							}
						}
					}
					else{
						handleOOS();

						return;
					}

					if (valueOutOfSync) { // Discard remaining stream to bring it back in-sync
						handleOOS();

						return;
					}

					if (streamStateObject['responseProperties']['returnCB']) {
						for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
							rolesMappedData.push({'role': streamStateObject['dataMapping'][i], 'llvalue': llvalues[i]});
						}

						for (var i = 0; i < rolesMappedData.length; i++) {
							if (rolesMappedData[i]['role'] === 'streamChunkData') {
								result.push(streamStateObject['responseProperties']['data'].splice(0, valueLength));
							}
							else if (rolesMappedData[i]['role'] === null) {
								result.push(rolesMappedData[i]['llvalue']);
							}
						}

						streamStateObject['responseProperties']['returnCB'].apply(device, result);
					}

					device.resetStreamStateObject(streamStateObject);

					if (streamStateObject['responseProperties']['callQueue'].length > 0) {
						streamStateObject['responseProperties']['callQueue'].shift()(device);
					}
					
				};

			streamStateObject['responseProperties']['responseHandler'] = responseHandler;
		}
		if (!streamStateObject['responseProperties']['running']) {
			streamStateObject['responseProperties']['running'] = true;
			streamStateObject['responseProperties']['returnCB'] = returnCallback;
			streamStateObject['responseProperties']['errorCB'] = errorCallback;
			this.ipcon.sendRequest(this,
			                       BrickletLEDStripV2.FUNCTION_GET_LED_VALUES_LOW_LEVEL,
			                       [index, length],
			                       'H H',
			                       72,
			                       'H H B60',
			                       returnCallback,
			                       errorCallback,
			                       true,
			                       true);
		}
		else {
			functionToQueue = function (device) {
				device.getLEDValues.call(device, index, length, returnCallback, errorCallback);
			}
			streamStateObject['responseProperties']['callQueue'].push(functionToQueue);
		}
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletLEDStripV2;

},{"./Device":279,"./IPConnection":280}],215:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletLaserRangeFinder.DEVICE_IDENTIFIER = 255;
BrickletLaserRangeFinder.DEVICE_DISPLAY_NAME = 'Laser Range Finder Bricklet';
BrickletLaserRangeFinder.CALLBACK_DISTANCE = 20;
BrickletLaserRangeFinder.CALLBACK_VELOCITY = 21;
BrickletLaserRangeFinder.CALLBACK_DISTANCE_REACHED = 22;
BrickletLaserRangeFinder.CALLBACK_VELOCITY_REACHED = 23;
BrickletLaserRangeFinder.FUNCTION_GET_DISTANCE = 1;
BrickletLaserRangeFinder.FUNCTION_GET_VELOCITY = 2;
BrickletLaserRangeFinder.FUNCTION_SET_DISTANCE_CALLBACK_PERIOD = 3;
BrickletLaserRangeFinder.FUNCTION_GET_DISTANCE_CALLBACK_PERIOD = 4;
BrickletLaserRangeFinder.FUNCTION_SET_VELOCITY_CALLBACK_PERIOD = 5;
BrickletLaserRangeFinder.FUNCTION_GET_VELOCITY_CALLBACK_PERIOD = 6;
BrickletLaserRangeFinder.FUNCTION_SET_DISTANCE_CALLBACK_THRESHOLD = 7;
BrickletLaserRangeFinder.FUNCTION_GET_DISTANCE_CALLBACK_THRESHOLD = 8;
BrickletLaserRangeFinder.FUNCTION_SET_VELOCITY_CALLBACK_THRESHOLD = 9;
BrickletLaserRangeFinder.FUNCTION_GET_VELOCITY_CALLBACK_THRESHOLD = 10;
BrickletLaserRangeFinder.FUNCTION_SET_DEBOUNCE_PERIOD = 11;
BrickletLaserRangeFinder.FUNCTION_GET_DEBOUNCE_PERIOD = 12;
BrickletLaserRangeFinder.FUNCTION_SET_MOVING_AVERAGE = 13;
BrickletLaserRangeFinder.FUNCTION_GET_MOVING_AVERAGE = 14;
BrickletLaserRangeFinder.FUNCTION_SET_MODE = 15;
BrickletLaserRangeFinder.FUNCTION_GET_MODE = 16;
BrickletLaserRangeFinder.FUNCTION_ENABLE_LASER = 17;
BrickletLaserRangeFinder.FUNCTION_DISABLE_LASER = 18;
BrickletLaserRangeFinder.FUNCTION_IS_LASER_ENABLED = 19;
BrickletLaserRangeFinder.FUNCTION_GET_SENSOR_HARDWARE_VERSION = 24;
BrickletLaserRangeFinder.FUNCTION_SET_CONFIGURATION = 25;
BrickletLaserRangeFinder.FUNCTION_GET_CONFIGURATION = 26;
BrickletLaserRangeFinder.FUNCTION_GET_IDENTITY = 255;
BrickletLaserRangeFinder.THRESHOLD_OPTION_OFF = 'x';
BrickletLaserRangeFinder.THRESHOLD_OPTION_OUTSIDE = 'o';
BrickletLaserRangeFinder.THRESHOLD_OPTION_INSIDE = 'i';
BrickletLaserRangeFinder.THRESHOLD_OPTION_SMALLER = '<';
BrickletLaserRangeFinder.THRESHOLD_OPTION_GREATER = '>';
BrickletLaserRangeFinder.MODE_DISTANCE = 0;
BrickletLaserRangeFinder.MODE_VELOCITY_MAX_13MS = 1;
BrickletLaserRangeFinder.MODE_VELOCITY_MAX_32MS = 2;
BrickletLaserRangeFinder.MODE_VELOCITY_MAX_64MS = 3;
BrickletLaserRangeFinder.MODE_VELOCITY_MAX_127MS = 4;
BrickletLaserRangeFinder.VERSION_1 = 1;
BrickletLaserRangeFinder.VERSION_3 = 3;

function BrickletLaserRangeFinder(uid, ipcon) {
	//Measures distance up to 40m with laser light

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletLaserRangeFinder.DEVICE_IDENTIFIER, BrickletLaserRangeFinder.DEVICE_DISPLAY_NAME);
	BrickletLaserRangeFinder.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 1];
	this.responseExpected[BrickletLaserRangeFinder.FUNCTION_GET_DISTANCE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLaserRangeFinder.FUNCTION_GET_VELOCITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLaserRangeFinder.FUNCTION_SET_DISTANCE_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletLaserRangeFinder.FUNCTION_GET_DISTANCE_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLaserRangeFinder.FUNCTION_SET_VELOCITY_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletLaserRangeFinder.FUNCTION_GET_VELOCITY_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLaserRangeFinder.FUNCTION_SET_DISTANCE_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletLaserRangeFinder.FUNCTION_GET_DISTANCE_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLaserRangeFinder.FUNCTION_SET_VELOCITY_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletLaserRangeFinder.FUNCTION_GET_VELOCITY_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLaserRangeFinder.FUNCTION_SET_DEBOUNCE_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletLaserRangeFinder.FUNCTION_GET_DEBOUNCE_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLaserRangeFinder.FUNCTION_SET_MOVING_AVERAGE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletLaserRangeFinder.FUNCTION_GET_MOVING_AVERAGE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLaserRangeFinder.FUNCTION_SET_MODE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletLaserRangeFinder.FUNCTION_GET_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLaserRangeFinder.FUNCTION_ENABLE_LASER] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletLaserRangeFinder.FUNCTION_DISABLE_LASER] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletLaserRangeFinder.FUNCTION_IS_LASER_ENABLED] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLaserRangeFinder.FUNCTION_GET_SENSOR_HARDWARE_VERSION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLaserRangeFinder.FUNCTION_SET_CONFIGURATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletLaserRangeFinder.FUNCTION_GET_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLaserRangeFinder.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletLaserRangeFinder.CALLBACK_DISTANCE] = [10, 'H'];
	this.callbackFormats[BrickletLaserRangeFinder.CALLBACK_VELOCITY] = [10, 'h'];
	this.callbackFormats[BrickletLaserRangeFinder.CALLBACK_DISTANCE_REACHED] = [10, 'H'];
	this.callbackFormats[BrickletLaserRangeFinder.CALLBACK_VELOCITY_REACHED] = [10, 'h'];



	this.getDistance = function(returnCallback, errorCallback) {
		/*
		Returns the measured distance.
		
		Sensor hardware version 1 (see :func:`Get Sensor Hardware Version`) cannot
		measure distance and velocity at the same time. Therefore, the distance mode
		has to be enabled using :func:`Set Mode`.
		Sensor hardware version 3 can measure distance and velocity at the same
		time. Also the laser has to be enabled, see :func:`Enable Laser`.
		
		If you want to get the distance periodically, it is recommended to
		use the :cb:`Distance` callback and set the period with
		:func:`Set Distance Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletLaserRangeFinder.FUNCTION_GET_DISTANCE, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.getVelocity = function(returnCallback, errorCallback) {
		/*
		Returns the measured velocity.
		
		Sensor hardware version 1 (see :func:`Get Sensor Hardware Version`) cannot
		measure distance and velocity at the same time. Therefore, the velocity mode
		has to be enabled using :func:`Set Mode`.
		Sensor hardware version 3 can measure distance and velocity at the same
		time, but the velocity measurement only produces stables results if a fixed
		measurement rate (see :func:`Set Configuration`) is configured. Also the laser
		has to be enabled, see :func:`Enable Laser`.
		
		If you want to get the velocity periodically, it is recommended to
		use the :cb:`Velocity` callback and set the period with
		:func:`Set Velocity Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletLaserRangeFinder.FUNCTION_GET_VELOCITY, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.setDistanceCallbackPeriod = function(period, returnCallback, errorCallback) {
		/*
		Sets the period with which the :cb:`Distance` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		The :cb:`Distance` callback is only triggered if the distance value has
		changed since the last triggering.
		*/
		this.ipcon.sendRequest(this, BrickletLaserRangeFinder.FUNCTION_SET_DISTANCE_CALLBACK_PERIOD, [period], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getDistanceCallbackPeriod = function(returnCallback, errorCallback) {
		/*
		Returns the period as set by :func:`Set Distance Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletLaserRangeFinder.FUNCTION_GET_DISTANCE_CALLBACK_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setVelocityCallbackPeriod = function(period, returnCallback, errorCallback) {
		/*
		Sets the period with which the :cb:`Velocity` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		The :cb:`Velocity` callback is only triggered if the velocity value has
		changed since the last triggering.
		*/
		this.ipcon.sendRequest(this, BrickletLaserRangeFinder.FUNCTION_SET_VELOCITY_CALLBACK_PERIOD, [period], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getVelocityCallbackPeriod = function(returnCallback, errorCallback) {
		/*
		Returns the period as set by :func:`Set Velocity Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletLaserRangeFinder.FUNCTION_GET_VELOCITY_CALLBACK_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setDistanceCallbackThreshold = function(option, min, max, returnCallback, errorCallback) {
		/*
		Sets the thresholds for the :cb:`Distance Reached` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Callback is turned off"
		 "'o'",    "Callback is triggered when the distance value is *outside* the min and max values"
		 "'i'",    "Callback is triggered when the distance value is *inside* the min and max values"
		 "'<'",    "Callback is triggered when the distance value is smaller than the min value (max is ignored)"
		 "'>'",    "Callback is triggered when the distance value is greater than the min value (max is ignored)"
		*/
		this.ipcon.sendRequest(this, BrickletLaserRangeFinder.FUNCTION_SET_DISTANCE_CALLBACK_THRESHOLD, [option, min, max], 'c H H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getDistanceCallbackThreshold = function(returnCallback, errorCallback) {
		/*
		Returns the threshold as set by :func:`Set Distance Callback Threshold`.
		*/
		this.ipcon.sendRequest(this, BrickletLaserRangeFinder.FUNCTION_GET_DISTANCE_CALLBACK_THRESHOLD, [], '', 13, 'c H H', returnCallback, errorCallback, false, true);
	};
	this.setVelocityCallbackThreshold = function(option, min, max, returnCallback, errorCallback) {
		/*
		Sets the thresholds for the :cb:`Velocity Reached` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Callback is turned off"
		 "'o'",    "Callback is triggered when the velocity is *outside* the min and max values"
		 "'i'",    "Callback is triggered when the velocity is *inside* the min and max values"
		 "'<'",    "Callback is triggered when the velocity is smaller than the min value (max is ignored)"
		 "'>'",    "Callback is triggered when the velocity is greater than the min value (max is ignored)"
		*/
		this.ipcon.sendRequest(this, BrickletLaserRangeFinder.FUNCTION_SET_VELOCITY_CALLBACK_THRESHOLD, [option, min, max], 'c h h', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getVelocityCallbackThreshold = function(returnCallback, errorCallback) {
		/*
		Returns the threshold as set by :func:`Set Velocity Callback Threshold`.
		*/
		this.ipcon.sendRequest(this, BrickletLaserRangeFinder.FUNCTION_GET_VELOCITY_CALLBACK_THRESHOLD, [], '', 13, 'c h h', returnCallback, errorCallback, false, true);
	};
	this.setDebouncePeriod = function(debounce, returnCallback, errorCallback) {
		/*
		Sets the period with which the threshold callbacks
		
		* :cb:`Distance Reached`,
		* :cb:`Velocity Reached`,
		
		are triggered, if the thresholds
		
		* :func:`Set Distance Callback Threshold`,
		* :func:`Set Velocity Callback Threshold`,
		
		keep being reached.
		*/
		this.ipcon.sendRequest(this, BrickletLaserRangeFinder.FUNCTION_SET_DEBOUNCE_PERIOD, [debounce], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getDebouncePeriod = function(returnCallback, errorCallback) {
		/*
		Returns the debounce period as set by :func:`Set Debounce Period`.
		*/
		this.ipcon.sendRequest(this, BrickletLaserRangeFinder.FUNCTION_GET_DEBOUNCE_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setMovingAverage = function(distanceAverageLength, velocityAverageLength, returnCallback, errorCallback) {
		/*
		Sets the length of a `moving averaging <https://en.wikipedia.org/wiki/Moving_average>`__
		for the distance and velocity.
		
		Setting the length to 0 will turn the averaging completely off. With less
		averaging, there is more noise on the data.
		*/
		this.ipcon.sendRequest(this, BrickletLaserRangeFinder.FUNCTION_SET_MOVING_AVERAGE, [distanceAverageLength, velocityAverageLength], 'B B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getMovingAverage = function(returnCallback, errorCallback) {
		/*
		Returns the length moving average as set by :func:`Set Moving Average`.
		*/
		this.ipcon.sendRequest(this, BrickletLaserRangeFinder.FUNCTION_GET_MOVING_AVERAGE, [], '', 10, 'B B', returnCallback, errorCallback, false, true);
	};
	this.setMode = function(mode, returnCallback, errorCallback) {
		/*
		.. note::
		 This function is only available if you have a LIDAR-Lite sensor with hardware
		 version 1. Use :func:`Set Configuration` for hardware version 3. You can check
		 the sensor hardware version using :func:`Get Sensor Hardware Version`.
		
		The LIDAR-Lite sensor (hardware version 1) has five different modes. One mode is
		for distance measurements and four modes are for velocity measurements with
		different ranges.
		
		The following modes are available:
		
		* 0: Distance is measured with resolution 1.0 cm and range 0-4000 cm
		* 1: Velocity is measured with resolution 0.1 m/s and range is 0-12.7 m/s
		* 2: Velocity is measured with resolution 0.25 m/s and range is 0-31.75 m/s
		* 3: Velocity is measured with resolution 0.5 m/s and range is 0-63.5 m/s
		* 4: Velocity is measured with resolution 1.0 m/s and range is 0-127 m/s
		*/
		this.ipcon.sendRequest(this, BrickletLaserRangeFinder.FUNCTION_SET_MODE, [mode], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getMode = function(returnCallback, errorCallback) {
		/*
		Returns the mode as set by :func:`Set Mode`.
		*/
		this.ipcon.sendRequest(this, BrickletLaserRangeFinder.FUNCTION_GET_MODE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.enableLaser = function(returnCallback, errorCallback) {
		/*
		Activates the laser of the LIDAR.
		
		We recommend that you wait 250ms after enabling the laser before
		the first call of :func:`Get Distance` to ensure stable measurements.
		*/
		this.ipcon.sendRequest(this, BrickletLaserRangeFinder.FUNCTION_ENABLE_LASER, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.disableLaser = function(returnCallback, errorCallback) {
		/*
		Deactivates the laser of the LIDAR.
		*/
		this.ipcon.sendRequest(this, BrickletLaserRangeFinder.FUNCTION_DISABLE_LASER, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.isLaserEnabled = function(returnCallback, errorCallback) {
		/*
		Returns *true* if the laser is enabled, *false* otherwise.
		*/
		this.ipcon.sendRequest(this, BrickletLaserRangeFinder.FUNCTION_IS_LASER_ENABLED, [], '', 9, '?', returnCallback, errorCallback, false, true);
	};
	this.getSensorHardwareVersion = function(returnCallback, errorCallback) {
		/*
		Returns the LIDAR-Lite hardware version.
		
		.. versionadded:: 2.0.3$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletLaserRangeFinder.FUNCTION_GET_SENSOR_HARDWARE_VERSION, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setConfiguration = function(acquisitionCount, enableQuickTermination, thresholdValue, measurementFrequency, returnCallback, errorCallback) {
		/*
		.. note::
		 This function is only available if you have a LIDAR-Lite sensor with hardware
		 version 3. Use :func:`Set Mode` for hardware version 1. You can check
		 the sensor hardware version using :func:`Get Sensor Hardware Version`.
		
		The **Acquisition Count** defines the number of times the Laser Range Finder Bricklet
		will integrate acquisitions to find a correlation record peak. With a higher count,
		the Bricklet can measure longer distances. With a lower count, the rate increases. The
		allowed values are 1-255.
		
		If you set **Enable Quick Termination** to true, the distance measurement will be terminated
		early if a high peak was already detected. This means that a higher measurement rate can be achieved
		and long distances can be measured at the same time. However, the chance of false-positive
		distance measurements increases.
		
		Normally the distance is calculated with a detection algorithm that uses peak value,
		signal strength and noise. You can however also define a fixed **Threshold Value**.
		Set this to a low value if you want to measure the distance to something that has
		very little reflection (e.g. glass) and set it to a high value if you want to measure
		the distance to something with a very high reflection (e.g. mirror). Set this to 0 to
		use the default algorithm. The other allowed values are 1-255.
		
		Set the **Measurement Frequency** to force a fixed measurement rate. If set to 0,
		the Laser Range Finder Bricklet will use the optimal frequency according to the other
		configurations and the actual measured distance. Since the rate is not fixed in this case,
		the velocity measurement is not stable. For a stable velocity measurement you should
		set a fixed measurement frequency. The lower the frequency, the higher is the resolution
		of the calculated velocity. The allowed values are 10Hz-500Hz (and 0 to turn the fixed
		frequency off).
		
		.. versionadded:: 2.0.3$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletLaserRangeFinder.FUNCTION_SET_CONFIGURATION, [acquisitionCount, enableQuickTermination, thresholdValue, measurementFrequency], 'B ? B H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Configuration`.
		
		.. versionadded:: 2.0.3$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletLaserRangeFinder.FUNCTION_GET_CONFIGURATION, [], '', 13, 'B ? B H', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletLaserRangeFinder.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletLaserRangeFinder;

},{"./Device":279,"./IPConnection":280}],216:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletLaserRangeFinderV2.DEVICE_IDENTIFIER = 2144;
BrickletLaserRangeFinderV2.DEVICE_DISPLAY_NAME = 'Laser Range Finder Bricklet 2.0';
BrickletLaserRangeFinderV2.CALLBACK_DISTANCE = 4;
BrickletLaserRangeFinderV2.CALLBACK_VELOCITY = 8;
BrickletLaserRangeFinderV2.FUNCTION_GET_DISTANCE = 1;
BrickletLaserRangeFinderV2.FUNCTION_SET_DISTANCE_CALLBACK_CONFIGURATION = 2;
BrickletLaserRangeFinderV2.FUNCTION_GET_DISTANCE_CALLBACK_CONFIGURATION = 3;
BrickletLaserRangeFinderV2.FUNCTION_GET_VELOCITY = 5;
BrickletLaserRangeFinderV2.FUNCTION_SET_VELOCITY_CALLBACK_CONFIGURATION = 6;
BrickletLaserRangeFinderV2.FUNCTION_GET_VELOCITY_CALLBACK_CONFIGURATION = 7;
BrickletLaserRangeFinderV2.FUNCTION_SET_ENABLE = 9;
BrickletLaserRangeFinderV2.FUNCTION_GET_ENABLE = 10;
BrickletLaserRangeFinderV2.FUNCTION_SET_CONFIGURATION = 11;
BrickletLaserRangeFinderV2.FUNCTION_GET_CONFIGURATION = 12;
BrickletLaserRangeFinderV2.FUNCTION_SET_MOVING_AVERAGE = 13;
BrickletLaserRangeFinderV2.FUNCTION_GET_MOVING_AVERAGE = 14;
BrickletLaserRangeFinderV2.FUNCTION_SET_OFFSET_CALIBRATION = 15;
BrickletLaserRangeFinderV2.FUNCTION_GET_OFFSET_CALIBRATION = 16;
BrickletLaserRangeFinderV2.FUNCTION_SET_DISTANCE_LED_CONFIG = 17;
BrickletLaserRangeFinderV2.FUNCTION_GET_DISTANCE_LED_CONFIG = 18;
BrickletLaserRangeFinderV2.FUNCTION_GET_SPITFP_ERROR_COUNT = 234;
BrickletLaserRangeFinderV2.FUNCTION_SET_BOOTLOADER_MODE = 235;
BrickletLaserRangeFinderV2.FUNCTION_GET_BOOTLOADER_MODE = 236;
BrickletLaserRangeFinderV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER = 237;
BrickletLaserRangeFinderV2.FUNCTION_WRITE_FIRMWARE = 238;
BrickletLaserRangeFinderV2.FUNCTION_SET_STATUS_LED_CONFIG = 239;
BrickletLaserRangeFinderV2.FUNCTION_GET_STATUS_LED_CONFIG = 240;
BrickletLaserRangeFinderV2.FUNCTION_GET_CHIP_TEMPERATURE = 242;
BrickletLaserRangeFinderV2.FUNCTION_RESET = 243;
BrickletLaserRangeFinderV2.FUNCTION_WRITE_UID = 248;
BrickletLaserRangeFinderV2.FUNCTION_READ_UID = 249;
BrickletLaserRangeFinderV2.FUNCTION_GET_IDENTITY = 255;
BrickletLaserRangeFinderV2.THRESHOLD_OPTION_OFF = 'x';
BrickletLaserRangeFinderV2.THRESHOLD_OPTION_OUTSIDE = 'o';
BrickletLaserRangeFinderV2.THRESHOLD_OPTION_INSIDE = 'i';
BrickletLaserRangeFinderV2.THRESHOLD_OPTION_SMALLER = '<';
BrickletLaserRangeFinderV2.THRESHOLD_OPTION_GREATER = '>';
BrickletLaserRangeFinderV2.DISTANCE_LED_CONFIG_OFF = 0;
BrickletLaserRangeFinderV2.DISTANCE_LED_CONFIG_ON = 1;
BrickletLaserRangeFinderV2.DISTANCE_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletLaserRangeFinderV2.DISTANCE_LED_CONFIG_SHOW_DISTANCE = 3;
BrickletLaserRangeFinderV2.BOOTLOADER_MODE_BOOTLOADER = 0;
BrickletLaserRangeFinderV2.BOOTLOADER_MODE_FIRMWARE = 1;
BrickletLaserRangeFinderV2.BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT = 2;
BrickletLaserRangeFinderV2.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT = 3;
BrickletLaserRangeFinderV2.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT = 4;
BrickletLaserRangeFinderV2.BOOTLOADER_STATUS_OK = 0;
BrickletLaserRangeFinderV2.BOOTLOADER_STATUS_INVALID_MODE = 1;
BrickletLaserRangeFinderV2.BOOTLOADER_STATUS_NO_CHANGE = 2;
BrickletLaserRangeFinderV2.BOOTLOADER_STATUS_ENTRY_FUNCTION_NOT_PRESENT = 3;
BrickletLaserRangeFinderV2.BOOTLOADER_STATUS_DEVICE_IDENTIFIER_INCORRECT = 4;
BrickletLaserRangeFinderV2.BOOTLOADER_STATUS_CRC_MISMATCH = 5;
BrickletLaserRangeFinderV2.STATUS_LED_CONFIG_OFF = 0;
BrickletLaserRangeFinderV2.STATUS_LED_CONFIG_ON = 1;
BrickletLaserRangeFinderV2.STATUS_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletLaserRangeFinderV2.STATUS_LED_CONFIG_SHOW_STATUS = 3;

function BrickletLaserRangeFinderV2(uid, ipcon) {
	//Measures distance up to 40m with laser light

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletLaserRangeFinderV2.DEVICE_IDENTIFIER, BrickletLaserRangeFinderV2.DEVICE_DISPLAY_NAME);
	BrickletLaserRangeFinderV2.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickletLaserRangeFinderV2.FUNCTION_GET_DISTANCE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLaserRangeFinderV2.FUNCTION_SET_DISTANCE_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletLaserRangeFinderV2.FUNCTION_GET_DISTANCE_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLaserRangeFinderV2.FUNCTION_GET_VELOCITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLaserRangeFinderV2.FUNCTION_SET_VELOCITY_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletLaserRangeFinderV2.FUNCTION_GET_VELOCITY_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLaserRangeFinderV2.FUNCTION_SET_ENABLE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletLaserRangeFinderV2.FUNCTION_GET_ENABLE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLaserRangeFinderV2.FUNCTION_SET_CONFIGURATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletLaserRangeFinderV2.FUNCTION_GET_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLaserRangeFinderV2.FUNCTION_SET_MOVING_AVERAGE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletLaserRangeFinderV2.FUNCTION_GET_MOVING_AVERAGE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLaserRangeFinderV2.FUNCTION_SET_OFFSET_CALIBRATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletLaserRangeFinderV2.FUNCTION_GET_OFFSET_CALIBRATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLaserRangeFinderV2.FUNCTION_SET_DISTANCE_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletLaserRangeFinderV2.FUNCTION_GET_DISTANCE_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLaserRangeFinderV2.FUNCTION_GET_SPITFP_ERROR_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLaserRangeFinderV2.FUNCTION_SET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLaserRangeFinderV2.FUNCTION_GET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLaserRangeFinderV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletLaserRangeFinderV2.FUNCTION_WRITE_FIRMWARE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLaserRangeFinderV2.FUNCTION_SET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletLaserRangeFinderV2.FUNCTION_GET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLaserRangeFinderV2.FUNCTION_GET_CHIP_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLaserRangeFinderV2.FUNCTION_RESET] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletLaserRangeFinderV2.FUNCTION_WRITE_UID] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletLaserRangeFinderV2.FUNCTION_READ_UID] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLaserRangeFinderV2.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletLaserRangeFinderV2.CALLBACK_DISTANCE] = [10, 'h'];
	this.callbackFormats[BrickletLaserRangeFinderV2.CALLBACK_VELOCITY] = [10, 'h'];



	this.getDistance = function(returnCallback, errorCallback) {
		/*
		Returns the measured distance.
		
		The laser has to be enabled, see :func:`Set Enable`.
		
		
		If you want to get the value periodically, it is recommended to use the
		:cb:`Distance` callback. You can set the callback configuration
		with :func:`Set Distance Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletLaserRangeFinderV2.FUNCTION_GET_DISTANCE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.setDistanceCallbackConfiguration = function(period, valueHasToChange, option, min, max, returnCallback, errorCallback) {
		/*
		The period is the period with which the :cb:`Distance` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		If the `value has to change`-parameter is set to true, the callback is only
		triggered after the value has changed. If the value didn't change
		within the period, the callback is triggered immediately on change.
		
		If it is set to false, the callback is continuously triggered with the period,
		independent of the value.
		
		It is furthermore possible to constrain the callback with thresholds.
		
		The `option`-parameter together with min/max sets a threshold for the :cb:`Distance` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Threshold is turned off"
		 "'o'",    "Threshold is triggered when the value is *outside* the min and max values"
		 "'i'",    "Threshold is triggered when the value is *inside* or equal to the min and max values"
		 "'<'",    "Threshold is triggered when the value is smaller than the min value (max is ignored)"
		 "'>'",    "Threshold is triggered when the value is greater than the min value (max is ignored)"
		
		If the option is set to 'x' (threshold turned off) the callback is triggered with the fixed period.
		*/
		this.ipcon.sendRequest(this, BrickletLaserRangeFinderV2.FUNCTION_SET_DISTANCE_CALLBACK_CONFIGURATION, [period, valueHasToChange, option, min, max], 'I ? c h h', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getDistanceCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the callback configuration as set by :func:`Set Distance Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletLaserRangeFinderV2.FUNCTION_GET_DISTANCE_CALLBACK_CONFIGURATION, [], '', 18, 'I ? c h h', returnCallback, errorCallback, false, true);
	};
	this.getVelocity = function(returnCallback, errorCallback) {
		/*
		Returns the measured velocity. The value has a range of -12800 to 12700
		and is given in 1/100 m/s.
		
		The velocity measurement only produces stables results if a fixed
		measurement rate (see :func:`Set Configuration`) is configured. Also the laser
		has to be enabled, see :func:`Set Enable`.
		
		
		If you want to get the value periodically, it is recommended to use the
		:cb:`Velocity` callback. You can set the callback configuration
		with :func:`Set Velocity Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletLaserRangeFinderV2.FUNCTION_GET_VELOCITY, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.setVelocityCallbackConfiguration = function(period, valueHasToChange, option, min, max, returnCallback, errorCallback) {
		/*
		The period is the period with which the :cb:`Velocity` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		If the `value has to change`-parameter is set to true, the callback is only
		triggered after the value has changed. If the value didn't change
		within the period, the callback is triggered immediately on change.
		
		If it is set to false, the callback is continuously triggered with the period,
		independent of the value.
		
		It is furthermore possible to constrain the callback with thresholds.
		
		The `option`-parameter together with min/max sets a threshold for the :cb:`Velocity` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Threshold is turned off"
		 "'o'",    "Threshold is triggered when the value is *outside* the min and max values"
		 "'i'",    "Threshold is triggered when the value is *inside* or equal to the min and max values"
		 "'<'",    "Threshold is triggered when the value is smaller than the min value (max is ignored)"
		 "'>'",    "Threshold is triggered when the value is greater than the min value (max is ignored)"
		
		If the option is set to 'x' (threshold turned off) the callback is triggered with the fixed period.
		*/
		this.ipcon.sendRequest(this, BrickletLaserRangeFinderV2.FUNCTION_SET_VELOCITY_CALLBACK_CONFIGURATION, [period, valueHasToChange, option, min, max], 'I ? c h h', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getVelocityCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the callback configuration as set by :func:`Set Velocity Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletLaserRangeFinderV2.FUNCTION_GET_VELOCITY_CALLBACK_CONFIGURATION, [], '', 18, 'I ? c h h', returnCallback, errorCallback, false, true);
	};
	this.setEnable = function(enable, returnCallback, errorCallback) {
		/*
		Enables the laser of the LIDAR if set to *true*.
		
		We recommend that you wait 250ms after enabling the laser before
		the first call of :func:`Get Distance` to ensure stable measurements.
		*/
		this.ipcon.sendRequest(this, BrickletLaserRangeFinderV2.FUNCTION_SET_ENABLE, [enable], '?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getEnable = function(returnCallback, errorCallback) {
		/*
		Returns the value as set by :func:`Set Enable`.
		*/
		this.ipcon.sendRequest(this, BrickletLaserRangeFinderV2.FUNCTION_GET_ENABLE, [], '', 9, '?', returnCallback, errorCallback, false, true);
	};
	this.setConfiguration = function(acquisitionCount, enableQuickTermination, thresholdValue, measurementFrequency, returnCallback, errorCallback) {
		/*
		The **Acquisition Count** defines the number of times the Laser Range Finder Bricklet
		will integrate acquisitions to find a correlation record peak. With a higher count,
		the Bricklet can measure longer distances. With a lower count, the rate increases. The
		allowed values are 1-255.
		
		If you set **Enable Quick Termination** to true, the distance measurement will be terminated
		early if a high peak was already detected. This means that a higher measurement rate can be achieved
		and long distances can be measured at the same time. However, the chance of false-positive
		distance measurements increases.
		
		Normally the distance is calculated with a detection algorithm that uses peak value,
		signal strength and noise. You can however also define a fixed **Threshold Value**.
		Set this to a low value if you want to measure the distance to something that has
		very little reflection (e.g. glass) and set it to a high value if you want to measure
		the distance to something with a very high reflection (e.g. mirror). Set this to 0 to
		use the default algorithm. The other allowed values are 1-255.
		
		Set the **Measurement Frequency** to force a fixed measurement rate. If set to 0,
		the Laser Range Finder Bricklet will use the optimal frequency according to the other
		configurations and the actual measured distance. Since the rate is not fixed in this case,
		the velocity measurement is not stable. For a stable velocity measurement you should
		set a fixed measurement frequency. The lower the frequency, the higher is the resolution
		of the calculated velocity. The allowed values are 10Hz-500Hz (and 0 to turn the fixed
		frequency off).
		
		The default values for Acquisition Count, Enable Quick Termination, Threshold Value and
		Measurement Frequency are 128, false, 0 and 0.
		*/
		this.ipcon.sendRequest(this, BrickletLaserRangeFinderV2.FUNCTION_SET_CONFIGURATION, [acquisitionCount, enableQuickTermination, thresholdValue, measurementFrequency], 'B ? B H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletLaserRangeFinderV2.FUNCTION_GET_CONFIGURATION, [], '', 13, 'B ? B H', returnCallback, errorCallback, false, true);
	};
	this.setMovingAverage = function(distanceAverageLength, velocityAverageLength, returnCallback, errorCallback) {
		/*
		Sets the length of a `moving averaging <https://en.wikipedia.org/wiki/Moving_average>`__
		for the distance and velocity.
		
		Setting the length to 0 will turn the averaging completely off. With less
		averaging, there is more noise on the data.
		*/
		this.ipcon.sendRequest(this, BrickletLaserRangeFinderV2.FUNCTION_SET_MOVING_AVERAGE, [distanceAverageLength, velocityAverageLength], 'B B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getMovingAverage = function(returnCallback, errorCallback) {
		/*
		Returns the length moving average as set by :func:`Set Moving Average`.
		*/
		this.ipcon.sendRequest(this, BrickletLaserRangeFinderV2.FUNCTION_GET_MOVING_AVERAGE, [], '', 10, 'B B', returnCallback, errorCallback, false, true);
	};
	this.setOffsetCalibration = function(offset, returnCallback, errorCallback) {
		/*
		The offset is added to the measured distance.
		It is saved in non-volatile memory, you only have to set it once.
		
		The Bricklet comes with a per-sensor factory-calibrated offset value,
		you should not have to call this function.
		
		If you want to re-calibrate the offset you first have to set it to 0.
		Calculate the offset by measuring the distance to a known distance
		and set it again.
		*/
		this.ipcon.sendRequest(this, BrickletLaserRangeFinderV2.FUNCTION_SET_OFFSET_CALIBRATION, [offset], 'h', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getOffsetCalibration = function(returnCallback, errorCallback) {
		/*
		Returns the offset value as set by :func:`Set Offset Calibration`.
		*/
		this.ipcon.sendRequest(this, BrickletLaserRangeFinderV2.FUNCTION_GET_OFFSET_CALIBRATION, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.setDistanceLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Configures the distance LED to be either turned off, turned on, blink in
		heartbeat mode or show the distance (brighter = object is nearer).
		*/
		this.ipcon.sendRequest(this, BrickletLaserRangeFinderV2.FUNCTION_SET_DISTANCE_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getDistanceLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the LED configuration as set by :func:`Set Distance LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletLaserRangeFinderV2.FUNCTION_GET_DISTANCE_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPErrorCount = function(returnCallback, errorCallback) {
		/*
		Returns the error count for the communication between Brick and Bricklet.
		
		The errors are divided into
		
		* ACK checksum errors,
		* message checksum errors,
		* framing errors and
		* overflow errors.
		
		The errors counts are for errors that occur on the Bricklet side. All
		Bricks have a similar function that returns the errors on the Brick side.
		*/
		this.ipcon.sendRequest(this, BrickletLaserRangeFinderV2.FUNCTION_GET_SPITFP_ERROR_COUNT, [], '', 24, 'I I I I', returnCallback, errorCallback, false, true);
	};
	this.setBootloaderMode = function(mode, returnCallback, errorCallback) {
		/*
		Sets the bootloader mode and returns the status after the requested
		mode change was instigated.
		
		You can change from bootloader mode to firmware mode and vice versa. A change
		from bootloader mode to firmware mode will only take place if the entry function,
		device identifier and CRC are present and correct.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletLaserRangeFinderV2.FUNCTION_SET_BOOTLOADER_MODE, [mode], 'B', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getBootloaderMode = function(returnCallback, errorCallback) {
		/*
		Returns the current bootloader mode, see :func:`Set Bootloader Mode`.
		*/
		this.ipcon.sendRequest(this, BrickletLaserRangeFinderV2.FUNCTION_GET_BOOTLOADER_MODE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setWriteFirmwarePointer = function(pointer, returnCallback, errorCallback) {
		/*
		Sets the firmware pointer for :func:`Write Firmware`. The pointer has
		to be increased by chunks of size 64. The data is written to flash
		every 4 chunks (which equals to one page of size 256).
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletLaserRangeFinderV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER, [pointer], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeFirmware = function(data, returnCallback, errorCallback) {
		/*
		Writes 64 Bytes of firmware at the position as written by
		:func:`Set Write Firmware Pointer` before. The firmware is written
		to flash every 4 chunks.
		
		You can only write firmware in bootloader mode.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletLaserRangeFinderV2.FUNCTION_WRITE_FIRMWARE, [data], 'B64', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setStatusLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Sets the status LED configuration. By default the LED shows
		communication traffic between Brick and Bricklet, it flickers once
		for every 10 received data packets.
		
		You can also turn the LED permanently on/off or show a heartbeat.
		
		If the Bricklet is in bootloader mode, the LED is will show heartbeat by default.
		*/
		this.ipcon.sendRequest(this, BrickletLaserRangeFinderV2.FUNCTION_SET_STATUS_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getStatusLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Status LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletLaserRangeFinderV2.FUNCTION_GET_STATUS_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getChipTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature as measured inside the microcontroller. The
		value returned is not the ambient temperature!
		
		The temperature is only proportional to the real temperature and it has bad
		accuracy. Practically it is only useful as an indicator for
		temperature changes.
		*/
		this.ipcon.sendRequest(this, BrickletLaserRangeFinderV2.FUNCTION_GET_CHIP_TEMPERATURE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.reset = function(returnCallback, errorCallback) {
		/*
		Calling this function will reset the Bricklet. All configurations
		will be lost.
		
		After a reset you have to create new device objects,
		calling functions on the existing ones will result in
		undefined behavior!
		*/
		this.ipcon.sendRequest(this, BrickletLaserRangeFinderV2.FUNCTION_RESET, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeUID = function(uid, returnCallback, errorCallback) {
		/*
		Writes a new UID into flash. If you want to set a new UID
		you have to decode the Base58 encoded UID string into an
		integer first.
		
		We recommend that you use Brick Viewer to change the UID.
		*/
		this.ipcon.sendRequest(this, BrickletLaserRangeFinderV2.FUNCTION_WRITE_UID, [uid], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.readUID = function(returnCallback, errorCallback) {
		/*
		Returns the current UID as an integer. Encode as
		Base58 to get the usual string version.
		*/
		this.ipcon.sendRequest(this, BrickletLaserRangeFinderV2.FUNCTION_READ_UID, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletLaserRangeFinderV2.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletLaserRangeFinderV2;

},{"./Device":279,"./IPConnection":280}],217:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletLine.DEVICE_IDENTIFIER = 241;
BrickletLine.DEVICE_DISPLAY_NAME = 'Line Bricklet';
BrickletLine.CALLBACK_REFLECTIVITY = 8;
BrickletLine.CALLBACK_REFLECTIVITY_REACHED = 9;
BrickletLine.FUNCTION_GET_REFLECTIVITY = 1;
BrickletLine.FUNCTION_SET_REFLECTIVITY_CALLBACK_PERIOD = 2;
BrickletLine.FUNCTION_GET_REFLECTIVITY_CALLBACK_PERIOD = 3;
BrickletLine.FUNCTION_SET_REFLECTIVITY_CALLBACK_THRESHOLD = 4;
BrickletLine.FUNCTION_GET_REFLECTIVITY_CALLBACK_THRESHOLD = 5;
BrickletLine.FUNCTION_SET_DEBOUNCE_PERIOD = 6;
BrickletLine.FUNCTION_GET_DEBOUNCE_PERIOD = 7;
BrickletLine.FUNCTION_GET_IDENTITY = 255;
BrickletLine.THRESHOLD_OPTION_OFF = 'x';
BrickletLine.THRESHOLD_OPTION_OUTSIDE = 'o';
BrickletLine.THRESHOLD_OPTION_INSIDE = 'i';
BrickletLine.THRESHOLD_OPTION_SMALLER = '<';
BrickletLine.THRESHOLD_OPTION_GREATER = '>';

function BrickletLine(uid, ipcon) {
	//Measures reflectivity of a surface

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletLine.DEVICE_IDENTIFIER, BrickletLine.DEVICE_DISPLAY_NAME);
	BrickletLine.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickletLine.FUNCTION_GET_REFLECTIVITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLine.FUNCTION_SET_REFLECTIVITY_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletLine.FUNCTION_GET_REFLECTIVITY_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLine.FUNCTION_SET_REFLECTIVITY_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletLine.FUNCTION_GET_REFLECTIVITY_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLine.FUNCTION_SET_DEBOUNCE_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletLine.FUNCTION_GET_DEBOUNCE_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLine.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletLine.CALLBACK_REFLECTIVITY] = [10, 'H'];
	this.callbackFormats[BrickletLine.CALLBACK_REFLECTIVITY_REACHED] = [10, 'H'];



	this.getReflectivity = function(returnCallback, errorCallback) {
		/*
		Returns the currently measured reflectivity. The reflectivity is
		a value between 0 (not reflective) and 4095 (very reflective).
		
		Usually black has a low reflectivity while white has a high
		reflectivity.
		
		If you want to get the reflectivity periodically, it is recommended
		to use the :cb:`Reflectivity` callback and set the period with
		:func:`Set Reflectivity Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletLine.FUNCTION_GET_REFLECTIVITY, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.setReflectivityCallbackPeriod = function(period, returnCallback, errorCallback) {
		/*
		Sets the period with which the :cb:`Reflectivity` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		The :cb:`Reflectivity` callback is only triggered if the reflectivity has
		changed since the last triggering.
		*/
		this.ipcon.sendRequest(this, BrickletLine.FUNCTION_SET_REFLECTIVITY_CALLBACK_PERIOD, [period], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getReflectivityCallbackPeriod = function(returnCallback, errorCallback) {
		/*
		Returns the period as set by :func:`Set Reflectivity Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletLine.FUNCTION_GET_REFLECTIVITY_CALLBACK_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setReflectivityCallbackThreshold = function(option, min, max, returnCallback, errorCallback) {
		/*
		Sets the thresholds for the :cb:`Reflectivity Reached` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Callback is turned off"
		 "'o'",    "Callback is triggered when the reflectivity is *outside* the min and max values"
		 "'i'",    "Callback is triggered when the reflectivity is *inside* the min and max values"
		 "'<'",    "Callback is triggered when the reflectivity is smaller than the min value (max is ignored)"
		 "'>'",    "Callback is triggered when the reflectivity is greater than the min value (max is ignored)"
		*/
		this.ipcon.sendRequest(this, BrickletLine.FUNCTION_SET_REFLECTIVITY_CALLBACK_THRESHOLD, [option, min, max], 'c H H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getReflectivityCallbackThreshold = function(returnCallback, errorCallback) {
		/*
		Returns the threshold as set by :func:`Set Reflectivity Callback Threshold`.
		*/
		this.ipcon.sendRequest(this, BrickletLine.FUNCTION_GET_REFLECTIVITY_CALLBACK_THRESHOLD, [], '', 13, 'c H H', returnCallback, errorCallback, false, true);
	};
	this.setDebouncePeriod = function(debounce, returnCallback, errorCallback) {
		/*
		Sets the period with which the threshold callback
		
		* :cb:`Reflectivity Reached`
		
		is triggered, if the threshold
		
		* :func:`Set Reflectivity Callback Threshold`
		
		keeps being reached.
		*/
		this.ipcon.sendRequest(this, BrickletLine.FUNCTION_SET_DEBOUNCE_PERIOD, [debounce], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getDebouncePeriod = function(returnCallback, errorCallback) {
		/*
		Returns the debounce period as set by :func:`Set Debounce Period`.
		*/
		this.ipcon.sendRequest(this, BrickletLine.FUNCTION_GET_DEBOUNCE_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletLine.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletLine;

},{"./Device":279,"./IPConnection":280}],218:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletLinearPoti.DEVICE_IDENTIFIER = 213;
BrickletLinearPoti.DEVICE_DISPLAY_NAME = 'Linear Poti Bricklet';
BrickletLinearPoti.CALLBACK_POSITION = 13;
BrickletLinearPoti.CALLBACK_ANALOG_VALUE = 14;
BrickletLinearPoti.CALLBACK_POSITION_REACHED = 15;
BrickletLinearPoti.CALLBACK_ANALOG_VALUE_REACHED = 16;
BrickletLinearPoti.FUNCTION_GET_POSITION = 1;
BrickletLinearPoti.FUNCTION_GET_ANALOG_VALUE = 2;
BrickletLinearPoti.FUNCTION_SET_POSITION_CALLBACK_PERIOD = 3;
BrickletLinearPoti.FUNCTION_GET_POSITION_CALLBACK_PERIOD = 4;
BrickletLinearPoti.FUNCTION_SET_ANALOG_VALUE_CALLBACK_PERIOD = 5;
BrickletLinearPoti.FUNCTION_GET_ANALOG_VALUE_CALLBACK_PERIOD = 6;
BrickletLinearPoti.FUNCTION_SET_POSITION_CALLBACK_THRESHOLD = 7;
BrickletLinearPoti.FUNCTION_GET_POSITION_CALLBACK_THRESHOLD = 8;
BrickletLinearPoti.FUNCTION_SET_ANALOG_VALUE_CALLBACK_THRESHOLD = 9;
BrickletLinearPoti.FUNCTION_GET_ANALOG_VALUE_CALLBACK_THRESHOLD = 10;
BrickletLinearPoti.FUNCTION_SET_DEBOUNCE_PERIOD = 11;
BrickletLinearPoti.FUNCTION_GET_DEBOUNCE_PERIOD = 12;
BrickletLinearPoti.FUNCTION_GET_IDENTITY = 255;
BrickletLinearPoti.THRESHOLD_OPTION_OFF = 'x';
BrickletLinearPoti.THRESHOLD_OPTION_OUTSIDE = 'o';
BrickletLinearPoti.THRESHOLD_OPTION_INSIDE = 'i';
BrickletLinearPoti.THRESHOLD_OPTION_SMALLER = '<';
BrickletLinearPoti.THRESHOLD_OPTION_GREATER = '>';

function BrickletLinearPoti(uid, ipcon) {
	//59mm linear potentiometer

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletLinearPoti.DEVICE_IDENTIFIER, BrickletLinearPoti.DEVICE_DISPLAY_NAME);
	BrickletLinearPoti.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 1];
	this.responseExpected[BrickletLinearPoti.FUNCTION_GET_POSITION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLinearPoti.FUNCTION_GET_ANALOG_VALUE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLinearPoti.FUNCTION_SET_POSITION_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletLinearPoti.FUNCTION_GET_POSITION_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLinearPoti.FUNCTION_SET_ANALOG_VALUE_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletLinearPoti.FUNCTION_GET_ANALOG_VALUE_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLinearPoti.FUNCTION_SET_POSITION_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletLinearPoti.FUNCTION_GET_POSITION_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLinearPoti.FUNCTION_SET_ANALOG_VALUE_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletLinearPoti.FUNCTION_GET_ANALOG_VALUE_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLinearPoti.FUNCTION_SET_DEBOUNCE_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletLinearPoti.FUNCTION_GET_DEBOUNCE_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLinearPoti.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletLinearPoti.CALLBACK_POSITION] = [10, 'H'];
	this.callbackFormats[BrickletLinearPoti.CALLBACK_ANALOG_VALUE] = [10, 'H'];
	this.callbackFormats[BrickletLinearPoti.CALLBACK_POSITION_REACHED] = [10, 'H'];
	this.callbackFormats[BrickletLinearPoti.CALLBACK_ANALOG_VALUE_REACHED] = [10, 'H'];



	this.getPosition = function(returnCallback, errorCallback) {
		/*
		Returns the position of the linear potentiometer. The value is
		between 0 (slider down) and 100 (slider up).
		
		If you want to get the position periodically, it is recommended to use the
		:cb:`Position` callback and set the period with
		:func:`Set Position Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletLinearPoti.FUNCTION_GET_POSITION, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.getAnalogValue = function(returnCallback, errorCallback) {
		/*
		Returns the value as read by a 12-bit analog-to-digital converter.
		
		.. note::
		 The value returned by :func:`Get Position` is averaged over several samples
		 to yield less noise, while :func:`Get Analog Value` gives back raw
		 unfiltered analog values. The only reason to use :func:`Get Analog Value` is,
		 if you need the full resolution of the analog-to-digital converter.
		
		If you want the analog value periodically, it is recommended to use the
		:cb:`Analog Value` callback and set the period with
		:func:`Set Analog Value Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletLinearPoti.FUNCTION_GET_ANALOG_VALUE, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.setPositionCallbackPeriod = function(period, returnCallback, errorCallback) {
		/*
		Sets the period with which the :cb:`Position` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		The :cb:`Position` callback is only triggered if the position has changed
		since the last triggering.
		*/
		this.ipcon.sendRequest(this, BrickletLinearPoti.FUNCTION_SET_POSITION_CALLBACK_PERIOD, [period], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getPositionCallbackPeriod = function(returnCallback, errorCallback) {
		/*
		Returns the period as set by :func:`Set Position Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletLinearPoti.FUNCTION_GET_POSITION_CALLBACK_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setAnalogValueCallbackPeriod = function(period, returnCallback, errorCallback) {
		/*
		Sets the period with which the :cb:`Analog Value` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		The :cb:`Analog Value` callback is only triggered if the analog value has
		changed since the last triggering.
		*/
		this.ipcon.sendRequest(this, BrickletLinearPoti.FUNCTION_SET_ANALOG_VALUE_CALLBACK_PERIOD, [period], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getAnalogValueCallbackPeriod = function(returnCallback, errorCallback) {
		/*
		Returns the period as set by :func:`Set Analog Value Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletLinearPoti.FUNCTION_GET_ANALOG_VALUE_CALLBACK_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setPositionCallbackThreshold = function(option, min, max, returnCallback, errorCallback) {
		/*
		Sets the thresholds for the :cb:`Position Reached` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Callback is turned off"
		 "'o'",    "Callback is triggered when the position is *outside* the min and max values"
		 "'i'",    "Callback is triggered when the position is *inside* the min and max values"
		 "'<'",    "Callback is triggered when the position is smaller than the min value (max is ignored)"
		 "'>'",    "Callback is triggered when the position is greater than the min value (max is ignored)"
		*/
		this.ipcon.sendRequest(this, BrickletLinearPoti.FUNCTION_SET_POSITION_CALLBACK_THRESHOLD, [option, min, max], 'c H H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getPositionCallbackThreshold = function(returnCallback, errorCallback) {
		/*
		Returns the threshold as set by :func:`Set Position Callback Threshold`.
		*/
		this.ipcon.sendRequest(this, BrickletLinearPoti.FUNCTION_GET_POSITION_CALLBACK_THRESHOLD, [], '', 13, 'c H H', returnCallback, errorCallback, false, true);
	};
	this.setAnalogValueCallbackThreshold = function(option, min, max, returnCallback, errorCallback) {
		/*
		Sets the thresholds for the :cb:`Analog Value Reached` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Callback is turned off"
		 "'o'",    "Callback is triggered when the analog value is *outside* the min and max values"
		 "'i'",    "Callback is triggered when the analog value is *inside* the min and max values"
		 "'<'",    "Callback is triggered when the analog value is smaller than the min value (max is ignored)"
		 "'>'",    "Callback is triggered when the analog value is greater than the min value (max is ignored)"
		*/
		this.ipcon.sendRequest(this, BrickletLinearPoti.FUNCTION_SET_ANALOG_VALUE_CALLBACK_THRESHOLD, [option, min, max], 'c H H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getAnalogValueCallbackThreshold = function(returnCallback, errorCallback) {
		/*
		Returns the threshold as set by :func:`Set Analog Value Callback Threshold`.
		*/
		this.ipcon.sendRequest(this, BrickletLinearPoti.FUNCTION_GET_ANALOG_VALUE_CALLBACK_THRESHOLD, [], '', 13, 'c H H', returnCallback, errorCallback, false, true);
	};
	this.setDebouncePeriod = function(debounce, returnCallback, errorCallback) {
		/*
		Sets the period with which the threshold callbacks
		
		* :cb:`Position Reached`,
		* :cb:`Analog Value Reached`
		
		are triggered, if the thresholds
		
		* :func:`Set Position Callback Threshold`,
		* :func:`Set Analog Value Callback Threshold`
		
		keep being reached.
		*/
		this.ipcon.sendRequest(this, BrickletLinearPoti.FUNCTION_SET_DEBOUNCE_PERIOD, [debounce], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getDebouncePeriod = function(returnCallback, errorCallback) {
		/*
		Returns the debounce period as set by :func:`Set Debounce Period`.
		*/
		this.ipcon.sendRequest(this, BrickletLinearPoti.FUNCTION_GET_DEBOUNCE_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletLinearPoti.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletLinearPoti;

},{"./Device":279,"./IPConnection":280}],219:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletLinearPotiV2.DEVICE_IDENTIFIER = 2139;
BrickletLinearPotiV2.DEVICE_DISPLAY_NAME = 'Linear Poti Bricklet 2.0';
BrickletLinearPotiV2.CALLBACK_POSITION = 4;
BrickletLinearPotiV2.FUNCTION_GET_POSITION = 1;
BrickletLinearPotiV2.FUNCTION_SET_POSITION_CALLBACK_CONFIGURATION = 2;
BrickletLinearPotiV2.FUNCTION_GET_POSITION_CALLBACK_CONFIGURATION = 3;
BrickletLinearPotiV2.FUNCTION_GET_SPITFP_ERROR_COUNT = 234;
BrickletLinearPotiV2.FUNCTION_SET_BOOTLOADER_MODE = 235;
BrickletLinearPotiV2.FUNCTION_GET_BOOTLOADER_MODE = 236;
BrickletLinearPotiV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER = 237;
BrickletLinearPotiV2.FUNCTION_WRITE_FIRMWARE = 238;
BrickletLinearPotiV2.FUNCTION_SET_STATUS_LED_CONFIG = 239;
BrickletLinearPotiV2.FUNCTION_GET_STATUS_LED_CONFIG = 240;
BrickletLinearPotiV2.FUNCTION_GET_CHIP_TEMPERATURE = 242;
BrickletLinearPotiV2.FUNCTION_RESET = 243;
BrickletLinearPotiV2.FUNCTION_WRITE_UID = 248;
BrickletLinearPotiV2.FUNCTION_READ_UID = 249;
BrickletLinearPotiV2.FUNCTION_GET_IDENTITY = 255;
BrickletLinearPotiV2.THRESHOLD_OPTION_OFF = 'x';
BrickletLinearPotiV2.THRESHOLD_OPTION_OUTSIDE = 'o';
BrickletLinearPotiV2.THRESHOLD_OPTION_INSIDE = 'i';
BrickletLinearPotiV2.THRESHOLD_OPTION_SMALLER = '<';
BrickletLinearPotiV2.THRESHOLD_OPTION_GREATER = '>';
BrickletLinearPotiV2.BOOTLOADER_MODE_BOOTLOADER = 0;
BrickletLinearPotiV2.BOOTLOADER_MODE_FIRMWARE = 1;
BrickletLinearPotiV2.BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT = 2;
BrickletLinearPotiV2.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT = 3;
BrickletLinearPotiV2.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT = 4;
BrickletLinearPotiV2.BOOTLOADER_STATUS_OK = 0;
BrickletLinearPotiV2.BOOTLOADER_STATUS_INVALID_MODE = 1;
BrickletLinearPotiV2.BOOTLOADER_STATUS_NO_CHANGE = 2;
BrickletLinearPotiV2.BOOTLOADER_STATUS_ENTRY_FUNCTION_NOT_PRESENT = 3;
BrickletLinearPotiV2.BOOTLOADER_STATUS_DEVICE_IDENTIFIER_INCORRECT = 4;
BrickletLinearPotiV2.BOOTLOADER_STATUS_CRC_MISMATCH = 5;
BrickletLinearPotiV2.STATUS_LED_CONFIG_OFF = 0;
BrickletLinearPotiV2.STATUS_LED_CONFIG_ON = 1;
BrickletLinearPotiV2.STATUS_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletLinearPotiV2.STATUS_LED_CONFIG_SHOW_STATUS = 3;

function BrickletLinearPotiV2(uid, ipcon) {
	//59mm linear potentiometer

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletLinearPotiV2.DEVICE_IDENTIFIER, BrickletLinearPotiV2.DEVICE_DISPLAY_NAME);
	BrickletLinearPotiV2.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickletLinearPotiV2.FUNCTION_GET_POSITION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLinearPotiV2.FUNCTION_SET_POSITION_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletLinearPotiV2.FUNCTION_GET_POSITION_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLinearPotiV2.FUNCTION_GET_SPITFP_ERROR_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLinearPotiV2.FUNCTION_SET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLinearPotiV2.FUNCTION_GET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLinearPotiV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletLinearPotiV2.FUNCTION_WRITE_FIRMWARE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLinearPotiV2.FUNCTION_SET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletLinearPotiV2.FUNCTION_GET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLinearPotiV2.FUNCTION_GET_CHIP_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLinearPotiV2.FUNCTION_RESET] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletLinearPotiV2.FUNCTION_WRITE_UID] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletLinearPotiV2.FUNCTION_READ_UID] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLinearPotiV2.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletLinearPotiV2.CALLBACK_POSITION] = [9, 'B'];



	this.getPosition = function(returnCallback, errorCallback) {
		/*
		Returns the position of the linear potentiometer. The value is
		between 0 (slider down) and 100 (slider up).
		
		
		If you want to get the value periodically, it is recommended to use the
		:cb:`Position` callback. You can set the callback configuration
		with :func:`Set Position Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletLinearPotiV2.FUNCTION_GET_POSITION, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setPositionCallbackConfiguration = function(period, valueHasToChange, option, min, max, returnCallback, errorCallback) {
		/*
		The period is the period with which the :cb:`Position` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		If the `value has to change`-parameter is set to true, the callback is only
		triggered after the value has changed. If the value didn't change
		within the period, the callback is triggered immediately on change.
		
		If it is set to false, the callback is continuously triggered with the period,
		independent of the value.
		
		It is furthermore possible to constrain the callback with thresholds.
		
		The `option`-parameter together with min/max sets a threshold for the :cb:`Position` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Threshold is turned off"
		 "'o'",    "Threshold is triggered when the value is *outside* the min and max values"
		 "'i'",    "Threshold is triggered when the value is *inside* or equal to the min and max values"
		 "'<'",    "Threshold is triggered when the value is smaller than the min value (max is ignored)"
		 "'>'",    "Threshold is triggered when the value is greater than the min value (max is ignored)"
		
		If the option is set to 'x' (threshold turned off) the callback is triggered with the fixed period.
		*/
		this.ipcon.sendRequest(this, BrickletLinearPotiV2.FUNCTION_SET_POSITION_CALLBACK_CONFIGURATION, [period, valueHasToChange, option, min, max], 'I ? c B B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getPositionCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the callback configuration as set by :func:`Set Position Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletLinearPotiV2.FUNCTION_GET_POSITION_CALLBACK_CONFIGURATION, [], '', 16, 'I ? c B B', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPErrorCount = function(returnCallback, errorCallback) {
		/*
		Returns the error count for the communication between Brick and Bricklet.
		
		The errors are divided into
		
		* ACK checksum errors,
		* message checksum errors,
		* framing errors and
		* overflow errors.
		
		The errors counts are for errors that occur on the Bricklet side. All
		Bricks have a similar function that returns the errors on the Brick side.
		*/
		this.ipcon.sendRequest(this, BrickletLinearPotiV2.FUNCTION_GET_SPITFP_ERROR_COUNT, [], '', 24, 'I I I I', returnCallback, errorCallback, false, true);
	};
	this.setBootloaderMode = function(mode, returnCallback, errorCallback) {
		/*
		Sets the bootloader mode and returns the status after the requested
		mode change was instigated.
		
		You can change from bootloader mode to firmware mode and vice versa. A change
		from bootloader mode to firmware mode will only take place if the entry function,
		device identifier and CRC are present and correct.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletLinearPotiV2.FUNCTION_SET_BOOTLOADER_MODE, [mode], 'B', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getBootloaderMode = function(returnCallback, errorCallback) {
		/*
		Returns the current bootloader mode, see :func:`Set Bootloader Mode`.
		*/
		this.ipcon.sendRequest(this, BrickletLinearPotiV2.FUNCTION_GET_BOOTLOADER_MODE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setWriteFirmwarePointer = function(pointer, returnCallback, errorCallback) {
		/*
		Sets the firmware pointer for :func:`Write Firmware`. The pointer has
		to be increased by chunks of size 64. The data is written to flash
		every 4 chunks (which equals to one page of size 256).
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletLinearPotiV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER, [pointer], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeFirmware = function(data, returnCallback, errorCallback) {
		/*
		Writes 64 Bytes of firmware at the position as written by
		:func:`Set Write Firmware Pointer` before. The firmware is written
		to flash every 4 chunks.
		
		You can only write firmware in bootloader mode.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletLinearPotiV2.FUNCTION_WRITE_FIRMWARE, [data], 'B64', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setStatusLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Sets the status LED configuration. By default the LED shows
		communication traffic between Brick and Bricklet, it flickers once
		for every 10 received data packets.
		
		You can also turn the LED permanently on/off or show a heartbeat.
		
		If the Bricklet is in bootloader mode, the LED is will show heartbeat by default.
		*/
		this.ipcon.sendRequest(this, BrickletLinearPotiV2.FUNCTION_SET_STATUS_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getStatusLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Status LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletLinearPotiV2.FUNCTION_GET_STATUS_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getChipTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature as measured inside the microcontroller. The
		value returned is not the ambient temperature!
		
		The temperature is only proportional to the real temperature and it has bad
		accuracy. Practically it is only useful as an indicator for
		temperature changes.
		*/
		this.ipcon.sendRequest(this, BrickletLinearPotiV2.FUNCTION_GET_CHIP_TEMPERATURE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.reset = function(returnCallback, errorCallback) {
		/*
		Calling this function will reset the Bricklet. All configurations
		will be lost.
		
		After a reset you have to create new device objects,
		calling functions on the existing ones will result in
		undefined behavior!
		*/
		this.ipcon.sendRequest(this, BrickletLinearPotiV2.FUNCTION_RESET, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeUID = function(uid, returnCallback, errorCallback) {
		/*
		Writes a new UID into flash. If you want to set a new UID
		you have to decode the Base58 encoded UID string into an
		integer first.
		
		We recommend that you use Brick Viewer to change the UID.
		*/
		this.ipcon.sendRequest(this, BrickletLinearPotiV2.FUNCTION_WRITE_UID, [uid], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.readUID = function(returnCallback, errorCallback) {
		/*
		Returns the current UID as an integer. Encode as
		Base58 to get the usual string version.
		*/
		this.ipcon.sendRequest(this, BrickletLinearPotiV2.FUNCTION_READ_UID, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletLinearPotiV2.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletLinearPotiV2;

},{"./Device":279,"./IPConnection":280}],220:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletLoadCell.DEVICE_IDENTIFIER = 253;
BrickletLoadCell.DEVICE_DISPLAY_NAME = 'Load Cell Bricklet';
BrickletLoadCell.CALLBACK_WEIGHT = 17;
BrickletLoadCell.CALLBACK_WEIGHT_REACHED = 18;
BrickletLoadCell.FUNCTION_GET_WEIGHT = 1;
BrickletLoadCell.FUNCTION_SET_WEIGHT_CALLBACK_PERIOD = 2;
BrickletLoadCell.FUNCTION_GET_WEIGHT_CALLBACK_PERIOD = 3;
BrickletLoadCell.FUNCTION_SET_WEIGHT_CALLBACK_THRESHOLD = 4;
BrickletLoadCell.FUNCTION_GET_WEIGHT_CALLBACK_THRESHOLD = 5;
BrickletLoadCell.FUNCTION_SET_DEBOUNCE_PERIOD = 6;
BrickletLoadCell.FUNCTION_GET_DEBOUNCE_PERIOD = 7;
BrickletLoadCell.FUNCTION_SET_MOVING_AVERAGE = 8;
BrickletLoadCell.FUNCTION_GET_MOVING_AVERAGE = 9;
BrickletLoadCell.FUNCTION_LED_ON = 10;
BrickletLoadCell.FUNCTION_LED_OFF = 11;
BrickletLoadCell.FUNCTION_IS_LED_ON = 12;
BrickletLoadCell.FUNCTION_CALIBRATE = 13;
BrickletLoadCell.FUNCTION_TARE = 14;
BrickletLoadCell.FUNCTION_SET_CONFIGURATION = 15;
BrickletLoadCell.FUNCTION_GET_CONFIGURATION = 16;
BrickletLoadCell.FUNCTION_GET_IDENTITY = 255;
BrickletLoadCell.THRESHOLD_OPTION_OFF = 'x';
BrickletLoadCell.THRESHOLD_OPTION_OUTSIDE = 'o';
BrickletLoadCell.THRESHOLD_OPTION_INSIDE = 'i';
BrickletLoadCell.THRESHOLD_OPTION_SMALLER = '<';
BrickletLoadCell.THRESHOLD_OPTION_GREATER = '>';
BrickletLoadCell.RATE_10HZ = 0;
BrickletLoadCell.RATE_80HZ = 1;
BrickletLoadCell.GAIN_128X = 0;
BrickletLoadCell.GAIN_64X = 1;
BrickletLoadCell.GAIN_32X = 2;

function BrickletLoadCell(uid, ipcon) {
	//Measures weight with a load cell

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletLoadCell.DEVICE_IDENTIFIER, BrickletLoadCell.DEVICE_DISPLAY_NAME);
	BrickletLoadCell.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickletLoadCell.FUNCTION_GET_WEIGHT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLoadCell.FUNCTION_SET_WEIGHT_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletLoadCell.FUNCTION_GET_WEIGHT_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLoadCell.FUNCTION_SET_WEIGHT_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletLoadCell.FUNCTION_GET_WEIGHT_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLoadCell.FUNCTION_SET_DEBOUNCE_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletLoadCell.FUNCTION_GET_DEBOUNCE_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLoadCell.FUNCTION_SET_MOVING_AVERAGE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletLoadCell.FUNCTION_GET_MOVING_AVERAGE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLoadCell.FUNCTION_LED_ON] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletLoadCell.FUNCTION_LED_OFF] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletLoadCell.FUNCTION_IS_LED_ON] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLoadCell.FUNCTION_CALIBRATE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletLoadCell.FUNCTION_TARE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletLoadCell.FUNCTION_SET_CONFIGURATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletLoadCell.FUNCTION_GET_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLoadCell.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletLoadCell.CALLBACK_WEIGHT] = [12, 'i'];
	this.callbackFormats[BrickletLoadCell.CALLBACK_WEIGHT_REACHED] = [12, 'i'];



	this.getWeight = function(returnCallback, errorCallback) {
		/*
		Returns the currently measured weight.
		
		If you want to get the weight periodically, it is recommended
		to use the :cb:`Weight` callback and set the period with
		:func:`Set Weight Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletLoadCell.FUNCTION_GET_WEIGHT, [], '', 12, 'i', returnCallback, errorCallback, false, true);
	};
	this.setWeightCallbackPeriod = function(period, returnCallback, errorCallback) {
		/*
		Sets the period with which the :cb:`Weight` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		The :cb:`Weight` callback is only triggered if the weight has changed since the
		last triggering.
		*/
		this.ipcon.sendRequest(this, BrickletLoadCell.FUNCTION_SET_WEIGHT_CALLBACK_PERIOD, [period], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getWeightCallbackPeriod = function(returnCallback, errorCallback) {
		/*
		Returns the period as set by :func:`Set Weight Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletLoadCell.FUNCTION_GET_WEIGHT_CALLBACK_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setWeightCallbackThreshold = function(option, min, max, returnCallback, errorCallback) {
		/*
		Sets the thresholds for the :cb:`Weight Reached` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Callback is turned off"
		 "'o'",    "Callback is triggered when the weight is *outside* the min and max values"
		 "'i'",    "Callback is triggered when the weight is *inside* the min and max values"
		 "'<'",    "Callback is triggered when the weight is smaller than the min value (max is ignored)"
		 "'>'",    "Callback is triggered when the weight is greater than the min value (max is ignored)"
		*/
		this.ipcon.sendRequest(this, BrickletLoadCell.FUNCTION_SET_WEIGHT_CALLBACK_THRESHOLD, [option, min, max], 'c i i', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getWeightCallbackThreshold = function(returnCallback, errorCallback) {
		/*
		Returns the threshold as set by :func:`Set Weight Callback Threshold`.
		*/
		this.ipcon.sendRequest(this, BrickletLoadCell.FUNCTION_GET_WEIGHT_CALLBACK_THRESHOLD, [], '', 17, 'c i i', returnCallback, errorCallback, false, true);
	};
	this.setDebouncePeriod = function(debounce, returnCallback, errorCallback) {
		/*
		Sets the period with which the threshold callback
		
		* :cb:`Weight Reached`
		
		is triggered, if the threshold
		
		* :func:`Set Weight Callback Threshold`
		
		keeps being reached.
		*/
		this.ipcon.sendRequest(this, BrickletLoadCell.FUNCTION_SET_DEBOUNCE_PERIOD, [debounce], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getDebouncePeriod = function(returnCallback, errorCallback) {
		/*
		Returns the debounce period as set by :func:`Set Debounce Period`.
		*/
		this.ipcon.sendRequest(this, BrickletLoadCell.FUNCTION_GET_DEBOUNCE_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setMovingAverage = function(average, returnCallback, errorCallback) {
		/*
		Sets the length of a `moving averaging <https://en.wikipedia.org/wiki/Moving_average>`__
		for the weight value.
		
		Setting the length to 1 will turn the averaging off. With less
		averaging, there is more noise on the data.
		*/
		this.ipcon.sendRequest(this, BrickletLoadCell.FUNCTION_SET_MOVING_AVERAGE, [average], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getMovingAverage = function(returnCallback, errorCallback) {
		/*
		Returns the length moving average as set by :func:`Set Moving Average`.
		*/
		this.ipcon.sendRequest(this, BrickletLoadCell.FUNCTION_GET_MOVING_AVERAGE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.ledOn = function(returnCallback, errorCallback) {
		/*
		Turns the LED on.
		*/
		this.ipcon.sendRequest(this, BrickletLoadCell.FUNCTION_LED_ON, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.ledOff = function(returnCallback, errorCallback) {
		/*
		Turns the LED off.
		*/
		this.ipcon.sendRequest(this, BrickletLoadCell.FUNCTION_LED_OFF, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.isLEDOn = function(returnCallback, errorCallback) {
		/*
		Returns *true* if the led is on, *false* otherwise.
		*/
		this.ipcon.sendRequest(this, BrickletLoadCell.FUNCTION_IS_LED_ON, [], '', 9, '?', returnCallback, errorCallback, false, true);
	};
	this.calibrate = function(weight, returnCallback, errorCallback) {
		/*
		To calibrate your Load Cell Bricklet you have to
		
		* empty the scale and call this function with 0 and
		* add a known weight to the scale and call this function with the weight.
		
		The calibration is saved in the EEPROM of the Bricklet and only
		needs to be done once.
		
		We recommend to use the Brick Viewer for calibration, you don't need
		to call this function in your source code.
		*/
		this.ipcon.sendRequest(this, BrickletLoadCell.FUNCTION_CALIBRATE, [weight], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.tare = function(returnCallback, errorCallback) {
		/*
		Sets the currently measured weight as tare weight.
		*/
		this.ipcon.sendRequest(this, BrickletLoadCell.FUNCTION_TARE, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.setConfiguration = function(rate, gain, returnCallback, errorCallback) {
		/*
		The measurement rate and gain are configurable.
		
		The rate can be either 10Hz or 80Hz. A faster rate will produce more noise.
		It is additionally possible to add a moving average
		(see :func:`Set Moving Average`) to the measurements.
		
		The gain can be 128x, 64x or 32x. It represents a measurement range of
		±20mV, ±40mV and ±80mV respectively. The Load Cell Bricklet uses an
		excitation voltage of 5V and most load cells use an output of 2mV/V. That
		means the voltage range is ±15mV for most load cells (i.e. gain of 128x
		is best). If you don't know what all of this means you should keep it at
		128x, it will most likely be correct.
		
		The configuration is saved in the EEPROM of the Bricklet and only
		needs to be done once.
		
		We recommend to use the Brick Viewer for configuration, you don't need
		to call this function in your source code.
		*/
		this.ipcon.sendRequest(this, BrickletLoadCell.FUNCTION_SET_CONFIGURATION, [rate, gain], 'B B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletLoadCell.FUNCTION_GET_CONFIGURATION, [], '', 10, 'B B', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletLoadCell.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletLoadCell;

},{"./Device":279,"./IPConnection":280}],221:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletLoadCellV2.DEVICE_IDENTIFIER = 2104;
BrickletLoadCellV2.DEVICE_DISPLAY_NAME = 'Load Cell Bricklet 2.0';
BrickletLoadCellV2.CALLBACK_WEIGHT = 4;
BrickletLoadCellV2.FUNCTION_GET_WEIGHT = 1;
BrickletLoadCellV2.FUNCTION_SET_WEIGHT_CALLBACK_CONFIGURATION = 2;
BrickletLoadCellV2.FUNCTION_GET_WEIGHT_CALLBACK_CONFIGURATION = 3;
BrickletLoadCellV2.FUNCTION_SET_MOVING_AVERAGE = 5;
BrickletLoadCellV2.FUNCTION_GET_MOVING_AVERAGE = 6;
BrickletLoadCellV2.FUNCTION_SET_INFO_LED_CONFIG = 7;
BrickletLoadCellV2.FUNCTION_GET_INFO_LED_CONFIG = 8;
BrickletLoadCellV2.FUNCTION_CALIBRATE = 9;
BrickletLoadCellV2.FUNCTION_TARE = 10;
BrickletLoadCellV2.FUNCTION_SET_CONFIGURATION = 11;
BrickletLoadCellV2.FUNCTION_GET_CONFIGURATION = 12;
BrickletLoadCellV2.FUNCTION_GET_SPITFP_ERROR_COUNT = 234;
BrickletLoadCellV2.FUNCTION_SET_BOOTLOADER_MODE = 235;
BrickletLoadCellV2.FUNCTION_GET_BOOTLOADER_MODE = 236;
BrickletLoadCellV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER = 237;
BrickletLoadCellV2.FUNCTION_WRITE_FIRMWARE = 238;
BrickletLoadCellV2.FUNCTION_SET_STATUS_LED_CONFIG = 239;
BrickletLoadCellV2.FUNCTION_GET_STATUS_LED_CONFIG = 240;
BrickletLoadCellV2.FUNCTION_GET_CHIP_TEMPERATURE = 242;
BrickletLoadCellV2.FUNCTION_RESET = 243;
BrickletLoadCellV2.FUNCTION_WRITE_UID = 248;
BrickletLoadCellV2.FUNCTION_READ_UID = 249;
BrickletLoadCellV2.FUNCTION_GET_IDENTITY = 255;
BrickletLoadCellV2.THRESHOLD_OPTION_OFF = 'x';
BrickletLoadCellV2.THRESHOLD_OPTION_OUTSIDE = 'o';
BrickletLoadCellV2.THRESHOLD_OPTION_INSIDE = 'i';
BrickletLoadCellV2.THRESHOLD_OPTION_SMALLER = '<';
BrickletLoadCellV2.THRESHOLD_OPTION_GREATER = '>';
BrickletLoadCellV2.INFO_LED_CONFIG_OFF = 0;
BrickletLoadCellV2.INFO_LED_CONFIG_ON = 1;
BrickletLoadCellV2.INFO_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletLoadCellV2.RATE_10HZ = 0;
BrickletLoadCellV2.RATE_80HZ = 1;
BrickletLoadCellV2.GAIN_128X = 0;
BrickletLoadCellV2.GAIN_64X = 1;
BrickletLoadCellV2.GAIN_32X = 2;
BrickletLoadCellV2.BOOTLOADER_MODE_BOOTLOADER = 0;
BrickletLoadCellV2.BOOTLOADER_MODE_FIRMWARE = 1;
BrickletLoadCellV2.BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT = 2;
BrickletLoadCellV2.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT = 3;
BrickletLoadCellV2.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT = 4;
BrickletLoadCellV2.BOOTLOADER_STATUS_OK = 0;
BrickletLoadCellV2.BOOTLOADER_STATUS_INVALID_MODE = 1;
BrickletLoadCellV2.BOOTLOADER_STATUS_NO_CHANGE = 2;
BrickletLoadCellV2.BOOTLOADER_STATUS_ENTRY_FUNCTION_NOT_PRESENT = 3;
BrickletLoadCellV2.BOOTLOADER_STATUS_DEVICE_IDENTIFIER_INCORRECT = 4;
BrickletLoadCellV2.BOOTLOADER_STATUS_CRC_MISMATCH = 5;
BrickletLoadCellV2.STATUS_LED_CONFIG_OFF = 0;
BrickletLoadCellV2.STATUS_LED_CONFIG_ON = 1;
BrickletLoadCellV2.STATUS_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletLoadCellV2.STATUS_LED_CONFIG_SHOW_STATUS = 3;

function BrickletLoadCellV2(uid, ipcon) {
	//Measures weight with a load cell

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletLoadCellV2.DEVICE_IDENTIFIER, BrickletLoadCellV2.DEVICE_DISPLAY_NAME);
	BrickletLoadCellV2.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickletLoadCellV2.FUNCTION_GET_WEIGHT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLoadCellV2.FUNCTION_SET_WEIGHT_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletLoadCellV2.FUNCTION_GET_WEIGHT_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLoadCellV2.FUNCTION_SET_MOVING_AVERAGE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletLoadCellV2.FUNCTION_GET_MOVING_AVERAGE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLoadCellV2.FUNCTION_SET_INFO_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletLoadCellV2.FUNCTION_GET_INFO_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLoadCellV2.FUNCTION_CALIBRATE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletLoadCellV2.FUNCTION_TARE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletLoadCellV2.FUNCTION_SET_CONFIGURATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletLoadCellV2.FUNCTION_GET_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLoadCellV2.FUNCTION_GET_SPITFP_ERROR_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLoadCellV2.FUNCTION_SET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLoadCellV2.FUNCTION_GET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLoadCellV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletLoadCellV2.FUNCTION_WRITE_FIRMWARE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLoadCellV2.FUNCTION_SET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletLoadCellV2.FUNCTION_GET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLoadCellV2.FUNCTION_GET_CHIP_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLoadCellV2.FUNCTION_RESET] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletLoadCellV2.FUNCTION_WRITE_UID] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletLoadCellV2.FUNCTION_READ_UID] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletLoadCellV2.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletLoadCellV2.CALLBACK_WEIGHT] = [12, 'i'];



	this.getWeight = function(returnCallback, errorCallback) {
		/*
		Returns the currently measured weight.
		
		
		If you want to get the value periodically, it is recommended to use the
		:cb:`Weight` callback. You can set the callback configuration
		with :func:`Set Weight Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletLoadCellV2.FUNCTION_GET_WEIGHT, [], '', 12, 'i', returnCallback, errorCallback, false, true);
	};
	this.setWeightCallbackConfiguration = function(period, valueHasToChange, option, min, max, returnCallback, errorCallback) {
		/*
		The period is the period with which the :cb:`Weight` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		If the `value has to change`-parameter is set to true, the callback is only
		triggered after the value has changed. If the value didn't change
		within the period, the callback is triggered immediately on change.
		
		If it is set to false, the callback is continuously triggered with the period,
		independent of the value.
		
		It is furthermore possible to constrain the callback with thresholds.
		
		The `option`-parameter together with min/max sets a threshold for the :cb:`Weight` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Threshold is turned off"
		 "'o'",    "Threshold is triggered when the value is *outside* the min and max values"
		 "'i'",    "Threshold is triggered when the value is *inside* or equal to the min and max values"
		 "'<'",    "Threshold is triggered when the value is smaller than the min value (max is ignored)"
		 "'>'",    "Threshold is triggered when the value is greater than the min value (max is ignored)"
		
		If the option is set to 'x' (threshold turned off) the callback is triggered with the fixed period.
		*/
		this.ipcon.sendRequest(this, BrickletLoadCellV2.FUNCTION_SET_WEIGHT_CALLBACK_CONFIGURATION, [period, valueHasToChange, option, min, max], 'I ? c i i', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getWeightCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the callback configuration as set by :func:`Set Weight Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletLoadCellV2.FUNCTION_GET_WEIGHT_CALLBACK_CONFIGURATION, [], '', 22, 'I ? c i i', returnCallback, errorCallback, false, true);
	};
	this.setMovingAverage = function(average, returnCallback, errorCallback) {
		/*
		Sets the length of a `moving averaging <https://en.wikipedia.org/wiki/Moving_average>`__
		for the weight value.
		
		Setting the length to 1 will turn the averaging off. With less
		averaging, there is more noise on the data.
		*/
		this.ipcon.sendRequest(this, BrickletLoadCellV2.FUNCTION_SET_MOVING_AVERAGE, [average], 'H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getMovingAverage = function(returnCallback, errorCallback) {
		/*
		Returns the length moving average as set by :func:`Set Moving Average`.
		*/
		this.ipcon.sendRequest(this, BrickletLoadCellV2.FUNCTION_GET_MOVING_AVERAGE, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.setInfoLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Configures the info LED to be either turned off, turned on, or blink in
		heartbeat mode.
		*/
		this.ipcon.sendRequest(this, BrickletLoadCellV2.FUNCTION_SET_INFO_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getInfoLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the LED configuration as set by :func:`Set Info LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletLoadCellV2.FUNCTION_GET_INFO_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.calibrate = function(weight, returnCallback, errorCallback) {
		/*
		To calibrate your Load Cell Bricklet 2.0 you have to
		
		* empty the scale and call this function with 0 and
		* add a known weight to the scale and call this function with the weight.
		
		The calibration is saved in the flash of the Bricklet and only
		needs to be done once.
		
		We recommend to use the Brick Viewer for calibration, you don't need
		to call this function in your source code.
		*/
		this.ipcon.sendRequest(this, BrickletLoadCellV2.FUNCTION_CALIBRATE, [weight], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.tare = function(returnCallback, errorCallback) {
		/*
		Sets the currently measured weight as tare weight.
		*/
		this.ipcon.sendRequest(this, BrickletLoadCellV2.FUNCTION_TARE, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.setConfiguration = function(rate, gain, returnCallback, errorCallback) {
		/*
		The measurement rate and gain are configurable.
		
		The rate can be either 10Hz or 80Hz. A faster rate will produce more noise.
		It is additionally possible to add a moving average
		(see :func:`Set Moving Average`) to the measurements.
		
		The gain can be 128x, 64x or 32x. It represents a measurement range of
		±20mV, ±40mV and ±80mV respectively. The Load Cell Bricklet uses an
		excitation voltage of 5V and most load cells use an output of 2mV/V. That
		means the voltage range is ±15mV for most load cells (i.e. gain of 128x
		is best). If you don't know what all of this means you should keep it at
		128x, it will most likely be correct.
		*/
		this.ipcon.sendRequest(this, BrickletLoadCellV2.FUNCTION_SET_CONFIGURATION, [rate, gain], 'B B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletLoadCellV2.FUNCTION_GET_CONFIGURATION, [], '', 10, 'B B', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPErrorCount = function(returnCallback, errorCallback) {
		/*
		Returns the error count for the communication between Brick and Bricklet.
		
		The errors are divided into
		
		* ACK checksum errors,
		* message checksum errors,
		* framing errors and
		* overflow errors.
		
		The errors counts are for errors that occur on the Bricklet side. All
		Bricks have a similar function that returns the errors on the Brick side.
		*/
		this.ipcon.sendRequest(this, BrickletLoadCellV2.FUNCTION_GET_SPITFP_ERROR_COUNT, [], '', 24, 'I I I I', returnCallback, errorCallback, false, true);
	};
	this.setBootloaderMode = function(mode, returnCallback, errorCallback) {
		/*
		Sets the bootloader mode and returns the status after the requested
		mode change was instigated.
		
		You can change from bootloader mode to firmware mode and vice versa. A change
		from bootloader mode to firmware mode will only take place if the entry function,
		device identifier and CRC are present and correct.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletLoadCellV2.FUNCTION_SET_BOOTLOADER_MODE, [mode], 'B', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getBootloaderMode = function(returnCallback, errorCallback) {
		/*
		Returns the current bootloader mode, see :func:`Set Bootloader Mode`.
		*/
		this.ipcon.sendRequest(this, BrickletLoadCellV2.FUNCTION_GET_BOOTLOADER_MODE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setWriteFirmwarePointer = function(pointer, returnCallback, errorCallback) {
		/*
		Sets the firmware pointer for :func:`Write Firmware`. The pointer has
		to be increased by chunks of size 64. The data is written to flash
		every 4 chunks (which equals to one page of size 256).
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletLoadCellV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER, [pointer], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeFirmware = function(data, returnCallback, errorCallback) {
		/*
		Writes 64 Bytes of firmware at the position as written by
		:func:`Set Write Firmware Pointer` before. The firmware is written
		to flash every 4 chunks.
		
		You can only write firmware in bootloader mode.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletLoadCellV2.FUNCTION_WRITE_FIRMWARE, [data], 'B64', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setStatusLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Sets the status LED configuration. By default the LED shows
		communication traffic between Brick and Bricklet, it flickers once
		for every 10 received data packets.
		
		You can also turn the LED permanently on/off or show a heartbeat.
		
		If the Bricklet is in bootloader mode, the LED is will show heartbeat by default.
		*/
		this.ipcon.sendRequest(this, BrickletLoadCellV2.FUNCTION_SET_STATUS_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getStatusLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Status LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletLoadCellV2.FUNCTION_GET_STATUS_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getChipTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature as measured inside the microcontroller. The
		value returned is not the ambient temperature!
		
		The temperature is only proportional to the real temperature and it has bad
		accuracy. Practically it is only useful as an indicator for
		temperature changes.
		*/
		this.ipcon.sendRequest(this, BrickletLoadCellV2.FUNCTION_GET_CHIP_TEMPERATURE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.reset = function(returnCallback, errorCallback) {
		/*
		Calling this function will reset the Bricklet. All configurations
		will be lost.
		
		After a reset you have to create new device objects,
		calling functions on the existing ones will result in
		undefined behavior!
		*/
		this.ipcon.sendRequest(this, BrickletLoadCellV2.FUNCTION_RESET, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeUID = function(uid, returnCallback, errorCallback) {
		/*
		Writes a new UID into flash. If you want to set a new UID
		you have to decode the Base58 encoded UID string into an
		integer first.
		
		We recommend that you use Brick Viewer to change the UID.
		*/
		this.ipcon.sendRequest(this, BrickletLoadCellV2.FUNCTION_WRITE_UID, [uid], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.readUID = function(returnCallback, errorCallback) {
		/*
		Returns the current UID as an integer. Encode as
		Base58 to get the usual string version.
		*/
		this.ipcon.sendRequest(this, BrickletLoadCellV2.FUNCTION_READ_UID, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletLoadCellV2.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletLoadCellV2;

},{"./Device":279,"./IPConnection":280}],222:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletMoisture.DEVICE_IDENTIFIER = 232;
BrickletMoisture.DEVICE_DISPLAY_NAME = 'Moisture Bricklet';
BrickletMoisture.CALLBACK_MOISTURE = 8;
BrickletMoisture.CALLBACK_MOISTURE_REACHED = 9;
BrickletMoisture.FUNCTION_GET_MOISTURE_VALUE = 1;
BrickletMoisture.FUNCTION_SET_MOISTURE_CALLBACK_PERIOD = 2;
BrickletMoisture.FUNCTION_GET_MOISTURE_CALLBACK_PERIOD = 3;
BrickletMoisture.FUNCTION_SET_MOISTURE_CALLBACK_THRESHOLD = 4;
BrickletMoisture.FUNCTION_GET_MOISTURE_CALLBACK_THRESHOLD = 5;
BrickletMoisture.FUNCTION_SET_DEBOUNCE_PERIOD = 6;
BrickletMoisture.FUNCTION_GET_DEBOUNCE_PERIOD = 7;
BrickletMoisture.FUNCTION_SET_MOVING_AVERAGE = 10;
BrickletMoisture.FUNCTION_GET_MOVING_AVERAGE = 11;
BrickletMoisture.FUNCTION_GET_IDENTITY = 255;
BrickletMoisture.THRESHOLD_OPTION_OFF = 'x';
BrickletMoisture.THRESHOLD_OPTION_OUTSIDE = 'o';
BrickletMoisture.THRESHOLD_OPTION_INSIDE = 'i';
BrickletMoisture.THRESHOLD_OPTION_SMALLER = '<';
BrickletMoisture.THRESHOLD_OPTION_GREATER = '>';

function BrickletMoisture(uid, ipcon) {
	//Measures soil moisture

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletMoisture.DEVICE_IDENTIFIER, BrickletMoisture.DEVICE_DISPLAY_NAME);
	BrickletMoisture.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickletMoisture.FUNCTION_GET_MOISTURE_VALUE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletMoisture.FUNCTION_SET_MOISTURE_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletMoisture.FUNCTION_GET_MOISTURE_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletMoisture.FUNCTION_SET_MOISTURE_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletMoisture.FUNCTION_GET_MOISTURE_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletMoisture.FUNCTION_SET_DEBOUNCE_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletMoisture.FUNCTION_GET_DEBOUNCE_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletMoisture.FUNCTION_SET_MOVING_AVERAGE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletMoisture.FUNCTION_GET_MOVING_AVERAGE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletMoisture.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletMoisture.CALLBACK_MOISTURE] = [10, 'H'];
	this.callbackFormats[BrickletMoisture.CALLBACK_MOISTURE_REACHED] = [10, 'H'];



	this.getMoistureValue = function(returnCallback, errorCallback) {
		/*
		Returns the current moisture value.
		A small value corresponds to little moisture, a big
		value corresponds to much moisture.
		
		If you want to get the moisture value periodically, it is recommended
		to use the :cb:`Moisture` callback and set the period with
		:func:`Set Moisture Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletMoisture.FUNCTION_GET_MOISTURE_VALUE, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.setMoistureCallbackPeriod = function(period, returnCallback, errorCallback) {
		/*
		Sets the period with which the :cb:`Moisture` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		The :cb:`Moisture` callback is only triggered if the moisture value has changed
		since the last triggering.
		*/
		this.ipcon.sendRequest(this, BrickletMoisture.FUNCTION_SET_MOISTURE_CALLBACK_PERIOD, [period], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getMoistureCallbackPeriod = function(returnCallback, errorCallback) {
		/*
		Returns the period as set by :func:`Set Moisture Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletMoisture.FUNCTION_GET_MOISTURE_CALLBACK_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setMoistureCallbackThreshold = function(option, min, max, returnCallback, errorCallback) {
		/*
		Sets the thresholds for the :cb:`Moisture Reached` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Callback is turned off"
		 "'o'",    "Callback is triggered when the moisture value is *outside* the min and max values"
		 "'i'",    "Callback is triggered when the moisture value is *inside* the min and max values"
		 "'<'",    "Callback is triggered when the moisture value is smaller than the min value (max is ignored)"
		 "'>'",    "Callback is triggered when the moisture value is greater than the min value (max is ignored)"
		*/
		this.ipcon.sendRequest(this, BrickletMoisture.FUNCTION_SET_MOISTURE_CALLBACK_THRESHOLD, [option, min, max], 'c H H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getMoistureCallbackThreshold = function(returnCallback, errorCallback) {
		/*
		Returns the threshold as set by :func:`Set Moisture Callback Threshold`.
		*/
		this.ipcon.sendRequest(this, BrickletMoisture.FUNCTION_GET_MOISTURE_CALLBACK_THRESHOLD, [], '', 13, 'c H H', returnCallback, errorCallback, false, true);
	};
	this.setDebouncePeriod = function(debounce, returnCallback, errorCallback) {
		/*
		Sets the period with which the threshold callback
		
		* :cb:`Moisture Reached`
		
		is triggered, if the threshold
		
		* :func:`Set Moisture Callback Threshold`
		
		keeps being reached.
		*/
		this.ipcon.sendRequest(this, BrickletMoisture.FUNCTION_SET_DEBOUNCE_PERIOD, [debounce], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getDebouncePeriod = function(returnCallback, errorCallback) {
		/*
		Returns the debounce period as set by :func:`Set Debounce Period`.
		*/
		this.ipcon.sendRequest(this, BrickletMoisture.FUNCTION_GET_DEBOUNCE_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setMovingAverage = function(average, returnCallback, errorCallback) {
		/*
		Sets the length of a `moving averaging <https://en.wikipedia.org/wiki/Moving_average>`__
		for the moisture value.
		
		Setting the length to 0 will turn the averaging completely off. With less
		averaging, there is more noise on the data.
		*/
		this.ipcon.sendRequest(this, BrickletMoisture.FUNCTION_SET_MOVING_AVERAGE, [average], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getMovingAverage = function(returnCallback, errorCallback) {
		/*
		Returns the length moving average as set by :func:`Set Moving Average`.
		*/
		this.ipcon.sendRequest(this, BrickletMoisture.FUNCTION_GET_MOVING_AVERAGE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletMoisture.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletMoisture;

},{"./Device":279,"./IPConnection":280}],223:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletMotionDetector.DEVICE_IDENTIFIER = 233;
BrickletMotionDetector.DEVICE_DISPLAY_NAME = 'Motion Detector Bricklet';
BrickletMotionDetector.CALLBACK_MOTION_DETECTED = 2;
BrickletMotionDetector.CALLBACK_DETECTION_CYCLE_ENDED = 3;
BrickletMotionDetector.FUNCTION_GET_MOTION_DETECTED = 1;
BrickletMotionDetector.FUNCTION_SET_STATUS_LED_CONFIG = 4;
BrickletMotionDetector.FUNCTION_GET_STATUS_LED_CONFIG = 5;
BrickletMotionDetector.FUNCTION_GET_IDENTITY = 255;
BrickletMotionDetector.MOTION_NOT_DETECTED = 0;
BrickletMotionDetector.MOTION_DETECTED = 1;
BrickletMotionDetector.STATUS_LED_CONFIG_OFF = 0;
BrickletMotionDetector.STATUS_LED_CONFIG_ON = 1;
BrickletMotionDetector.STATUS_LED_CONFIG_SHOW_STATUS = 2;

function BrickletMotionDetector(uid, ipcon) {
	//Passive infrared (PIR) motion sensor with 7m range

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletMotionDetector.DEVICE_IDENTIFIER, BrickletMotionDetector.DEVICE_DISPLAY_NAME);
	BrickletMotionDetector.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 1];
	this.responseExpected[BrickletMotionDetector.FUNCTION_GET_MOTION_DETECTED] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletMotionDetector.FUNCTION_SET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletMotionDetector.FUNCTION_GET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletMotionDetector.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletMotionDetector.CALLBACK_MOTION_DETECTED] = [8, ''];
	this.callbackFormats[BrickletMotionDetector.CALLBACK_DETECTION_CYCLE_ENDED] = [8, ''];



	this.getMotionDetected = function(returnCallback, errorCallback) {
		/*
		Returns 1 if a motion was detected. How long this returns 1 after a motion
		was detected can be adjusted with one of the small potentiometers on the
		Motion Detector Bricklet, see :ref:`here
		<motion_detector_bricklet_sensitivity_delay_block_time>`.
		
		There is also a blue LED on the Bricklet that is on as long as the Bricklet is
		in the "motion detected" state.
		*/
		this.ipcon.sendRequest(this, BrickletMotionDetector.FUNCTION_GET_MOTION_DETECTED, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setStatusLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Sets the status led configuration.
		
		By default the status LED turns on if a motion is detected and off is no motion
		is detected.
		
		You can also turn the LED permanently on/off.
		
		.. versionadded:: 2.0.1$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletMotionDetector.FUNCTION_SET_STATUS_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getStatusLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Status LED Config`.
		
		.. versionadded:: 2.0.1$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletMotionDetector.FUNCTION_GET_STATUS_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletMotionDetector.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletMotionDetector;

},{"./Device":279,"./IPConnection":280}],224:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletMotionDetectorV2.DEVICE_IDENTIFIER = 292;
BrickletMotionDetectorV2.DEVICE_DISPLAY_NAME = 'Motion Detector Bricklet 2.0';
BrickletMotionDetectorV2.CALLBACK_MOTION_DETECTED = 6;
BrickletMotionDetectorV2.CALLBACK_DETECTION_CYCLE_ENDED = 7;
BrickletMotionDetectorV2.FUNCTION_GET_MOTION_DETECTED = 1;
BrickletMotionDetectorV2.FUNCTION_SET_SENSITIVITY = 2;
BrickletMotionDetectorV2.FUNCTION_GET_SENSITIVITY = 3;
BrickletMotionDetectorV2.FUNCTION_SET_INDICATOR = 4;
BrickletMotionDetectorV2.FUNCTION_GET_INDICATOR = 5;
BrickletMotionDetectorV2.FUNCTION_GET_SPITFP_ERROR_COUNT = 234;
BrickletMotionDetectorV2.FUNCTION_SET_BOOTLOADER_MODE = 235;
BrickletMotionDetectorV2.FUNCTION_GET_BOOTLOADER_MODE = 236;
BrickletMotionDetectorV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER = 237;
BrickletMotionDetectorV2.FUNCTION_WRITE_FIRMWARE = 238;
BrickletMotionDetectorV2.FUNCTION_SET_STATUS_LED_CONFIG = 239;
BrickletMotionDetectorV2.FUNCTION_GET_STATUS_LED_CONFIG = 240;
BrickletMotionDetectorV2.FUNCTION_GET_CHIP_TEMPERATURE = 242;
BrickletMotionDetectorV2.FUNCTION_RESET = 243;
BrickletMotionDetectorV2.FUNCTION_WRITE_UID = 248;
BrickletMotionDetectorV2.FUNCTION_READ_UID = 249;
BrickletMotionDetectorV2.FUNCTION_GET_IDENTITY = 255;
BrickletMotionDetectorV2.MOTION_NOT_DETECTED = 0;
BrickletMotionDetectorV2.MOTION_DETECTED = 1;
BrickletMotionDetectorV2.BOOTLOADER_MODE_BOOTLOADER = 0;
BrickletMotionDetectorV2.BOOTLOADER_MODE_FIRMWARE = 1;
BrickletMotionDetectorV2.BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT = 2;
BrickletMotionDetectorV2.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT = 3;
BrickletMotionDetectorV2.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT = 4;
BrickletMotionDetectorV2.BOOTLOADER_STATUS_OK = 0;
BrickletMotionDetectorV2.BOOTLOADER_STATUS_INVALID_MODE = 1;
BrickletMotionDetectorV2.BOOTLOADER_STATUS_NO_CHANGE = 2;
BrickletMotionDetectorV2.BOOTLOADER_STATUS_ENTRY_FUNCTION_NOT_PRESENT = 3;
BrickletMotionDetectorV2.BOOTLOADER_STATUS_DEVICE_IDENTIFIER_INCORRECT = 4;
BrickletMotionDetectorV2.BOOTLOADER_STATUS_CRC_MISMATCH = 5;
BrickletMotionDetectorV2.STATUS_LED_CONFIG_OFF = 0;
BrickletMotionDetectorV2.STATUS_LED_CONFIG_ON = 1;
BrickletMotionDetectorV2.STATUS_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletMotionDetectorV2.STATUS_LED_CONFIG_SHOW_STATUS = 3;

function BrickletMotionDetectorV2(uid, ipcon) {
	//Passive infrared (PIR) motion sensor with 12m range and dimmable backlight

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletMotionDetectorV2.DEVICE_IDENTIFIER, BrickletMotionDetectorV2.DEVICE_DISPLAY_NAME);
	BrickletMotionDetectorV2.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickletMotionDetectorV2.FUNCTION_GET_MOTION_DETECTED] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletMotionDetectorV2.FUNCTION_SET_SENSITIVITY] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletMotionDetectorV2.FUNCTION_GET_SENSITIVITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletMotionDetectorV2.FUNCTION_SET_INDICATOR] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletMotionDetectorV2.FUNCTION_GET_INDICATOR] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletMotionDetectorV2.FUNCTION_GET_SPITFP_ERROR_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletMotionDetectorV2.FUNCTION_SET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletMotionDetectorV2.FUNCTION_GET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletMotionDetectorV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletMotionDetectorV2.FUNCTION_WRITE_FIRMWARE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletMotionDetectorV2.FUNCTION_SET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletMotionDetectorV2.FUNCTION_GET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletMotionDetectorV2.FUNCTION_GET_CHIP_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletMotionDetectorV2.FUNCTION_RESET] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletMotionDetectorV2.FUNCTION_WRITE_UID] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletMotionDetectorV2.FUNCTION_READ_UID] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletMotionDetectorV2.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletMotionDetectorV2.CALLBACK_MOTION_DETECTED] = [8, ''];
	this.callbackFormats[BrickletMotionDetectorV2.CALLBACK_DETECTION_CYCLE_ENDED] = [8, ''];



	this.getMotionDetected = function(returnCallback, errorCallback) {
		/*
		Returns 1 if a motion was detected. It returns 1 approx. for 1.8 seconds
		until the sensor checks for a new movement.
		
		There is also a blue LED on the Bricklet that is on as long as the Bricklet is
		in the "motion detected" state.
		*/
		this.ipcon.sendRequest(this, BrickletMotionDetectorV2.FUNCTION_GET_MOTION_DETECTED, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setSensitivity = function(sensitivity, returnCallback, errorCallback) {
		/*
		Sets the sensitivity of the PIR sensor. At full
		sensitivity (100), the Bricklet can detect motion in a range of approximately 12m.
		
		The actual range depends on many things in the environment (e.g. reflections) and the
		size of the object to be detected. While a big person might be detected in a range
		of 10m a cat may only be detected at 2m distance with the same setting.
		
		So you will have to find a good sensitivity for your application by trial and error.
		*/
		this.ipcon.sendRequest(this, BrickletMotionDetectorV2.FUNCTION_SET_SENSITIVITY, [sensitivity], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getSensitivity = function(returnCallback, errorCallback) {
		/*
		Returns the sensitivity as set by :func:`Set Sensitivity`.
		*/
		this.ipcon.sendRequest(this, BrickletMotionDetectorV2.FUNCTION_GET_SENSITIVITY, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setIndicator = function(topLeft, topRight, bottom, returnCallback, errorCallback) {
		/*
		Sets the blue backlight of the fresnel lens. The backlight consists of
		three LEDs. The brightness of each LED can be controlled with a 8-bit value
		(0-255). A value of 0 turns the LED off and a value of 255 turns the LED
		to full brightness.
		*/
		this.ipcon.sendRequest(this, BrickletMotionDetectorV2.FUNCTION_SET_INDICATOR, [topLeft, topRight, bottom], 'B B B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getIndicator = function(returnCallback, errorCallback) {
		/*
		Returns the indicator configuration as set by :func:`Set Indicator`.
		*/
		this.ipcon.sendRequest(this, BrickletMotionDetectorV2.FUNCTION_GET_INDICATOR, [], '', 11, 'B B B', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPErrorCount = function(returnCallback, errorCallback) {
		/*
		Returns the error count for the communication between Brick and Bricklet.
		
		The errors are divided into
		
		* ACK checksum errors,
		* message checksum errors,
		* framing errors and
		* overflow errors.
		
		The errors counts are for errors that occur on the Bricklet side. All
		Bricks have a similar function that returns the errors on the Brick side.
		*/
		this.ipcon.sendRequest(this, BrickletMotionDetectorV2.FUNCTION_GET_SPITFP_ERROR_COUNT, [], '', 24, 'I I I I', returnCallback, errorCallback, false, true);
	};
	this.setBootloaderMode = function(mode, returnCallback, errorCallback) {
		/*
		Sets the bootloader mode and returns the status after the requested
		mode change was instigated.
		
		You can change from bootloader mode to firmware mode and vice versa. A change
		from bootloader mode to firmware mode will only take place if the entry function,
		device identifier and CRC are present and correct.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletMotionDetectorV2.FUNCTION_SET_BOOTLOADER_MODE, [mode], 'B', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getBootloaderMode = function(returnCallback, errorCallback) {
		/*
		Returns the current bootloader mode, see :func:`Set Bootloader Mode`.
		*/
		this.ipcon.sendRequest(this, BrickletMotionDetectorV2.FUNCTION_GET_BOOTLOADER_MODE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setWriteFirmwarePointer = function(pointer, returnCallback, errorCallback) {
		/*
		Sets the firmware pointer for :func:`Write Firmware`. The pointer has
		to be increased by chunks of size 64. The data is written to flash
		every 4 chunks (which equals to one page of size 256).
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletMotionDetectorV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER, [pointer], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeFirmware = function(data, returnCallback, errorCallback) {
		/*
		Writes 64 Bytes of firmware at the position as written by
		:func:`Set Write Firmware Pointer` before. The firmware is written
		to flash every 4 chunks.
		
		You can only write firmware in bootloader mode.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletMotionDetectorV2.FUNCTION_WRITE_FIRMWARE, [data], 'B64', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setStatusLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Sets the status LED configuration. By default the LED shows
		communication traffic between Brick and Bricklet, it flickers once
		for every 10 received data packets.
		
		You can also turn the LED permanently on/off or show a heartbeat.
		
		If the Bricklet is in bootloader mode, the LED is will show heartbeat by default.
		*/
		this.ipcon.sendRequest(this, BrickletMotionDetectorV2.FUNCTION_SET_STATUS_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getStatusLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Status LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletMotionDetectorV2.FUNCTION_GET_STATUS_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getChipTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature as measured inside the microcontroller. The
		value returned is not the ambient temperature!
		
		The temperature is only proportional to the real temperature and it has bad
		accuracy. Practically it is only useful as an indicator for
		temperature changes.
		*/
		this.ipcon.sendRequest(this, BrickletMotionDetectorV2.FUNCTION_GET_CHIP_TEMPERATURE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.reset = function(returnCallback, errorCallback) {
		/*
		Calling this function will reset the Bricklet. All configurations
		will be lost.
		
		After a reset you have to create new device objects,
		calling functions on the existing ones will result in
		undefined behavior!
		*/
		this.ipcon.sendRequest(this, BrickletMotionDetectorV2.FUNCTION_RESET, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeUID = function(uid, returnCallback, errorCallback) {
		/*
		Writes a new UID into flash. If you want to set a new UID
		you have to decode the Base58 encoded UID string into an
		integer first.
		
		We recommend that you use Brick Viewer to change the UID.
		*/
		this.ipcon.sendRequest(this, BrickletMotionDetectorV2.FUNCTION_WRITE_UID, [uid], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.readUID = function(returnCallback, errorCallback) {
		/*
		Returns the current UID as an integer. Encode as
		Base58 to get the usual string version.
		*/
		this.ipcon.sendRequest(this, BrickletMotionDetectorV2.FUNCTION_READ_UID, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletMotionDetectorV2.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletMotionDetectorV2;

},{"./Device":279,"./IPConnection":280}],225:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletMotorizedLinearPoti.DEVICE_IDENTIFIER = 267;
BrickletMotorizedLinearPoti.DEVICE_DISPLAY_NAME = 'Motorized Linear Poti Bricklet';
BrickletMotorizedLinearPoti.CALLBACK_POSITION = 4;
BrickletMotorizedLinearPoti.CALLBACK_POSITION_REACHED = 10;
BrickletMotorizedLinearPoti.FUNCTION_GET_POSITION = 1;
BrickletMotorizedLinearPoti.FUNCTION_SET_POSITION_CALLBACK_CONFIGURATION = 2;
BrickletMotorizedLinearPoti.FUNCTION_GET_POSITION_CALLBACK_CONFIGURATION = 3;
BrickletMotorizedLinearPoti.FUNCTION_SET_MOTOR_POSITION = 5;
BrickletMotorizedLinearPoti.FUNCTION_GET_MOTOR_POSITION = 6;
BrickletMotorizedLinearPoti.FUNCTION_CALIBRATE = 7;
BrickletMotorizedLinearPoti.FUNCTION_SET_POSITION_REACHED_CALLBACK_CONFIGURATION = 8;
BrickletMotorizedLinearPoti.FUNCTION_GET_POSITION_REACHED_CALLBACK_CONFIGURATION = 9;
BrickletMotorizedLinearPoti.FUNCTION_GET_SPITFP_ERROR_COUNT = 234;
BrickletMotorizedLinearPoti.FUNCTION_SET_BOOTLOADER_MODE = 235;
BrickletMotorizedLinearPoti.FUNCTION_GET_BOOTLOADER_MODE = 236;
BrickletMotorizedLinearPoti.FUNCTION_SET_WRITE_FIRMWARE_POINTER = 237;
BrickletMotorizedLinearPoti.FUNCTION_WRITE_FIRMWARE = 238;
BrickletMotorizedLinearPoti.FUNCTION_SET_STATUS_LED_CONFIG = 239;
BrickletMotorizedLinearPoti.FUNCTION_GET_STATUS_LED_CONFIG = 240;
BrickletMotorizedLinearPoti.FUNCTION_GET_CHIP_TEMPERATURE = 242;
BrickletMotorizedLinearPoti.FUNCTION_RESET = 243;
BrickletMotorizedLinearPoti.FUNCTION_WRITE_UID = 248;
BrickletMotorizedLinearPoti.FUNCTION_READ_UID = 249;
BrickletMotorizedLinearPoti.FUNCTION_GET_IDENTITY = 255;
BrickletMotorizedLinearPoti.THRESHOLD_OPTION_OFF = 'x';
BrickletMotorizedLinearPoti.THRESHOLD_OPTION_OUTSIDE = 'o';
BrickletMotorizedLinearPoti.THRESHOLD_OPTION_INSIDE = 'i';
BrickletMotorizedLinearPoti.THRESHOLD_OPTION_SMALLER = '<';
BrickletMotorizedLinearPoti.THRESHOLD_OPTION_GREATER = '>';
BrickletMotorizedLinearPoti.DRIVE_MODE_FAST = 0;
BrickletMotorizedLinearPoti.DRIVE_MODE_SMOOTH = 1;
BrickletMotorizedLinearPoti.BOOTLOADER_MODE_BOOTLOADER = 0;
BrickletMotorizedLinearPoti.BOOTLOADER_MODE_FIRMWARE = 1;
BrickletMotorizedLinearPoti.BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT = 2;
BrickletMotorizedLinearPoti.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT = 3;
BrickletMotorizedLinearPoti.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT = 4;
BrickletMotorizedLinearPoti.BOOTLOADER_STATUS_OK = 0;
BrickletMotorizedLinearPoti.BOOTLOADER_STATUS_INVALID_MODE = 1;
BrickletMotorizedLinearPoti.BOOTLOADER_STATUS_NO_CHANGE = 2;
BrickletMotorizedLinearPoti.BOOTLOADER_STATUS_ENTRY_FUNCTION_NOT_PRESENT = 3;
BrickletMotorizedLinearPoti.BOOTLOADER_STATUS_DEVICE_IDENTIFIER_INCORRECT = 4;
BrickletMotorizedLinearPoti.BOOTLOADER_STATUS_CRC_MISMATCH = 5;
BrickletMotorizedLinearPoti.STATUS_LED_CONFIG_OFF = 0;
BrickletMotorizedLinearPoti.STATUS_LED_CONFIG_ON = 1;
BrickletMotorizedLinearPoti.STATUS_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletMotorizedLinearPoti.STATUS_LED_CONFIG_SHOW_STATUS = 3;

function BrickletMotorizedLinearPoti(uid, ipcon) {
	//Motorized Linear Potentiometer

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletMotorizedLinearPoti.DEVICE_IDENTIFIER, BrickletMotorizedLinearPoti.DEVICE_DISPLAY_NAME);
	BrickletMotorizedLinearPoti.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickletMotorizedLinearPoti.FUNCTION_GET_POSITION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletMotorizedLinearPoti.FUNCTION_SET_POSITION_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletMotorizedLinearPoti.FUNCTION_GET_POSITION_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletMotorizedLinearPoti.FUNCTION_SET_MOTOR_POSITION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletMotorizedLinearPoti.FUNCTION_GET_MOTOR_POSITION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletMotorizedLinearPoti.FUNCTION_CALIBRATE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletMotorizedLinearPoti.FUNCTION_SET_POSITION_REACHED_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletMotorizedLinearPoti.FUNCTION_GET_POSITION_REACHED_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletMotorizedLinearPoti.FUNCTION_GET_SPITFP_ERROR_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletMotorizedLinearPoti.FUNCTION_SET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletMotorizedLinearPoti.FUNCTION_GET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletMotorizedLinearPoti.FUNCTION_SET_WRITE_FIRMWARE_POINTER] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletMotorizedLinearPoti.FUNCTION_WRITE_FIRMWARE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletMotorizedLinearPoti.FUNCTION_SET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletMotorizedLinearPoti.FUNCTION_GET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletMotorizedLinearPoti.FUNCTION_GET_CHIP_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletMotorizedLinearPoti.FUNCTION_RESET] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletMotorizedLinearPoti.FUNCTION_WRITE_UID] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletMotorizedLinearPoti.FUNCTION_READ_UID] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletMotorizedLinearPoti.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletMotorizedLinearPoti.CALLBACK_POSITION] = [10, 'H'];
	this.callbackFormats[BrickletMotorizedLinearPoti.CALLBACK_POSITION_REACHED] = [10, 'H'];



	this.getPosition = function(returnCallback, errorCallback) {
		/*
		Returns the position of the linear potentiometer. The value is
		between 0 (slider down) and 100 (slider up).
		
		
		If you want to get the value periodically, it is recommended to use the
		:cb:`Position` callback. You can set the callback configuration
		with :func:`Set Position Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletMotorizedLinearPoti.FUNCTION_GET_POSITION, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.setPositionCallbackConfiguration = function(period, valueHasToChange, option, min, max, returnCallback, errorCallback) {
		/*
		The period is the period with which the :cb:`Position` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		If the `value has to change`-parameter is set to true, the callback is only
		triggered after the value has changed. If the value didn't change
		within the period, the callback is triggered immediately on change.
		
		If it is set to false, the callback is continuously triggered with the period,
		independent of the value.
		
		It is furthermore possible to constrain the callback with thresholds.
		
		The `option`-parameter together with min/max sets a threshold for the :cb:`Position` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Threshold is turned off"
		 "'o'",    "Threshold is triggered when the value is *outside* the min and max values"
		 "'i'",    "Threshold is triggered when the value is *inside* or equal to the min and max values"
		 "'<'",    "Threshold is triggered when the value is smaller than the min value (max is ignored)"
		 "'>'",    "Threshold is triggered when the value is greater than the min value (max is ignored)"
		
		If the option is set to 'x' (threshold turned off) the callback is triggered with the fixed period.
		*/
		this.ipcon.sendRequest(this, BrickletMotorizedLinearPoti.FUNCTION_SET_POSITION_CALLBACK_CONFIGURATION, [period, valueHasToChange, option, min, max], 'I ? c H H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getPositionCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the callback configuration as set by :func:`Set Position Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletMotorizedLinearPoti.FUNCTION_GET_POSITION_CALLBACK_CONFIGURATION, [], '', 18, 'I ? c H H', returnCallback, errorCallback, false, true);
	};
	this.setMotorPosition = function(position, driveMode, holdPosition, returnCallback, errorCallback) {
		/*
		Sets the position of the potentiometer. The motorized potentiometer will
		immediately start to approach the position. Depending on the chosen drive mode,
		the position will either be reached as fast as possible or in a slow but smooth
		motion.
		
		The position has to be between 0 (slider down) and 100 (slider up).
		
		If you set the hold position parameter to true, the position will automatically
		be retained. If a user changes the position of the potentiometer, it will
		automatically drive back to the original set point.
		
		If the hold position parameter is set to false, the potentiometer can be changed
		again by the user as soon as the set point was reached once.
		*/
		this.ipcon.sendRequest(this, BrickletMotorizedLinearPoti.FUNCTION_SET_MOTOR_POSITION, [position, driveMode, holdPosition], 'H B ?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getMotorPosition = function(returnCallback, errorCallback) {
		/*
		Returns the last motor position as set by :func:`Set Motor Position`. This is not
		the current position (use :func:`Get Position` to get the current position). This
		is the last used set point and configuration.
		
		The position reached parameter is true if the position has been reached at one point.
		The position may have been changed again in the meantime by the user.
		*/
		this.ipcon.sendRequest(this, BrickletMotorizedLinearPoti.FUNCTION_GET_MOTOR_POSITION, [], '', 13, 'H B ? ?', returnCallback, errorCallback, false, true);
	};
	this.calibrate = function(returnCallback, errorCallback) {
		/*
		Starts a calibration procedure. The potentiometer will be driven to the extreme
		points to calibrate the potentiometer.
		
		The calibration is saved in flash, it does not have to be called on every start up.
		
		The Motorized Linear Poti Bricklet is already factory-calibrated during
		testing at Tinkerforge.
		*/
		this.ipcon.sendRequest(this, BrickletMotorizedLinearPoti.FUNCTION_CALIBRATE, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.setPositionReachedCallbackConfiguration = function(enabled, returnCallback, errorCallback) {
		/*
		Enables/Disables :cb:`Position Reached` callback.
		*/
		this.ipcon.sendRequest(this, BrickletMotorizedLinearPoti.FUNCTION_SET_POSITION_REACHED_CALLBACK_CONFIGURATION, [enabled], '?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getPositionReachedCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the :cb:`Position Reached` callback configuration
		as set by :func:`Set Position Reached Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletMotorizedLinearPoti.FUNCTION_GET_POSITION_REACHED_CALLBACK_CONFIGURATION, [], '', 9, '?', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPErrorCount = function(returnCallback, errorCallback) {
		/*
		Returns the error count for the communication between Brick and Bricklet.
		
		The errors are divided into
		
		* ACK checksum errors,
		* message checksum errors,
		* framing errors and
		* overflow errors.
		
		The errors counts are for errors that occur on the Bricklet side. All
		Bricks have a similar function that returns the errors on the Brick side.
		*/
		this.ipcon.sendRequest(this, BrickletMotorizedLinearPoti.FUNCTION_GET_SPITFP_ERROR_COUNT, [], '', 24, 'I I I I', returnCallback, errorCallback, false, true);
	};
	this.setBootloaderMode = function(mode, returnCallback, errorCallback) {
		/*
		Sets the bootloader mode and returns the status after the requested
		mode change was instigated.
		
		You can change from bootloader mode to firmware mode and vice versa. A change
		from bootloader mode to firmware mode will only take place if the entry function,
		device identifier and CRC are present and correct.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletMotorizedLinearPoti.FUNCTION_SET_BOOTLOADER_MODE, [mode], 'B', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getBootloaderMode = function(returnCallback, errorCallback) {
		/*
		Returns the current bootloader mode, see :func:`Set Bootloader Mode`.
		*/
		this.ipcon.sendRequest(this, BrickletMotorizedLinearPoti.FUNCTION_GET_BOOTLOADER_MODE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setWriteFirmwarePointer = function(pointer, returnCallback, errorCallback) {
		/*
		Sets the firmware pointer for :func:`Write Firmware`. The pointer has
		to be increased by chunks of size 64. The data is written to flash
		every 4 chunks (which equals to one page of size 256).
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletMotorizedLinearPoti.FUNCTION_SET_WRITE_FIRMWARE_POINTER, [pointer], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeFirmware = function(data, returnCallback, errorCallback) {
		/*
		Writes 64 Bytes of firmware at the position as written by
		:func:`Set Write Firmware Pointer` before. The firmware is written
		to flash every 4 chunks.
		
		You can only write firmware in bootloader mode.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletMotorizedLinearPoti.FUNCTION_WRITE_FIRMWARE, [data], 'B64', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setStatusLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Sets the status LED configuration. By default the LED shows
		communication traffic between Brick and Bricklet, it flickers once
		for every 10 received data packets.
		
		You can also turn the LED permanently on/off or show a heartbeat.
		
		If the Bricklet is in bootloader mode, the LED is will show heartbeat by default.
		*/
		this.ipcon.sendRequest(this, BrickletMotorizedLinearPoti.FUNCTION_SET_STATUS_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getStatusLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Status LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletMotorizedLinearPoti.FUNCTION_GET_STATUS_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getChipTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature as measured inside the microcontroller. The
		value returned is not the ambient temperature!
		
		The temperature is only proportional to the real temperature and it has bad
		accuracy. Practically it is only useful as an indicator for
		temperature changes.
		*/
		this.ipcon.sendRequest(this, BrickletMotorizedLinearPoti.FUNCTION_GET_CHIP_TEMPERATURE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.reset = function(returnCallback, errorCallback) {
		/*
		Calling this function will reset the Bricklet. All configurations
		will be lost.
		
		After a reset you have to create new device objects,
		calling functions on the existing ones will result in
		undefined behavior!
		*/
		this.ipcon.sendRequest(this, BrickletMotorizedLinearPoti.FUNCTION_RESET, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeUID = function(uid, returnCallback, errorCallback) {
		/*
		Writes a new UID into flash. If you want to set a new UID
		you have to decode the Base58 encoded UID string into an
		integer first.
		
		We recommend that you use Brick Viewer to change the UID.
		*/
		this.ipcon.sendRequest(this, BrickletMotorizedLinearPoti.FUNCTION_WRITE_UID, [uid], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.readUID = function(returnCallback, errorCallback) {
		/*
		Returns the current UID as an integer. Encode as
		Base58 to get the usual string version.
		*/
		this.ipcon.sendRequest(this, BrickletMotorizedLinearPoti.FUNCTION_READ_UID, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletMotorizedLinearPoti.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletMotorizedLinearPoti;

},{"./Device":279,"./IPConnection":280}],226:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletMultiTouch.DEVICE_IDENTIFIER = 234;
BrickletMultiTouch.DEVICE_DISPLAY_NAME = 'Multi Touch Bricklet';
BrickletMultiTouch.CALLBACK_TOUCH_STATE = 5;
BrickletMultiTouch.FUNCTION_GET_TOUCH_STATE = 1;
BrickletMultiTouch.FUNCTION_RECALIBRATE = 2;
BrickletMultiTouch.FUNCTION_SET_ELECTRODE_CONFIG = 3;
BrickletMultiTouch.FUNCTION_GET_ELECTRODE_CONFIG = 4;
BrickletMultiTouch.FUNCTION_SET_ELECTRODE_SENSITIVITY = 6;
BrickletMultiTouch.FUNCTION_GET_ELECTRODE_SENSITIVITY = 7;
BrickletMultiTouch.FUNCTION_GET_IDENTITY = 255;

function BrickletMultiTouch(uid, ipcon) {
	//Capacitive touch sensor for 12 electrodes

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletMultiTouch.DEVICE_IDENTIFIER, BrickletMultiTouch.DEVICE_DISPLAY_NAME);
	BrickletMultiTouch.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickletMultiTouch.FUNCTION_GET_TOUCH_STATE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletMultiTouch.FUNCTION_RECALIBRATE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletMultiTouch.FUNCTION_SET_ELECTRODE_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletMultiTouch.FUNCTION_GET_ELECTRODE_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletMultiTouch.FUNCTION_SET_ELECTRODE_SENSITIVITY] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletMultiTouch.FUNCTION_GET_ELECTRODE_SENSITIVITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletMultiTouch.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletMultiTouch.CALLBACK_TOUCH_STATE] = [10, 'H'];



	this.getTouchState = function(returnCallback, errorCallback) {
		/*
		Returns the current touch state. The state is given as a bitfield.
		
		Bits 0 to 11 represent the 12 electrodes and bit 12 represents
		the proximity.
		
		If an electrode is touched, the corresponding bit is *true*. If
		a hand or similar is in proximity to the electrodes, bit 12 is
		*true*.
		
		Example: The state 4103 = 0x1007 = 0b1000000000111 means that
		electrodes 0, 1 and 2 are touched and that something is in the
		proximity of the electrodes.
		
		The proximity is activated with a distance of 1-2cm. An electrode
		is already counted as touched if a finger is nearly touching the
		electrode. This means that you can put a piece of paper or foil
		or similar on top of a electrode to build a touch panel with
		a professional look.
		*/
		this.ipcon.sendRequest(this, BrickletMultiTouch.FUNCTION_GET_TOUCH_STATE, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.recalibrate = function(returnCallback, errorCallback) {
		/*
		Recalibrates the electrodes. Call this function whenever you changed
		or moved you electrodes.
		*/
		this.ipcon.sendRequest(this, BrickletMultiTouch.FUNCTION_RECALIBRATE, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.setElectrodeConfig = function(enabledElectrodes, returnCallback, errorCallback) {
		/*
		Enables/disables electrodes with a bitfield (see :func:`Get Touch State`).
		
		*True* enables the electrode, *false* disables the electrode. A
		disabled electrode will always return *false* as its state. If you
		don't need all electrodes you can disable the electrodes that are
		not needed.
		
		It is recommended that you disable the proximity bit (bit 12) if
		the proximity feature is not needed. This will reduce the amount of
		traffic that is produced by the :cb:`Touch State` callback.
		
		Disabling electrodes will also reduce power consumption.
		
		Default: 8191 = 0x1FFF = 0b1111111111111 (all electrodes and proximity feature enabled)
		*/
		this.ipcon.sendRequest(this, BrickletMultiTouch.FUNCTION_SET_ELECTRODE_CONFIG, [enabledElectrodes], 'H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getElectrodeConfig = function(returnCallback, errorCallback) {
		/*
		Returns the electrode configuration, as set by :func:`Set Electrode Config`.
		*/
		this.ipcon.sendRequest(this, BrickletMultiTouch.FUNCTION_GET_ELECTRODE_CONFIG, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.setElectrodeSensitivity = function(sensitivity, returnCallback, errorCallback) {
		/*
		Sets the sensitivity of the electrodes. An electrode with a high sensitivity
		will register a touch earlier then an electrode with a low sensitivity.
		
		If you build a big electrode you might need to decrease the sensitivity, since
		the area that can be charged will get bigger. If you want to be able to
		activate an electrode from further away you need to increase the sensitivity.
		
		After a new sensitivity is set, you likely want to call :func:`Recalibrate`
		to calibrate the electrodes with the newly defined sensitivity.
		*/
		this.ipcon.sendRequest(this, BrickletMultiTouch.FUNCTION_SET_ELECTRODE_SENSITIVITY, [sensitivity], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getElectrodeSensitivity = function(returnCallback, errorCallback) {
		/*
		Returns the current sensitivity, as set by :func:`Set Electrode Sensitivity`.
		*/
		this.ipcon.sendRequest(this, BrickletMultiTouch.FUNCTION_GET_ELECTRODE_SENSITIVITY, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletMultiTouch.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletMultiTouch;

},{"./Device":279,"./IPConnection":280}],227:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletMultiTouchV2.DEVICE_IDENTIFIER = 2129;
BrickletMultiTouchV2.DEVICE_DISPLAY_NAME = 'Multi Touch Bricklet 2.0';
BrickletMultiTouchV2.CALLBACK_TOUCH_STATE = 4;
BrickletMultiTouchV2.FUNCTION_GET_TOUCH_STATE = 1;
BrickletMultiTouchV2.FUNCTION_SET_TOUCH_STATE_CALLBACK_CONFIGURATION = 2;
BrickletMultiTouchV2.FUNCTION_GET_TOUCH_STATE_CALLBACK_CONFIGURATION = 3;
BrickletMultiTouchV2.FUNCTION_RECALIBRATE = 5;
BrickletMultiTouchV2.FUNCTION_SET_ELECTRODE_CONFIG = 6;
BrickletMultiTouchV2.FUNCTION_GET_ELECTRODE_CONFIG = 7;
BrickletMultiTouchV2.FUNCTION_SET_ELECTRODE_SENSITIVITY = 8;
BrickletMultiTouchV2.FUNCTION_GET_ELECTRODE_SENSITIVITY = 9;
BrickletMultiTouchV2.FUNCTION_SET_TOUCH_LED_CONFIG = 10;
BrickletMultiTouchV2.FUNCTION_GET_TOUCH_LED_CONFIG = 11;
BrickletMultiTouchV2.FUNCTION_GET_SPITFP_ERROR_COUNT = 234;
BrickletMultiTouchV2.FUNCTION_SET_BOOTLOADER_MODE = 235;
BrickletMultiTouchV2.FUNCTION_GET_BOOTLOADER_MODE = 236;
BrickletMultiTouchV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER = 237;
BrickletMultiTouchV2.FUNCTION_WRITE_FIRMWARE = 238;
BrickletMultiTouchV2.FUNCTION_SET_STATUS_LED_CONFIG = 239;
BrickletMultiTouchV2.FUNCTION_GET_STATUS_LED_CONFIG = 240;
BrickletMultiTouchV2.FUNCTION_GET_CHIP_TEMPERATURE = 242;
BrickletMultiTouchV2.FUNCTION_RESET = 243;
BrickletMultiTouchV2.FUNCTION_WRITE_UID = 248;
BrickletMultiTouchV2.FUNCTION_READ_UID = 249;
BrickletMultiTouchV2.FUNCTION_GET_IDENTITY = 255;
BrickletMultiTouchV2.TOUCH_LED_CONFIG_OFF = 0;
BrickletMultiTouchV2.TOUCH_LED_CONFIG_ON = 1;
BrickletMultiTouchV2.TOUCH_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletMultiTouchV2.TOUCH_LED_CONFIG_SHOW_TOUCH = 3;
BrickletMultiTouchV2.BOOTLOADER_MODE_BOOTLOADER = 0;
BrickletMultiTouchV2.BOOTLOADER_MODE_FIRMWARE = 1;
BrickletMultiTouchV2.BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT = 2;
BrickletMultiTouchV2.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT = 3;
BrickletMultiTouchV2.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT = 4;
BrickletMultiTouchV2.BOOTLOADER_STATUS_OK = 0;
BrickletMultiTouchV2.BOOTLOADER_STATUS_INVALID_MODE = 1;
BrickletMultiTouchV2.BOOTLOADER_STATUS_NO_CHANGE = 2;
BrickletMultiTouchV2.BOOTLOADER_STATUS_ENTRY_FUNCTION_NOT_PRESENT = 3;
BrickletMultiTouchV2.BOOTLOADER_STATUS_DEVICE_IDENTIFIER_INCORRECT = 4;
BrickletMultiTouchV2.BOOTLOADER_STATUS_CRC_MISMATCH = 5;
BrickletMultiTouchV2.STATUS_LED_CONFIG_OFF = 0;
BrickletMultiTouchV2.STATUS_LED_CONFIG_ON = 1;
BrickletMultiTouchV2.STATUS_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletMultiTouchV2.STATUS_LED_CONFIG_SHOW_STATUS = 3;

function BrickletMultiTouchV2(uid, ipcon) {
	//Capacitive touch sensor for 12 electrodes

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletMultiTouchV2.DEVICE_IDENTIFIER, BrickletMultiTouchV2.DEVICE_DISPLAY_NAME);
	BrickletMultiTouchV2.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickletMultiTouchV2.FUNCTION_GET_TOUCH_STATE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletMultiTouchV2.FUNCTION_SET_TOUCH_STATE_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletMultiTouchV2.FUNCTION_GET_TOUCH_STATE_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletMultiTouchV2.FUNCTION_RECALIBRATE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletMultiTouchV2.FUNCTION_SET_ELECTRODE_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletMultiTouchV2.FUNCTION_GET_ELECTRODE_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletMultiTouchV2.FUNCTION_SET_ELECTRODE_SENSITIVITY] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletMultiTouchV2.FUNCTION_GET_ELECTRODE_SENSITIVITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletMultiTouchV2.FUNCTION_SET_TOUCH_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletMultiTouchV2.FUNCTION_GET_TOUCH_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletMultiTouchV2.FUNCTION_GET_SPITFP_ERROR_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletMultiTouchV2.FUNCTION_SET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletMultiTouchV2.FUNCTION_GET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletMultiTouchV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletMultiTouchV2.FUNCTION_WRITE_FIRMWARE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletMultiTouchV2.FUNCTION_SET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletMultiTouchV2.FUNCTION_GET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletMultiTouchV2.FUNCTION_GET_CHIP_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletMultiTouchV2.FUNCTION_RESET] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletMultiTouchV2.FUNCTION_WRITE_UID] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletMultiTouchV2.FUNCTION_READ_UID] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletMultiTouchV2.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletMultiTouchV2.CALLBACK_TOUCH_STATE] = [10, '?13'];



	this.getTouchState = function(returnCallback, errorCallback) {
		/*
		Returns the current touch state. The state is given as a array of
		bools.
		
		Element 0 to 11 represent the 12 electrodes and element 12 represents
		the proximity.
		
		If an electrode is touched, the corresponding element is *true*. If
		a hand or similar is in proximity to the electrodes, element 12 is
		*true*.
		
		The proximity is activated with a distance of 1-2cm. An electrode
		is already counted as touched if a finger is nearly touching the
		electrode. This means that you can put a piece of paper or foil
		or similar on top of a electrode to build a touch panel with
		a professional look.
		
		If you want to get the value periodically, it is recommended to use the
		:cb:`Touch State` callback. You can set the callback configuration
		with :func:`Set Touch State Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletMultiTouchV2.FUNCTION_GET_TOUCH_STATE, [], '', 10, '?13', returnCallback, errorCallback, false, true);
	};
	this.setTouchStateCallbackConfiguration = function(period, valueHasToChange, returnCallback, errorCallback) {
		/*
		The period is the period with which the :cb:`Touch State` callback
		is triggered periodically. A value of 0 turns the callback off.
		
		If the `value has to change`-parameter is set to true, the callback is only
		triggered after the value has changed. If the value didn't change within the
		period, the callback is triggered immediately on change.
		
		If it is set to false, the callback is continuously triggered with the period,
		independent of the value.
		*/
		this.ipcon.sendRequest(this, BrickletMultiTouchV2.FUNCTION_SET_TOUCH_STATE_CALLBACK_CONFIGURATION, [period, valueHasToChange], 'I ?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getTouchStateCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the callback configuration as set by
		:func:`Set Touch State Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletMultiTouchV2.FUNCTION_GET_TOUCH_STATE_CALLBACK_CONFIGURATION, [], '', 13, 'I ?', returnCallback, errorCallback, false, true);
	};
	this.recalibrate = function(returnCallback, errorCallback) {
		/*
		Recalibrates the electrodes. Call this function whenever you changed
		or moved you electrodes.
		*/
		this.ipcon.sendRequest(this, BrickletMultiTouchV2.FUNCTION_RECALIBRATE, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.setElectrodeConfig = function(enabledElectrodes, returnCallback, errorCallback) {
		/*
		Enables/disables electrodes with a bool array (see :func:`Get Touch State`).
		
		*True* enables the electrode, *false* disables the electrode. A
		disabled electrode will always return *false* as its state. If you
		don't need all electrodes you can disable the electrodes that are
		not needed.
		
		It is recommended that you disable the proximity electrode (element 12) if
		the proximity feature is not needed. This will reduce the amount of
		traffic that is produced by the :cb:`Touch State` callback.
		
		Disabling electrodes will also reduce power consumption.
		*/
		this.ipcon.sendRequest(this, BrickletMultiTouchV2.FUNCTION_SET_ELECTRODE_CONFIG, [enabledElectrodes], '?13', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getElectrodeConfig = function(returnCallback, errorCallback) {
		/*
		Returns the electrode configuration, as set by :func:`Set Electrode Config`.
		*/
		this.ipcon.sendRequest(this, BrickletMultiTouchV2.FUNCTION_GET_ELECTRODE_CONFIG, [], '', 10, '?13', returnCallback, errorCallback, false, true);
	};
	this.setElectrodeSensitivity = function(sensitivity, returnCallback, errorCallback) {
		/*
		Sets the sensitivity of the electrodes. An electrode with a high sensitivity
		will register a touch earlier then an electrode with a low sensitivity.
		
		If you build a big electrode you might need to decrease the sensitivity, since
		the area that can be charged will get bigger. If you want to be able to
		activate an electrode from further away you need to increase the sensitivity.
		
		After a new sensitivity is set, you likely want to call :func:`Recalibrate`
		to calibrate the electrodes with the newly defined sensitivity.
		*/
		this.ipcon.sendRequest(this, BrickletMultiTouchV2.FUNCTION_SET_ELECTRODE_SENSITIVITY, [sensitivity], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getElectrodeSensitivity = function(returnCallback, errorCallback) {
		/*
		Returns the current sensitivity, as set by :func:`Set Electrode Sensitivity`.
		*/
		this.ipcon.sendRequest(this, BrickletMultiTouchV2.FUNCTION_GET_ELECTRODE_SENSITIVITY, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setTouchLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Configures the touch LED to be either turned off, turned on, blink in
		heartbeat mode or show the touch state (electrode touched = LED on).
		*/
		this.ipcon.sendRequest(this, BrickletMultiTouchV2.FUNCTION_SET_TOUCH_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getTouchLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the LED configuration as set by :func:`Set Touch LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletMultiTouchV2.FUNCTION_GET_TOUCH_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPErrorCount = function(returnCallback, errorCallback) {
		/*
		Returns the error count for the communication between Brick and Bricklet.
		
		The errors are divided into
		
		* ACK checksum errors,
		* message checksum errors,
		* framing errors and
		* overflow errors.
		
		The errors counts are for errors that occur on the Bricklet side. All
		Bricks have a similar function that returns the errors on the Brick side.
		*/
		this.ipcon.sendRequest(this, BrickletMultiTouchV2.FUNCTION_GET_SPITFP_ERROR_COUNT, [], '', 24, 'I I I I', returnCallback, errorCallback, false, true);
	};
	this.setBootloaderMode = function(mode, returnCallback, errorCallback) {
		/*
		Sets the bootloader mode and returns the status after the requested
		mode change was instigated.
		
		You can change from bootloader mode to firmware mode and vice versa. A change
		from bootloader mode to firmware mode will only take place if the entry function,
		device identifier and CRC are present and correct.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletMultiTouchV2.FUNCTION_SET_BOOTLOADER_MODE, [mode], 'B', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getBootloaderMode = function(returnCallback, errorCallback) {
		/*
		Returns the current bootloader mode, see :func:`Set Bootloader Mode`.
		*/
		this.ipcon.sendRequest(this, BrickletMultiTouchV2.FUNCTION_GET_BOOTLOADER_MODE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setWriteFirmwarePointer = function(pointer, returnCallback, errorCallback) {
		/*
		Sets the firmware pointer for :func:`Write Firmware`. The pointer has
		to be increased by chunks of size 64. The data is written to flash
		every 4 chunks (which equals to one page of size 256).
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletMultiTouchV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER, [pointer], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeFirmware = function(data, returnCallback, errorCallback) {
		/*
		Writes 64 Bytes of firmware at the position as written by
		:func:`Set Write Firmware Pointer` before. The firmware is written
		to flash every 4 chunks.
		
		You can only write firmware in bootloader mode.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletMultiTouchV2.FUNCTION_WRITE_FIRMWARE, [data], 'B64', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setStatusLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Sets the status LED configuration. By default the LED shows
		communication traffic between Brick and Bricklet, it flickers once
		for every 10 received data packets.
		
		You can also turn the LED permanently on/off or show a heartbeat.
		
		If the Bricklet is in bootloader mode, the LED is will show heartbeat by default.
		*/
		this.ipcon.sendRequest(this, BrickletMultiTouchV2.FUNCTION_SET_STATUS_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getStatusLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Status LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletMultiTouchV2.FUNCTION_GET_STATUS_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getChipTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature as measured inside the microcontroller. The
		value returned is not the ambient temperature!
		
		The temperature is only proportional to the real temperature and it has bad
		accuracy. Practically it is only useful as an indicator for
		temperature changes.
		*/
		this.ipcon.sendRequest(this, BrickletMultiTouchV2.FUNCTION_GET_CHIP_TEMPERATURE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.reset = function(returnCallback, errorCallback) {
		/*
		Calling this function will reset the Bricklet. All configurations
		will be lost.
		
		After a reset you have to create new device objects,
		calling functions on the existing ones will result in
		undefined behavior!
		*/
		this.ipcon.sendRequest(this, BrickletMultiTouchV2.FUNCTION_RESET, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeUID = function(uid, returnCallback, errorCallback) {
		/*
		Writes a new UID into flash. If you want to set a new UID
		you have to decode the Base58 encoded UID string into an
		integer first.
		
		We recommend that you use Brick Viewer to change the UID.
		*/
		this.ipcon.sendRequest(this, BrickletMultiTouchV2.FUNCTION_WRITE_UID, [uid], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.readUID = function(returnCallback, errorCallback) {
		/*
		Returns the current UID as an integer. Encode as
		Base58 to get the usual string version.
		*/
		this.ipcon.sendRequest(this, BrickletMultiTouchV2.FUNCTION_READ_UID, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletMultiTouchV2.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletMultiTouchV2;

},{"./Device":279,"./IPConnection":280}],228:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletNFC.DEVICE_IDENTIFIER = 286;
BrickletNFC.DEVICE_DISPLAY_NAME = 'NFC Bricklet';
BrickletNFC.CALLBACK_READER_STATE_CHANGED = 13;
BrickletNFC.CALLBACK_CARDEMU_STATE_CHANGED = 18;
BrickletNFC.CALLBACK_P2P_STATE_CHANGED = 24;
BrickletNFC.FUNCTION_SET_MODE = 1;
BrickletNFC.FUNCTION_GET_MODE = 2;
BrickletNFC.FUNCTION_READER_REQUEST_TAG_ID = 3;
BrickletNFC.FUNCTION_READER_GET_TAG_ID_LOW_LEVEL = 4;
BrickletNFC.FUNCTION_READER_GET_STATE = 5;
BrickletNFC.FUNCTION_READER_WRITE_NDEF_LOW_LEVEL = 6;
BrickletNFC.FUNCTION_READER_REQUEST_NDEF = 7;
BrickletNFC.FUNCTION_READER_READ_NDEF_LOW_LEVEL = 8;
BrickletNFC.FUNCTION_READER_AUTHENTICATE_MIFARE_CLASSIC_PAGE = 9;
BrickletNFC.FUNCTION_READER_WRITE_PAGE_LOW_LEVEL = 10;
BrickletNFC.FUNCTION_READER_REQUEST_PAGE = 11;
BrickletNFC.FUNCTION_READER_READ_PAGE_LOW_LEVEL = 12;
BrickletNFC.FUNCTION_CARDEMU_GET_STATE = 14;
BrickletNFC.FUNCTION_CARDEMU_START_DISCOVERY = 15;
BrickletNFC.FUNCTION_CARDEMU_WRITE_NDEF_LOW_LEVEL = 16;
BrickletNFC.FUNCTION_CARDEMU_START_TRANSFER = 17;
BrickletNFC.FUNCTION_P2P_GET_STATE = 19;
BrickletNFC.FUNCTION_P2P_START_DISCOVERY = 20;
BrickletNFC.FUNCTION_P2P_WRITE_NDEF_LOW_LEVEL = 21;
BrickletNFC.FUNCTION_P2P_START_TRANSFER = 22;
BrickletNFC.FUNCTION_P2P_READ_NDEF_LOW_LEVEL = 23;
BrickletNFC.FUNCTION_SET_DETECTION_LED_CONFIG = 25;
BrickletNFC.FUNCTION_GET_DETECTION_LED_CONFIG = 26;
BrickletNFC.FUNCTION_SET_MAXIMUM_TIMEOUT = 27;
BrickletNFC.FUNCTION_GET_MAXIMUM_TIMEOUT = 28;
BrickletNFC.FUNCTION_GET_SPITFP_ERROR_COUNT = 234;
BrickletNFC.FUNCTION_SET_BOOTLOADER_MODE = 235;
BrickletNFC.FUNCTION_GET_BOOTLOADER_MODE = 236;
BrickletNFC.FUNCTION_SET_WRITE_FIRMWARE_POINTER = 237;
BrickletNFC.FUNCTION_WRITE_FIRMWARE = 238;
BrickletNFC.FUNCTION_SET_STATUS_LED_CONFIG = 239;
BrickletNFC.FUNCTION_GET_STATUS_LED_CONFIG = 240;
BrickletNFC.FUNCTION_GET_CHIP_TEMPERATURE = 242;
BrickletNFC.FUNCTION_RESET = 243;
BrickletNFC.FUNCTION_WRITE_UID = 248;
BrickletNFC.FUNCTION_READ_UID = 249;
BrickletNFC.FUNCTION_GET_IDENTITY = 255;
BrickletNFC.MODE_OFF = 0;
BrickletNFC.MODE_CARDEMU = 1;
BrickletNFC.MODE_P2P = 2;
BrickletNFC.MODE_READER = 3;
BrickletNFC.TAG_TYPE_MIFARE_CLASSIC = 0;
BrickletNFC.TAG_TYPE_TYPE1 = 1;
BrickletNFC.TAG_TYPE_TYPE2 = 2;
BrickletNFC.TAG_TYPE_TYPE3 = 3;
BrickletNFC.TAG_TYPE_TYPE4 = 4;
BrickletNFC.READER_STATE_INITIALIZATION = 0;
BrickletNFC.READER_STATE_IDLE = 128;
BrickletNFC.READER_STATE_ERROR = 192;
BrickletNFC.READER_STATE_REQUEST_TAG_ID = 2;
BrickletNFC.READER_STATE_REQUEST_TAG_ID_READY = 130;
BrickletNFC.READER_STATE_REQUEST_TAG_ID_ERROR = 194;
BrickletNFC.READER_STATE_AUTHENTICATE_MIFARE_CLASSIC_PAGE = 3;
BrickletNFC.READER_STATE_AUTHENTICATE_MIFARE_CLASSIC_PAGE_READY = 131;
BrickletNFC.READER_STATE_AUTHENTICATE_MIFARE_CLASSIC_PAGE_ERROR = 195;
BrickletNFC.READER_STATE_WRITE_PAGE = 4;
BrickletNFC.READER_STATE_WRITE_PAGE_READY = 132;
BrickletNFC.READER_STATE_WRITE_PAGE_ERROR = 196;
BrickletNFC.READER_STATE_REQUEST_PAGE = 5;
BrickletNFC.READER_STATE_REQUEST_PAGE_READY = 133;
BrickletNFC.READER_STATE_REQUEST_PAGE_ERROR = 197;
BrickletNFC.READER_STATE_WRITE_NDEF = 6;
BrickletNFC.READER_STATE_WRITE_NDEF_READY = 134;
BrickletNFC.READER_STATE_WRITE_NDEF_ERROR = 198;
BrickletNFC.READER_STATE_REQUEST_NDEF = 7;
BrickletNFC.READER_STATE_REQUEST_NDEF_READY = 135;
BrickletNFC.READER_STATE_REQUEST_NDEF_ERROR = 199;
BrickletNFC.KEY_A = 0;
BrickletNFC.KEY_B = 1;
BrickletNFC.READER_WRITE_TYPE4_CAPABILITY_CONTAINER = 3;
BrickletNFC.READER_WRITE_TYPE4_NDEF = 4;
BrickletNFC.READER_REQUEST_TYPE4_CAPABILITY_CONTAINER = 3;
BrickletNFC.READER_REQUEST_TYPE4_NDEF = 4;
BrickletNFC.CARDEMU_STATE_INITIALIZATION = 0;
BrickletNFC.CARDEMU_STATE_IDLE = 128;
BrickletNFC.CARDEMU_STATE_ERROR = 192;
BrickletNFC.CARDEMU_STATE_DISCOVER = 2;
BrickletNFC.CARDEMU_STATE_DISCOVER_READY = 130;
BrickletNFC.CARDEMU_STATE_DISCOVER_ERROR = 194;
BrickletNFC.CARDEMU_STATE_TRANSFER_NDEF = 3;
BrickletNFC.CARDEMU_STATE_TRANSFER_NDEF_READY = 131;
BrickletNFC.CARDEMU_STATE_TRANSFER_NDEF_ERROR = 195;
BrickletNFC.CARDEMU_TRANSFER_ABORT = 0;
BrickletNFC.CARDEMU_TRANSFER_WRITE = 1;
BrickletNFC.P2P_STATE_INITIALIZATION = 0;
BrickletNFC.P2P_STATE_IDLE = 128;
BrickletNFC.P2P_STATE_ERROR = 192;
BrickletNFC.P2P_STATE_DISCOVER = 2;
BrickletNFC.P2P_STATE_DISCOVER_READY = 130;
BrickletNFC.P2P_STATE_DISCOVER_ERROR = 194;
BrickletNFC.P2P_STATE_TRANSFER_NDEF = 3;
BrickletNFC.P2P_STATE_TRANSFER_NDEF_READY = 131;
BrickletNFC.P2P_STATE_TRANSFER_NDEF_ERROR = 195;
BrickletNFC.P2P_TRANSFER_ABORT = 0;
BrickletNFC.P2P_TRANSFER_WRITE = 1;
BrickletNFC.P2P_TRANSFER_READ = 2;
BrickletNFC.DETECTION_LED_CONFIG_OFF = 0;
BrickletNFC.DETECTION_LED_CONFIG_ON = 1;
BrickletNFC.DETECTION_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletNFC.DETECTION_LED_CONFIG_SHOW_DETECTION = 3;
BrickletNFC.BOOTLOADER_MODE_BOOTLOADER = 0;
BrickletNFC.BOOTLOADER_MODE_FIRMWARE = 1;
BrickletNFC.BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT = 2;
BrickletNFC.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT = 3;
BrickletNFC.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT = 4;
BrickletNFC.BOOTLOADER_STATUS_OK = 0;
BrickletNFC.BOOTLOADER_STATUS_INVALID_MODE = 1;
BrickletNFC.BOOTLOADER_STATUS_NO_CHANGE = 2;
BrickletNFC.BOOTLOADER_STATUS_ENTRY_FUNCTION_NOT_PRESENT = 3;
BrickletNFC.BOOTLOADER_STATUS_DEVICE_IDENTIFIER_INCORRECT = 4;
BrickletNFC.BOOTLOADER_STATUS_CRC_MISMATCH = 5;
BrickletNFC.STATUS_LED_CONFIG_OFF = 0;
BrickletNFC.STATUS_LED_CONFIG_ON = 1;
BrickletNFC.STATUS_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletNFC.STATUS_LED_CONFIG_SHOW_STATUS = 3;

function BrickletNFC(uid, ipcon) {
	//NFC tag read/write, NFC P2P and Card Emulation

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletNFC.DEVICE_IDENTIFIER, BrickletNFC.DEVICE_DISPLAY_NAME);
	BrickletNFC.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 1];
	this.responseExpected[BrickletNFC.FUNCTION_SET_MODE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletNFC.FUNCTION_GET_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletNFC.FUNCTION_READER_REQUEST_TAG_ID] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletNFC.FUNCTION_READER_GET_TAG_ID_LOW_LEVEL] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletNFC.FUNCTION_READER_GET_STATE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletNFC.FUNCTION_READER_WRITE_NDEF_LOW_LEVEL] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletNFC.FUNCTION_READER_REQUEST_NDEF] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletNFC.FUNCTION_READER_READ_NDEF_LOW_LEVEL] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletNFC.FUNCTION_READER_AUTHENTICATE_MIFARE_CLASSIC_PAGE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletNFC.FUNCTION_READER_WRITE_PAGE_LOW_LEVEL] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletNFC.FUNCTION_READER_REQUEST_PAGE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletNFC.FUNCTION_READER_READ_PAGE_LOW_LEVEL] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletNFC.FUNCTION_CARDEMU_GET_STATE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletNFC.FUNCTION_CARDEMU_START_DISCOVERY] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletNFC.FUNCTION_CARDEMU_WRITE_NDEF_LOW_LEVEL] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletNFC.FUNCTION_CARDEMU_START_TRANSFER] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletNFC.FUNCTION_P2P_GET_STATE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletNFC.FUNCTION_P2P_START_DISCOVERY] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletNFC.FUNCTION_P2P_WRITE_NDEF_LOW_LEVEL] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletNFC.FUNCTION_P2P_START_TRANSFER] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletNFC.FUNCTION_P2P_READ_NDEF_LOW_LEVEL] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletNFC.FUNCTION_SET_DETECTION_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletNFC.FUNCTION_GET_DETECTION_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletNFC.FUNCTION_SET_MAXIMUM_TIMEOUT] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletNFC.FUNCTION_GET_MAXIMUM_TIMEOUT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletNFC.FUNCTION_GET_SPITFP_ERROR_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletNFC.FUNCTION_SET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletNFC.FUNCTION_GET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletNFC.FUNCTION_SET_WRITE_FIRMWARE_POINTER] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletNFC.FUNCTION_WRITE_FIRMWARE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletNFC.FUNCTION_SET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletNFC.FUNCTION_GET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletNFC.FUNCTION_GET_CHIP_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletNFC.FUNCTION_RESET] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletNFC.FUNCTION_WRITE_UID] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletNFC.FUNCTION_READ_UID] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletNFC.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletNFC.CALLBACK_READER_STATE_CHANGED] = [10, 'B ?'];
	this.callbackFormats[BrickletNFC.CALLBACK_CARDEMU_STATE_CHANGED] = [10, 'B ?'];
	this.callbackFormats[BrickletNFC.CALLBACK_P2P_STATE_CHANGED] = [10, 'B ?'];


	this.streamStateObjects[BrickletNFC.FUNCTION_READER_GET_TAG_ID_LOW_LEVEL] = {
		'dataMapping': [null, 'streamLength', 'streamChunkData'],
		'dataMappingStreamIn': [],
		'streamProperties': {
			'fixedLength': null,
			'singleChunk': true,
			'shortWrite': false
		},
		'responseProperties': {
			'running': false,
			'runningSubcall': false,
			'runningSubcallOOS': false,
			'waitingFirstChunk': true,
			'timeout': null,
			'data': [],
			'streamInChunkOffset': 0,
			'streamInChunkLength': 0,
			'streamInResponseEmpty': true,
			'streamInWritten': 0,
			'streamInLLParams': null,
			'responseHandler': null,
			'packFormatString': '',
			'unpackFormatString': 'B B B32',
			'returnCB': null,
			'errorCB': null,
			'callQueue': []
		}
	};
	this.streamStateObjects[BrickletNFC.FUNCTION_READER_WRITE_NDEF_LOW_LEVEL] = {
		'dataMapping': [],
		'dataMappingStreamIn': ['streamLength', 'streamChunkOffset', 'streamChunkData'],
		'streamProperties': {
			'fixedLength': null,
			'singleChunk': false,
			'shortWrite': false
		},
		'responseProperties': {
			'running': false,
			'runningSubcall': false,
			'runningSubcallOOS': false,
			'waitingFirstChunk': true,
			'timeout': null,
			'data': [],
			'streamInChunkOffset': 0,
			'streamInChunkLength': 0,
			'streamInResponseEmpty': true,
			'streamInWritten': 0,
			'streamInLLParams': null,
			'responseHandler': null,
			'packFormatString': 'H H B60',
			'unpackFormatString': '',
			'returnCB': null,
			'errorCB': null,
			'callQueue': []
		}
	};
	this.streamStateObjects[BrickletNFC.FUNCTION_READER_READ_NDEF_LOW_LEVEL] = {
		'dataMapping': ['streamLength', 'streamChunkOffset', 'streamChunkData'],
		'dataMappingStreamIn': [],
		'streamProperties': {
			'fixedLength': null,
			'singleChunk': false,
			'shortWrite': false
		},
		'responseProperties': {
			'running': false,
			'runningSubcall': false,
			'runningSubcallOOS': false,
			'waitingFirstChunk': true,
			'timeout': null,
			'data': [],
			'streamInChunkOffset': 0,
			'streamInChunkLength': 0,
			'streamInResponseEmpty': true,
			'streamInWritten': 0,
			'streamInLLParams': null,
			'responseHandler': null,
			'packFormatString': '',
			'unpackFormatString': 'H H B60',
			'returnCB': null,
			'errorCB': null,
			'callQueue': []
		}
	};
	this.streamStateObjects[BrickletNFC.FUNCTION_READER_WRITE_PAGE_LOW_LEVEL] = {
		'dataMapping': [],
		'dataMappingStreamIn': [null, 'streamLength', 'streamChunkOffset', 'streamChunkData'],
		'streamProperties': {
			'fixedLength': null,
			'singleChunk': false,
			'shortWrite': false
		},
		'responseProperties': {
			'running': false,
			'runningSubcall': false,
			'runningSubcallOOS': false,
			'waitingFirstChunk': true,
			'timeout': null,
			'data': [],
			'streamInChunkOffset': 0,
			'streamInChunkLength': 0,
			'streamInResponseEmpty': true,
			'streamInWritten': 0,
			'streamInLLParams': null,
			'responseHandler': null,
			'packFormatString': 'H H H B58',
			'unpackFormatString': '',
			'returnCB': null,
			'errorCB': null,
			'callQueue': []
		}
	};
	this.streamStateObjects[BrickletNFC.FUNCTION_READER_READ_PAGE_LOW_LEVEL] = {
		'dataMapping': ['streamLength', 'streamChunkOffset', 'streamChunkData'],
		'dataMappingStreamIn': [],
		'streamProperties': {
			'fixedLength': null,
			'singleChunk': false,
			'shortWrite': false
		},
		'responseProperties': {
			'running': false,
			'runningSubcall': false,
			'runningSubcallOOS': false,
			'waitingFirstChunk': true,
			'timeout': null,
			'data': [],
			'streamInChunkOffset': 0,
			'streamInChunkLength': 0,
			'streamInResponseEmpty': true,
			'streamInWritten': 0,
			'streamInLLParams': null,
			'responseHandler': null,
			'packFormatString': '',
			'unpackFormatString': 'H H B60',
			'returnCB': null,
			'errorCB': null,
			'callQueue': []
		}
	};
	this.streamStateObjects[BrickletNFC.FUNCTION_CARDEMU_WRITE_NDEF_LOW_LEVEL] = {
		'dataMapping': [],
		'dataMappingStreamIn': ['streamLength', 'streamChunkOffset', 'streamChunkData'],
		'streamProperties': {
			'fixedLength': null,
			'singleChunk': false,
			'shortWrite': false
		},
		'responseProperties': {
			'running': false,
			'runningSubcall': false,
			'runningSubcallOOS': false,
			'waitingFirstChunk': true,
			'timeout': null,
			'data': [],
			'streamInChunkOffset': 0,
			'streamInChunkLength': 0,
			'streamInResponseEmpty': true,
			'streamInWritten': 0,
			'streamInLLParams': null,
			'responseHandler': null,
			'packFormatString': 'H H B60',
			'unpackFormatString': '',
			'returnCB': null,
			'errorCB': null,
			'callQueue': []
		}
	};
	this.streamStateObjects[BrickletNFC.FUNCTION_P2P_WRITE_NDEF_LOW_LEVEL] = {
		'dataMapping': [],
		'dataMappingStreamIn': ['streamLength', 'streamChunkOffset', 'streamChunkData'],
		'streamProperties': {
			'fixedLength': null,
			'singleChunk': false,
			'shortWrite': false
		},
		'responseProperties': {
			'running': false,
			'runningSubcall': false,
			'runningSubcallOOS': false,
			'waitingFirstChunk': true,
			'timeout': null,
			'data': [],
			'streamInChunkOffset': 0,
			'streamInChunkLength': 0,
			'streamInResponseEmpty': true,
			'streamInWritten': 0,
			'streamInLLParams': null,
			'responseHandler': null,
			'packFormatString': 'H H B60',
			'unpackFormatString': '',
			'returnCB': null,
			'errorCB': null,
			'callQueue': []
		}
	};
	this.streamStateObjects[BrickletNFC.FUNCTION_P2P_READ_NDEF_LOW_LEVEL] = {
		'dataMapping': ['streamLength', 'streamChunkOffset', 'streamChunkData'],
		'dataMappingStreamIn': [],
		'streamProperties': {
			'fixedLength': null,
			'singleChunk': false,
			'shortWrite': false
		},
		'responseProperties': {
			'running': false,
			'runningSubcall': false,
			'runningSubcallOOS': false,
			'waitingFirstChunk': true,
			'timeout': null,
			'data': [],
			'streamInChunkOffset': 0,
			'streamInChunkLength': 0,
			'streamInResponseEmpty': true,
			'streamInWritten': 0,
			'streamInLLParams': null,
			'responseHandler': null,
			'packFormatString': '',
			'unpackFormatString': 'H H B60',
			'returnCB': null,
			'errorCB': null,
			'callQueue': []
		}
	};

	this.setMode = function(mode, returnCallback, errorCallback) {
		/*
		Sets the mode. The NFC Bricklet supports four modes:
		
		* Off
		* Card Emulation (Cardemu): Emulates a tag for other readers
		* Peer to Peer (P2P): Exchange data with other readers
		* Reader: Reads and writes tags
		
		If you change a mode, the Bricklet will reconfigure the hardware for this mode.
		Therefore, you can only use functions corresponding to the current mode. For
		example, in Reader mode you can only use Reader functions.
		*/
		this.ipcon.sendRequest(this, BrickletNFC.FUNCTION_SET_MODE, [mode], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getMode = function(returnCallback, errorCallback) {
		/*
		Returns the mode as set by :func:`Set Mode`.
		*/
		this.ipcon.sendRequest(this, BrickletNFC.FUNCTION_GET_MODE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.readerRequestTagID = function(returnCallback, errorCallback) {
		/*
		After you call :func:`Reader Request Tag ID` the NFC Bricklet will try to read
		the tag ID from the tag. After this process is done the state will change.
		You can either register the :cb:`Reader State Changed` callback or you can poll
		:func:`Reader Get State` to find out about the state change.
		
		If the state changes to *ReaderRequestTagIDError* it means that either there was
		no tag present or that the tag has an incompatible type. If the state
		changes to *ReaderRequestTagIDReady* it means that a compatible tag was found
		and that the tag ID has been saved. You can now read out the tag ID by
		calling :func:`Reader Get Tag ID`.
		
		If two tags are in the proximity of the NFC Bricklet, this
		function will cycle through the tags. To select a specific tag you have
		to call :func:`Reader Request Tag ID` until the correct tag ID is found.
		
		In case of any *ReaderError* state the selection is lost and you have to
		start again by calling :func:`Reader Request Tag ID`.
		*/
		this.ipcon.sendRequest(this, BrickletNFC.FUNCTION_READER_REQUEST_TAG_ID, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.readerGetTagIDLowLevel = function(returnCallback, errorCallback) {
		/*
		Returns the tag type and the tag ID. This function can only be called if the
		NFC Bricklet is currently in one of the *ReaderReady* states. The returned tag ID
		is the tag ID that was saved through the last call of :func:`Reader Request Tag ID`.
		
		To get the tag ID of a tag the approach is as follows:
		
		1. Call :func:`Reader Request Tag ID`
		2. Wait for state to change to *ReaderRequestTagIDReady* (see :func:`Reader Get State` or
		   :cb:`Reader State Changed` callback)
		3. Call :func:`Reader Get Tag ID`
		*/
		this.ipcon.sendRequest(this, BrickletNFC.FUNCTION_READER_GET_TAG_ID_LOW_LEVEL, [], '', 42, 'B B B32', returnCallback, errorCallback, false, true);
	};
	this.readerGetState = function(returnCallback, errorCallback) {
		/*
		Returns the current reader state of the NFC Bricklet.
		
		On startup the Bricklet will be in the *ReaderInitialization* state. The
		initialization will only take about 20ms. After that it changes to *ReaderIdle*.
		
		The Bricklet is also reinitialized if the mode is changed, see :func:`Set Mode`.
		
		The functions of this Bricklet can be called in the *ReaderIdle* state and all of
		the *ReaderReady* and *ReaderError* states.
		
		Example: If you call :func:`Reader Request Page`, the state will change to
		*ReaderRequestPage* until the reading of the page is finished. Then it will change
		to either *ReaderRequestPageReady* if it worked or to *ReaderRequestPageError* if it
		didn't. If the request worked you can get the page by calling :func:`Reader Read Page`.
		
		The same approach is used analogously for the other API functions.
		*/
		this.ipcon.sendRequest(this, BrickletNFC.FUNCTION_READER_GET_STATE, [], '', 10, 'B ?', returnCallback, errorCallback, false, true);
	};
	this.readerWriteNDEFLowLevel = function(ndefLength, ndefChunkOffset, ndefChunkData, returnCallback, errorCallback) {
		/*
		Writes NDEF formated data.
		
		This function currently supports NFC Forum Type 2 and 4.
		
		The general approach for writing a NDEF message is as follows:
		
		1. Call :func:`Reader Request Tag ID`
		2. Wait for state to change to *ReaderRequestTagIDReady* (see
		   :func:`Reader Get State` or :cb:`Reader State Changed` callback)
		3. If looking for a specific tag then call :func:`Reader Get Tag ID` and check
		   if the expected tag was found, if it was not found got back to step 1
		4. Call :func:`Reader Write NDEF` with the NDEF message that you want to write
		5. Wait for state to change to *ReaderWriteNDEFReady* (see :func:`Reader Get State`
		   or :cb:`Reader State Changed` callback)
		*/
		this.ipcon.sendRequest(this, BrickletNFC.FUNCTION_READER_WRITE_NDEF_LOW_LEVEL, [ndefLength, ndefChunkOffset, ndefChunkData], 'H H B60', 0, '', returnCallback, errorCallback, false, true);
	};
	this.readerRequestNDEF = function(returnCallback, errorCallback) {
		/*
		Reads NDEF formated data from a tag.
		
		This function currently supports NFC Forum Type 1, 2, 3 and 4.
		
		The general approach for reading a NDEF message is as follows:
		
		1. Call :func:`Reader Request Tag ID`
		2. Wait for state to change to *RequestTagIDReady* (see :func:`Reader Get State`
		   or :cb:`Reader State Changed` callback)
		3. If looking for a specific tag then call :func:`Reader Get Tag ID` and check if the
		   expected tag was found, if it was not found got back to step 1
		4. Call :func:`Reader Request NDEF`
		5. Wait for state to change to *ReaderRequestNDEFReady* (see :func:`Reader Get State`
		   or :cb:`Reader State Changed` callback)
		6. Call :func:`Reader Read NDEF` to retrieve the NDEF message from the buffer
		*/
		this.ipcon.sendRequest(this, BrickletNFC.FUNCTION_READER_REQUEST_NDEF, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.readerReadNDEFLowLevel = function(returnCallback, errorCallback) {
		/*
		Returns the NDEF data from an internal buffer. To fill the buffer
		with a NDEF message you have to call :func:`Reader Request NDEF` beforehand.
		*/
		this.ipcon.sendRequest(this, BrickletNFC.FUNCTION_READER_READ_NDEF_LOW_LEVEL, [], '', 72, 'H H B60', returnCallback, errorCallback, false, true);
	};
	this.readerAuthenticateMifareClassicPage = function(page, keyNumber, key, returnCallback, errorCallback) {
		/*
		Mifare Classic tags use authentication. If you want to read from or write to
		a Mifare Classic page you have to authenticate it beforehand.
		Each page can be authenticated with two keys: A (``key_number`` = 0) and B
		(``key_number`` = 1). A new Mifare Classic
		tag that has not yet been written to can be accessed with key A
		and the default key ``[0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]``.
		
		The approach to read or write a Mifare Classic page is as follows:
		
		1. Call :func:`Reader Request Tag ID`
		2. Wait for state to change to *ReaderRequestTagIDReady* (see :func:`Reader Get State`
		   or :cb:`Reader State Changed` callback)
		3. If looking for a specific tag then call :func:`Reader Get Tag ID` and check if the
		   expected tag was found, if it was not found got back to step 1
		4. Call :func:`Reader Authenticate Mifare Classic Page` with page and key for the page
		5. Wait for state to change to *ReaderAuthenticatingMifareClassicPageReady* (see
		   :func:`Reader Get State` or :cb:`Reader State Changed` callback)
		6. Call :func:`Reader Request Page` or :func:`Reader Write Page` to read/write page
		
		The authentication will always work for one whole sector (4 pages).
		*/
		this.ipcon.sendRequest(this, BrickletNFC.FUNCTION_READER_AUTHENTICATE_MIFARE_CLASSIC_PAGE, [page, keyNumber, key], 'H B B6', 0, '', returnCallback, errorCallback, false, true);
	};
	this.readerWritePageLowLevel = function(page, dataLength, dataChunkOffset, dataChunkData, returnCallback, errorCallback) {
		/*
		Writes a maximum of 8192 bytes starting from the given page. How many pages are written
		depends on the tag type. The page sizes are as follows:
		
		* Mifare Classic page size: 16 byte
		* NFC Forum Type 1 page size: 8 byte
		* NFC Forum Type 2 page size: 4 byte
		* NFC Forum Type 3 page size: 16 byte
		* NFC Forum Type 4: No pages, page = file selection (CC or NDEF, see below)
		
		The general approach for writing to a tag is as follows:
		
		1. Call :func:`Reader Request Tag ID`
		2. Wait for state to change to *ReaderRequestTagIDReady* (see :func:`Reader Get State` or
		   :cb:`Reader State Changed` callback)
		3. If looking for a specific tag then call :func:`Reader Get Tag ID` and check if the
		   expected tag was found, if it was not found got back to step 1
		4. Call :func:`Reader Write Page` with page number and data
		5. Wait for state to change to *ReaderWritePageReady* (see :func:`Reader Get State` or
		   :cb:`Reader State Changed` callback)
		
		If you use a Mifare Classic tag you have to authenticate a page before you
		can write to it. See :func:`Reader Authenticate Mifare Classic Page`.
		
		NFC Forum Type 4 tags are not organized into pages but different files. We currently
		support two files: Capability Container file (CC) and NDEF file.
		
		Choose CC by setting page to 3 or NDEF by setting page to 4.
		*/
		this.ipcon.sendRequest(this, BrickletNFC.FUNCTION_READER_WRITE_PAGE_LOW_LEVEL, [page, dataLength, dataChunkOffset, dataChunkData], 'H H H B58', 0, '', returnCallback, errorCallback, false, true);
	};
	this.readerRequestPage = function(page, length, returnCallback, errorCallback) {
		/*
		Reads a maximum of 8192 bytes starting from the given page and stores them into a buffer.
		The buffer can then be read out with :func:`Reader Read Page`.
		How many pages are read depends on the tag type. The page sizes are
		as follows:
		
		* Mifare Classic page size: 16 byte
		* NFC Forum Type 1 page size: 8 byte
		* NFC Forum Type 2 page size: 4 byte
		* NFC Forum Type 3 page size: 16 byte
		* NFC Forum Type 4: No pages, page = file selection (CC or NDEF, see below)
		
		The general approach for reading a tag is as follows:
		
		1. Call :func:`Reader Request Tag ID`
		2. Wait for state to change to *RequestTagIDReady* (see :func:`Reader Get State`
		   or :cb:`Reader State Changed` callback)
		3. If looking for a specific tag then call :func:`Reader Get Tag ID` and check if the
		   expected tag was found, if it was not found got back to step 1
		4. Call :func:`Reader Request Page` with page number
		5. Wait for state to change to *ReaderRequestPageReady* (see :func:`Reader Get State`
		   or :cb:`Reader State Changed` callback)
		6. Call :func:`Reader Read Page` to retrieve the page from the buffer
		
		If you use a Mifare Classic tag you have to authenticate a page before you
		can read it. See :func:`Reader Authenticate Mifare Classic Page`.
		
		NFC Forum Type 4 tags are not organized into pages but different files. We currently
		support two files: Capability Container file (CC) and NDEF file.
		
		Choose CC by setting page to 3 or NDEF by setting page to 4.
		*/
		this.ipcon.sendRequest(this, BrickletNFC.FUNCTION_READER_REQUEST_PAGE, [page, length], 'H H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.readerReadPageLowLevel = function(returnCallback, errorCallback) {
		/*
		Returns the page data from an internal buffer. To fill the buffer
		with specific pages you have to call :func:`Reader Request Page` beforehand.
		*/
		this.ipcon.sendRequest(this, BrickletNFC.FUNCTION_READER_READ_PAGE_LOW_LEVEL, [], '', 72, 'H H B60', returnCallback, errorCallback, false, true);
	};
	this.cardemuGetState = function(returnCallback, errorCallback) {
		/*
		Returns the current cardemu state of the NFC Bricklet.
		
		On startup the Bricklet will be in the *CardemuInitialization* state. The
		initialization will only take about 20ms. After that it changes to *CardemuIdle*.
		
		The Bricklet is also reinitialized if the mode is changed, see :func:`Set Mode`.
		
		The functions of this Bricklet can be called in the *CardemuIdle* state and all of
		the *CardemuReady* and *CardemuError* states.
		
		Example: If you call :func:`Cardemu Start Discovery`, the state will change to
		*CardemuDiscover* until the discovery is finished. Then it will change
		to either *CardemuDiscoverReady* if it worked or to *CardemuDiscoverError* if it
		didn't.
		
		The same approach is used analogously for the other API functions.
		*/
		this.ipcon.sendRequest(this, BrickletNFC.FUNCTION_CARDEMU_GET_STATE, [], '', 10, 'B ?', returnCallback, errorCallback, false, true);
	};
	this.cardemuStartDiscovery = function(returnCallback, errorCallback) {
		/*
		Starts the discovery process. If you call this function while a NFC
		reader device is near to the NFC Bricklet the state will change from
		*CardemuDiscovery* to *CardemuDiscoveryReady*.
		
		If no NFC reader device can be found or if there is an error during
		discovery the cardemu state will change to *CardemuDiscoveryError*. In this case you
		have to restart the discovery process.
		
		If the cardemu state changes to *CardemuDiscoveryReady* you can start the NDEF message
		transfer with :func:`Cardemu Write NDEF` and :func:`Cardemu Start Transfer`.
		*/
		this.ipcon.sendRequest(this, BrickletNFC.FUNCTION_CARDEMU_START_DISCOVERY, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.cardemuWriteNDEFLowLevel = function(ndefLength, ndefChunkOffset, ndefChunkData, returnCallback, errorCallback) {
		/*
		Writes the NDEF message that is to be transferred to the NFC peer.
		
		The maximum supported NDEF message size in Cardemu mode is 255 byte.
		
		You can call this function at any time in Cardemu mode. The internal buffer
		will not be overwritten until you call this function again or change the
		mode.
		*/
		this.ipcon.sendRequest(this, BrickletNFC.FUNCTION_CARDEMU_WRITE_NDEF_LOW_LEVEL, [ndefLength, ndefChunkOffset, ndefChunkData], 'H H B60', 0, '', returnCallback, errorCallback, false, true);
	};
	this.cardemuStartTransfer = function(transfer, returnCallback, errorCallback) {
		/*
		You can start the transfer of a NDEF message if the cardemu state is *CardemuDiscoveryReady*.
		
		Before you call this function to start a write transfer, the NDEF message that
		is to be transferred has to be written via :func:`Cardemu Write NDEF` first.
		
		After you call this function the state will change to *CardemuTransferNDEF*. It will
		change to *CardemuTransferNDEFReady* if the transfer was successful or
		*CardemuTransferNDEFError* if it wasn't.
		*/
		this.ipcon.sendRequest(this, BrickletNFC.FUNCTION_CARDEMU_START_TRANSFER, [transfer], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.p2pGetState = function(returnCallback, errorCallback) {
		/*
		Returns the current P2P state of the NFC Bricklet.
		
		On startup the Bricklet will be in the *P2PInitialization* state. The
		initialization will only take about 20ms. After that it changes to *P2PIdle*.
		
		The Bricklet is also reinitialized if the mode is changed, see :func:`Set Mode`.
		
		The functions of this Bricklet can be called in the *P2PIdle* state and all of
		the *P2PReady* and *P2PError* states.
		
		Example: If you call :func:`P2P Start Discovery`, the state will change to
		*P2PDiscover* until the discovery is finished. Then it will change
		to either P2PDiscoverReady* if it worked or to *P2PDiscoverError* if it
		didn't.
		
		The same approach is used analogously for the other API functions.
		*/
		this.ipcon.sendRequest(this, BrickletNFC.FUNCTION_P2P_GET_STATE, [], '', 10, 'B ?', returnCallback, errorCallback, false, true);
	};
	this.p2pStartDiscovery = function(returnCallback, errorCallback) {
		/*
		Starts the discovery process. If you call this function while another NFC
		P2P enabled device is near to the NFC Bricklet the state will change from
		*P2PDiscovery* to *P2PDiscoveryReady*.
		
		If no NFC P2P enabled device can be found or if there is an error during
		discovery the P2P state will change to *P2PDiscoveryError*. In this case you
		have to restart the discovery process.
		
		If the P2P state changes to *P2PDiscoveryReady* you can start the NDEF message
		transfer with :func:`P2P Start Transfer`.
		*/
		this.ipcon.sendRequest(this, BrickletNFC.FUNCTION_P2P_START_DISCOVERY, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.p2pWriteNDEFLowLevel = function(ndefLength, ndefChunkOffset, ndefChunkData, returnCallback, errorCallback) {
		/*
		Writes the NDEF message that is to be transferred to the NFC peer.
		
		The maximum supported NDEF message size for P2P transfer is 255 byte.
		
		You can call this function at any time in P2P mode. The internal buffer
		will not be overwritten until you call this function again, change the
		mode or use P2P to read an NDEF messages.
		*/
		this.ipcon.sendRequest(this, BrickletNFC.FUNCTION_P2P_WRITE_NDEF_LOW_LEVEL, [ndefLength, ndefChunkOffset, ndefChunkData], 'H H B60', 0, '', returnCallback, errorCallback, false, true);
	};
	this.p2pStartTransfer = function(transfer, returnCallback, errorCallback) {
		/*
		You can start the transfer of a NDEF message if the P2P state is *P2PDiscoveryReady*.
		
		Before you call this function to start a write transfer, the NDEF message that
		is to be transferred has to be written via :func:`P2P Write NDEF` first.
		
		After you call this function the P2P state will change to *P2PTransferNDEF*. It will
		change to *P2PTransferNDEFReady* if the transfer was successfull or
		*P2PTransferNDEFError* if it wasn't.
		
		If you started a write transfer you are now done. If you started a read transfer
		you can now use :func:`P2P Read NDEF` to read the NDEF message that was written
		by the NFC peer.
		*/
		this.ipcon.sendRequest(this, BrickletNFC.FUNCTION_P2P_START_TRANSFER, [transfer], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.p2pReadNDEFLowLevel = function(returnCallback, errorCallback) {
		/*
		Returns the NDEF message that was written by a NFC peer in NFC P2P mode.
		
		The NDEF message is ready if you called :func:`P2P Start Transfer` with a
		read transfer and the P2P state changed to *P2PTransferNDEFReady*.
		*/
		this.ipcon.sendRequest(this, BrickletNFC.FUNCTION_P2P_READ_NDEF_LOW_LEVEL, [], '', 72, 'H H B60', returnCallback, errorCallback, false, true);
	};
	this.setDetectionLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Sets the detection LED configuration. By default the LED shows
		if a card/reader is detected.
		
		You can also turn the LED permanently on/off or show a heartbeat.
		
		If the Bricklet is in bootloader mode, the LED is off.
		*/
		this.ipcon.sendRequest(this, BrickletNFC.FUNCTION_SET_DETECTION_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getDetectionLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Detection LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletNFC.FUNCTION_GET_DETECTION_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setMaximumTimeout = function(timeout, returnCallback, errorCallback) {
		/*
		Sets the maximum timeout.
		
		This is a global maximum used for all internal state timeouts. The timeouts depend heavily
		on the used tags etc. For example: If you use a Type 2 tag and you want to detect if
		it is present, you have to use :func:`Reader Request Tag ID` and wait for the state
		to change to either the error state or the ready state.
		
		With the default configuration this takes 2-3 seconds. By setting the maximum timeout to
		100ms you can reduce this time to ~150-200ms. For Type 2 this would also still work
		with a 20ms timeout (a Type 2 tag answers usually within 10ms). A type 4 tag can take
		up to 500ms in our tests.
		
		If you need a fast response time to discover if a tag is present or not you can find
		a good timeout value by trial and error for your specific tag.
		
		By default we use a very conservative timeout, to be sure that any tag can always
		answer in time.
		
		.. versionadded:: 2.0.1$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletNFC.FUNCTION_SET_MAXIMUM_TIMEOUT, [timeout], 'H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getMaximumTimeout = function(returnCallback, errorCallback) {
		/*
		Returns the timeout as set by :func:`Set Maximum Timeout`
		
		.. versionadded:: 2.0.1$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletNFC.FUNCTION_GET_MAXIMUM_TIMEOUT, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPErrorCount = function(returnCallback, errorCallback) {
		/*
		Returns the error count for the communication between Brick and Bricklet.
		
		The errors are divided into
		
		* ACK checksum errors,
		* message checksum errors,
		* framing errors and
		* overflow errors.
		
		The errors counts are for errors that occur on the Bricklet side. All
		Bricks have a similar function that returns the errors on the Brick side.
		*/
		this.ipcon.sendRequest(this, BrickletNFC.FUNCTION_GET_SPITFP_ERROR_COUNT, [], '', 24, 'I I I I', returnCallback, errorCallback, false, true);
	};
	this.setBootloaderMode = function(mode, returnCallback, errorCallback) {
		/*
		Sets the bootloader mode and returns the status after the requested
		mode change was instigated.
		
		You can change from bootloader mode to firmware mode and vice versa. A change
		from bootloader mode to firmware mode will only take place if the entry function,
		device identifier and CRC are present and correct.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletNFC.FUNCTION_SET_BOOTLOADER_MODE, [mode], 'B', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getBootloaderMode = function(returnCallback, errorCallback) {
		/*
		Returns the current bootloader mode, see :func:`Set Bootloader Mode`.
		*/
		this.ipcon.sendRequest(this, BrickletNFC.FUNCTION_GET_BOOTLOADER_MODE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setWriteFirmwarePointer = function(pointer, returnCallback, errorCallback) {
		/*
		Sets the firmware pointer for :func:`Write Firmware`. The pointer has
		to be increased by chunks of size 64. The data is written to flash
		every 4 chunks (which equals to one page of size 256).
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletNFC.FUNCTION_SET_WRITE_FIRMWARE_POINTER, [pointer], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeFirmware = function(data, returnCallback, errorCallback) {
		/*
		Writes 64 Bytes of firmware at the position as written by
		:func:`Set Write Firmware Pointer` before. The firmware is written
		to flash every 4 chunks.
		
		You can only write firmware in bootloader mode.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletNFC.FUNCTION_WRITE_FIRMWARE, [data], 'B64', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setStatusLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Sets the status LED configuration. By default the LED shows
		communication traffic between Brick and Bricklet, it flickers once
		for every 10 received data packets.
		
		You can also turn the LED permanently on/off or show a heartbeat.
		
		If the Bricklet is in bootloader mode, the LED is will show heartbeat by default.
		*/
		this.ipcon.sendRequest(this, BrickletNFC.FUNCTION_SET_STATUS_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getStatusLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Status LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletNFC.FUNCTION_GET_STATUS_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getChipTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature as measured inside the microcontroller. The
		value returned is not the ambient temperature!
		
		The temperature is only proportional to the real temperature and it has bad
		accuracy. Practically it is only useful as an indicator for
		temperature changes.
		*/
		this.ipcon.sendRequest(this, BrickletNFC.FUNCTION_GET_CHIP_TEMPERATURE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.reset = function(returnCallback, errorCallback) {
		/*
		Calling this function will reset the Bricklet. All configurations
		will be lost.
		
		After a reset you have to create new device objects,
		calling functions on the existing ones will result in
		undefined behavior!
		*/
		this.ipcon.sendRequest(this, BrickletNFC.FUNCTION_RESET, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeUID = function(uid, returnCallback, errorCallback) {
		/*
		Writes a new UID into flash. If you want to set a new UID
		you have to decode the Base58 encoded UID string into an
		integer first.
		
		We recommend that you use Brick Viewer to change the UID.
		*/
		this.ipcon.sendRequest(this, BrickletNFC.FUNCTION_WRITE_UID, [uid], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.readUID = function(returnCallback, errorCallback) {
		/*
		Returns the current UID as an integer. Encode as
		Base58 to get the usual string version.
		*/
		this.ipcon.sendRequest(this, BrickletNFC.FUNCTION_READ_UID, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletNFC.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.readerGetTagID = function(returnCallback, errorCallback) {
		/*
		Returns the tag type and the tag ID. This function can only be called if the
		NFC Bricklet is currently in one of the *ReaderReady* states. The returned tag ID
		is the tag ID that was saved through the last call of :func:`Reader Request Tag ID`.
		
		To get the tag ID of a tag the approach is as follows:
		
		1. Call :func:`Reader Request Tag ID`
		2. Wait for state to change to *ReaderRequestTagIDReady* (see :func:`Reader Get State` or
		   :cb:`Reader State Changed` callback)
		3. Call :func:`Reader Get Tag ID`
		*/
		var responseHandler = null;
		var functionToQueue = null;
		var streamStateObject = this.streamStateObjects[4];
		if (streamStateObject['responseProperties']['responseHandler'] === null) {
			responseHandler = 
				function (device, fid, packetResponse) {
					var result = [];
					var llvalues = null;
					var packetErrorFlag = 0;
					var rolesMappedData = [];
					var tagIDLength = null;
					var tagIDChunkData = null;
					var tagIDOutOfSync = false;
					var streamStateObject = device.streamStateObjects[fid];
					var tagIDChunkOffset = null;
					var payload = device.ipcon.getPayloadFromPacket(packetResponse);

					packetErrorFlag = device.ipcon.getEFromPacket(packetResponse);

					if (packetErrorFlag !== 0) {
						if (streamStateObject['responseProperties']['errorCB'] !== undefined) {
							if (packetErrorFlag === 1) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_INVALID_PARAMETER);
							}
							else if (packetErrorFlag === 2) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_FUNCTION_NOT_SUPPORTED);
							}
							else {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_UNKNOWN_ERROR);
							}
						}

						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}

						return;
					}

					if (payload.length === 0) {
						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}

						return;
					}

					llvalues = device.ipcon.unpack(payload,
					                               streamStateObject['responseProperties']['unpackFormatString']);

					for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
						if (streamStateObject['dataMapping'][i] === 'streamChunkData') {
							tagIDChunkData = llvalues[i];
						}
						else if (streamStateObject['dataMapping'][i] === 'streamChunkOffset') {
							tagIDChunkOffset = llvalues[i];
						}
					}

					for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
						if (streamStateObject['dataMapping'][i] === 'streamLength') {
							tagIDLength = llvalues[i];
							break;
						}
					}

					tagIDChunkOffset = 0;

					if (streamStateObject['responseProperties']['returnCB']) {
						for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
							rolesMappedData.push({'role': streamStateObject['dataMapping'][i], 'llvalue': llvalues[i]});
						}

						for (var i = 0; i < rolesMappedData.length; i++) {
							if (rolesMappedData[i]['role'] === 'streamChunkData') {
								result.push(tagIDChunkData.splice(0, tagIDLength));
							}
							else if (rolesMappedData[i]['role'] === null) {
								result.push(rolesMappedData[i]['llvalue']);
							}
						}

						streamStateObject['responseProperties']['returnCB'].apply(device, result);
					}

					device.resetStreamStateObject(streamStateObject);

					if (streamStateObject['responseProperties']['callQueue'].length > 0) {
						streamStateObject['responseProperties']['callQueue'].shift()(device);
					}
				};

			streamStateObject['responseProperties']['responseHandler'] = responseHandler;
		}
		if (!streamStateObject['responseProperties']['running']) {
			streamStateObject['responseProperties']['running'] = true;
			streamStateObject['responseProperties']['returnCB'] = returnCallback;
			streamStateObject['responseProperties']['errorCB'] = errorCallback;
			this.ipcon.sendRequest(this,
			                       BrickletNFC.FUNCTION_READER_GET_TAG_ID_LOW_LEVEL,
			                       [],
			                       '',
			                       42,
			                       'B B B32',
			                       returnCallback,
			                       errorCallback,
			                       true,
			                       true);
		}
		else {
			functionToQueue = function (device) {
				device.readerGetTagID.call(device, returnCallback, errorCallback);
			}
			streamStateObject['responseProperties']['callQueue'].push(functionToQueue);
		}
	};
	this.readerWriteNDEF = function(ndef, returnCallback, errorCallback) {
		/*
		Writes NDEF formated data.
		
		This function currently supports NFC Forum Type 2 and 4.
		
		The general approach for writing a NDEF message is as follows:
		
		1. Call :func:`Reader Request Tag ID`
		2. Wait for state to change to *ReaderRequestTagIDReady* (see
		   :func:`Reader Get State` or :cb:`Reader State Changed` callback)
		3. If looking for a specific tag then call :func:`Reader Get Tag ID` and check
		   if the expected tag was found, if it was not found got back to step 1
		4. Call :func:`Reader Write NDEF` with the NDEF message that you want to write
		5. Wait for state to change to *ReaderWriteNDEFReady* (see :func:`Reader Get State`
		   or :cb:`Reader State Changed` callback)
		*/

		var ndefLength = 0;
		var ndefChunkData = [];
		var ndefChunkOffset = 0;
		var streamStateObject = this.streamStateObjects[6];

		if (ndef.length > 65535) {
			if (errorCallback !== null){
				errorCallback(IPConnection.ERROR_INVALID_PARAMETER);
			}

			this.resetStreamStateObject(streamStateObject);

			if (streamStateObject['responseProperties']['callQueue'].length > 0) {
				streamStateObject['responseProperties']['callQueue'].shift()(device);
			}

			return;
		}

		if (!this.getResponseExpected(6)) {
			if (streamStateObject['streamProperties']['fixedLength']) {
				ndefLength = streamStateObject['streamProperties']['fixedLength'];
			}
			else {
				ndefLength = ndef.length;
			}

			if (streamStateObject['streamProperties']['singleChunk']) {
				ndefChunkData =
					this.ipcon.createChunkData(ndef, 0, 60, '\0');

				this.ipcon.sendRequest(this,
				                       BrickletNFC.FUNCTION_READER_WRITE_NDEF_LOW_LEVEL,
				                       [ndefLength, ndefChunkOffset, ndefChunkData],
				                       'H H B60',
				                       0,
				                       '',
				                       returnCallback,
				                       errorCallback,
				                       false,
				                       true);
			}
			else {
				while (ndefChunkOffset < ndef.length) {
					ndefChunkData =
						this.ipcon.createChunkData(ndef, ndefChunkOffset, 60, '\0');

					this.ipcon.sendRequest(this,
					                       BrickletNFC.FUNCTION_READER_WRITE_NDEF_LOW_LEVEL,
					                       [ndefLength, ndefChunkOffset, ndefChunkData],
					                       'H H B60',
					                       0,
					                       '',
					                       returnCallback,
					                       errorCallback,
					                       false,
					                       true);

					ndefChunkOffset += 60;
				}
			}

			if (returnCallback) {
				returnCallback();
			}
		}
		else {
			var responseHandler = null;
			var functionToQueue = null;

			if (streamStateObject['responseProperties']['responseHandler'] === null) {
				responseHandler = function (device, fid, packetResponse) {
					var result = [];
					var payload = null;
					var llvalues = null;
					var packetErrorFlag = 0;
					var rolesMappedData = [];
					var shortWriteWritten = -1;
					var streamStateObject = device.streamStateObjects[fid];
					var responseEmpty = streamStateObject['responseProperties']['streamInResponseEmpty'];
					var ndefLength = 0;
					var ndefChunkData = [];
					var ndefChunkOffset = 0;

					function doNextLLCall() {
						ndefLength = streamStateObject['responseProperties']['data'].length;
						ndefChunkData =
							device.ipcon.createChunkData(streamStateObject['responseProperties']['data'],
							                             streamStateObject['responseProperties']['streamInChunkOffset'],
							                             streamStateObject['responseProperties']['streamInChunkLength'],
							                             '\0');
						ndefChunkOffset = streamStateObject['responseProperties']['streamInChunkOffset'];

						for (var i = 0; i < streamStateObject['dataMappingStreamIn'].length; i++) {
							if (streamStateObject['dataMappingStreamIn'][i] === null) {
								continue;
							}

							if (streamStateObject['dataMappingStreamIn'][i].endsWith('Length')) {
								streamStateObject['responseProperties']['streamInLLParams'][i] = ndefLength;
							}
							else if (streamStateObject['dataMappingStreamIn'][i].endsWith('Offset')) {
								streamStateObject['responseProperties']['streamInLLParams'][i] = ndefChunkOffset;
							}
							else if (streamStateObject['dataMappingStreamIn'][i].endsWith('Data')) {
								streamStateObject['responseProperties']['streamInLLParams'][i] = ndefChunkData;
							}
						}

						device.ipcon.sendRequest(device,
						                         BrickletNFC.FUNCTION_READER_WRITE_NDEF_LOW_LEVEL,
						                         streamStateObject['responseProperties']['streamInLLParams'],
						                         'H H B60',
						                         0,
						                         '',
						                         returnCallback,
						                         errorCallback,
						                         true,
						                         true);

						streamStateObject['responseProperties']['streamInChunkOffset'] += 60;
					}

					function handleStreamInDone() {
						if (streamStateObject['responseProperties']['returnCB']) {
							if (streamStateObject['streamProperties']['shortWrite']) {
								for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
									if (streamStateObject['dataMapping'][i].endsWith('Written')) {
										result[i] = streamStateObject['responseProperties']['streamInWritten'];
										break;
									}
								}
							}

							if (!responseEmpty) {
								streamStateObject['responseProperties']['returnCB'].apply(device, result);
							}
							else {
								streamStateObject['responseProperties']['returnCB'].apply(device);
							}
						}

						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}
					}

					if (!streamStateObject) {
						return;
					}

					packetErrorFlag = device.ipcon.getEFromPacket(packetResponse);

					if (packetErrorFlag !== 0) {
						if (streamStateObject['responseProperties']['errorCB'] !== undefined) {
							if (packetErrorFlag === 1) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_INVALID_PARAMETER);
							}
							else if (packetErrorFlag === 2) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_FUNCTION_NOT_SUPPORTED);
							}
							else {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_UNKNOWN_ERROR);
							}
						}

						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}

						return;
					}

					if (responseEmpty) {
						if (streamStateObject['streamProperties']['singleChunk']) {
							handleStreamInDone();

							return;
						}

						if (streamStateObject['responseProperties']['streamInChunkOffset'] < streamStateObject['responseProperties']['data'].length) {
							doNextLLCall();
						}
						else {
							handleStreamInDone();
						}
					}
					else {
						payload = device.ipcon.getPayloadFromPacket(packetResponse);
						llvalues = device.ipcon.unpack(payload,
						                               streamStateObject['responseProperties']['unpackFormatString']);

						if (!payload || !llvalues) {
							device.resetStreamStateObject(streamStateObject);

							if (streamStateObject['responseProperties']['callQueue'].length > 0) {
								streamStateObject['responseProperties']['callQueue'].shift()(device);
							}

							return;
						}

						for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
							result.push(llvalues[i]);
						}

						if (streamStateObject['streamProperties']['singleChunk']) {
							if (streamStateObject['responseProperties']['returnCB']) {
								streamStateObject['responseProperties']['returnCB'].apply(device, result);
							}

							device.resetStreamStateObject(streamStateObject);

							if (streamStateObject['responseProperties']['callQueue'].length > 0) {
								streamStateObject['responseProperties']['callQueue'].shift()(device);
							}

							return;
						}

						if (streamStateObject['streamProperties']['shortWrite']) {
							for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
								if (streamStateObject['dataMapping'][i].endsWith('Written')) {
									shortWriteWritten = llvalues[i];
									streamStateObject['responseProperties']['streamInWritten'] += shortWriteWritten;
									break;
								}
							}
							if ((shortWriteWritten !== -1) && (shortWriteWritten < 60)) {
								// Either last chunk or short write
								handleStreamInDone();
								return;
							}
						}

						if (streamStateObject['responseProperties']['streamInChunkOffset'] < streamStateObject['responseProperties']['data'].length) {
							doNextLLCall();
						}
						else {
							handleStreamInDone();
						}
					}
				};

				streamStateObject['responseProperties']['responseHandler'] = responseHandler;
			}

			if (!streamStateObject['responseProperties']['running']) {
				streamStateObject['responseProperties']['running'] = true;
				streamStateObject['responseProperties']['returnCB'] = returnCallback;
				streamStateObject['responseProperties']['errorCB'] = errorCallback;
				streamStateObject['responseProperties']['data'].length = 0;
				streamStateObject['responseProperties']['data'].push.apply(streamStateObject['responseProperties']['data'],
				                                                           ndef);

				if (streamStateObject['streamProperties']['fixedLength']) {
					ndefLength = streamStateObject['streamProperties']['fixedLength'];
				}
				else {
					ndefLength = ndef.length;
				}

				ndefChunkOffset = 0;
				ndefChunkData =
					this.ipcon.createChunkData(ndef, 0, 60, '\0');

				streamStateObject['responseProperties']['streamInChunkOffset'] = 60;
				streamStateObject['responseProperties']['streamInChunkLength'] = 60;
				streamStateObject['responseProperties']['streamInLLParams'] = [ndefLength, ndefChunkOffset, ndefChunkData];

				this.ipcon.sendRequest(this,
				                       BrickletNFC.FUNCTION_READER_WRITE_NDEF_LOW_LEVEL,
				                       [ndefLength, ndefChunkOffset, ndefChunkData],
				                       'H H B60',
				                       0,
				                       '',
				                       returnCallback,
				                       errorCallback,
				                       true,
				                       true);
			}
			else {
				functionToQueue = function (device) {
					device.readerWriteNDEF.call(device, ndef, returnCallback, errorCallback);
				}

				streamStateObject['responseProperties']['callQueue'].push(functionToQueue);
			}
		}
	};

	this.readerReadNDEF = function(returnCallback, errorCallback) {
		/*
		Returns the NDEF data from an internal buffer. To fill the buffer
		with a NDEF message you have to call :func:`Reader Request NDEF` beforehand.
		*/
		var responseHandler = null;
		var functionToQueue = null;
		var streamStateObject = this.streamStateObjects[8];
		if (streamStateObject['responseProperties']['responseHandler'] === null) {
			responseHandler = 
				function (device, fid, packetResponse) {
					var result = [];
					var llvalues = null;
					var packetErrorFlag = 0;
					var rolesMappedData = [];
					var ndefLength = null;
					var ndefChunkData = null;
					var ndefOutOfSync = false;
					var streamStateObject = device.streamStateObjects[fid];
					var ndefChunkOffset = null;
					var payload = device.ipcon.getPayloadFromPacket(packetResponse);

					packetErrorFlag = device.ipcon.getEFromPacket(packetResponse);

					if (packetErrorFlag !== 0) {
						if (streamStateObject['responseProperties']['errorCB'] !== undefined) {
							if (packetErrorFlag === 1) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_INVALID_PARAMETER);
							}
							else if (packetErrorFlag === 2) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_FUNCTION_NOT_SUPPORTED);
							}
							else {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_UNKNOWN_ERROR);
							}
						}

						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}

						return;
					}

					if (payload.length === 0) {
						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}

						return;
					}

					llvalues = device.ipcon.unpack(payload,
					                               streamStateObject['responseProperties']['unpackFormatString']);

					for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
						if (streamStateObject['dataMapping'][i] === 'streamChunkData') {
							ndefChunkData = llvalues[i];
						}
						else if (streamStateObject['dataMapping'][i] === 'streamChunkOffset') {
							ndefChunkOffset = llvalues[i];
						}
					}

					for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
						if (streamStateObject['dataMapping'][i] === 'streamLength') {
							ndefLength = llvalues[i];
							break;
						}
					}

					function handleOOS() {
						if ((ndefChunkOffset + 60) < ndefLength) {
							streamStateObject['responseProperties']['runningSubcallOOS'] = true;
							device.ipcon.sendRequest(device, BrickletNFC.FUNCTION_READER_READ_NDEF_LOW_LEVEL, [], '', 72, 'H H B60', streamStateObject['responseProperties']['returnCB'], streamStateObject['responseProperties']['errorCB'], true, true);

							return;
						}

						if (streamStateObject['responseProperties']['errorCB']) {
							streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_STREAM_OUT_OF_SYNC);
						}

						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}
					}

					if (streamStateObject['responseProperties']['waitingFirstChunk']) {
						streamStateObject['responseProperties']['waitingFirstChunk'] = false;
						ndefOutOfSync = (ndefChunkOffset !== 0);
						streamStateObject['responseProperties']['data'] = ndefChunkData;
					}

					if (!streamStateObject['responseProperties']['runningSubcallOOS']) {
						if (!streamStateObject['responseProperties']['runningSubcall']) {
							if (!ndefOutOfSync &&
							    (streamStateObject['responseProperties']['data'].length < ndefLength)) {
							        streamStateObject['responseProperties']['runningSubcall'] = true;
							        device.ipcon.sendRequest(device, BrickletNFC.FUNCTION_READER_READ_NDEF_LOW_LEVEL, [], '', 72, 'H H B60', streamStateObject['responseProperties']['returnCB'], streamStateObject['responseProperties']['errorCB'], true, true);

							        return;
							}
						}
						else {
							ndefOutOfSync =
								(ndefChunkOffset !== streamStateObject['responseProperties']['data'].length);

							if (!ndefOutOfSync &&
								(streamStateObject['responseProperties']['data'].length < ndefLength)) {
									streamStateObject['responseProperties']['data'] =
										streamStateObject['responseProperties']['data'].concat(ndefChunkData);

									if (streamStateObject['responseProperties']['data'].length >= ndefLength) {
										streamStateObject['responseProperties']['data'] =
											streamStateObject['responseProperties']['data'].splice(0, ndefLength);
									}
									else {
										device.ipcon.sendRequest(device, BrickletNFC.FUNCTION_READER_READ_NDEF_LOW_LEVEL, [], '', 72, 'H H B60', streamStateObject['responseProperties']['returnCB'], streamStateObject['responseProperties']['errorCB'], true, true);

										return;
									}
							}
						}
					}
					else{
						handleOOS();

						return;
					}

					if (ndefOutOfSync) { // Discard remaining stream to bring it back in-sync
						handleOOS();

						return;
					}

					if (streamStateObject['responseProperties']['returnCB']) {
						for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
							rolesMappedData.push({'role': streamStateObject['dataMapping'][i], 'llvalue': llvalues[i]});
						}

						for (var i = 0; i < rolesMappedData.length; i++) {
							if (rolesMappedData[i]['role'] === 'streamChunkData') {
								result.push(streamStateObject['responseProperties']['data'].splice(0, ndefLength));
							}
							else if (rolesMappedData[i]['role'] === null) {
								result.push(rolesMappedData[i]['llvalue']);
							}
						}

						streamStateObject['responseProperties']['returnCB'].apply(device, result);
					}

					device.resetStreamStateObject(streamStateObject);

					if (streamStateObject['responseProperties']['callQueue'].length > 0) {
						streamStateObject['responseProperties']['callQueue'].shift()(device);
					}
					
				};

			streamStateObject['responseProperties']['responseHandler'] = responseHandler;
		}
		if (!streamStateObject['responseProperties']['running']) {
			streamStateObject['responseProperties']['running'] = true;
			streamStateObject['responseProperties']['returnCB'] = returnCallback;
			streamStateObject['responseProperties']['errorCB'] = errorCallback;
			this.ipcon.sendRequest(this,
			                       BrickletNFC.FUNCTION_READER_READ_NDEF_LOW_LEVEL,
			                       [],
			                       '',
			                       72,
			                       'H H B60',
			                       returnCallback,
			                       errorCallback,
			                       true,
			                       true);
		}
		else {
			functionToQueue = function (device) {
				device.readerReadNDEF.call(device, returnCallback, errorCallback);
			}
			streamStateObject['responseProperties']['callQueue'].push(functionToQueue);
		}
	};
	this.readerWritePage = function(page, data, returnCallback, errorCallback) {
		/*
		Writes a maximum of 8192 bytes starting from the given page. How many pages are written
		depends on the tag type. The page sizes are as follows:
		
		* Mifare Classic page size: 16 byte
		* NFC Forum Type 1 page size: 8 byte
		* NFC Forum Type 2 page size: 4 byte
		* NFC Forum Type 3 page size: 16 byte
		* NFC Forum Type 4: No pages, page = file selection (CC or NDEF, see below)
		
		The general approach for writing to a tag is as follows:
		
		1. Call :func:`Reader Request Tag ID`
		2. Wait for state to change to *ReaderRequestTagIDReady* (see :func:`Reader Get State` or
		   :cb:`Reader State Changed` callback)
		3. If looking for a specific tag then call :func:`Reader Get Tag ID` and check if the
		   expected tag was found, if it was not found got back to step 1
		4. Call :func:`Reader Write Page` with page number and data
		5. Wait for state to change to *ReaderWritePageReady* (see :func:`Reader Get State` or
		   :cb:`Reader State Changed` callback)
		
		If you use a Mifare Classic tag you have to authenticate a page before you
		can write to it. See :func:`Reader Authenticate Mifare Classic Page`.
		
		NFC Forum Type 4 tags are not organized into pages but different files. We currently
		support two files: Capability Container file (CC) and NDEF file.
		
		Choose CC by setting page to 3 or NDEF by setting page to 4.
		*/

		var dataLength = 0;
		var dataChunkData = [];
		var dataChunkOffset = 0;
		var streamStateObject = this.streamStateObjects[10];

		if (data.length > 65535) {
			if (errorCallback !== null){
				errorCallback(IPConnection.ERROR_INVALID_PARAMETER);
			}

			this.resetStreamStateObject(streamStateObject);

			if (streamStateObject['responseProperties']['callQueue'].length > 0) {
				streamStateObject['responseProperties']['callQueue'].shift()(device);
			}

			return;
		}

		if (!this.getResponseExpected(10)) {
			if (streamStateObject['streamProperties']['fixedLength']) {
				dataLength = streamStateObject['streamProperties']['fixedLength'];
			}
			else {
				dataLength = data.length;
			}

			if (streamStateObject['streamProperties']['singleChunk']) {
				dataChunkData =
					this.ipcon.createChunkData(data, 0, 58, '\0');

				this.ipcon.sendRequest(this,
				                       BrickletNFC.FUNCTION_READER_WRITE_PAGE_LOW_LEVEL,
				                       [page, dataLength, dataChunkOffset, dataChunkData],
				                       'H H H B58',
				                       0,
				                       '',
				                       returnCallback,
				                       errorCallback,
				                       false,
				                       true);
			}
			else {
				while (dataChunkOffset < data.length) {
					dataChunkData =
						this.ipcon.createChunkData(data, dataChunkOffset, 58, '\0');

					this.ipcon.sendRequest(this,
					                       BrickletNFC.FUNCTION_READER_WRITE_PAGE_LOW_LEVEL,
					                       [page, dataLength, dataChunkOffset, dataChunkData],
					                       'H H H B58',
					                       0,
					                       '',
					                       returnCallback,
					                       errorCallback,
					                       false,
					                       true);

					dataChunkOffset += 58;
				}
			}

			if (returnCallback) {
				returnCallback();
			}
		}
		else {
			var responseHandler = null;
			var functionToQueue = null;

			if (streamStateObject['responseProperties']['responseHandler'] === null) {
				responseHandler = function (device, fid, packetResponse) {
					var result = [];
					var payload = null;
					var llvalues = null;
					var packetErrorFlag = 0;
					var rolesMappedData = [];
					var shortWriteWritten = -1;
					var streamStateObject = device.streamStateObjects[fid];
					var responseEmpty = streamStateObject['responseProperties']['streamInResponseEmpty'];
					var dataLength = 0;
					var dataChunkData = [];
					var dataChunkOffset = 0;

					function doNextLLCall() {
						dataLength = streamStateObject['responseProperties']['data'].length;
						dataChunkData =
							device.ipcon.createChunkData(streamStateObject['responseProperties']['data'],
							                             streamStateObject['responseProperties']['streamInChunkOffset'],
							                             streamStateObject['responseProperties']['streamInChunkLength'],
							                             '\0');
						dataChunkOffset = streamStateObject['responseProperties']['streamInChunkOffset'];

						for (var i = 0; i < streamStateObject['dataMappingStreamIn'].length; i++) {
							if (streamStateObject['dataMappingStreamIn'][i] === null) {
								continue;
							}

							if (streamStateObject['dataMappingStreamIn'][i].endsWith('Length')) {
								streamStateObject['responseProperties']['streamInLLParams'][i] = dataLength;
							}
							else if (streamStateObject['dataMappingStreamIn'][i].endsWith('Offset')) {
								streamStateObject['responseProperties']['streamInLLParams'][i] = dataChunkOffset;
							}
							else if (streamStateObject['dataMappingStreamIn'][i].endsWith('Data')) {
								streamStateObject['responseProperties']['streamInLLParams'][i] = dataChunkData;
							}
						}

						device.ipcon.sendRequest(device,
						                         BrickletNFC.FUNCTION_READER_WRITE_PAGE_LOW_LEVEL,
						                         streamStateObject['responseProperties']['streamInLLParams'],
						                         'H H H B58',
						                         0,
						                         '',
						                         returnCallback,
						                         errorCallback,
						                         true,
						                         true);

						streamStateObject['responseProperties']['streamInChunkOffset'] += 58;
					}

					function handleStreamInDone() {
						if (streamStateObject['responseProperties']['returnCB']) {
							if (streamStateObject['streamProperties']['shortWrite']) {
								for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
									if (streamStateObject['dataMapping'][i].endsWith('Written')) {
										result[i] = streamStateObject['responseProperties']['streamInWritten'];
										break;
									}
								}
							}

							if (!responseEmpty) {
								streamStateObject['responseProperties']['returnCB'].apply(device, result);
							}
							else {
								streamStateObject['responseProperties']['returnCB'].apply(device);
							}
						}

						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}
					}

					if (!streamStateObject) {
						return;
					}

					packetErrorFlag = device.ipcon.getEFromPacket(packetResponse);

					if (packetErrorFlag !== 0) {
						if (streamStateObject['responseProperties']['errorCB'] !== undefined) {
							if (packetErrorFlag === 1) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_INVALID_PARAMETER);
							}
							else if (packetErrorFlag === 2) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_FUNCTION_NOT_SUPPORTED);
							}
							else {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_UNKNOWN_ERROR);
							}
						}

						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}

						return;
					}

					if (responseEmpty) {
						if (streamStateObject['streamProperties']['singleChunk']) {
							handleStreamInDone();

							return;
						}

						if (streamStateObject['responseProperties']['streamInChunkOffset'] < streamStateObject['responseProperties']['data'].length) {
							doNextLLCall();
						}
						else {
							handleStreamInDone();
						}
					}
					else {
						payload = device.ipcon.getPayloadFromPacket(packetResponse);
						llvalues = device.ipcon.unpack(payload,
						                               streamStateObject['responseProperties']['unpackFormatString']);

						if (!payload || !llvalues) {
							device.resetStreamStateObject(streamStateObject);

							if (streamStateObject['responseProperties']['callQueue'].length > 0) {
								streamStateObject['responseProperties']['callQueue'].shift()(device);
							}

							return;
						}

						for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
							result.push(llvalues[i]);
						}

						if (streamStateObject['streamProperties']['singleChunk']) {
							if (streamStateObject['responseProperties']['returnCB']) {
								streamStateObject['responseProperties']['returnCB'].apply(device, result);
							}

							device.resetStreamStateObject(streamStateObject);

							if (streamStateObject['responseProperties']['callQueue'].length > 0) {
								streamStateObject['responseProperties']['callQueue'].shift()(device);
							}

							return;
						}

						if (streamStateObject['streamProperties']['shortWrite']) {
							for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
								if (streamStateObject['dataMapping'][i].endsWith('Written')) {
									shortWriteWritten = llvalues[i];
									streamStateObject['responseProperties']['streamInWritten'] += shortWriteWritten;
									break;
								}
							}
							if ((shortWriteWritten !== -1) && (shortWriteWritten < 58)) {
								// Either last chunk or short write
								handleStreamInDone();
								return;
							}
						}

						if (streamStateObject['responseProperties']['streamInChunkOffset'] < streamStateObject['responseProperties']['data'].length) {
							doNextLLCall();
						}
						else {
							handleStreamInDone();
						}
					}
				};

				streamStateObject['responseProperties']['responseHandler'] = responseHandler;
			}

			if (!streamStateObject['responseProperties']['running']) {
				streamStateObject['responseProperties']['running'] = true;
				streamStateObject['responseProperties']['returnCB'] = returnCallback;
				streamStateObject['responseProperties']['errorCB'] = errorCallback;
				streamStateObject['responseProperties']['data'].length = 0;
				streamStateObject['responseProperties']['data'].push.apply(streamStateObject['responseProperties']['data'],
				                                                           data);

				if (streamStateObject['streamProperties']['fixedLength']) {
					dataLength = streamStateObject['streamProperties']['fixedLength'];
				}
				else {
					dataLength = data.length;
				}

				dataChunkOffset = 0;
				dataChunkData =
					this.ipcon.createChunkData(data, 0, 58, '\0');

				streamStateObject['responseProperties']['streamInChunkOffset'] = 58;
				streamStateObject['responseProperties']['streamInChunkLength'] = 58;
				streamStateObject['responseProperties']['streamInLLParams'] = [page, dataLength, dataChunkOffset, dataChunkData];

				this.ipcon.sendRequest(this,
				                       BrickletNFC.FUNCTION_READER_WRITE_PAGE_LOW_LEVEL,
				                       [page, dataLength, dataChunkOffset, dataChunkData],
				                       'H H H B58',
				                       0,
				                       '',
				                       returnCallback,
				                       errorCallback,
				                       true,
				                       true);
			}
			else {
				functionToQueue = function (device) {
					device.readerWritePage.call(device, page, data, returnCallback, errorCallback);
				}

				streamStateObject['responseProperties']['callQueue'].push(functionToQueue);
			}
		}
	};

	this.readerReadPage = function(returnCallback, errorCallback) {
		/*
		Returns the page data from an internal buffer. To fill the buffer
		with specific pages you have to call :func:`Reader Request Page` beforehand.
		*/
		var responseHandler = null;
		var functionToQueue = null;
		var streamStateObject = this.streamStateObjects[12];
		if (streamStateObject['responseProperties']['responseHandler'] === null) {
			responseHandler = 
				function (device, fid, packetResponse) {
					var result = [];
					var llvalues = null;
					var packetErrorFlag = 0;
					var rolesMappedData = [];
					var dataLength = null;
					var dataChunkData = null;
					var dataOutOfSync = false;
					var streamStateObject = device.streamStateObjects[fid];
					var dataChunkOffset = null;
					var payload = device.ipcon.getPayloadFromPacket(packetResponse);

					packetErrorFlag = device.ipcon.getEFromPacket(packetResponse);

					if (packetErrorFlag !== 0) {
						if (streamStateObject['responseProperties']['errorCB'] !== undefined) {
							if (packetErrorFlag === 1) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_INVALID_PARAMETER);
							}
							else if (packetErrorFlag === 2) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_FUNCTION_NOT_SUPPORTED);
							}
							else {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_UNKNOWN_ERROR);
							}
						}

						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}

						return;
					}

					if (payload.length === 0) {
						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}

						return;
					}

					llvalues = device.ipcon.unpack(payload,
					                               streamStateObject['responseProperties']['unpackFormatString']);

					for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
						if (streamStateObject['dataMapping'][i] === 'streamChunkData') {
							dataChunkData = llvalues[i];
						}
						else if (streamStateObject['dataMapping'][i] === 'streamChunkOffset') {
							dataChunkOffset = llvalues[i];
						}
					}

					for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
						if (streamStateObject['dataMapping'][i] === 'streamLength') {
							dataLength = llvalues[i];
							break;
						}
					}

					function handleOOS() {
						if ((dataChunkOffset + 60) < dataLength) {
							streamStateObject['responseProperties']['runningSubcallOOS'] = true;
							device.ipcon.sendRequest(device, BrickletNFC.FUNCTION_READER_READ_PAGE_LOW_LEVEL, [], '', 72, 'H H B60', streamStateObject['responseProperties']['returnCB'], streamStateObject['responseProperties']['errorCB'], true, true);

							return;
						}

						if (streamStateObject['responseProperties']['errorCB']) {
							streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_STREAM_OUT_OF_SYNC);
						}

						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}
					}

					if (streamStateObject['responseProperties']['waitingFirstChunk']) {
						streamStateObject['responseProperties']['waitingFirstChunk'] = false;
						dataOutOfSync = (dataChunkOffset !== 0);
						streamStateObject['responseProperties']['data'] = dataChunkData;
					}

					if (!streamStateObject['responseProperties']['runningSubcallOOS']) {
						if (!streamStateObject['responseProperties']['runningSubcall']) {
							if (!dataOutOfSync &&
							    (streamStateObject['responseProperties']['data'].length < dataLength)) {
							        streamStateObject['responseProperties']['runningSubcall'] = true;
							        device.ipcon.sendRequest(device, BrickletNFC.FUNCTION_READER_READ_PAGE_LOW_LEVEL, [], '', 72, 'H H B60', streamStateObject['responseProperties']['returnCB'], streamStateObject['responseProperties']['errorCB'], true, true);

							        return;
							}
						}
						else {
							dataOutOfSync =
								(dataChunkOffset !== streamStateObject['responseProperties']['data'].length);

							if (!dataOutOfSync &&
								(streamStateObject['responseProperties']['data'].length < dataLength)) {
									streamStateObject['responseProperties']['data'] =
										streamStateObject['responseProperties']['data'].concat(dataChunkData);

									if (streamStateObject['responseProperties']['data'].length >= dataLength) {
										streamStateObject['responseProperties']['data'] =
											streamStateObject['responseProperties']['data'].splice(0, dataLength);
									}
									else {
										device.ipcon.sendRequest(device, BrickletNFC.FUNCTION_READER_READ_PAGE_LOW_LEVEL, [], '', 72, 'H H B60', streamStateObject['responseProperties']['returnCB'], streamStateObject['responseProperties']['errorCB'], true, true);

										return;
									}
							}
						}
					}
					else{
						handleOOS();

						return;
					}

					if (dataOutOfSync) { // Discard remaining stream to bring it back in-sync
						handleOOS();

						return;
					}

					if (streamStateObject['responseProperties']['returnCB']) {
						for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
							rolesMappedData.push({'role': streamStateObject['dataMapping'][i], 'llvalue': llvalues[i]});
						}

						for (var i = 0; i < rolesMappedData.length; i++) {
							if (rolesMappedData[i]['role'] === 'streamChunkData') {
								result.push(streamStateObject['responseProperties']['data'].splice(0, dataLength));
							}
							else if (rolesMappedData[i]['role'] === null) {
								result.push(rolesMappedData[i]['llvalue']);
							}
						}

						streamStateObject['responseProperties']['returnCB'].apply(device, result);
					}

					device.resetStreamStateObject(streamStateObject);

					if (streamStateObject['responseProperties']['callQueue'].length > 0) {
						streamStateObject['responseProperties']['callQueue'].shift()(device);
					}
					
				};

			streamStateObject['responseProperties']['responseHandler'] = responseHandler;
		}
		if (!streamStateObject['responseProperties']['running']) {
			streamStateObject['responseProperties']['running'] = true;
			streamStateObject['responseProperties']['returnCB'] = returnCallback;
			streamStateObject['responseProperties']['errorCB'] = errorCallback;
			this.ipcon.sendRequest(this,
			                       BrickletNFC.FUNCTION_READER_READ_PAGE_LOW_LEVEL,
			                       [],
			                       '',
			                       72,
			                       'H H B60',
			                       returnCallback,
			                       errorCallback,
			                       true,
			                       true);
		}
		else {
			functionToQueue = function (device) {
				device.readerReadPage.call(device, returnCallback, errorCallback);
			}
			streamStateObject['responseProperties']['callQueue'].push(functionToQueue);
		}
	};
	this.cardemuWriteNDEF = function(ndef, returnCallback, errorCallback) {
		/*
		Writes the NDEF message that is to be transferred to the NFC peer.
		
		The maximum supported NDEF message size in Cardemu mode is 255 byte.
		
		You can call this function at any time in Cardemu mode. The internal buffer
		will not be overwritten until you call this function again or change the
		mode.
		*/

		var ndefLength = 0;
		var ndefChunkData = [];
		var ndefChunkOffset = 0;
		var streamStateObject = this.streamStateObjects[16];

		if (ndef.length > 65535) {
			if (errorCallback !== null){
				errorCallback(IPConnection.ERROR_INVALID_PARAMETER);
			}

			this.resetStreamStateObject(streamStateObject);

			if (streamStateObject['responseProperties']['callQueue'].length > 0) {
				streamStateObject['responseProperties']['callQueue'].shift()(device);
			}

			return;
		}

		if (!this.getResponseExpected(16)) {
			if (streamStateObject['streamProperties']['fixedLength']) {
				ndefLength = streamStateObject['streamProperties']['fixedLength'];
			}
			else {
				ndefLength = ndef.length;
			}

			if (streamStateObject['streamProperties']['singleChunk']) {
				ndefChunkData =
					this.ipcon.createChunkData(ndef, 0, 60, '\0');

				this.ipcon.sendRequest(this,
				                       BrickletNFC.FUNCTION_CARDEMU_WRITE_NDEF_LOW_LEVEL,
				                       [ndefLength, ndefChunkOffset, ndefChunkData],
				                       'H H B60',
				                       0,
				                       '',
				                       returnCallback,
				                       errorCallback,
				                       false,
				                       true);
			}
			else {
				while (ndefChunkOffset < ndef.length) {
					ndefChunkData =
						this.ipcon.createChunkData(ndef, ndefChunkOffset, 60, '\0');

					this.ipcon.sendRequest(this,
					                       BrickletNFC.FUNCTION_CARDEMU_WRITE_NDEF_LOW_LEVEL,
					                       [ndefLength, ndefChunkOffset, ndefChunkData],
					                       'H H B60',
					                       0,
					                       '',
					                       returnCallback,
					                       errorCallback,
					                       false,
					                       true);

					ndefChunkOffset += 60;
				}
			}

			if (returnCallback) {
				returnCallback();
			}
		}
		else {
			var responseHandler = null;
			var functionToQueue = null;

			if (streamStateObject['responseProperties']['responseHandler'] === null) {
				responseHandler = function (device, fid, packetResponse) {
					var result = [];
					var payload = null;
					var llvalues = null;
					var packetErrorFlag = 0;
					var rolesMappedData = [];
					var shortWriteWritten = -1;
					var streamStateObject = device.streamStateObjects[fid];
					var responseEmpty = streamStateObject['responseProperties']['streamInResponseEmpty'];
					var ndefLength = 0;
					var ndefChunkData = [];
					var ndefChunkOffset = 0;

					function doNextLLCall() {
						ndefLength = streamStateObject['responseProperties']['data'].length;
						ndefChunkData =
							device.ipcon.createChunkData(streamStateObject['responseProperties']['data'],
							                             streamStateObject['responseProperties']['streamInChunkOffset'],
							                             streamStateObject['responseProperties']['streamInChunkLength'],
							                             '\0');
						ndefChunkOffset = streamStateObject['responseProperties']['streamInChunkOffset'];

						for (var i = 0; i < streamStateObject['dataMappingStreamIn'].length; i++) {
							if (streamStateObject['dataMappingStreamIn'][i] === null) {
								continue;
							}

							if (streamStateObject['dataMappingStreamIn'][i].endsWith('Length')) {
								streamStateObject['responseProperties']['streamInLLParams'][i] = ndefLength;
							}
							else if (streamStateObject['dataMappingStreamIn'][i].endsWith('Offset')) {
								streamStateObject['responseProperties']['streamInLLParams'][i] = ndefChunkOffset;
							}
							else if (streamStateObject['dataMappingStreamIn'][i].endsWith('Data')) {
								streamStateObject['responseProperties']['streamInLLParams'][i] = ndefChunkData;
							}
						}

						device.ipcon.sendRequest(device,
						                         BrickletNFC.FUNCTION_CARDEMU_WRITE_NDEF_LOW_LEVEL,
						                         streamStateObject['responseProperties']['streamInLLParams'],
						                         'H H B60',
						                         0,
						                         '',
						                         returnCallback,
						                         errorCallback,
						                         true,
						                         true);

						streamStateObject['responseProperties']['streamInChunkOffset'] += 60;
					}

					function handleStreamInDone() {
						if (streamStateObject['responseProperties']['returnCB']) {
							if (streamStateObject['streamProperties']['shortWrite']) {
								for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
									if (streamStateObject['dataMapping'][i].endsWith('Written')) {
										result[i] = streamStateObject['responseProperties']['streamInWritten'];
										break;
									}
								}
							}

							if (!responseEmpty) {
								streamStateObject['responseProperties']['returnCB'].apply(device, result);
							}
							else {
								streamStateObject['responseProperties']['returnCB'].apply(device);
							}
						}

						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}
					}

					if (!streamStateObject) {
						return;
					}

					packetErrorFlag = device.ipcon.getEFromPacket(packetResponse);

					if (packetErrorFlag !== 0) {
						if (streamStateObject['responseProperties']['errorCB'] !== undefined) {
							if (packetErrorFlag === 1) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_INVALID_PARAMETER);
							}
							else if (packetErrorFlag === 2) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_FUNCTION_NOT_SUPPORTED);
							}
							else {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_UNKNOWN_ERROR);
							}
						}

						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}

						return;
					}

					if (responseEmpty) {
						if (streamStateObject['streamProperties']['singleChunk']) {
							handleStreamInDone();

							return;
						}

						if (streamStateObject['responseProperties']['streamInChunkOffset'] < streamStateObject['responseProperties']['data'].length) {
							doNextLLCall();
						}
						else {
							handleStreamInDone();
						}
					}
					else {
						payload = device.ipcon.getPayloadFromPacket(packetResponse);
						llvalues = device.ipcon.unpack(payload,
						                               streamStateObject['responseProperties']['unpackFormatString']);

						if (!payload || !llvalues) {
							device.resetStreamStateObject(streamStateObject);

							if (streamStateObject['responseProperties']['callQueue'].length > 0) {
								streamStateObject['responseProperties']['callQueue'].shift()(device);
							}

							return;
						}

						for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
							result.push(llvalues[i]);
						}

						if (streamStateObject['streamProperties']['singleChunk']) {
							if (streamStateObject['responseProperties']['returnCB']) {
								streamStateObject['responseProperties']['returnCB'].apply(device, result);
							}

							device.resetStreamStateObject(streamStateObject);

							if (streamStateObject['responseProperties']['callQueue'].length > 0) {
								streamStateObject['responseProperties']['callQueue'].shift()(device);
							}

							return;
						}

						if (streamStateObject['streamProperties']['shortWrite']) {
							for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
								if (streamStateObject['dataMapping'][i].endsWith('Written')) {
									shortWriteWritten = llvalues[i];
									streamStateObject['responseProperties']['streamInWritten'] += shortWriteWritten;
									break;
								}
							}
							if ((shortWriteWritten !== -1) && (shortWriteWritten < 60)) {
								// Either last chunk or short write
								handleStreamInDone();
								return;
							}
						}

						if (streamStateObject['responseProperties']['streamInChunkOffset'] < streamStateObject['responseProperties']['data'].length) {
							doNextLLCall();
						}
						else {
							handleStreamInDone();
						}
					}
				};

				streamStateObject['responseProperties']['responseHandler'] = responseHandler;
			}

			if (!streamStateObject['responseProperties']['running']) {
				streamStateObject['responseProperties']['running'] = true;
				streamStateObject['responseProperties']['returnCB'] = returnCallback;
				streamStateObject['responseProperties']['errorCB'] = errorCallback;
				streamStateObject['responseProperties']['data'].length = 0;
				streamStateObject['responseProperties']['data'].push.apply(streamStateObject['responseProperties']['data'],
				                                                           ndef);

				if (streamStateObject['streamProperties']['fixedLength']) {
					ndefLength = streamStateObject['streamProperties']['fixedLength'];
				}
				else {
					ndefLength = ndef.length;
				}

				ndefChunkOffset = 0;
				ndefChunkData =
					this.ipcon.createChunkData(ndef, 0, 60, '\0');

				streamStateObject['responseProperties']['streamInChunkOffset'] = 60;
				streamStateObject['responseProperties']['streamInChunkLength'] = 60;
				streamStateObject['responseProperties']['streamInLLParams'] = [ndefLength, ndefChunkOffset, ndefChunkData];

				this.ipcon.sendRequest(this,
				                       BrickletNFC.FUNCTION_CARDEMU_WRITE_NDEF_LOW_LEVEL,
				                       [ndefLength, ndefChunkOffset, ndefChunkData],
				                       'H H B60',
				                       0,
				                       '',
				                       returnCallback,
				                       errorCallback,
				                       true,
				                       true);
			}
			else {
				functionToQueue = function (device) {
					device.cardemuWriteNDEF.call(device, ndef, returnCallback, errorCallback);
				}

				streamStateObject['responseProperties']['callQueue'].push(functionToQueue);
			}
		}
	};
	this.p2pWriteNDEF = function(ndef, returnCallback, errorCallback) {
		/*
		Writes the NDEF message that is to be transferred to the NFC peer.
		
		The maximum supported NDEF message size for P2P transfer is 255 byte.
		
		You can call this function at any time in P2P mode. The internal buffer
		will not be overwritten until you call this function again, change the
		mode or use P2P to read an NDEF messages.
		*/

		var ndefLength = 0;
		var ndefChunkData = [];
		var ndefChunkOffset = 0;
		var streamStateObject = this.streamStateObjects[21];

		if (ndef.length > 65535) {
			if (errorCallback !== null){
				errorCallback(IPConnection.ERROR_INVALID_PARAMETER);
			}

			this.resetStreamStateObject(streamStateObject);

			if (streamStateObject['responseProperties']['callQueue'].length > 0) {
				streamStateObject['responseProperties']['callQueue'].shift()(device);
			}

			return;
		}

		if (!this.getResponseExpected(21)) {
			if (streamStateObject['streamProperties']['fixedLength']) {
				ndefLength = streamStateObject['streamProperties']['fixedLength'];
			}
			else {
				ndefLength = ndef.length;
			}

			if (streamStateObject['streamProperties']['singleChunk']) {
				ndefChunkData =
					this.ipcon.createChunkData(ndef, 0, 60, '\0');

				this.ipcon.sendRequest(this,
				                       BrickletNFC.FUNCTION_P2P_WRITE_NDEF_LOW_LEVEL,
				                       [ndefLength, ndefChunkOffset, ndefChunkData],
				                       'H H B60',
				                       0,
				                       '',
				                       returnCallback,
				                       errorCallback,
				                       false,
				                       true);
			}
			else {
				while (ndefChunkOffset < ndef.length) {
					ndefChunkData =
						this.ipcon.createChunkData(ndef, ndefChunkOffset, 60, '\0');

					this.ipcon.sendRequest(this,
					                       BrickletNFC.FUNCTION_P2P_WRITE_NDEF_LOW_LEVEL,
					                       [ndefLength, ndefChunkOffset, ndefChunkData],
					                       'H H B60',
					                       0,
					                       '',
					                       returnCallback,
					                       errorCallback,
					                       false,
					                       true);

					ndefChunkOffset += 60;
				}
			}

			if (returnCallback) {
				returnCallback();
			}
		}
		else {
			var responseHandler = null;
			var functionToQueue = null;

			if (streamStateObject['responseProperties']['responseHandler'] === null) {
				responseHandler = function (device, fid, packetResponse) {
					var result = [];
					var payload = null;
					var llvalues = null;
					var packetErrorFlag = 0;
					var rolesMappedData = [];
					var shortWriteWritten = -1;
					var streamStateObject = device.streamStateObjects[fid];
					var responseEmpty = streamStateObject['responseProperties']['streamInResponseEmpty'];
					var ndefLength = 0;
					var ndefChunkData = [];
					var ndefChunkOffset = 0;

					function doNextLLCall() {
						ndefLength = streamStateObject['responseProperties']['data'].length;
						ndefChunkData =
							device.ipcon.createChunkData(streamStateObject['responseProperties']['data'],
							                             streamStateObject['responseProperties']['streamInChunkOffset'],
							                             streamStateObject['responseProperties']['streamInChunkLength'],
							                             '\0');
						ndefChunkOffset = streamStateObject['responseProperties']['streamInChunkOffset'];

						for (var i = 0; i < streamStateObject['dataMappingStreamIn'].length; i++) {
							if (streamStateObject['dataMappingStreamIn'][i] === null) {
								continue;
							}

							if (streamStateObject['dataMappingStreamIn'][i].endsWith('Length')) {
								streamStateObject['responseProperties']['streamInLLParams'][i] = ndefLength;
							}
							else if (streamStateObject['dataMappingStreamIn'][i].endsWith('Offset')) {
								streamStateObject['responseProperties']['streamInLLParams'][i] = ndefChunkOffset;
							}
							else if (streamStateObject['dataMappingStreamIn'][i].endsWith('Data')) {
								streamStateObject['responseProperties']['streamInLLParams'][i] = ndefChunkData;
							}
						}

						device.ipcon.sendRequest(device,
						                         BrickletNFC.FUNCTION_P2P_WRITE_NDEF_LOW_LEVEL,
						                         streamStateObject['responseProperties']['streamInLLParams'],
						                         'H H B60',
						                         0,
						                         '',
						                         returnCallback,
						                         errorCallback,
						                         true,
						                         true);

						streamStateObject['responseProperties']['streamInChunkOffset'] += 60;
					}

					function handleStreamInDone() {
						if (streamStateObject['responseProperties']['returnCB']) {
							if (streamStateObject['streamProperties']['shortWrite']) {
								for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
									if (streamStateObject['dataMapping'][i].endsWith('Written')) {
										result[i] = streamStateObject['responseProperties']['streamInWritten'];
										break;
									}
								}
							}

							if (!responseEmpty) {
								streamStateObject['responseProperties']['returnCB'].apply(device, result);
							}
							else {
								streamStateObject['responseProperties']['returnCB'].apply(device);
							}
						}

						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}
					}

					if (!streamStateObject) {
						return;
					}

					packetErrorFlag = device.ipcon.getEFromPacket(packetResponse);

					if (packetErrorFlag !== 0) {
						if (streamStateObject['responseProperties']['errorCB'] !== undefined) {
							if (packetErrorFlag === 1) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_INVALID_PARAMETER);
							}
							else if (packetErrorFlag === 2) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_FUNCTION_NOT_SUPPORTED);
							}
							else {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_UNKNOWN_ERROR);
							}
						}

						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}

						return;
					}

					if (responseEmpty) {
						if (streamStateObject['streamProperties']['singleChunk']) {
							handleStreamInDone();

							return;
						}

						if (streamStateObject['responseProperties']['streamInChunkOffset'] < streamStateObject['responseProperties']['data'].length) {
							doNextLLCall();
						}
						else {
							handleStreamInDone();
						}
					}
					else {
						payload = device.ipcon.getPayloadFromPacket(packetResponse);
						llvalues = device.ipcon.unpack(payload,
						                               streamStateObject['responseProperties']['unpackFormatString']);

						if (!payload || !llvalues) {
							device.resetStreamStateObject(streamStateObject);

							if (streamStateObject['responseProperties']['callQueue'].length > 0) {
								streamStateObject['responseProperties']['callQueue'].shift()(device);
							}

							return;
						}

						for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
							result.push(llvalues[i]);
						}

						if (streamStateObject['streamProperties']['singleChunk']) {
							if (streamStateObject['responseProperties']['returnCB']) {
								streamStateObject['responseProperties']['returnCB'].apply(device, result);
							}

							device.resetStreamStateObject(streamStateObject);

							if (streamStateObject['responseProperties']['callQueue'].length > 0) {
								streamStateObject['responseProperties']['callQueue'].shift()(device);
							}

							return;
						}

						if (streamStateObject['streamProperties']['shortWrite']) {
							for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
								if (streamStateObject['dataMapping'][i].endsWith('Written')) {
									shortWriteWritten = llvalues[i];
									streamStateObject['responseProperties']['streamInWritten'] += shortWriteWritten;
									break;
								}
							}
							if ((shortWriteWritten !== -1) && (shortWriteWritten < 60)) {
								// Either last chunk or short write
								handleStreamInDone();
								return;
							}
						}

						if (streamStateObject['responseProperties']['streamInChunkOffset'] < streamStateObject['responseProperties']['data'].length) {
							doNextLLCall();
						}
						else {
							handleStreamInDone();
						}
					}
				};

				streamStateObject['responseProperties']['responseHandler'] = responseHandler;
			}

			if (!streamStateObject['responseProperties']['running']) {
				streamStateObject['responseProperties']['running'] = true;
				streamStateObject['responseProperties']['returnCB'] = returnCallback;
				streamStateObject['responseProperties']['errorCB'] = errorCallback;
				streamStateObject['responseProperties']['data'].length = 0;
				streamStateObject['responseProperties']['data'].push.apply(streamStateObject['responseProperties']['data'],
				                                                           ndef);

				if (streamStateObject['streamProperties']['fixedLength']) {
					ndefLength = streamStateObject['streamProperties']['fixedLength'];
				}
				else {
					ndefLength = ndef.length;
				}

				ndefChunkOffset = 0;
				ndefChunkData =
					this.ipcon.createChunkData(ndef, 0, 60, '\0');

				streamStateObject['responseProperties']['streamInChunkOffset'] = 60;
				streamStateObject['responseProperties']['streamInChunkLength'] = 60;
				streamStateObject['responseProperties']['streamInLLParams'] = [ndefLength, ndefChunkOffset, ndefChunkData];

				this.ipcon.sendRequest(this,
				                       BrickletNFC.FUNCTION_P2P_WRITE_NDEF_LOW_LEVEL,
				                       [ndefLength, ndefChunkOffset, ndefChunkData],
				                       'H H B60',
				                       0,
				                       '',
				                       returnCallback,
				                       errorCallback,
				                       true,
				                       true);
			}
			else {
				functionToQueue = function (device) {
					device.p2pWriteNDEF.call(device, ndef, returnCallback, errorCallback);
				}

				streamStateObject['responseProperties']['callQueue'].push(functionToQueue);
			}
		}
	};

	this.p2pReadNDEF = function(returnCallback, errorCallback) {
		/*
		Returns the NDEF message that was written by a NFC peer in NFC P2P mode.
		
		The NDEF message is ready if you called :func:`P2P Start Transfer` with a
		read transfer and the P2P state changed to *P2PTransferNDEFReady*.
		*/
		var responseHandler = null;
		var functionToQueue = null;
		var streamStateObject = this.streamStateObjects[23];
		if (streamStateObject['responseProperties']['responseHandler'] === null) {
			responseHandler = 
				function (device, fid, packetResponse) {
					var result = [];
					var llvalues = null;
					var packetErrorFlag = 0;
					var rolesMappedData = [];
					var ndefLength = null;
					var ndefChunkData = null;
					var ndefOutOfSync = false;
					var streamStateObject = device.streamStateObjects[fid];
					var ndefChunkOffset = null;
					var payload = device.ipcon.getPayloadFromPacket(packetResponse);

					packetErrorFlag = device.ipcon.getEFromPacket(packetResponse);

					if (packetErrorFlag !== 0) {
						if (streamStateObject['responseProperties']['errorCB'] !== undefined) {
							if (packetErrorFlag === 1) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_INVALID_PARAMETER);
							}
							else if (packetErrorFlag === 2) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_FUNCTION_NOT_SUPPORTED);
							}
							else {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_UNKNOWN_ERROR);
							}
						}

						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}

						return;
					}

					if (payload.length === 0) {
						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}

						return;
					}

					llvalues = device.ipcon.unpack(payload,
					                               streamStateObject['responseProperties']['unpackFormatString']);

					for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
						if (streamStateObject['dataMapping'][i] === 'streamChunkData') {
							ndefChunkData = llvalues[i];
						}
						else if (streamStateObject['dataMapping'][i] === 'streamChunkOffset') {
							ndefChunkOffset = llvalues[i];
						}
					}

					for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
						if (streamStateObject['dataMapping'][i] === 'streamLength') {
							ndefLength = llvalues[i];
							break;
						}
					}

					function handleOOS() {
						if ((ndefChunkOffset + 60) < ndefLength) {
							streamStateObject['responseProperties']['runningSubcallOOS'] = true;
							device.ipcon.sendRequest(device, BrickletNFC.FUNCTION_P2P_READ_NDEF_LOW_LEVEL, [], '', 72, 'H H B60', streamStateObject['responseProperties']['returnCB'], streamStateObject['responseProperties']['errorCB'], true, true);

							return;
						}

						if (streamStateObject['responseProperties']['errorCB']) {
							streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_STREAM_OUT_OF_SYNC);
						}

						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}
					}

					if (streamStateObject['responseProperties']['waitingFirstChunk']) {
						streamStateObject['responseProperties']['waitingFirstChunk'] = false;
						ndefOutOfSync = (ndefChunkOffset !== 0);
						streamStateObject['responseProperties']['data'] = ndefChunkData;
					}

					if (!streamStateObject['responseProperties']['runningSubcallOOS']) {
						if (!streamStateObject['responseProperties']['runningSubcall']) {
							if (!ndefOutOfSync &&
							    (streamStateObject['responseProperties']['data'].length < ndefLength)) {
							        streamStateObject['responseProperties']['runningSubcall'] = true;
							        device.ipcon.sendRequest(device, BrickletNFC.FUNCTION_P2P_READ_NDEF_LOW_LEVEL, [], '', 72, 'H H B60', streamStateObject['responseProperties']['returnCB'], streamStateObject['responseProperties']['errorCB'], true, true);

							        return;
							}
						}
						else {
							ndefOutOfSync =
								(ndefChunkOffset !== streamStateObject['responseProperties']['data'].length);

							if (!ndefOutOfSync &&
								(streamStateObject['responseProperties']['data'].length < ndefLength)) {
									streamStateObject['responseProperties']['data'] =
										streamStateObject['responseProperties']['data'].concat(ndefChunkData);

									if (streamStateObject['responseProperties']['data'].length >= ndefLength) {
										streamStateObject['responseProperties']['data'] =
											streamStateObject['responseProperties']['data'].splice(0, ndefLength);
									}
									else {
										device.ipcon.sendRequest(device, BrickletNFC.FUNCTION_P2P_READ_NDEF_LOW_LEVEL, [], '', 72, 'H H B60', streamStateObject['responseProperties']['returnCB'], streamStateObject['responseProperties']['errorCB'], true, true);

										return;
									}
							}
						}
					}
					else{
						handleOOS();

						return;
					}

					if (ndefOutOfSync) { // Discard remaining stream to bring it back in-sync
						handleOOS();

						return;
					}

					if (streamStateObject['responseProperties']['returnCB']) {
						for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
							rolesMappedData.push({'role': streamStateObject['dataMapping'][i], 'llvalue': llvalues[i]});
						}

						for (var i = 0; i < rolesMappedData.length; i++) {
							if (rolesMappedData[i]['role'] === 'streamChunkData') {
								result.push(streamStateObject['responseProperties']['data'].splice(0, ndefLength));
							}
							else if (rolesMappedData[i]['role'] === null) {
								result.push(rolesMappedData[i]['llvalue']);
							}
						}

						streamStateObject['responseProperties']['returnCB'].apply(device, result);
					}

					device.resetStreamStateObject(streamStateObject);

					if (streamStateObject['responseProperties']['callQueue'].length > 0) {
						streamStateObject['responseProperties']['callQueue'].shift()(device);
					}
					
				};

			streamStateObject['responseProperties']['responseHandler'] = responseHandler;
		}
		if (!streamStateObject['responseProperties']['running']) {
			streamStateObject['responseProperties']['running'] = true;
			streamStateObject['responseProperties']['returnCB'] = returnCallback;
			streamStateObject['responseProperties']['errorCB'] = errorCallback;
			this.ipcon.sendRequest(this,
			                       BrickletNFC.FUNCTION_P2P_READ_NDEF_LOW_LEVEL,
			                       [],
			                       '',
			                       72,
			                       'H H B60',
			                       returnCallback,
			                       errorCallback,
			                       true,
			                       true);
		}
		else {
			functionToQueue = function (device) {
				device.p2pReadNDEF.call(device, returnCallback, errorCallback);
			}
			streamStateObject['responseProperties']['callQueue'].push(functionToQueue);
		}
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletNFC;

},{"./Device":279,"./IPConnection":280}],229:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletNFCRFID.DEVICE_IDENTIFIER = 246;
BrickletNFCRFID.DEVICE_DISPLAY_NAME = 'NFC/RFID Bricklet';
BrickletNFCRFID.CALLBACK_STATE_CHANGED = 8;
BrickletNFCRFID.FUNCTION_REQUEST_TAG_ID = 1;
BrickletNFCRFID.FUNCTION_GET_TAG_ID = 2;
BrickletNFCRFID.FUNCTION_GET_STATE = 3;
BrickletNFCRFID.FUNCTION_AUTHENTICATE_MIFARE_CLASSIC_PAGE = 4;
BrickletNFCRFID.FUNCTION_WRITE_PAGE = 5;
BrickletNFCRFID.FUNCTION_REQUEST_PAGE = 6;
BrickletNFCRFID.FUNCTION_GET_PAGE = 7;
BrickletNFCRFID.FUNCTION_GET_IDENTITY = 255;
BrickletNFCRFID.TAG_TYPE_MIFARE_CLASSIC = 0;
BrickletNFCRFID.TAG_TYPE_TYPE1 = 1;
BrickletNFCRFID.TAG_TYPE_TYPE2 = 2;
BrickletNFCRFID.STATE_INITIALIZATION = 0;
BrickletNFCRFID.STATE_IDLE = 128;
BrickletNFCRFID.STATE_ERROR = 192;
BrickletNFCRFID.STATE_REQUEST_TAG_ID = 2;
BrickletNFCRFID.STATE_REQUEST_TAG_ID_READY = 130;
BrickletNFCRFID.STATE_REQUEST_TAG_ID_ERROR = 194;
BrickletNFCRFID.STATE_AUTHENTICATING_MIFARE_CLASSIC_PAGE = 3;
BrickletNFCRFID.STATE_AUTHENTICATING_MIFARE_CLASSIC_PAGE_READY = 131;
BrickletNFCRFID.STATE_AUTHENTICATING_MIFARE_CLASSIC_PAGE_ERROR = 195;
BrickletNFCRFID.STATE_WRITE_PAGE = 4;
BrickletNFCRFID.STATE_WRITE_PAGE_READY = 132;
BrickletNFCRFID.STATE_WRITE_PAGE_ERROR = 196;
BrickletNFCRFID.STATE_REQUEST_PAGE = 5;
BrickletNFCRFID.STATE_REQUEST_PAGE_READY = 133;
BrickletNFCRFID.STATE_REQUEST_PAGE_ERROR = 197;
BrickletNFCRFID.KEY_A = 0;
BrickletNFCRFID.KEY_B = 1;

function BrickletNFCRFID(uid, ipcon) {
	//Reads and writes NFC and RFID tags

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletNFCRFID.DEVICE_IDENTIFIER, BrickletNFCRFID.DEVICE_DISPLAY_NAME);
	BrickletNFCRFID.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickletNFCRFID.FUNCTION_REQUEST_TAG_ID] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletNFCRFID.FUNCTION_GET_TAG_ID] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletNFCRFID.FUNCTION_GET_STATE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletNFCRFID.FUNCTION_AUTHENTICATE_MIFARE_CLASSIC_PAGE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletNFCRFID.FUNCTION_WRITE_PAGE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletNFCRFID.FUNCTION_REQUEST_PAGE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletNFCRFID.FUNCTION_GET_PAGE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletNFCRFID.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletNFCRFID.CALLBACK_STATE_CHANGED] = [10, 'B ?'];



	this.requestTagID = function(tagType, returnCallback, errorCallback) {
		/*
		To read or write a tag that is in proximity of the NFC/RFID Bricklet you
		first have to call this function with the expected tag type as parameter.
		It is no problem if you don't know the tag type. You can cycle through
		the available tag types until the tag gives an answer to the request.
		
		Currently the following tag types are supported:
		
		* Mifare Classic
		* NFC Forum Type 1
		* NFC Forum Type 2
		
		After you call :func:`Request Tag ID` the NFC/RFID Bricklet will try to read
		the tag ID from the tag. After this process is done the state will change.
		You can either register the :cb:`State Changed` callback or you can poll
		:func:`Get State` to find out about the state change.
		
		If the state changes to *RequestTagIDError* it means that either there was
		no tag present or that the tag is of an incompatible type. If the state
		changes to *RequestTagIDReady* it means that a compatible tag was found
		and that the tag ID could be read out. You can now get the tag ID by
		calling :func:`Get Tag ID`.
		
		If two tags are in the proximity of the NFC/RFID Bricklet, this
		function will cycle through the tags. To select a specific tag you have
		to call :func:`Request Tag ID` until the correct tag id is found.
		
		In case of any *Error* state the selection is lost and you have to
		start again by calling :func:`Request Tag ID`.
		*/
		this.ipcon.sendRequest(this, BrickletNFCRFID.FUNCTION_REQUEST_TAG_ID, [tagType], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getTagID = function(returnCallback, errorCallback) {
		/*
		Returns the tag type, tag ID and the length of the tag ID
		(4 or 7 bytes are possible length). This function can only be called if the
		NFC/RFID is currently in one of the *Ready* states. The returned ID
		is the ID that was saved through the last call of :func:`Request Tag ID`.
		
		To get the tag ID of a tag the approach is as follows:
		
		1. Call :func:`Request Tag ID`
		2. Wait for state to change to *RequestTagIDReady* (see :func:`Get State` or
		   :cb:`State Changed` callback)
		3. Call :func:`Get Tag ID`
		*/
		this.ipcon.sendRequest(this, BrickletNFCRFID.FUNCTION_GET_TAG_ID, [], '', 17, 'B B B7', returnCallback, errorCallback, false, true);
	};
	this.getState = function(returnCallback, errorCallback) {
		/*
		Returns the current state of the NFC/RFID Bricklet.
		
		On startup the Bricklet will be in the *Initialization* state. The
		initialization will only take about 20ms. After that it changes to *Idle*.
		
		The functions of this Bricklet can be called in the *Idle* state and all of
		the *Ready* and *Error* states.
		
		Example: If you call :func:`Request Page`, the state will change to
		*RequestPage* until the reading of the page is finished. Then it will change
		to either *RequestPageReady* if it worked or to *RequestPageError* if it
		didn't. If the request worked you can get the page by calling :func:`Get Page`.
		
		The same approach is used analogously for the other API functions.
		*/
		this.ipcon.sendRequest(this, BrickletNFCRFID.FUNCTION_GET_STATE, [], '', 10, 'B ?', returnCallback, errorCallback, false, true);
	};
	this.authenticateMifareClassicPage = function(page, keyNumber, key, returnCallback, errorCallback) {
		/*
		Mifare Classic tags use authentication. If you want to read from or write to
		a Mifare Classic page you have to authenticate it beforehand.
		Each page can be authenticated with two keys: A (``key_number`` = 0) and B
		(``key_number`` = 1). A new Mifare Classic
		tag that has not yet been written to can be accessed with key A
		and the default key ``[0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]``.
		
		The approach to read or write a Mifare Classic page is as follows:
		
		1. Call :func:`Request Tag ID`
		2. Wait for state to change to *RequestTagIDReady* (see :func:`Get State`
		   or :cb:`State Changed` callback)
		3. If looking for a specific tag then call :func:`Get Tag ID` and check if the
		   expected tag was found, if it was not found go back to step 1
		4. Call :func:`Authenticate Mifare Classic Page` with page and key for the page
		5. Wait for state to change to *AuthenticatingMifareClassicPageReady* (see
		   :func:`Get State` or :cb:`State Changed` callback)
		6. Call :func:`Request Page` or :func:`Write Page` to read/write page
		*/
		this.ipcon.sendRequest(this, BrickletNFCRFID.FUNCTION_AUTHENTICATE_MIFARE_CLASSIC_PAGE, [page, keyNumber, key], 'H B B6', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writePage = function(page, data, returnCallback, errorCallback) {
		/*
		Writes 16 bytes starting from the given page. How many pages are written
		depends on the tag type. The page sizes are as follows:
		
		* Mifare Classic page size: 16 byte (one page is written)
		* NFC Forum Type 1 page size: 8 byte (two pages are written)
		* NFC Forum Type 2 page size: 4 byte (four pages are written)
		
		The general approach for writing to a tag is as follows:
		
		1. Call :func:`Request Tag ID`
		2. Wait for state to change to *RequestTagIDReady* (see :func:`Get State` or
		   :cb:`State Changed` callback)
		3. If looking for a specific tag then call :func:`Get Tag ID` and check if the
		   expected tag was found, if it was not found got back to step 1
		4. Call :func:`Write Page` with page number and data
		5. Wait for state to change to *WritePageReady* (see :func:`Get State` or
		   :cb:`State Changed` callback)
		
		If you use a Mifare Classic tag you have to authenticate a page before you
		can write to it. See :func:`Authenticate Mifare Classic Page`.
		*/
		this.ipcon.sendRequest(this, BrickletNFCRFID.FUNCTION_WRITE_PAGE, [page, data], 'H B16', 0, '', returnCallback, errorCallback, false, true);
	};
	this.requestPage = function(page, returnCallback, errorCallback) {
		/*
		Reads 16 bytes starting from the given page and stores them into a buffer.
		The buffer can then be read out with :func:`Get Page`.
		How many pages are read depends on the tag type. The page sizes are
		as follows:
		
		* Mifare Classic page size: 16 byte (one page is read)
		* NFC Forum Type 1 page size: 8 byte (two pages are read)
		* NFC Forum Type 2 page size: 4 byte (four pages are read)
		
		The general approach for reading a tag is as follows:
		
		1. Call :func:`Request Tag ID`
		2. Wait for state to change to *RequestTagIDReady* (see :func:`Get State`
		   or :cb:`State Changed` callback)
		3. If looking for a specific tag then call :func:`Get Tag ID` and check if the
		   expected tag was found, if it was not found got back to step 1
		4. Call :func:`Request Page` with page number
		5. Wait for state to change to *RequestPageReady* (see :func:`Get State`
		   or :cb:`State Changed` callback)
		6. Call :func:`Get Page` to retrieve the page from the buffer
		
		If you use a Mifare Classic tag you have to authenticate a page before you
		can read it. See :func:`Authenticate Mifare Classic Page`.
		*/
		this.ipcon.sendRequest(this, BrickletNFCRFID.FUNCTION_REQUEST_PAGE, [page], 'H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getPage = function(returnCallback, errorCallback) {
		/*
		Returns 16 bytes of data from an internal buffer. To fill the buffer
		with specific pages you have to call :func:`Request Page` beforehand.
		*/
		this.ipcon.sendRequest(this, BrickletNFCRFID.FUNCTION_GET_PAGE, [], '', 24, 'B16', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletNFCRFID.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletNFCRFID;

},{"./Device":279,"./IPConnection":280}],230:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletOLED128x64.DEVICE_IDENTIFIER = 263;
BrickletOLED128x64.DEVICE_DISPLAY_NAME = 'OLED 128x64 Bricklet';
BrickletOLED128x64.FUNCTION_WRITE = 1;
BrickletOLED128x64.FUNCTION_NEW_WINDOW = 2;
BrickletOLED128x64.FUNCTION_CLEAR_DISPLAY = 3;
BrickletOLED128x64.FUNCTION_SET_DISPLAY_CONFIGURATION = 4;
BrickletOLED128x64.FUNCTION_GET_DISPLAY_CONFIGURATION = 5;
BrickletOLED128x64.FUNCTION_WRITE_LINE = 6;
BrickletOLED128x64.FUNCTION_GET_IDENTITY = 255;

function BrickletOLED128x64(uid, ipcon) {
	//3.3cm (1.3") OLED display with 128x64 pixels

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletOLED128x64.DEVICE_IDENTIFIER, BrickletOLED128x64.DEVICE_DISPLAY_NAME);
	BrickletOLED128x64.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickletOLED128x64.FUNCTION_WRITE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletOLED128x64.FUNCTION_NEW_WINDOW] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletOLED128x64.FUNCTION_CLEAR_DISPLAY] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletOLED128x64.FUNCTION_SET_DISPLAY_CONFIGURATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletOLED128x64.FUNCTION_GET_DISPLAY_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletOLED128x64.FUNCTION_WRITE_LINE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletOLED128x64.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;



	this.write = function(data, returnCallback, errorCallback) {
		/*
		Appends 64 byte of data to the window as set by :func:`New Window`.
		
		Each row has a height of 8 pixels which corresponds to one byte of data.
		
		Example: if you call :func:`New Window` with column from 0 to 127 and row
		from 0 to 7 (the whole display) each call of :func:`Write` (red arrow) will
		write half of a row.
		
		.. image:: /Images/Bricklets/bricklet_oled_128x64_display.png
		   :scale: 100 %
		   :alt: Display pixel order
		   :align: center
		   :target: ../../_images/Bricklets/bricklet_oled_128x64_display.png
		
		The LSB (D0) of each data byte is at the top and the MSB (D7) is at the
		bottom of the row.
		
		The next call of :func:`Write` will write the second half of the row
		and the next two the second row and so on. To fill the whole display
		you need to call :func:`Write` 16 times.
		*/
		this.ipcon.sendRequest(this, BrickletOLED128x64.FUNCTION_WRITE, [data], 'B64', 0, '', returnCallback, errorCallback, false, true);
	};
	this.newWindow = function(columnFrom, columnTo, rowFrom, rowTo, returnCallback, errorCallback) {
		/*
		Sets the window in which you can write with :func:`Write`. One row
		has a height of 8 pixels.
		*/
		this.ipcon.sendRequest(this, BrickletOLED128x64.FUNCTION_NEW_WINDOW, [columnFrom, columnTo, rowFrom, rowTo], 'B B B B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.clearDisplay = function(returnCallback, errorCallback) {
		/*
		Clears the current content of the window as set by :func:`New Window`.
		*/
		this.ipcon.sendRequest(this, BrickletOLED128x64.FUNCTION_CLEAR_DISPLAY, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.setDisplayConfiguration = function(contrast, invert, returnCallback, errorCallback) {
		/*
		Sets the configuration of the display.
		
		You can set a contrast value from 0 to 255 and you can invert the color
		(black/white) of the display.
		*/
		this.ipcon.sendRequest(this, BrickletOLED128x64.FUNCTION_SET_DISPLAY_CONFIGURATION, [contrast, invert], 'B ?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getDisplayConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Display Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletOLED128x64.FUNCTION_GET_DISPLAY_CONFIGURATION, [], '', 10, 'B ?', returnCallback, errorCallback, false, true);
	};
	this.writeLine = function(line, position, text, returnCallback, errorCallback) {
		/*
		Writes text to a specific line with a specific position.
		The text can have a maximum of 26 characters.
		
		For example: (1, 10, "Hello") will write *Hello* in the middle of the
		second line of the display.
		
		You can draw to the display with :func:`Write` and then add text to it
		afterwards.
		
		The display uses a special 5x7 pixel charset. You can view the characters
		of the charset in Brick Viewer.
		*/
		this.ipcon.sendRequest(this, BrickletOLED128x64.FUNCTION_WRITE_LINE, [line, position, text], 'B B s26', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletOLED128x64.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletOLED128x64;

},{"./Device":279,"./IPConnection":280}],231:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletOLED128x64V2.DEVICE_IDENTIFIER = 2112;
BrickletOLED128x64V2.DEVICE_DISPLAY_NAME = 'OLED 128x64 Bricklet 2.0';
BrickletOLED128x64V2.FUNCTION_WRITE_PIXELS_LOW_LEVEL = 1;
BrickletOLED128x64V2.FUNCTION_READ_PIXELS_LOW_LEVEL = 2;
BrickletOLED128x64V2.FUNCTION_CLEAR_DISPLAY = 3;
BrickletOLED128x64V2.FUNCTION_SET_DISPLAY_CONFIGURATION = 4;
BrickletOLED128x64V2.FUNCTION_GET_DISPLAY_CONFIGURATION = 5;
BrickletOLED128x64V2.FUNCTION_WRITE_LINE = 6;
BrickletOLED128x64V2.FUNCTION_DRAW_BUFFERED_FRAME = 7;
BrickletOLED128x64V2.FUNCTION_GET_SPITFP_ERROR_COUNT = 234;
BrickletOLED128x64V2.FUNCTION_SET_BOOTLOADER_MODE = 235;
BrickletOLED128x64V2.FUNCTION_GET_BOOTLOADER_MODE = 236;
BrickletOLED128x64V2.FUNCTION_SET_WRITE_FIRMWARE_POINTER = 237;
BrickletOLED128x64V2.FUNCTION_WRITE_FIRMWARE = 238;
BrickletOLED128x64V2.FUNCTION_SET_STATUS_LED_CONFIG = 239;
BrickletOLED128x64V2.FUNCTION_GET_STATUS_LED_CONFIG = 240;
BrickletOLED128x64V2.FUNCTION_GET_CHIP_TEMPERATURE = 242;
BrickletOLED128x64V2.FUNCTION_RESET = 243;
BrickletOLED128x64V2.FUNCTION_WRITE_UID = 248;
BrickletOLED128x64V2.FUNCTION_READ_UID = 249;
BrickletOLED128x64V2.FUNCTION_GET_IDENTITY = 255;
BrickletOLED128x64V2.BOOTLOADER_MODE_BOOTLOADER = 0;
BrickletOLED128x64V2.BOOTLOADER_MODE_FIRMWARE = 1;
BrickletOLED128x64V2.BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT = 2;
BrickletOLED128x64V2.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT = 3;
BrickletOLED128x64V2.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT = 4;
BrickletOLED128x64V2.BOOTLOADER_STATUS_OK = 0;
BrickletOLED128x64V2.BOOTLOADER_STATUS_INVALID_MODE = 1;
BrickletOLED128x64V2.BOOTLOADER_STATUS_NO_CHANGE = 2;
BrickletOLED128x64V2.BOOTLOADER_STATUS_ENTRY_FUNCTION_NOT_PRESENT = 3;
BrickletOLED128x64V2.BOOTLOADER_STATUS_DEVICE_IDENTIFIER_INCORRECT = 4;
BrickletOLED128x64V2.BOOTLOADER_STATUS_CRC_MISMATCH = 5;
BrickletOLED128x64V2.STATUS_LED_CONFIG_OFF = 0;
BrickletOLED128x64V2.STATUS_LED_CONFIG_ON = 1;
BrickletOLED128x64V2.STATUS_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletOLED128x64V2.STATUS_LED_CONFIG_SHOW_STATUS = 3;

function BrickletOLED128x64V2(uid, ipcon) {
	//3.3cm (1.3") OLED display with 128x64 pixels

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletOLED128x64V2.DEVICE_IDENTIFIER, BrickletOLED128x64V2.DEVICE_DISPLAY_NAME);
	BrickletOLED128x64V2.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickletOLED128x64V2.FUNCTION_WRITE_PIXELS_LOW_LEVEL] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletOLED128x64V2.FUNCTION_READ_PIXELS_LOW_LEVEL] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletOLED128x64V2.FUNCTION_CLEAR_DISPLAY] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletOLED128x64V2.FUNCTION_SET_DISPLAY_CONFIGURATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletOLED128x64V2.FUNCTION_GET_DISPLAY_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletOLED128x64V2.FUNCTION_WRITE_LINE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletOLED128x64V2.FUNCTION_DRAW_BUFFERED_FRAME] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletOLED128x64V2.FUNCTION_GET_SPITFP_ERROR_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletOLED128x64V2.FUNCTION_SET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletOLED128x64V2.FUNCTION_GET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletOLED128x64V2.FUNCTION_SET_WRITE_FIRMWARE_POINTER] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletOLED128x64V2.FUNCTION_WRITE_FIRMWARE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletOLED128x64V2.FUNCTION_SET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletOLED128x64V2.FUNCTION_GET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletOLED128x64V2.FUNCTION_GET_CHIP_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletOLED128x64V2.FUNCTION_RESET] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletOLED128x64V2.FUNCTION_WRITE_UID] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletOLED128x64V2.FUNCTION_READ_UID] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletOLED128x64V2.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;


	this.streamStateObjects[BrickletOLED128x64V2.FUNCTION_WRITE_PIXELS_LOW_LEVEL] = {
		'dataMapping': [],
		'dataMappingStreamIn': [null, null, null, null, 'streamLength', 'streamChunkOffset', 'streamChunkData'],
		'streamProperties': {
			'fixedLength': null,
			'singleChunk': false,
			'shortWrite': false
		},
		'responseProperties': {
			'running': false,
			'runningSubcall': false,
			'runningSubcallOOS': false,
			'waitingFirstChunk': true,
			'timeout': null,
			'data': [],
			'streamInChunkOffset': 0,
			'streamInChunkLength': 0,
			'streamInResponseEmpty': true,
			'streamInWritten': 0,
			'streamInLLParams': null,
			'responseHandler': null,
			'packFormatString': 'B B B B H H ?448',
			'unpackFormatString': '',
			'returnCB': null,
			'errorCB': null,
			'callQueue': []
		}
	};
	this.streamStateObjects[BrickletOLED128x64V2.FUNCTION_READ_PIXELS_LOW_LEVEL] = {
		'dataMapping': ['streamLength', 'streamChunkOffset', 'streamChunkData'],
		'dataMappingStreamIn': [],
		'streamProperties': {
			'fixedLength': null,
			'singleChunk': false,
			'shortWrite': false
		},
		'responseProperties': {
			'running': false,
			'runningSubcall': false,
			'runningSubcallOOS': false,
			'waitingFirstChunk': true,
			'timeout': null,
			'data': [],
			'streamInChunkOffset': 0,
			'streamInChunkLength': 0,
			'streamInResponseEmpty': true,
			'streamInWritten': 0,
			'streamInLLParams': null,
			'responseHandler': null,
			'packFormatString': 'B B B B',
			'unpackFormatString': 'H H ?480',
			'returnCB': null,
			'errorCB': null,
			'callQueue': []
		}
	};

	this.writePixelsLowLevel = function(xStart, yStart, xEnd, yEnd, pixelsLength, pixelsChunkOffset, pixelsChunkData, returnCallback, errorCallback) {
		/*
		Writes pixels to the specified window.
		
		The pixels are written into the window line by line top to bottom
		and each line is written from left to right.
		
		If automatic draw is enabled (default) the pixels are directly written to
		the screen. Only pixels that have actually changed are updated on the screen,
		the rest stays the same.
		
		If automatic draw is disabled the pixels are written to an internal buffer and
		the buffer is transferred to the display only after :func:`Draw Buffered Frame`
		is called. This can be used to avoid flicker when drawing a complex frame in
		multiple steps.
		
		Automatic draw can be configured with the :func:`Set Display Configuration`
		function.
		*/
		this.ipcon.sendRequest(this, BrickletOLED128x64V2.FUNCTION_WRITE_PIXELS_LOW_LEVEL, [xStart, yStart, xEnd, yEnd, pixelsLength, pixelsChunkOffset, pixelsChunkData], 'B B B B H H ?448', 0, '', returnCallback, errorCallback, false, true);
	};
	this.readPixelsLowLevel = function(xStart, yStart, xEnd, yEnd, returnCallback, errorCallback) {
		/*
		Reads pixels from the specified window.
		
		The pixels are read from the window line by line top to bottom
		and each line is read from left to right.
		
		If automatic draw is enabled (default) the pixels that are read are always the
		same that are shown on the display.
		
		If automatic draw is disabled the pixels are read from the internal buffer
		(see :func:`Draw Buffered Frame`).
		
		Automatic draw can be configured with the :func:`Set Display Configuration`
		function.
		*/
		this.ipcon.sendRequest(this, BrickletOLED128x64V2.FUNCTION_READ_PIXELS_LOW_LEVEL, [xStart, yStart, xEnd, yEnd], 'B B B B', 72, 'H H ?480', returnCallback, errorCallback, false, true);
	};
	this.clearDisplay = function(returnCallback, errorCallback) {
		/*
		Clears the complete content of the display.
		
		If automatic draw is enabled (default) the pixels are directly cleared.
		
		If automatic draw is disabled the the internal buffer is cleared and
		the buffer is transferred to the display only after :func:`Draw Buffered Frame`
		is called. This can be used to avoid flicker when drawing a complex frame in
		multiple steps.
		
		Automatic draw can be configured with the :func:`Set Display Configuration`
		function.
		*/
		this.ipcon.sendRequest(this, BrickletOLED128x64V2.FUNCTION_CLEAR_DISPLAY, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.setDisplayConfiguration = function(contrast, invert, automaticDraw, returnCallback, errorCallback) {
		/*
		Sets the configuration of the display.
		
		You can set a contrast value from 0 to 255 and you can invert the color
		(white/black) of the display.
		
		If automatic draw is set to *true*, the display is automatically updated with every
		call of :func:`Write Pixels` or :func:`Write Line`. If it is set to false, the
		changes are written into an internal buffer and only shown on the display after
		a call of :func:`Draw Buffered Frame`.
		*/
		this.ipcon.sendRequest(this, BrickletOLED128x64V2.FUNCTION_SET_DISPLAY_CONFIGURATION, [contrast, invert, automaticDraw], 'B ? ?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getDisplayConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Display Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletOLED128x64V2.FUNCTION_GET_DISPLAY_CONFIGURATION, [], '', 11, 'B ? ?', returnCallback, errorCallback, false, true);
	};
	this.writeLine = function(line, position, text, returnCallback, errorCallback) {
		/*
		Writes text to a specific line with a specific position.
		The text can have a maximum of 22 characters.
		
		For example: (1, 10, "Hello") will write *Hello* in the middle of the
		second line of the display.
		
		The display uses a special 5x7 pixel charset. You can view the characters
		of the charset in Brick Viewer.
		
		If automatic draw is enabled (default) the text is directly written to
		the screen. Only pixels that have actually changed are updated on the screen,
		the rest stays the same.
		
		If automatic draw is disabled the text is written to an internal buffer and
		the buffer is transferred to the display only after :func:`Draw Buffered Frame`
		is called. This can be used to avoid flicker when drawing a complex frame in
		multiple steps.
		
		Automatic draw can be configured with the :func:`Set Display Configuration`
		function.
		*/
		this.ipcon.sendRequest(this, BrickletOLED128x64V2.FUNCTION_WRITE_LINE, [line, position, text], 'B B s22', 0, '', returnCallback, errorCallback, false, true);
	};
	this.drawBufferedFrame = function(forceCompleteRedraw, returnCallback, errorCallback) {
		/*
		Draws the currently buffered frame. Normally each call of :func:`Write Pixels` and
		:func:`Write Line` draws directly onto the display. If you turn automatic draw off
		(:func:`Set Display Configuration`), the data is written in an internal buffer and
		only transferred to the display by calling this function. This can be used to
		avoid flicker when drawing a complex frame in multiple steps.
		
		Set the `force complete redraw` to *true* to redraw the whole display
		instead of only the changed parts. Normally it should not be necessary to set this to
		*true*. It may only become necessary in case of stuck pixels because of errors.
		*/
		this.ipcon.sendRequest(this, BrickletOLED128x64V2.FUNCTION_DRAW_BUFFERED_FRAME, [forceCompleteRedraw], '?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPErrorCount = function(returnCallback, errorCallback) {
		/*
		Returns the error count for the communication between Brick and Bricklet.
		
		The errors are divided into
		
		* ACK checksum errors,
		* message checksum errors,
		* framing errors and
		* overflow errors.
		
		The errors counts are for errors that occur on the Bricklet side. All
		Bricks have a similar function that returns the errors on the Brick side.
		*/
		this.ipcon.sendRequest(this, BrickletOLED128x64V2.FUNCTION_GET_SPITFP_ERROR_COUNT, [], '', 24, 'I I I I', returnCallback, errorCallback, false, true);
	};
	this.setBootloaderMode = function(mode, returnCallback, errorCallback) {
		/*
		Sets the bootloader mode and returns the status after the requested
		mode change was instigated.
		
		You can change from bootloader mode to firmware mode and vice versa. A change
		from bootloader mode to firmware mode will only take place if the entry function,
		device identifier and CRC are present and correct.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletOLED128x64V2.FUNCTION_SET_BOOTLOADER_MODE, [mode], 'B', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getBootloaderMode = function(returnCallback, errorCallback) {
		/*
		Returns the current bootloader mode, see :func:`Set Bootloader Mode`.
		*/
		this.ipcon.sendRequest(this, BrickletOLED128x64V2.FUNCTION_GET_BOOTLOADER_MODE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setWriteFirmwarePointer = function(pointer, returnCallback, errorCallback) {
		/*
		Sets the firmware pointer for :func:`Write Firmware`. The pointer has
		to be increased by chunks of size 64. The data is written to flash
		every 4 chunks (which equals to one page of size 256).
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletOLED128x64V2.FUNCTION_SET_WRITE_FIRMWARE_POINTER, [pointer], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeFirmware = function(data, returnCallback, errorCallback) {
		/*
		Writes 64 Bytes of firmware at the position as written by
		:func:`Set Write Firmware Pointer` before. The firmware is written
		to flash every 4 chunks.
		
		You can only write firmware in bootloader mode.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletOLED128x64V2.FUNCTION_WRITE_FIRMWARE, [data], 'B64', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setStatusLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Sets the status LED configuration. By default the LED shows
		communication traffic between Brick and Bricklet, it flickers once
		for every 10 received data packets.
		
		You can also turn the LED permanently on/off or show a heartbeat.
		
		If the Bricklet is in bootloader mode, the LED is will show heartbeat by default.
		*/
		this.ipcon.sendRequest(this, BrickletOLED128x64V2.FUNCTION_SET_STATUS_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getStatusLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Status LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletOLED128x64V2.FUNCTION_GET_STATUS_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getChipTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature as measured inside the microcontroller. The
		value returned is not the ambient temperature!
		
		The temperature is only proportional to the real temperature and it has bad
		accuracy. Practically it is only useful as an indicator for
		temperature changes.
		*/
		this.ipcon.sendRequest(this, BrickletOLED128x64V2.FUNCTION_GET_CHIP_TEMPERATURE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.reset = function(returnCallback, errorCallback) {
		/*
		Calling this function will reset the Bricklet. All configurations
		will be lost.
		
		After a reset you have to create new device objects,
		calling functions on the existing ones will result in
		undefined behavior!
		*/
		this.ipcon.sendRequest(this, BrickletOLED128x64V2.FUNCTION_RESET, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeUID = function(uid, returnCallback, errorCallback) {
		/*
		Writes a new UID into flash. If you want to set a new UID
		you have to decode the Base58 encoded UID string into an
		integer first.
		
		We recommend that you use Brick Viewer to change the UID.
		*/
		this.ipcon.sendRequest(this, BrickletOLED128x64V2.FUNCTION_WRITE_UID, [uid], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.readUID = function(returnCallback, errorCallback) {
		/*
		Returns the current UID as an integer. Encode as
		Base58 to get the usual string version.
		*/
		this.ipcon.sendRequest(this, BrickletOLED128x64V2.FUNCTION_READ_UID, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletOLED128x64V2.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};
	this.writePixels = function(xStart, yStart, xEnd, yEnd, pixels, returnCallback, errorCallback) {
		/*
		Writes pixels to the specified window.
		
		The pixels are written into the window line by line top to bottom
		and each line is written from left to right.
		
		If automatic draw is enabled (default) the pixels are directly written to
		the screen. Only pixels that have actually changed are updated on the screen,
		the rest stays the same.
		
		If automatic draw is disabled the pixels are written to an internal buffer and
		the buffer is transferred to the display only after :func:`Draw Buffered Frame`
		is called. This can be used to avoid flicker when drawing a complex frame in
		multiple steps.
		
		Automatic draw can be configured with the :func:`Set Display Configuration`
		function.
		*/

		var pixelsLength = 0;
		var pixelsChunkData = [];
		var pixelsChunkOffset = 0;
		var streamStateObject = this.streamStateObjects[1];

		if (pixels.length > 65535) {
			if (errorCallback !== null){
				errorCallback(IPConnection.ERROR_INVALID_PARAMETER);
			}

			this.resetStreamStateObject(streamStateObject);

			if (streamStateObject['responseProperties']['callQueue'].length > 0) {
				streamStateObject['responseProperties']['callQueue'].shift()(device);
			}

			return;
		}

		if (!this.getResponseExpected(1)) {
			if (streamStateObject['streamProperties']['fixedLength']) {
				pixelsLength = streamStateObject['streamProperties']['fixedLength'];
			}
			else {
				pixelsLength = pixels.length;
			}

			if (streamStateObject['streamProperties']['singleChunk']) {
				pixelsChunkData =
					this.ipcon.createChunkData(pixels, 0, 448, '\0');

				this.ipcon.sendRequest(this,
				                       BrickletOLED128x64V2.FUNCTION_WRITE_PIXELS_LOW_LEVEL,
				                       [xStart, yStart, xEnd, yEnd, pixelsLength, pixelsChunkOffset, pixelsChunkData],
				                       'B B B B H H ?448',
				                       0,
				                       '',
				                       returnCallback,
				                       errorCallback,
				                       false,
				                       true);
			}
			else {
				while (pixelsChunkOffset < pixels.length) {
					pixelsChunkData =
						this.ipcon.createChunkData(pixels, pixelsChunkOffset, 448, '\0');

					this.ipcon.sendRequest(this,
					                       BrickletOLED128x64V2.FUNCTION_WRITE_PIXELS_LOW_LEVEL,
					                       [xStart, yStart, xEnd, yEnd, pixelsLength, pixelsChunkOffset, pixelsChunkData],
					                       'B B B B H H ?448',
					                       0,
					                       '',
					                       returnCallback,
					                       errorCallback,
					                       false,
					                       true);

					pixelsChunkOffset += 448;
				}
			}

			if (returnCallback) {
				returnCallback();
			}
		}
		else {
			var responseHandler = null;
			var functionToQueue = null;

			if (streamStateObject['responseProperties']['responseHandler'] === null) {
				responseHandler = function (device, fid, packetResponse) {
					var result = [];
					var payload = null;
					var llvalues = null;
					var packetErrorFlag = 0;
					var rolesMappedData = [];
					var shortWriteWritten = -1;
					var streamStateObject = device.streamStateObjects[fid];
					var responseEmpty = streamStateObject['responseProperties']['streamInResponseEmpty'];
					var pixelsLength = 0;
					var pixelsChunkData = [];
					var pixelsChunkOffset = 0;

					function doNextLLCall() {
						pixelsLength = streamStateObject['responseProperties']['data'].length;
						pixelsChunkData =
							device.ipcon.createChunkData(streamStateObject['responseProperties']['data'],
							                             streamStateObject['responseProperties']['streamInChunkOffset'],
							                             streamStateObject['responseProperties']['streamInChunkLength'],
							                             '\0');
						pixelsChunkOffset = streamStateObject['responseProperties']['streamInChunkOffset'];

						for (var i = 0; i < streamStateObject['dataMappingStreamIn'].length; i++) {
							if (streamStateObject['dataMappingStreamIn'][i] === null) {
								continue;
							}

							if (streamStateObject['dataMappingStreamIn'][i].endsWith('Length')) {
								streamStateObject['responseProperties']['streamInLLParams'][i] = pixelsLength;
							}
							else if (streamStateObject['dataMappingStreamIn'][i].endsWith('Offset')) {
								streamStateObject['responseProperties']['streamInLLParams'][i] = pixelsChunkOffset;
							}
							else if (streamStateObject['dataMappingStreamIn'][i].endsWith('Data')) {
								streamStateObject['responseProperties']['streamInLLParams'][i] = pixelsChunkData;
							}
						}

						device.ipcon.sendRequest(device,
						                         BrickletOLED128x64V2.FUNCTION_WRITE_PIXELS_LOW_LEVEL,
						                         streamStateObject['responseProperties']['streamInLLParams'],
						                         'B B B B H H ?448',
						                         0,
						                         '',
						                         returnCallback,
						                         errorCallback,
						                         true,
						                         true);

						streamStateObject['responseProperties']['streamInChunkOffset'] += 448;
					}

					function handleStreamInDone() {
						if (streamStateObject['responseProperties']['returnCB']) {
							if (streamStateObject['streamProperties']['shortWrite']) {
								for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
									if (streamStateObject['dataMapping'][i].endsWith('Written')) {
										result[i] = streamStateObject['responseProperties']['streamInWritten'];
										break;
									}
								}
							}

							if (!responseEmpty) {
								streamStateObject['responseProperties']['returnCB'].apply(device, result);
							}
							else {
								streamStateObject['responseProperties']['returnCB'].apply(device);
							}
						}

						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}
					}

					if (!streamStateObject) {
						return;
					}

					packetErrorFlag = device.ipcon.getEFromPacket(packetResponse);

					if (packetErrorFlag !== 0) {
						if (streamStateObject['responseProperties']['errorCB'] !== undefined) {
							if (packetErrorFlag === 1) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_INVALID_PARAMETER);
							}
							else if (packetErrorFlag === 2) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_FUNCTION_NOT_SUPPORTED);
							}
							else {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_UNKNOWN_ERROR);
							}
						}

						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}

						return;
					}

					if (responseEmpty) {
						if (streamStateObject['streamProperties']['singleChunk']) {
							handleStreamInDone();

							return;
						}

						if (streamStateObject['responseProperties']['streamInChunkOffset'] < streamStateObject['responseProperties']['data'].length) {
							doNextLLCall();
						}
						else {
							handleStreamInDone();
						}
					}
					else {
						payload = device.ipcon.getPayloadFromPacket(packetResponse);
						llvalues = device.ipcon.unpack(payload,
						                               streamStateObject['responseProperties']['unpackFormatString']);

						if (!payload || !llvalues) {
							device.resetStreamStateObject(streamStateObject);

							if (streamStateObject['responseProperties']['callQueue'].length > 0) {
								streamStateObject['responseProperties']['callQueue'].shift()(device);
							}

							return;
						}

						for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
							result.push(llvalues[i]);
						}

						if (streamStateObject['streamProperties']['singleChunk']) {
							if (streamStateObject['responseProperties']['returnCB']) {
								streamStateObject['responseProperties']['returnCB'].apply(device, result);
							}

							device.resetStreamStateObject(streamStateObject);

							if (streamStateObject['responseProperties']['callQueue'].length > 0) {
								streamStateObject['responseProperties']['callQueue'].shift()(device);
							}

							return;
						}

						if (streamStateObject['streamProperties']['shortWrite']) {
							for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
								if (streamStateObject['dataMapping'][i].endsWith('Written')) {
									shortWriteWritten = llvalues[i];
									streamStateObject['responseProperties']['streamInWritten'] += shortWriteWritten;
									break;
								}
							}
							if ((shortWriteWritten !== -1) && (shortWriteWritten < 448)) {
								// Either last chunk or short write
								handleStreamInDone();
								return;
							}
						}

						if (streamStateObject['responseProperties']['streamInChunkOffset'] < streamStateObject['responseProperties']['data'].length) {
							doNextLLCall();
						}
						else {
							handleStreamInDone();
						}
					}
				};

				streamStateObject['responseProperties']['responseHandler'] = responseHandler;
			}

			if (!streamStateObject['responseProperties']['running']) {
				streamStateObject['responseProperties']['running'] = true;
				streamStateObject['responseProperties']['returnCB'] = returnCallback;
				streamStateObject['responseProperties']['errorCB'] = errorCallback;
				streamStateObject['responseProperties']['data'].length = 0;
				streamStateObject['responseProperties']['data'].push.apply(streamStateObject['responseProperties']['data'],
				                                                           pixels);

				if (streamStateObject['streamProperties']['fixedLength']) {
					pixelsLength = streamStateObject['streamProperties']['fixedLength'];
				}
				else {
					pixelsLength = pixels.length;
				}

				pixelsChunkOffset = 0;
				pixelsChunkData =
					this.ipcon.createChunkData(pixels, 0, 448, '\0');

				streamStateObject['responseProperties']['streamInChunkOffset'] = 448;
				streamStateObject['responseProperties']['streamInChunkLength'] = 448;
				streamStateObject['responseProperties']['streamInLLParams'] = [xStart, yStart, xEnd, yEnd, pixelsLength, pixelsChunkOffset, pixelsChunkData];

				this.ipcon.sendRequest(this,
				                       BrickletOLED128x64V2.FUNCTION_WRITE_PIXELS_LOW_LEVEL,
				                       [xStart, yStart, xEnd, yEnd, pixelsLength, pixelsChunkOffset, pixelsChunkData],
				                       'B B B B H H ?448',
				                       0,
				                       '',
				                       returnCallback,
				                       errorCallback,
				                       true,
				                       true);
			}
			else {
				functionToQueue = function (device) {
					device.writePixels.call(device, xStart, yStart, xEnd, yEnd, pixels, returnCallback, errorCallback);
				}

				streamStateObject['responseProperties']['callQueue'].push(functionToQueue);
			}
		}
	};

	this.readPixels = function(xStart, yStart, xEnd, yEnd, returnCallback, errorCallback) {
		/*
		Reads pixels from the specified window.
		
		The pixels are read from the window line by line top to bottom
		and each line is read from left to right.
		
		If automatic draw is enabled (default) the pixels that are read are always the
		same that are shown on the display.
		
		If automatic draw is disabled the pixels are read from the internal buffer
		(see :func:`Draw Buffered Frame`).
		
		Automatic draw can be configured with the :func:`Set Display Configuration`
		function.
		*/
		var responseHandler = null;
		var functionToQueue = null;
		var streamStateObject = this.streamStateObjects[2];
		if (streamStateObject['responseProperties']['responseHandler'] === null) {
			responseHandler = 
				function (device, fid, packetResponse) {
					var result = [];
					var llvalues = null;
					var packetErrorFlag = 0;
					var rolesMappedData = [];
					var pixelsLength = null;
					var pixelsChunkData = null;
					var pixelsOutOfSync = false;
					var streamStateObject = device.streamStateObjects[fid];
					var pixelsChunkOffset = null;
					var payload = device.ipcon.getPayloadFromPacket(packetResponse);

					packetErrorFlag = device.ipcon.getEFromPacket(packetResponse);

					if (packetErrorFlag !== 0) {
						if (streamStateObject['responseProperties']['errorCB'] !== undefined) {
							if (packetErrorFlag === 1) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_INVALID_PARAMETER);
							}
							else if (packetErrorFlag === 2) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_FUNCTION_NOT_SUPPORTED);
							}
							else {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_UNKNOWN_ERROR);
							}
						}

						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}

						return;
					}

					if (payload.length === 0) {
						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}

						return;
					}

					llvalues = device.ipcon.unpack(payload,
					                               streamStateObject['responseProperties']['unpackFormatString']);

					for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
						if (streamStateObject['dataMapping'][i] === 'streamChunkData') {
							pixelsChunkData = llvalues[i];
						}
						else if (streamStateObject['dataMapping'][i] === 'streamChunkOffset') {
							pixelsChunkOffset = llvalues[i];
						}
					}

					for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
						if (streamStateObject['dataMapping'][i] === 'streamLength') {
							pixelsLength = llvalues[i];
							break;
						}
					}

					function handleOOS() {
						if ((pixelsChunkOffset + 480) < pixelsLength) {
							streamStateObject['responseProperties']['runningSubcallOOS'] = true;
							device.ipcon.sendRequest(device, BrickletOLED128x64V2.FUNCTION_READ_PIXELS_LOW_LEVEL, [xStart, yStart, xEnd, yEnd], 'B B B B', 72, 'H H ?480', streamStateObject['responseProperties']['returnCB'], streamStateObject['responseProperties']['errorCB'], true, true);

							return;
						}

						if (streamStateObject['responseProperties']['errorCB']) {
							streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_STREAM_OUT_OF_SYNC);
						}

						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}
					}

					if (streamStateObject['responseProperties']['waitingFirstChunk']) {
						streamStateObject['responseProperties']['waitingFirstChunk'] = false;
						pixelsOutOfSync = (pixelsChunkOffset !== 0);
						streamStateObject['responseProperties']['data'] = pixelsChunkData;
					}

					if (!streamStateObject['responseProperties']['runningSubcallOOS']) {
						if (!streamStateObject['responseProperties']['runningSubcall']) {
							if (!pixelsOutOfSync &&
							    (streamStateObject['responseProperties']['data'].length < pixelsLength)) {
							        streamStateObject['responseProperties']['runningSubcall'] = true;
							        device.ipcon.sendRequest(device, BrickletOLED128x64V2.FUNCTION_READ_PIXELS_LOW_LEVEL, [xStart, yStart, xEnd, yEnd], 'B B B B', 72, 'H H ?480', streamStateObject['responseProperties']['returnCB'], streamStateObject['responseProperties']['errorCB'], true, true);

							        return;
							}
						}
						else {
							pixelsOutOfSync =
								(pixelsChunkOffset !== streamStateObject['responseProperties']['data'].length);

							if (!pixelsOutOfSync &&
								(streamStateObject['responseProperties']['data'].length < pixelsLength)) {
									streamStateObject['responseProperties']['data'] =
										streamStateObject['responseProperties']['data'].concat(pixelsChunkData);

									if (streamStateObject['responseProperties']['data'].length >= pixelsLength) {
										streamStateObject['responseProperties']['data'] =
											streamStateObject['responseProperties']['data'].splice(0, pixelsLength);
									}
									else {
										device.ipcon.sendRequest(device, BrickletOLED128x64V2.FUNCTION_READ_PIXELS_LOW_LEVEL, [xStart, yStart, xEnd, yEnd], 'B B B B', 72, 'H H ?480', streamStateObject['responseProperties']['returnCB'], streamStateObject['responseProperties']['errorCB'], true, true);

										return;
									}
							}
						}
					}
					else{
						handleOOS();

						return;
					}

					if (pixelsOutOfSync) { // Discard remaining stream to bring it back in-sync
						handleOOS();

						return;
					}

					if (streamStateObject['responseProperties']['returnCB']) {
						for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
							rolesMappedData.push({'role': streamStateObject['dataMapping'][i], 'llvalue': llvalues[i]});
						}

						for (var i = 0; i < rolesMappedData.length; i++) {
							if (rolesMappedData[i]['role'] === 'streamChunkData') {
								result.push(streamStateObject['responseProperties']['data'].splice(0, pixelsLength));
							}
							else if (rolesMappedData[i]['role'] === null) {
								result.push(rolesMappedData[i]['llvalue']);
							}
						}

						streamStateObject['responseProperties']['returnCB'].apply(device, result);
					}

					device.resetStreamStateObject(streamStateObject);

					if (streamStateObject['responseProperties']['callQueue'].length > 0) {
						streamStateObject['responseProperties']['callQueue'].shift()(device);
					}
					
				};

			streamStateObject['responseProperties']['responseHandler'] = responseHandler;
		}
		if (!streamStateObject['responseProperties']['running']) {
			streamStateObject['responseProperties']['running'] = true;
			streamStateObject['responseProperties']['returnCB'] = returnCallback;
			streamStateObject['responseProperties']['errorCB'] = errorCallback;
			this.ipcon.sendRequest(this,
			                       BrickletOLED128x64V2.FUNCTION_READ_PIXELS_LOW_LEVEL,
			                       [xStart, yStart, xEnd, yEnd],
			                       'B B B B',
			                       72,
			                       'H H ?480',
			                       returnCallback,
			                       errorCallback,
			                       true,
			                       true);
		}
		else {
			functionToQueue = function (device) {
				device.readPixels.call(device, xStart, yStart, xEnd, yEnd, returnCallback, errorCallback);
			}
			streamStateObject['responseProperties']['callQueue'].push(functionToQueue);
		}
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletOLED128x64V2;

},{"./Device":279,"./IPConnection":280}],232:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletOLED64x48.DEVICE_IDENTIFIER = 264;
BrickletOLED64x48.DEVICE_DISPLAY_NAME = 'OLED 64x48 Bricklet';
BrickletOLED64x48.FUNCTION_WRITE = 1;
BrickletOLED64x48.FUNCTION_NEW_WINDOW = 2;
BrickletOLED64x48.FUNCTION_CLEAR_DISPLAY = 3;
BrickletOLED64x48.FUNCTION_SET_DISPLAY_CONFIGURATION = 4;
BrickletOLED64x48.FUNCTION_GET_DISPLAY_CONFIGURATION = 5;
BrickletOLED64x48.FUNCTION_WRITE_LINE = 6;
BrickletOLED64x48.FUNCTION_GET_IDENTITY = 255;

function BrickletOLED64x48(uid, ipcon) {
	//1.68cm (0.66") OLED display with 64x48 pixels

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletOLED64x48.DEVICE_IDENTIFIER, BrickletOLED64x48.DEVICE_DISPLAY_NAME);
	BrickletOLED64x48.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickletOLED64x48.FUNCTION_WRITE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletOLED64x48.FUNCTION_NEW_WINDOW] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletOLED64x48.FUNCTION_CLEAR_DISPLAY] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletOLED64x48.FUNCTION_SET_DISPLAY_CONFIGURATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletOLED64x48.FUNCTION_GET_DISPLAY_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletOLED64x48.FUNCTION_WRITE_LINE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletOLED64x48.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;



	this.write = function(data, returnCallback, errorCallback) {
		/*
		Appends 64 byte of data to the window as set by :func:`New Window`.
		
		Each row has a height of 8 pixels which corresponds to one byte of data.
		
		Example: if you call :func:`New Window` with column from 0 to 63 and row
		from 0 to 5 (the whole display) each call of :func:`Write` (red arrow) will
		write one row.
		
		.. image:: /Images/Bricklets/bricklet_oled_64x48_display.png
		   :scale: 100 %
		   :alt: Display pixel order
		   :align: center
		   :target: ../../_images/Bricklets/bricklet_oled_64x48_display.png
		
		The LSB (D0) of each data byte is at the top and the MSB (D7) is at the
		bottom of the row.
		
		The next call of :func:`Write` will write the second row and so on. To
		fill the whole display you need to call :func:`Write` 6 times.
		*/
		this.ipcon.sendRequest(this, BrickletOLED64x48.FUNCTION_WRITE, [data], 'B64', 0, '', returnCallback, errorCallback, false, true);
	};
	this.newWindow = function(columnFrom, columnTo, rowFrom, rowTo, returnCallback, errorCallback) {
		/*
		Sets the window in which you can write with :func:`Write`. One row
		has a height of 8 pixels.
		*/
		this.ipcon.sendRequest(this, BrickletOLED64x48.FUNCTION_NEW_WINDOW, [columnFrom, columnTo, rowFrom, rowTo], 'B B B B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.clearDisplay = function(returnCallback, errorCallback) {
		/*
		Clears the current content of the window as set by :func:`New Window`.
		*/
		this.ipcon.sendRequest(this, BrickletOLED64x48.FUNCTION_CLEAR_DISPLAY, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.setDisplayConfiguration = function(contrast, invert, returnCallback, errorCallback) {
		/*
		Sets the configuration of the display.
		
		You can set a contrast value from 0 to 255 and you can invert the color
		(black/white) of the display.
		*/
		this.ipcon.sendRequest(this, BrickletOLED64x48.FUNCTION_SET_DISPLAY_CONFIGURATION, [contrast, invert], 'B ?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getDisplayConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Display Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletOLED64x48.FUNCTION_GET_DISPLAY_CONFIGURATION, [], '', 10, 'B ?', returnCallback, errorCallback, false, true);
	};
	this.writeLine = function(line, position, text, returnCallback, errorCallback) {
		/*
		Writes text to a specific line with a specific position.
		The text can have a maximum of 13 characters.
		
		For example: (1, 4, "Hello") will write *Hello* in the middle of the
		second line of the display.
		
		You can draw to the display with :func:`Write` and then add text to it
		afterwards.
		
		The display uses a special 5x7 pixel charset. You can view the characters
		of the charset in Brick Viewer.
		*/
		this.ipcon.sendRequest(this, BrickletOLED64x48.FUNCTION_WRITE_LINE, [line, position, text], 'B B s13', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletOLED64x48.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletOLED64x48;

},{"./Device":279,"./IPConnection":280}],233:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletOneWire.DEVICE_IDENTIFIER = 2123;
BrickletOneWire.DEVICE_DISPLAY_NAME = 'One Wire Bricklet';
BrickletOneWire.FUNCTION_SEARCH_BUS_LOW_LEVEL = 1;
BrickletOneWire.FUNCTION_RESET_BUS = 2;
BrickletOneWire.FUNCTION_WRITE = 3;
BrickletOneWire.FUNCTION_READ = 4;
BrickletOneWire.FUNCTION_WRITE_COMMAND = 5;
BrickletOneWire.FUNCTION_SET_COMMUNICATION_LED_CONFIG = 6;
BrickletOneWire.FUNCTION_GET_COMMUNICATION_LED_CONFIG = 7;
BrickletOneWire.FUNCTION_GET_SPITFP_ERROR_COUNT = 234;
BrickletOneWire.FUNCTION_SET_BOOTLOADER_MODE = 235;
BrickletOneWire.FUNCTION_GET_BOOTLOADER_MODE = 236;
BrickletOneWire.FUNCTION_SET_WRITE_FIRMWARE_POINTER = 237;
BrickletOneWire.FUNCTION_WRITE_FIRMWARE = 238;
BrickletOneWire.FUNCTION_SET_STATUS_LED_CONFIG = 239;
BrickletOneWire.FUNCTION_GET_STATUS_LED_CONFIG = 240;
BrickletOneWire.FUNCTION_GET_CHIP_TEMPERATURE = 242;
BrickletOneWire.FUNCTION_RESET = 243;
BrickletOneWire.FUNCTION_WRITE_UID = 248;
BrickletOneWire.FUNCTION_READ_UID = 249;
BrickletOneWire.FUNCTION_GET_IDENTITY = 255;
BrickletOneWire.STATUS_OK = 0;
BrickletOneWire.STATUS_BUSY = 1;
BrickletOneWire.STATUS_NO_PRESENCE = 2;
BrickletOneWire.STATUS_TIMEOUT = 3;
BrickletOneWire.STATUS_ERROR = 4;
BrickletOneWire.COMMUNICATION_LED_CONFIG_OFF = 0;
BrickletOneWire.COMMUNICATION_LED_CONFIG_ON = 1;
BrickletOneWire.COMMUNICATION_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletOneWire.COMMUNICATION_LED_CONFIG_SHOW_COMMUNICATION = 3;
BrickletOneWire.BOOTLOADER_MODE_BOOTLOADER = 0;
BrickletOneWire.BOOTLOADER_MODE_FIRMWARE = 1;
BrickletOneWire.BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT = 2;
BrickletOneWire.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT = 3;
BrickletOneWire.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT = 4;
BrickletOneWire.BOOTLOADER_STATUS_OK = 0;
BrickletOneWire.BOOTLOADER_STATUS_INVALID_MODE = 1;
BrickletOneWire.BOOTLOADER_STATUS_NO_CHANGE = 2;
BrickletOneWire.BOOTLOADER_STATUS_ENTRY_FUNCTION_NOT_PRESENT = 3;
BrickletOneWire.BOOTLOADER_STATUS_DEVICE_IDENTIFIER_INCORRECT = 4;
BrickletOneWire.BOOTLOADER_STATUS_CRC_MISMATCH = 5;
BrickletOneWire.STATUS_LED_CONFIG_OFF = 0;
BrickletOneWire.STATUS_LED_CONFIG_ON = 1;
BrickletOneWire.STATUS_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletOneWire.STATUS_LED_CONFIG_SHOW_STATUS = 3;

function BrickletOneWire(uid, ipcon) {
	//Communicates with up 64 1-Wire devices

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletOneWire.DEVICE_IDENTIFIER, BrickletOneWire.DEVICE_DISPLAY_NAME);
	BrickletOneWire.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickletOneWire.FUNCTION_SEARCH_BUS_LOW_LEVEL] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletOneWire.FUNCTION_RESET_BUS] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletOneWire.FUNCTION_WRITE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletOneWire.FUNCTION_READ] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletOneWire.FUNCTION_WRITE_COMMAND] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletOneWire.FUNCTION_SET_COMMUNICATION_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletOneWire.FUNCTION_GET_COMMUNICATION_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletOneWire.FUNCTION_GET_SPITFP_ERROR_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletOneWire.FUNCTION_SET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletOneWire.FUNCTION_GET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletOneWire.FUNCTION_SET_WRITE_FIRMWARE_POINTER] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletOneWire.FUNCTION_WRITE_FIRMWARE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletOneWire.FUNCTION_SET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletOneWire.FUNCTION_GET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletOneWire.FUNCTION_GET_CHIP_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletOneWire.FUNCTION_RESET] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletOneWire.FUNCTION_WRITE_UID] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletOneWire.FUNCTION_READ_UID] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletOneWire.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;


	this.streamStateObjects[BrickletOneWire.FUNCTION_SEARCH_BUS_LOW_LEVEL] = {
		'dataMapping': ['streamLength', 'streamChunkOffset', 'streamChunkData', null],
		'dataMappingStreamIn': [],
		'streamProperties': {
			'fixedLength': null,
			'singleChunk': false,
			'shortWrite': false
		},
		'responseProperties': {
			'running': false,
			'runningSubcall': false,
			'runningSubcallOOS': false,
			'waitingFirstChunk': true,
			'timeout': null,
			'data': [],
			'streamInChunkOffset': 0,
			'streamInChunkLength': 0,
			'streamInResponseEmpty': true,
			'streamInWritten': 0,
			'streamInLLParams': null,
			'responseHandler': null,
			'packFormatString': '',
			'unpackFormatString': 'H H Q7 B',
			'returnCB': null,
			'errorCB': null,
			'callQueue': []
		}
	};

	this.searchBusLowLevel = function(returnCallback, errorCallback) {
		/*
		Returns a list of up to 64 identifiers of the connected 1-Wire devices.
		Each identifier is 64-bit and consists of 8-bit family code, 48-bit ID and
		8-bit CRC.
		
		To get these identifiers the Bricklet runs the
		`SEARCH ROM algorithm <https://www.maximintegrated.com/en/app-notes/index.mvp/id/187>`__,
		as defined by Maxim.
		*/
		this.ipcon.sendRequest(this, BrickletOneWire.FUNCTION_SEARCH_BUS_LOW_LEVEL, [], '', 69, 'H H Q7 B', returnCallback, errorCallback, false, true);
	};
	this.resetBus = function(returnCallback, errorCallback) {
		/*
		Resets the bus with the 1-Wire reset operation.
		*/
		this.ipcon.sendRequest(this, BrickletOneWire.FUNCTION_RESET_BUS, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.write = function(data, returnCallback, errorCallback) {
		/*
		Writes a byte of data to the 1-Wire bus.
		*/
		this.ipcon.sendRequest(this, BrickletOneWire.FUNCTION_WRITE, [data], 'B', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.read = function(returnCallback, errorCallback) {
		/*
		Reads a byte of data from the 1-Wire bus.
		*/
		this.ipcon.sendRequest(this, BrickletOneWire.FUNCTION_READ, [], '', 10, 'B B', returnCallback, errorCallback, false, true);
	};
	this.writeCommand = function(identifier, command, returnCallback, errorCallback) {
		/*
		Writes a command to the 1-Wire device with the given identifier. You can obtain
		the identifier by calling :func:`Search Bus`. The MATCH ROM operation is used to
		write the command.
		
		If you only have one device connected or want to broadcast to all devices
		you can set the identifier to 0. In this case the SKIP ROM operation is used to
		write the command.
		*/
		this.ipcon.sendRequest(this, BrickletOneWire.FUNCTION_WRITE_COMMAND, [identifier, command], 'Q B', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setCommunicationLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Sets the communication LED configuration. By default the LED shows 1-wire
		communication traffic by flickering.
		
		You can also turn the LED permanently on/off or show a heartbeat.
		
		If the Bricklet is in bootloader mode, the LED is off.
		*/
		this.ipcon.sendRequest(this, BrickletOneWire.FUNCTION_SET_COMMUNICATION_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getCommunicationLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Communication LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletOneWire.FUNCTION_GET_COMMUNICATION_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPErrorCount = function(returnCallback, errorCallback) {
		/*
		Returns the error count for the communication between Brick and Bricklet.
		
		The errors are divided into
		
		* ACK checksum errors,
		* message checksum errors,
		* framing errors and
		* overflow errors.
		
		The errors counts are for errors that occur on the Bricklet side. All
		Bricks have a similar function that returns the errors on the Brick side.
		*/
		this.ipcon.sendRequest(this, BrickletOneWire.FUNCTION_GET_SPITFP_ERROR_COUNT, [], '', 24, 'I I I I', returnCallback, errorCallback, false, true);
	};
	this.setBootloaderMode = function(mode, returnCallback, errorCallback) {
		/*
		Sets the bootloader mode and returns the status after the requested
		mode change was instigated.
		
		You can change from bootloader mode to firmware mode and vice versa. A change
		from bootloader mode to firmware mode will only take place if the entry function,
		device identifier and CRC are present and correct.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletOneWire.FUNCTION_SET_BOOTLOADER_MODE, [mode], 'B', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getBootloaderMode = function(returnCallback, errorCallback) {
		/*
		Returns the current bootloader mode, see :func:`Set Bootloader Mode`.
		*/
		this.ipcon.sendRequest(this, BrickletOneWire.FUNCTION_GET_BOOTLOADER_MODE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setWriteFirmwarePointer = function(pointer, returnCallback, errorCallback) {
		/*
		Sets the firmware pointer for :func:`Write Firmware`. The pointer has
		to be increased by chunks of size 64. The data is written to flash
		every 4 chunks (which equals to one page of size 256).
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletOneWire.FUNCTION_SET_WRITE_FIRMWARE_POINTER, [pointer], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeFirmware = function(data, returnCallback, errorCallback) {
		/*
		Writes 64 Bytes of firmware at the position as written by
		:func:`Set Write Firmware Pointer` before. The firmware is written
		to flash every 4 chunks.
		
		You can only write firmware in bootloader mode.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletOneWire.FUNCTION_WRITE_FIRMWARE, [data], 'B64', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setStatusLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Sets the status LED configuration. By default the LED shows
		communication traffic between Brick and Bricklet, it flickers once
		for every 10 received data packets.
		
		You can also turn the LED permanently on/off or show a heartbeat.
		
		If the Bricklet is in bootloader mode, the LED is will show heartbeat by default.
		*/
		this.ipcon.sendRequest(this, BrickletOneWire.FUNCTION_SET_STATUS_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getStatusLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Status LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletOneWire.FUNCTION_GET_STATUS_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getChipTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature as measured inside the microcontroller. The
		value returned is not the ambient temperature!
		
		The temperature is only proportional to the real temperature and it has bad
		accuracy. Practically it is only useful as an indicator for
		temperature changes.
		*/
		this.ipcon.sendRequest(this, BrickletOneWire.FUNCTION_GET_CHIP_TEMPERATURE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.reset = function(returnCallback, errorCallback) {
		/*
		Calling this function will reset the Bricklet. All configurations
		will be lost.
		
		After a reset you have to create new device objects,
		calling functions on the existing ones will result in
		undefined behavior!
		*/
		this.ipcon.sendRequest(this, BrickletOneWire.FUNCTION_RESET, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeUID = function(uid, returnCallback, errorCallback) {
		/*
		Writes a new UID into flash. If you want to set a new UID
		you have to decode the Base58 encoded UID string into an
		integer first.
		
		We recommend that you use Brick Viewer to change the UID.
		*/
		this.ipcon.sendRequest(this, BrickletOneWire.FUNCTION_WRITE_UID, [uid], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.readUID = function(returnCallback, errorCallback) {
		/*
		Returns the current UID as an integer. Encode as
		Base58 to get the usual string version.
		*/
		this.ipcon.sendRequest(this, BrickletOneWire.FUNCTION_READ_UID, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletOneWire.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.searchBus = function(returnCallback, errorCallback) {
		/*
		Returns a list of up to 64 identifiers of the connected 1-Wire devices.
		Each identifier is 64-bit and consists of 8-bit family code, 48-bit ID and
		8-bit CRC.
		
		To get these identifiers the Bricklet runs the
		`SEARCH ROM algorithm <https://www.maximintegrated.com/en/app-notes/index.mvp/id/187>`__,
		as defined by Maxim.
		*/
		var responseHandler = null;
		var functionToQueue = null;
		var streamStateObject = this.streamStateObjects[1];
		if (streamStateObject['responseProperties']['responseHandler'] === null) {
			responseHandler = 
				function (device, fid, packetResponse) {
					var result = [];
					var llvalues = null;
					var packetErrorFlag = 0;
					var rolesMappedData = [];
					var identifierLength = null;
					var identifierChunkData = null;
					var identifierOutOfSync = false;
					var streamStateObject = device.streamStateObjects[fid];
					var identifierChunkOffset = null;
					var payload = device.ipcon.getPayloadFromPacket(packetResponse);

					packetErrorFlag = device.ipcon.getEFromPacket(packetResponse);

					if (packetErrorFlag !== 0) {
						if (streamStateObject['responseProperties']['errorCB'] !== undefined) {
							if (packetErrorFlag === 1) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_INVALID_PARAMETER);
							}
							else if (packetErrorFlag === 2) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_FUNCTION_NOT_SUPPORTED);
							}
							else {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_UNKNOWN_ERROR);
							}
						}

						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}

						return;
					}

					if (payload.length === 0) {
						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}

						return;
					}

					llvalues = device.ipcon.unpack(payload,
					                               streamStateObject['responseProperties']['unpackFormatString']);

					for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
						if (streamStateObject['dataMapping'][i] === 'streamChunkData') {
							identifierChunkData = llvalues[i];
						}
						else if (streamStateObject['dataMapping'][i] === 'streamChunkOffset') {
							identifierChunkOffset = llvalues[i];
						}
					}

					for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
						if (streamStateObject['dataMapping'][i] === 'streamLength') {
							identifierLength = llvalues[i];
							break;
						}
					}

					function handleOOS() {
						if ((identifierChunkOffset + 7) < identifierLength) {
							streamStateObject['responseProperties']['runningSubcallOOS'] = true;
							device.ipcon.sendRequest(device, BrickletOneWire.FUNCTION_SEARCH_BUS_LOW_LEVEL, [], '', 69, 'H H Q7 B', streamStateObject['responseProperties']['returnCB'], streamStateObject['responseProperties']['errorCB'], true, true);

							return;
						}

						if (streamStateObject['responseProperties']['errorCB']) {
							streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_STREAM_OUT_OF_SYNC);
						}

						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}
					}

					if (streamStateObject['responseProperties']['waitingFirstChunk']) {
						streamStateObject['responseProperties']['waitingFirstChunk'] = false;
						identifierOutOfSync = (identifierChunkOffset !== 0);
						streamStateObject['responseProperties']['data'] = identifierChunkData;
					}

					if (!streamStateObject['responseProperties']['runningSubcallOOS']) {
						if (!streamStateObject['responseProperties']['runningSubcall']) {
							if (!identifierOutOfSync &&
							    (streamStateObject['responseProperties']['data'].length < identifierLength)) {
							        streamStateObject['responseProperties']['runningSubcall'] = true;
							        device.ipcon.sendRequest(device, BrickletOneWire.FUNCTION_SEARCH_BUS_LOW_LEVEL, [], '', 69, 'H H Q7 B', streamStateObject['responseProperties']['returnCB'], streamStateObject['responseProperties']['errorCB'], true, true);

							        return;
							}
						}
						else {
							identifierOutOfSync =
								(identifierChunkOffset !== streamStateObject['responseProperties']['data'].length);

							if (!identifierOutOfSync &&
								(streamStateObject['responseProperties']['data'].length < identifierLength)) {
									streamStateObject['responseProperties']['data'] =
										streamStateObject['responseProperties']['data'].concat(identifierChunkData);

									if (streamStateObject['responseProperties']['data'].length >= identifierLength) {
										streamStateObject['responseProperties']['data'] =
											streamStateObject['responseProperties']['data'].splice(0, identifierLength);
									}
									else {
										device.ipcon.sendRequest(device, BrickletOneWire.FUNCTION_SEARCH_BUS_LOW_LEVEL, [], '', 69, 'H H Q7 B', streamStateObject['responseProperties']['returnCB'], streamStateObject['responseProperties']['errorCB'], true, true);

										return;
									}
							}
						}
					}
					else{
						handleOOS();

						return;
					}

					if (identifierOutOfSync) { // Discard remaining stream to bring it back in-sync
						handleOOS();

						return;
					}

					if (streamStateObject['responseProperties']['returnCB']) {
						for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
							rolesMappedData.push({'role': streamStateObject['dataMapping'][i], 'llvalue': llvalues[i]});
						}

						for (var i = 0; i < rolesMappedData.length; i++) {
							if (rolesMappedData[i]['role'] === 'streamChunkData') {
								result.push(streamStateObject['responseProperties']['data'].splice(0, identifierLength));
							}
							else if (rolesMappedData[i]['role'] === null) {
								result.push(rolesMappedData[i]['llvalue']);
							}
						}

						streamStateObject['responseProperties']['returnCB'].apply(device, result);
					}

					device.resetStreamStateObject(streamStateObject);

					if (streamStateObject['responseProperties']['callQueue'].length > 0) {
						streamStateObject['responseProperties']['callQueue'].shift()(device);
					}
					
				};

			streamStateObject['responseProperties']['responseHandler'] = responseHandler;
		}
		if (!streamStateObject['responseProperties']['running']) {
			streamStateObject['responseProperties']['running'] = true;
			streamStateObject['responseProperties']['returnCB'] = returnCallback;
			streamStateObject['responseProperties']['errorCB'] = errorCallback;
			this.ipcon.sendRequest(this,
			                       BrickletOneWire.FUNCTION_SEARCH_BUS_LOW_LEVEL,
			                       [],
			                       '',
			                       69,
			                       'H H Q7 B',
			                       returnCallback,
			                       errorCallback,
			                       true,
			                       true);
		}
		else {
			functionToQueue = function (device) {
				device.searchBus.call(device, returnCallback, errorCallback);
			}
			streamStateObject['responseProperties']['callQueue'].push(functionToQueue);
		}
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletOneWire;

},{"./Device":279,"./IPConnection":280}],234:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletOutdoorWeather.DEVICE_IDENTIFIER = 288;
BrickletOutdoorWeather.DEVICE_DISPLAY_NAME = 'Outdoor Weather Bricklet';
BrickletOutdoorWeather.CALLBACK_STATION_DATA = 9;
BrickletOutdoorWeather.CALLBACK_SENSOR_DATA = 10;
BrickletOutdoorWeather.FUNCTION_GET_STATION_IDENTIFIERS_LOW_LEVEL = 1;
BrickletOutdoorWeather.FUNCTION_GET_SENSOR_IDENTIFIERS_LOW_LEVEL = 2;
BrickletOutdoorWeather.FUNCTION_GET_STATION_DATA = 3;
BrickletOutdoorWeather.FUNCTION_GET_SENSOR_DATA = 4;
BrickletOutdoorWeather.FUNCTION_SET_STATION_CALLBACK_CONFIGURATION = 5;
BrickletOutdoorWeather.FUNCTION_GET_STATION_CALLBACK_CONFIGURATION = 6;
BrickletOutdoorWeather.FUNCTION_SET_SENSOR_CALLBACK_CONFIGURATION = 7;
BrickletOutdoorWeather.FUNCTION_GET_SENSOR_CALLBACK_CONFIGURATION = 8;
BrickletOutdoorWeather.FUNCTION_GET_SPITFP_ERROR_COUNT = 234;
BrickletOutdoorWeather.FUNCTION_SET_BOOTLOADER_MODE = 235;
BrickletOutdoorWeather.FUNCTION_GET_BOOTLOADER_MODE = 236;
BrickletOutdoorWeather.FUNCTION_SET_WRITE_FIRMWARE_POINTER = 237;
BrickletOutdoorWeather.FUNCTION_WRITE_FIRMWARE = 238;
BrickletOutdoorWeather.FUNCTION_SET_STATUS_LED_CONFIG = 239;
BrickletOutdoorWeather.FUNCTION_GET_STATUS_LED_CONFIG = 240;
BrickletOutdoorWeather.FUNCTION_GET_CHIP_TEMPERATURE = 242;
BrickletOutdoorWeather.FUNCTION_RESET = 243;
BrickletOutdoorWeather.FUNCTION_WRITE_UID = 248;
BrickletOutdoorWeather.FUNCTION_READ_UID = 249;
BrickletOutdoorWeather.FUNCTION_GET_IDENTITY = 255;
BrickletOutdoorWeather.WIND_DIRECTION_N = 0;
BrickletOutdoorWeather.WIND_DIRECTION_NNE = 1;
BrickletOutdoorWeather.WIND_DIRECTION_NE = 2;
BrickletOutdoorWeather.WIND_DIRECTION_ENE = 3;
BrickletOutdoorWeather.WIND_DIRECTION_E = 4;
BrickletOutdoorWeather.WIND_DIRECTION_ESE = 5;
BrickletOutdoorWeather.WIND_DIRECTION_SE = 6;
BrickletOutdoorWeather.WIND_DIRECTION_SSE = 7;
BrickletOutdoorWeather.WIND_DIRECTION_S = 8;
BrickletOutdoorWeather.WIND_DIRECTION_SSW = 9;
BrickletOutdoorWeather.WIND_DIRECTION_SW = 10;
BrickletOutdoorWeather.WIND_DIRECTION_WSW = 11;
BrickletOutdoorWeather.WIND_DIRECTION_W = 12;
BrickletOutdoorWeather.WIND_DIRECTION_WNW = 13;
BrickletOutdoorWeather.WIND_DIRECTION_NW = 14;
BrickletOutdoorWeather.WIND_DIRECTION_NNW = 15;
BrickletOutdoorWeather.WIND_DIRECTION_ERROR = 255;
BrickletOutdoorWeather.BOOTLOADER_MODE_BOOTLOADER = 0;
BrickletOutdoorWeather.BOOTLOADER_MODE_FIRMWARE = 1;
BrickletOutdoorWeather.BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT = 2;
BrickletOutdoorWeather.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT = 3;
BrickletOutdoorWeather.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT = 4;
BrickletOutdoorWeather.BOOTLOADER_STATUS_OK = 0;
BrickletOutdoorWeather.BOOTLOADER_STATUS_INVALID_MODE = 1;
BrickletOutdoorWeather.BOOTLOADER_STATUS_NO_CHANGE = 2;
BrickletOutdoorWeather.BOOTLOADER_STATUS_ENTRY_FUNCTION_NOT_PRESENT = 3;
BrickletOutdoorWeather.BOOTLOADER_STATUS_DEVICE_IDENTIFIER_INCORRECT = 4;
BrickletOutdoorWeather.BOOTLOADER_STATUS_CRC_MISMATCH = 5;
BrickletOutdoorWeather.STATUS_LED_CONFIG_OFF = 0;
BrickletOutdoorWeather.STATUS_LED_CONFIG_ON = 1;
BrickletOutdoorWeather.STATUS_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletOutdoorWeather.STATUS_LED_CONFIG_SHOW_STATUS = 3;

function BrickletOutdoorWeather(uid, ipcon) {
	//433MHz receiver for outdoor weather station

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletOutdoorWeather.DEVICE_IDENTIFIER, BrickletOutdoorWeather.DEVICE_DISPLAY_NAME);
	BrickletOutdoorWeather.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickletOutdoorWeather.FUNCTION_GET_STATION_IDENTIFIERS_LOW_LEVEL] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletOutdoorWeather.FUNCTION_GET_SENSOR_IDENTIFIERS_LOW_LEVEL] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletOutdoorWeather.FUNCTION_GET_STATION_DATA] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletOutdoorWeather.FUNCTION_GET_SENSOR_DATA] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletOutdoorWeather.FUNCTION_SET_STATION_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletOutdoorWeather.FUNCTION_GET_STATION_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletOutdoorWeather.FUNCTION_SET_SENSOR_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletOutdoorWeather.FUNCTION_GET_SENSOR_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletOutdoorWeather.FUNCTION_GET_SPITFP_ERROR_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletOutdoorWeather.FUNCTION_SET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletOutdoorWeather.FUNCTION_GET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletOutdoorWeather.FUNCTION_SET_WRITE_FIRMWARE_POINTER] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletOutdoorWeather.FUNCTION_WRITE_FIRMWARE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletOutdoorWeather.FUNCTION_SET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletOutdoorWeather.FUNCTION_GET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletOutdoorWeather.FUNCTION_GET_CHIP_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletOutdoorWeather.FUNCTION_RESET] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletOutdoorWeather.FUNCTION_WRITE_UID] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletOutdoorWeather.FUNCTION_READ_UID] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletOutdoorWeather.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletOutdoorWeather.CALLBACK_STATION_DATA] = [26, 'B h B I I I B ?'];
	this.callbackFormats[BrickletOutdoorWeather.CALLBACK_SENSOR_DATA] = [12, 'B h B'];


	this.streamStateObjects[BrickletOutdoorWeather.FUNCTION_GET_STATION_IDENTIFIERS_LOW_LEVEL] = {
		'dataMapping': ['streamLength', 'streamChunkOffset', 'streamChunkData'],
		'dataMappingStreamIn': [],
		'streamProperties': {
			'fixedLength': null,
			'singleChunk': false,
			'shortWrite': false
		},
		'responseProperties': {
			'running': false,
			'runningSubcall': false,
			'runningSubcallOOS': false,
			'waitingFirstChunk': true,
			'timeout': null,
			'data': [],
			'streamInChunkOffset': 0,
			'streamInChunkLength': 0,
			'streamInResponseEmpty': true,
			'streamInWritten': 0,
			'streamInLLParams': null,
			'responseHandler': null,
			'packFormatString': '',
			'unpackFormatString': 'H H B60',
			'returnCB': null,
			'errorCB': null,
			'callQueue': []
		}
	};
	this.streamStateObjects[BrickletOutdoorWeather.FUNCTION_GET_SENSOR_IDENTIFIERS_LOW_LEVEL] = {
		'dataMapping': ['streamLength', 'streamChunkOffset', 'streamChunkData'],
		'dataMappingStreamIn': [],
		'streamProperties': {
			'fixedLength': null,
			'singleChunk': false,
			'shortWrite': false
		},
		'responseProperties': {
			'running': false,
			'runningSubcall': false,
			'runningSubcallOOS': false,
			'waitingFirstChunk': true,
			'timeout': null,
			'data': [],
			'streamInChunkOffset': 0,
			'streamInChunkLength': 0,
			'streamInResponseEmpty': true,
			'streamInWritten': 0,
			'streamInLLParams': null,
			'responseHandler': null,
			'packFormatString': '',
			'unpackFormatString': 'H H B60',
			'returnCB': null,
			'errorCB': null,
			'callQueue': []
		}
	};

	this.getStationIdentifiersLowLevel = function(returnCallback, errorCallback) {
		/*
		Returns the identifiers (number between 0 and 255) of all `stations
		<https://www.tinkerforge.com/en/shop/accessories/sensors/outdoor-weather-station-ws-6147.html>`__
		that have been seen since the startup of the Bricklet.
		
		Each station gives itself a random identifier on first startup.
		
		Since firmware version 2.0.2 a station is removed from the list if no data was received for
		12 hours.
		*/
		this.ipcon.sendRequest(this, BrickletOutdoorWeather.FUNCTION_GET_STATION_IDENTIFIERS_LOW_LEVEL, [], '', 72, 'H H B60', returnCallback, errorCallback, false, true);
	};
	this.getSensorIdentifiersLowLevel = function(returnCallback, errorCallback) {
		/*
		Returns the identifiers (number between 0 and 255) of all `sensors
		<https://www.tinkerforge.com/en/shop/accessories/sensors/temperature-humidity-sensor-th-6148.html>`__
		that have been seen since the startup of the Bricklet.
		
		Each sensor gives itself a random identifier on first startup.
		
		Since firmware version 2.0.2 a sensor is removed from the list if no data was received for
		12 hours.
		*/
		this.ipcon.sendRequest(this, BrickletOutdoorWeather.FUNCTION_GET_SENSOR_IDENTIFIERS_LOW_LEVEL, [], '', 72, 'H H B60', returnCallback, errorCallback, false, true);
	};
	this.getStationData = function(identifier, returnCallback, errorCallback) {
		/*
		Returns the last received data for a station with the given identifier.
		Call :func:`Get Station Identifiers` for a list of all available identifiers.
		
		The return values are:
		
		* Temperature,
		* Humidity,
		* Wind Speed,
		* Gust Speed,
		* Rain Fall (accumulated since station power-up),
		* Wind Direction,
		* Battery Low (true if battery is low) and
		* Last Change (seconds since the reception of this data).
		*/
		this.ipcon.sendRequest(this, BrickletOutdoorWeather.FUNCTION_GET_STATION_DATA, [identifier], 'B', 27, 'h B I I I B ? H', returnCallback, errorCallback, false, true);
	};
	this.getSensorData = function(identifier, returnCallback, errorCallback) {
		/*
		Returns the last measured data for a sensor with the given identifier.
		Call :func:`Get Sensor Identifiers` for a list of all available identifiers.
		
		The return values are:
		
		* Temperature,
		* Humidity and
		* Last Change (seconds since the last reception of data).
		*/
		this.ipcon.sendRequest(this, BrickletOutdoorWeather.FUNCTION_GET_SENSOR_DATA, [identifier], 'B', 13, 'h B H', returnCallback, errorCallback, false, true);
	};
	this.setStationCallbackConfiguration = function(enableCallback, returnCallback, errorCallback) {
		/*
		Turns callback for station data on or off.
		*/
		this.ipcon.sendRequest(this, BrickletOutdoorWeather.FUNCTION_SET_STATION_CALLBACK_CONFIGURATION, [enableCallback], '?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getStationCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Station Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletOutdoorWeather.FUNCTION_GET_STATION_CALLBACK_CONFIGURATION, [], '', 9, '?', returnCallback, errorCallback, false, true);
	};
	this.setSensorCallbackConfiguration = function(enableCallback, returnCallback, errorCallback) {
		/*
		Turns callback for sensor data on or off.
		*/
		this.ipcon.sendRequest(this, BrickletOutdoorWeather.FUNCTION_SET_SENSOR_CALLBACK_CONFIGURATION, [enableCallback], '?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getSensorCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Sensor Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletOutdoorWeather.FUNCTION_GET_SENSOR_CALLBACK_CONFIGURATION, [], '', 9, '?', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPErrorCount = function(returnCallback, errorCallback) {
		/*
		Returns the error count for the communication between Brick and Bricklet.
		
		The errors are divided into
		
		* ACK checksum errors,
		* message checksum errors,
		* framing errors and
		* overflow errors.
		
		The errors counts are for errors that occur on the Bricklet side. All
		Bricks have a similar function that returns the errors on the Brick side.
		*/
		this.ipcon.sendRequest(this, BrickletOutdoorWeather.FUNCTION_GET_SPITFP_ERROR_COUNT, [], '', 24, 'I I I I', returnCallback, errorCallback, false, true);
	};
	this.setBootloaderMode = function(mode, returnCallback, errorCallback) {
		/*
		Sets the bootloader mode and returns the status after the requested
		mode change was instigated.
		
		You can change from bootloader mode to firmware mode and vice versa. A change
		from bootloader mode to firmware mode will only take place if the entry function,
		device identifier and CRC are present and correct.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletOutdoorWeather.FUNCTION_SET_BOOTLOADER_MODE, [mode], 'B', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getBootloaderMode = function(returnCallback, errorCallback) {
		/*
		Returns the current bootloader mode, see :func:`Set Bootloader Mode`.
		*/
		this.ipcon.sendRequest(this, BrickletOutdoorWeather.FUNCTION_GET_BOOTLOADER_MODE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setWriteFirmwarePointer = function(pointer, returnCallback, errorCallback) {
		/*
		Sets the firmware pointer for :func:`Write Firmware`. The pointer has
		to be increased by chunks of size 64. The data is written to flash
		every 4 chunks (which equals to one page of size 256).
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletOutdoorWeather.FUNCTION_SET_WRITE_FIRMWARE_POINTER, [pointer], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeFirmware = function(data, returnCallback, errorCallback) {
		/*
		Writes 64 Bytes of firmware at the position as written by
		:func:`Set Write Firmware Pointer` before. The firmware is written
		to flash every 4 chunks.
		
		You can only write firmware in bootloader mode.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletOutdoorWeather.FUNCTION_WRITE_FIRMWARE, [data], 'B64', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setStatusLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Sets the status LED configuration. By default the LED shows
		communication traffic between Brick and Bricklet, it flickers once
		for every 10 received data packets.
		
		You can also turn the LED permanently on/off or show a heartbeat.
		
		If the Bricklet is in bootloader mode, the LED is will show heartbeat by default.
		*/
		this.ipcon.sendRequest(this, BrickletOutdoorWeather.FUNCTION_SET_STATUS_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getStatusLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Status LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletOutdoorWeather.FUNCTION_GET_STATUS_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getChipTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature as measured inside the microcontroller. The
		value returned is not the ambient temperature!
		
		The temperature is only proportional to the real temperature and it has bad
		accuracy. Practically it is only useful as an indicator for
		temperature changes.
		*/
		this.ipcon.sendRequest(this, BrickletOutdoorWeather.FUNCTION_GET_CHIP_TEMPERATURE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.reset = function(returnCallback, errorCallback) {
		/*
		Calling this function will reset the Bricklet. All configurations
		will be lost.
		
		After a reset you have to create new device objects,
		calling functions on the existing ones will result in
		undefined behavior!
		*/
		this.ipcon.sendRequest(this, BrickletOutdoorWeather.FUNCTION_RESET, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeUID = function(uid, returnCallback, errorCallback) {
		/*
		Writes a new UID into flash. If you want to set a new UID
		you have to decode the Base58 encoded UID string into an
		integer first.
		
		We recommend that you use Brick Viewer to change the UID.
		*/
		this.ipcon.sendRequest(this, BrickletOutdoorWeather.FUNCTION_WRITE_UID, [uid], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.readUID = function(returnCallback, errorCallback) {
		/*
		Returns the current UID as an integer. Encode as
		Base58 to get the usual string version.
		*/
		this.ipcon.sendRequest(this, BrickletOutdoorWeather.FUNCTION_READ_UID, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletOutdoorWeather.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.getStationIdentifiers = function(returnCallback, errorCallback) {
		/*
		Returns the identifiers (number between 0 and 255) of all `stations
		<https://www.tinkerforge.com/en/shop/accessories/sensors/outdoor-weather-station-ws-6147.html>`__
		that have been seen since the startup of the Bricklet.
		
		Each station gives itself a random identifier on first startup.
		
		Since firmware version 2.0.2 a station is removed from the list if no data was received for
		12 hours.
		*/
		var responseHandler = null;
		var functionToQueue = null;
		var streamStateObject = this.streamStateObjects[1];
		if (streamStateObject['responseProperties']['responseHandler'] === null) {
			responseHandler = 
				function (device, fid, packetResponse) {
					var result = [];
					var llvalues = null;
					var packetErrorFlag = 0;
					var rolesMappedData = [];
					var identifiersLength = null;
					var identifiersChunkData = null;
					var identifiersOutOfSync = false;
					var streamStateObject = device.streamStateObjects[fid];
					var identifiersChunkOffset = null;
					var payload = device.ipcon.getPayloadFromPacket(packetResponse);

					packetErrorFlag = device.ipcon.getEFromPacket(packetResponse);

					if (packetErrorFlag !== 0) {
						if (streamStateObject['responseProperties']['errorCB'] !== undefined) {
							if (packetErrorFlag === 1) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_INVALID_PARAMETER);
							}
							else if (packetErrorFlag === 2) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_FUNCTION_NOT_SUPPORTED);
							}
							else {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_UNKNOWN_ERROR);
							}
						}

						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}

						return;
					}

					if (payload.length === 0) {
						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}

						return;
					}

					llvalues = device.ipcon.unpack(payload,
					                               streamStateObject['responseProperties']['unpackFormatString']);

					for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
						if (streamStateObject['dataMapping'][i] === 'streamChunkData') {
							identifiersChunkData = llvalues[i];
						}
						else if (streamStateObject['dataMapping'][i] === 'streamChunkOffset') {
							identifiersChunkOffset = llvalues[i];
						}
					}

					for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
						if (streamStateObject['dataMapping'][i] === 'streamLength') {
							identifiersLength = llvalues[i];
							break;
						}
					}

					function handleOOS() {
						if ((identifiersChunkOffset + 60) < identifiersLength) {
							streamStateObject['responseProperties']['runningSubcallOOS'] = true;
							device.ipcon.sendRequest(device, BrickletOutdoorWeather.FUNCTION_GET_STATION_IDENTIFIERS_LOW_LEVEL, [], '', 72, 'H H B60', streamStateObject['responseProperties']['returnCB'], streamStateObject['responseProperties']['errorCB'], true, true);

							return;
						}

						if (streamStateObject['responseProperties']['errorCB']) {
							streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_STREAM_OUT_OF_SYNC);
						}

						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}
					}

					if (streamStateObject['responseProperties']['waitingFirstChunk']) {
						streamStateObject['responseProperties']['waitingFirstChunk'] = false;
						identifiersOutOfSync = (identifiersChunkOffset !== 0);
						streamStateObject['responseProperties']['data'] = identifiersChunkData;
					}

					if (!streamStateObject['responseProperties']['runningSubcallOOS']) {
						if (!streamStateObject['responseProperties']['runningSubcall']) {
							if (!identifiersOutOfSync &&
							    (streamStateObject['responseProperties']['data'].length < identifiersLength)) {
							        streamStateObject['responseProperties']['runningSubcall'] = true;
							        device.ipcon.sendRequest(device, BrickletOutdoorWeather.FUNCTION_GET_STATION_IDENTIFIERS_LOW_LEVEL, [], '', 72, 'H H B60', streamStateObject['responseProperties']['returnCB'], streamStateObject['responseProperties']['errorCB'], true, true);

							        return;
							}
						}
						else {
							identifiersOutOfSync =
								(identifiersChunkOffset !== streamStateObject['responseProperties']['data'].length);

							if (!identifiersOutOfSync &&
								(streamStateObject['responseProperties']['data'].length < identifiersLength)) {
									streamStateObject['responseProperties']['data'] =
										streamStateObject['responseProperties']['data'].concat(identifiersChunkData);

									if (streamStateObject['responseProperties']['data'].length >= identifiersLength) {
										streamStateObject['responseProperties']['data'] =
											streamStateObject['responseProperties']['data'].splice(0, identifiersLength);
									}
									else {
										device.ipcon.sendRequest(device, BrickletOutdoorWeather.FUNCTION_GET_STATION_IDENTIFIERS_LOW_LEVEL, [], '', 72, 'H H B60', streamStateObject['responseProperties']['returnCB'], streamStateObject['responseProperties']['errorCB'], true, true);

										return;
									}
							}
						}
					}
					else{
						handleOOS();

						return;
					}

					if (identifiersOutOfSync) { // Discard remaining stream to bring it back in-sync
						handleOOS();

						return;
					}

					if (streamStateObject['responseProperties']['returnCB']) {
						for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
							rolesMappedData.push({'role': streamStateObject['dataMapping'][i], 'llvalue': llvalues[i]});
						}

						for (var i = 0; i < rolesMappedData.length; i++) {
							if (rolesMappedData[i]['role'] === 'streamChunkData') {
								result.push(streamStateObject['responseProperties']['data'].splice(0, identifiersLength));
							}
							else if (rolesMappedData[i]['role'] === null) {
								result.push(rolesMappedData[i]['llvalue']);
							}
						}

						streamStateObject['responseProperties']['returnCB'].apply(device, result);
					}

					device.resetStreamStateObject(streamStateObject);

					if (streamStateObject['responseProperties']['callQueue'].length > 0) {
						streamStateObject['responseProperties']['callQueue'].shift()(device);
					}
					
				};

			streamStateObject['responseProperties']['responseHandler'] = responseHandler;
		}
		if (!streamStateObject['responseProperties']['running']) {
			streamStateObject['responseProperties']['running'] = true;
			streamStateObject['responseProperties']['returnCB'] = returnCallback;
			streamStateObject['responseProperties']['errorCB'] = errorCallback;
			this.ipcon.sendRequest(this,
			                       BrickletOutdoorWeather.FUNCTION_GET_STATION_IDENTIFIERS_LOW_LEVEL,
			                       [],
			                       '',
			                       72,
			                       'H H B60',
			                       returnCallback,
			                       errorCallback,
			                       true,
			                       true);
		}
		else {
			functionToQueue = function (device) {
				device.getStationIdentifiers.call(device, returnCallback, errorCallback);
			}
			streamStateObject['responseProperties']['callQueue'].push(functionToQueue);
		}
	};

	this.getSensorIdentifiers = function(returnCallback, errorCallback) {
		/*
		Returns the identifiers (number between 0 and 255) of all `sensors
		<https://www.tinkerforge.com/en/shop/accessories/sensors/temperature-humidity-sensor-th-6148.html>`__
		that have been seen since the startup of the Bricklet.
		
		Each sensor gives itself a random identifier on first startup.
		
		Since firmware version 2.0.2 a sensor is removed from the list if no data was received for
		12 hours.
		*/
		var responseHandler = null;
		var functionToQueue = null;
		var streamStateObject = this.streamStateObjects[2];
		if (streamStateObject['responseProperties']['responseHandler'] === null) {
			responseHandler = 
				function (device, fid, packetResponse) {
					var result = [];
					var llvalues = null;
					var packetErrorFlag = 0;
					var rolesMappedData = [];
					var identifiersLength = null;
					var identifiersChunkData = null;
					var identifiersOutOfSync = false;
					var streamStateObject = device.streamStateObjects[fid];
					var identifiersChunkOffset = null;
					var payload = device.ipcon.getPayloadFromPacket(packetResponse);

					packetErrorFlag = device.ipcon.getEFromPacket(packetResponse);

					if (packetErrorFlag !== 0) {
						if (streamStateObject['responseProperties']['errorCB'] !== undefined) {
							if (packetErrorFlag === 1) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_INVALID_PARAMETER);
							}
							else if (packetErrorFlag === 2) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_FUNCTION_NOT_SUPPORTED);
							}
							else {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_UNKNOWN_ERROR);
							}
						}

						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}

						return;
					}

					if (payload.length === 0) {
						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}

						return;
					}

					llvalues = device.ipcon.unpack(payload,
					                               streamStateObject['responseProperties']['unpackFormatString']);

					for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
						if (streamStateObject['dataMapping'][i] === 'streamChunkData') {
							identifiersChunkData = llvalues[i];
						}
						else if (streamStateObject['dataMapping'][i] === 'streamChunkOffset') {
							identifiersChunkOffset = llvalues[i];
						}
					}

					for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
						if (streamStateObject['dataMapping'][i] === 'streamLength') {
							identifiersLength = llvalues[i];
							break;
						}
					}

					function handleOOS() {
						if ((identifiersChunkOffset + 60) < identifiersLength) {
							streamStateObject['responseProperties']['runningSubcallOOS'] = true;
							device.ipcon.sendRequest(device, BrickletOutdoorWeather.FUNCTION_GET_SENSOR_IDENTIFIERS_LOW_LEVEL, [], '', 72, 'H H B60', streamStateObject['responseProperties']['returnCB'], streamStateObject['responseProperties']['errorCB'], true, true);

							return;
						}

						if (streamStateObject['responseProperties']['errorCB']) {
							streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_STREAM_OUT_OF_SYNC);
						}

						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}
					}

					if (streamStateObject['responseProperties']['waitingFirstChunk']) {
						streamStateObject['responseProperties']['waitingFirstChunk'] = false;
						identifiersOutOfSync = (identifiersChunkOffset !== 0);
						streamStateObject['responseProperties']['data'] = identifiersChunkData;
					}

					if (!streamStateObject['responseProperties']['runningSubcallOOS']) {
						if (!streamStateObject['responseProperties']['runningSubcall']) {
							if (!identifiersOutOfSync &&
							    (streamStateObject['responseProperties']['data'].length < identifiersLength)) {
							        streamStateObject['responseProperties']['runningSubcall'] = true;
							        device.ipcon.sendRequest(device, BrickletOutdoorWeather.FUNCTION_GET_SENSOR_IDENTIFIERS_LOW_LEVEL, [], '', 72, 'H H B60', streamStateObject['responseProperties']['returnCB'], streamStateObject['responseProperties']['errorCB'], true, true);

							        return;
							}
						}
						else {
							identifiersOutOfSync =
								(identifiersChunkOffset !== streamStateObject['responseProperties']['data'].length);

							if (!identifiersOutOfSync &&
								(streamStateObject['responseProperties']['data'].length < identifiersLength)) {
									streamStateObject['responseProperties']['data'] =
										streamStateObject['responseProperties']['data'].concat(identifiersChunkData);

									if (streamStateObject['responseProperties']['data'].length >= identifiersLength) {
										streamStateObject['responseProperties']['data'] =
											streamStateObject['responseProperties']['data'].splice(0, identifiersLength);
									}
									else {
										device.ipcon.sendRequest(device, BrickletOutdoorWeather.FUNCTION_GET_SENSOR_IDENTIFIERS_LOW_LEVEL, [], '', 72, 'H H B60', streamStateObject['responseProperties']['returnCB'], streamStateObject['responseProperties']['errorCB'], true, true);

										return;
									}
							}
						}
					}
					else{
						handleOOS();

						return;
					}

					if (identifiersOutOfSync) { // Discard remaining stream to bring it back in-sync
						handleOOS();

						return;
					}

					if (streamStateObject['responseProperties']['returnCB']) {
						for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
							rolesMappedData.push({'role': streamStateObject['dataMapping'][i], 'llvalue': llvalues[i]});
						}

						for (var i = 0; i < rolesMappedData.length; i++) {
							if (rolesMappedData[i]['role'] === 'streamChunkData') {
								result.push(streamStateObject['responseProperties']['data'].splice(0, identifiersLength));
							}
							else if (rolesMappedData[i]['role'] === null) {
								result.push(rolesMappedData[i]['llvalue']);
							}
						}

						streamStateObject['responseProperties']['returnCB'].apply(device, result);
					}

					device.resetStreamStateObject(streamStateObject);

					if (streamStateObject['responseProperties']['callQueue'].length > 0) {
						streamStateObject['responseProperties']['callQueue'].shift()(device);
					}
					
				};

			streamStateObject['responseProperties']['responseHandler'] = responseHandler;
		}
		if (!streamStateObject['responseProperties']['running']) {
			streamStateObject['responseProperties']['running'] = true;
			streamStateObject['responseProperties']['returnCB'] = returnCallback;
			streamStateObject['responseProperties']['errorCB'] = errorCallback;
			this.ipcon.sendRequest(this,
			                       BrickletOutdoorWeather.FUNCTION_GET_SENSOR_IDENTIFIERS_LOW_LEVEL,
			                       [],
			                       '',
			                       72,
			                       'H H B60',
			                       returnCallback,
			                       errorCallback,
			                       true,
			                       true);
		}
		else {
			functionToQueue = function (device) {
				device.getSensorIdentifiers.call(device, returnCallback, errorCallback);
			}
			streamStateObject['responseProperties']['callQueue'].push(functionToQueue);
		}
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletOutdoorWeather;

},{"./Device":279,"./IPConnection":280}],235:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletPTC.DEVICE_IDENTIFIER = 226;
BrickletPTC.DEVICE_DISPLAY_NAME = 'PTC Bricklet';
BrickletPTC.CALLBACK_TEMPERATURE = 13;
BrickletPTC.CALLBACK_TEMPERATURE_REACHED = 14;
BrickletPTC.CALLBACK_RESISTANCE = 15;
BrickletPTC.CALLBACK_RESISTANCE_REACHED = 16;
BrickletPTC.CALLBACK_SENSOR_CONNECTED = 24;
BrickletPTC.FUNCTION_GET_TEMPERATURE = 1;
BrickletPTC.FUNCTION_GET_RESISTANCE = 2;
BrickletPTC.FUNCTION_SET_TEMPERATURE_CALLBACK_PERIOD = 3;
BrickletPTC.FUNCTION_GET_TEMPERATURE_CALLBACK_PERIOD = 4;
BrickletPTC.FUNCTION_SET_RESISTANCE_CALLBACK_PERIOD = 5;
BrickletPTC.FUNCTION_GET_RESISTANCE_CALLBACK_PERIOD = 6;
BrickletPTC.FUNCTION_SET_TEMPERATURE_CALLBACK_THRESHOLD = 7;
BrickletPTC.FUNCTION_GET_TEMPERATURE_CALLBACK_THRESHOLD = 8;
BrickletPTC.FUNCTION_SET_RESISTANCE_CALLBACK_THRESHOLD = 9;
BrickletPTC.FUNCTION_GET_RESISTANCE_CALLBACK_THRESHOLD = 10;
BrickletPTC.FUNCTION_SET_DEBOUNCE_PERIOD = 11;
BrickletPTC.FUNCTION_GET_DEBOUNCE_PERIOD = 12;
BrickletPTC.FUNCTION_SET_NOISE_REJECTION_FILTER = 17;
BrickletPTC.FUNCTION_GET_NOISE_REJECTION_FILTER = 18;
BrickletPTC.FUNCTION_IS_SENSOR_CONNECTED = 19;
BrickletPTC.FUNCTION_SET_WIRE_MODE = 20;
BrickletPTC.FUNCTION_GET_WIRE_MODE = 21;
BrickletPTC.FUNCTION_SET_SENSOR_CONNECTED_CALLBACK_CONFIGURATION = 22;
BrickletPTC.FUNCTION_GET_SENSOR_CONNECTED_CALLBACK_CONFIGURATION = 23;
BrickletPTC.FUNCTION_GET_IDENTITY = 255;
BrickletPTC.THRESHOLD_OPTION_OFF = 'x';
BrickletPTC.THRESHOLD_OPTION_OUTSIDE = 'o';
BrickletPTC.THRESHOLD_OPTION_INSIDE = 'i';
BrickletPTC.THRESHOLD_OPTION_SMALLER = '<';
BrickletPTC.THRESHOLD_OPTION_GREATER = '>';
BrickletPTC.FILTER_OPTION_50HZ = 0;
BrickletPTC.FILTER_OPTION_60HZ = 1;
BrickletPTC.WIRE_MODE_2 = 2;
BrickletPTC.WIRE_MODE_3 = 3;
BrickletPTC.WIRE_MODE_4 = 4;

function BrickletPTC(uid, ipcon) {
	//Reads temperatures from Pt100 und Pt1000 sensors

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletPTC.DEVICE_IDENTIFIER, BrickletPTC.DEVICE_DISPLAY_NAME);
	BrickletPTC.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 1];
	this.responseExpected[BrickletPTC.FUNCTION_GET_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletPTC.FUNCTION_GET_RESISTANCE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletPTC.FUNCTION_SET_TEMPERATURE_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletPTC.FUNCTION_GET_TEMPERATURE_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletPTC.FUNCTION_SET_RESISTANCE_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletPTC.FUNCTION_GET_RESISTANCE_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletPTC.FUNCTION_SET_TEMPERATURE_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletPTC.FUNCTION_GET_TEMPERATURE_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletPTC.FUNCTION_SET_RESISTANCE_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletPTC.FUNCTION_GET_RESISTANCE_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletPTC.FUNCTION_SET_DEBOUNCE_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletPTC.FUNCTION_GET_DEBOUNCE_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletPTC.FUNCTION_SET_NOISE_REJECTION_FILTER] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletPTC.FUNCTION_GET_NOISE_REJECTION_FILTER] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletPTC.FUNCTION_IS_SENSOR_CONNECTED] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletPTC.FUNCTION_SET_WIRE_MODE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletPTC.FUNCTION_GET_WIRE_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletPTC.FUNCTION_SET_SENSOR_CONNECTED_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletPTC.FUNCTION_GET_SENSOR_CONNECTED_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletPTC.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletPTC.CALLBACK_TEMPERATURE] = [12, 'i'];
	this.callbackFormats[BrickletPTC.CALLBACK_TEMPERATURE_REACHED] = [12, 'i'];
	this.callbackFormats[BrickletPTC.CALLBACK_RESISTANCE] = [12, 'i'];
	this.callbackFormats[BrickletPTC.CALLBACK_RESISTANCE_REACHED] = [12, 'i'];
	this.callbackFormats[BrickletPTC.CALLBACK_SENSOR_CONNECTED] = [9, '?'];



	this.getTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature of connected sensor.
		
		If you want to get the temperature periodically, it is recommended
		to use the :cb:`Temperature` callback and set the period with
		:func:`Set Temperature Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletPTC.FUNCTION_GET_TEMPERATURE, [], '', 12, 'i', returnCallback, errorCallback, false, true);
	};
	this.getResistance = function(returnCallback, errorCallback) {
		/*
		Returns the value as measured by the MAX31865 precision delta-sigma ADC.
		
		The value can be converted with the following formulas:
		
		* Pt100:  resistance = (value * 390) / 32768
		* Pt1000: resistance = (value * 3900) / 32768
		
		If you want to get the resistance periodically, it is recommended
		to use the :cb:`Resistance` callback and set the period with
		:func:`Set Resistance Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletPTC.FUNCTION_GET_RESISTANCE, [], '', 12, 'i', returnCallback, errorCallback, false, true);
	};
	this.setTemperatureCallbackPeriod = function(period, returnCallback, errorCallback) {
		/*
		Sets the period with which the :cb:`Temperature` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		The :cb:`Temperature` callback is only triggered if the temperature has
		changed since the last triggering.
		*/
		this.ipcon.sendRequest(this, BrickletPTC.FUNCTION_SET_TEMPERATURE_CALLBACK_PERIOD, [period], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getTemperatureCallbackPeriod = function(returnCallback, errorCallback) {
		/*
		Returns the period as set by :func:`Set Temperature Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletPTC.FUNCTION_GET_TEMPERATURE_CALLBACK_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setResistanceCallbackPeriod = function(period, returnCallback, errorCallback) {
		/*
		Sets the period with which the :cb:`Resistance` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		The :cb:`Resistance` callback is only triggered if the resistance has changed
		since the last triggering.
		*/
		this.ipcon.sendRequest(this, BrickletPTC.FUNCTION_SET_RESISTANCE_CALLBACK_PERIOD, [period], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getResistanceCallbackPeriod = function(returnCallback, errorCallback) {
		/*
		Returns the period as set by :func:`Set Resistance Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletPTC.FUNCTION_GET_RESISTANCE_CALLBACK_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setTemperatureCallbackThreshold = function(option, min, max, returnCallback, errorCallback) {
		/*
		Sets the thresholds for the :cb:`Temperature Reached` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Callback is turned off"
		 "'o'",    "Callback is triggered when the temperature is *outside* the min and max values"
		 "'i'",    "Callback is triggered when the temperature is *inside* the min and max values"
		 "'<'",    "Callback is triggered when the temperature is smaller than the min value (max is ignored)"
		 "'>'",    "Callback is triggered when the temperature is greater than the min value (max is ignored)"
		*/
		this.ipcon.sendRequest(this, BrickletPTC.FUNCTION_SET_TEMPERATURE_CALLBACK_THRESHOLD, [option, min, max], 'c i i', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getTemperatureCallbackThreshold = function(returnCallback, errorCallback) {
		/*
		Returns the threshold as set by :func:`Set Temperature Callback Threshold`.
		*/
		this.ipcon.sendRequest(this, BrickletPTC.FUNCTION_GET_TEMPERATURE_CALLBACK_THRESHOLD, [], '', 17, 'c i i', returnCallback, errorCallback, false, true);
	};
	this.setResistanceCallbackThreshold = function(option, min, max, returnCallback, errorCallback) {
		/*
		Sets the thresholds for the :cb:`Resistance Reached` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Callback is turned off"
		 "'o'",    "Callback is triggered when the temperature is *outside* the min and max values"
		 "'i'",    "Callback is triggered when the temperature is *inside* the min and max values"
		 "'<'",    "Callback is triggered when the temperature is smaller than the min value (max is ignored)"
		 "'>'",    "Callback is triggered when the temperature is greater than the min value (max is ignored)"
		*/
		this.ipcon.sendRequest(this, BrickletPTC.FUNCTION_SET_RESISTANCE_CALLBACK_THRESHOLD, [option, min, max], 'c i i', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getResistanceCallbackThreshold = function(returnCallback, errorCallback) {
		/*
		Returns the threshold as set by :func:`Set Resistance Callback Threshold`.
		*/
		this.ipcon.sendRequest(this, BrickletPTC.FUNCTION_GET_RESISTANCE_CALLBACK_THRESHOLD, [], '', 17, 'c i i', returnCallback, errorCallback, false, true);
	};
	this.setDebouncePeriod = function(debounce, returnCallback, errorCallback) {
		/*
		Sets the period with which the threshold callback
		
		* :cb:`Temperature Reached`,
		* :cb:`Resistance Reached`
		
		is triggered, if the threshold
		
		* :func:`Set Temperature Callback Threshold`,
		* :func:`Set Resistance Callback Threshold`
		
		keeps being reached.
		*/
		this.ipcon.sendRequest(this, BrickletPTC.FUNCTION_SET_DEBOUNCE_PERIOD, [debounce], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getDebouncePeriod = function(returnCallback, errorCallback) {
		/*
		Returns the debounce period as set by :func:`Set Debounce Period`.
		*/
		this.ipcon.sendRequest(this, BrickletPTC.FUNCTION_GET_DEBOUNCE_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setNoiseRejectionFilter = function(filter, returnCallback, errorCallback) {
		/*
		Sets the noise rejection filter to either 50Hz (0) or 60Hz (1).
		Noise from 50Hz or 60Hz power sources (including
		harmonics of the AC power's fundamental frequency) is
		attenuated by 82dB.
		*/
		this.ipcon.sendRequest(this, BrickletPTC.FUNCTION_SET_NOISE_REJECTION_FILTER, [filter], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getNoiseRejectionFilter = function(returnCallback, errorCallback) {
		/*
		Returns the noise rejection filter option as set by
		:func:`Set Noise Rejection Filter`
		*/
		this.ipcon.sendRequest(this, BrickletPTC.FUNCTION_GET_NOISE_REJECTION_FILTER, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.isSensorConnected = function(returnCallback, errorCallback) {
		/*
		Returns *true* if the sensor is connected correctly.
		
		If this function
		returns *false*, there is either no Pt100 or Pt1000 sensor connected,
		the sensor is connected incorrectly or the sensor itself is faulty.
		*/
		this.ipcon.sendRequest(this, BrickletPTC.FUNCTION_IS_SENSOR_CONNECTED, [], '', 9, '?', returnCallback, errorCallback, false, true);
	};
	this.setWireMode = function(mode, returnCallback, errorCallback) {
		/*
		Sets the wire mode of the sensor. Possible values are 2, 3 and 4 which
		correspond to 2-, 3- and 4-wire sensors. The value has to match the jumper
		configuration on the Bricklet.
		*/
		this.ipcon.sendRequest(this, BrickletPTC.FUNCTION_SET_WIRE_MODE, [mode], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getWireMode = function(returnCallback, errorCallback) {
		/*
		Returns the wire mode as set by :func:`Set Wire Mode`
		*/
		this.ipcon.sendRequest(this, BrickletPTC.FUNCTION_GET_WIRE_MODE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setSensorConnectedCallbackConfiguration = function(enabled, returnCallback, errorCallback) {
		/*
		If you enable this callback, the :cb:`Sensor Connected` callback is triggered
		every time a Pt sensor is connected/disconnected.
		
		.. versionadded:: 2.0.2$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletPTC.FUNCTION_SET_SENSOR_CONNECTED_CALLBACK_CONFIGURATION, [enabled], '?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getSensorConnectedCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Sensor Connected Callback Configuration`.
		
		.. versionadded:: 2.0.2$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletPTC.FUNCTION_GET_SENSOR_CONNECTED_CALLBACK_CONFIGURATION, [], '', 9, '?', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletPTC.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletPTC;

},{"./Device":279,"./IPConnection":280}],236:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletPTCV2.DEVICE_IDENTIFIER = 2101;
BrickletPTCV2.DEVICE_DISPLAY_NAME = 'PTC Bricklet 2.0';
BrickletPTCV2.CALLBACK_TEMPERATURE = 4;
BrickletPTCV2.CALLBACK_RESISTANCE = 8;
BrickletPTCV2.CALLBACK_SENSOR_CONNECTED = 18;
BrickletPTCV2.FUNCTION_GET_TEMPERATURE = 1;
BrickletPTCV2.FUNCTION_SET_TEMPERATURE_CALLBACK_CONFIGURATION = 2;
BrickletPTCV2.FUNCTION_GET_TEMPERATURE_CALLBACK_CONFIGURATION = 3;
BrickletPTCV2.FUNCTION_GET_RESISTANCE = 5;
BrickletPTCV2.FUNCTION_SET_RESISTANCE_CALLBACK_CONFIGURATION = 6;
BrickletPTCV2.FUNCTION_GET_RESISTANCE_CALLBACK_CONFIGURATION = 7;
BrickletPTCV2.FUNCTION_SET_NOISE_REJECTION_FILTER = 9;
BrickletPTCV2.FUNCTION_GET_NOISE_REJECTION_FILTER = 10;
BrickletPTCV2.FUNCTION_IS_SENSOR_CONNECTED = 11;
BrickletPTCV2.FUNCTION_SET_WIRE_MODE = 12;
BrickletPTCV2.FUNCTION_GET_WIRE_MODE = 13;
BrickletPTCV2.FUNCTION_SET_MOVING_AVERAGE_CONFIGURATION = 14;
BrickletPTCV2.FUNCTION_GET_MOVING_AVERAGE_CONFIGURATION = 15;
BrickletPTCV2.FUNCTION_SET_SENSOR_CONNECTED_CALLBACK_CONFIGURATION = 16;
BrickletPTCV2.FUNCTION_GET_SENSOR_CONNECTED_CALLBACK_CONFIGURATION = 17;
BrickletPTCV2.FUNCTION_GET_SPITFP_ERROR_COUNT = 234;
BrickletPTCV2.FUNCTION_SET_BOOTLOADER_MODE = 235;
BrickletPTCV2.FUNCTION_GET_BOOTLOADER_MODE = 236;
BrickletPTCV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER = 237;
BrickletPTCV2.FUNCTION_WRITE_FIRMWARE = 238;
BrickletPTCV2.FUNCTION_SET_STATUS_LED_CONFIG = 239;
BrickletPTCV2.FUNCTION_GET_STATUS_LED_CONFIG = 240;
BrickletPTCV2.FUNCTION_GET_CHIP_TEMPERATURE = 242;
BrickletPTCV2.FUNCTION_RESET = 243;
BrickletPTCV2.FUNCTION_WRITE_UID = 248;
BrickletPTCV2.FUNCTION_READ_UID = 249;
BrickletPTCV2.FUNCTION_GET_IDENTITY = 255;
BrickletPTCV2.THRESHOLD_OPTION_OFF = 'x';
BrickletPTCV2.THRESHOLD_OPTION_OUTSIDE = 'o';
BrickletPTCV2.THRESHOLD_OPTION_INSIDE = 'i';
BrickletPTCV2.THRESHOLD_OPTION_SMALLER = '<';
BrickletPTCV2.THRESHOLD_OPTION_GREATER = '>';
BrickletPTCV2.FILTER_OPTION_50HZ = 0;
BrickletPTCV2.FILTER_OPTION_60HZ = 1;
BrickletPTCV2.WIRE_MODE_2 = 2;
BrickletPTCV2.WIRE_MODE_3 = 3;
BrickletPTCV2.WIRE_MODE_4 = 4;
BrickletPTCV2.BOOTLOADER_MODE_BOOTLOADER = 0;
BrickletPTCV2.BOOTLOADER_MODE_FIRMWARE = 1;
BrickletPTCV2.BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT = 2;
BrickletPTCV2.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT = 3;
BrickletPTCV2.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT = 4;
BrickletPTCV2.BOOTLOADER_STATUS_OK = 0;
BrickletPTCV2.BOOTLOADER_STATUS_INVALID_MODE = 1;
BrickletPTCV2.BOOTLOADER_STATUS_NO_CHANGE = 2;
BrickletPTCV2.BOOTLOADER_STATUS_ENTRY_FUNCTION_NOT_PRESENT = 3;
BrickletPTCV2.BOOTLOADER_STATUS_DEVICE_IDENTIFIER_INCORRECT = 4;
BrickletPTCV2.BOOTLOADER_STATUS_CRC_MISMATCH = 5;
BrickletPTCV2.STATUS_LED_CONFIG_OFF = 0;
BrickletPTCV2.STATUS_LED_CONFIG_ON = 1;
BrickletPTCV2.STATUS_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletPTCV2.STATUS_LED_CONFIG_SHOW_STATUS = 3;

function BrickletPTCV2(uid, ipcon) {
	//Reads temperatures from Pt100 und Pt1000 sensors

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletPTCV2.DEVICE_IDENTIFIER, BrickletPTCV2.DEVICE_DISPLAY_NAME);
	BrickletPTCV2.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickletPTCV2.FUNCTION_GET_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletPTCV2.FUNCTION_SET_TEMPERATURE_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletPTCV2.FUNCTION_GET_TEMPERATURE_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletPTCV2.FUNCTION_GET_RESISTANCE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletPTCV2.FUNCTION_SET_RESISTANCE_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletPTCV2.FUNCTION_GET_RESISTANCE_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletPTCV2.FUNCTION_SET_NOISE_REJECTION_FILTER] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletPTCV2.FUNCTION_GET_NOISE_REJECTION_FILTER] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletPTCV2.FUNCTION_IS_SENSOR_CONNECTED] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletPTCV2.FUNCTION_SET_WIRE_MODE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletPTCV2.FUNCTION_GET_WIRE_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletPTCV2.FUNCTION_SET_MOVING_AVERAGE_CONFIGURATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletPTCV2.FUNCTION_GET_MOVING_AVERAGE_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletPTCV2.FUNCTION_SET_SENSOR_CONNECTED_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletPTCV2.FUNCTION_GET_SENSOR_CONNECTED_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletPTCV2.FUNCTION_GET_SPITFP_ERROR_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletPTCV2.FUNCTION_SET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletPTCV2.FUNCTION_GET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletPTCV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletPTCV2.FUNCTION_WRITE_FIRMWARE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletPTCV2.FUNCTION_SET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletPTCV2.FUNCTION_GET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletPTCV2.FUNCTION_GET_CHIP_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletPTCV2.FUNCTION_RESET] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletPTCV2.FUNCTION_WRITE_UID] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletPTCV2.FUNCTION_READ_UID] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletPTCV2.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletPTCV2.CALLBACK_TEMPERATURE] = [12, 'i'];
	this.callbackFormats[BrickletPTCV2.CALLBACK_RESISTANCE] = [12, 'i'];
	this.callbackFormats[BrickletPTCV2.CALLBACK_SENSOR_CONNECTED] = [9, '?'];



	this.getTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature of the connected sensor.
		
		
		If you want to get the value periodically, it is recommended to use the
		:cb:`Temperature` callback. You can set the callback configuration
		with :func:`Set Temperature Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletPTCV2.FUNCTION_GET_TEMPERATURE, [], '', 12, 'i', returnCallback, errorCallback, false, true);
	};
	this.setTemperatureCallbackConfiguration = function(period, valueHasToChange, option, min, max, returnCallback, errorCallback) {
		/*
		The period is the period with which the :cb:`Temperature` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		If the `value has to change`-parameter is set to true, the callback is only
		triggered after the value has changed. If the value didn't change
		within the period, the callback is triggered immediately on change.
		
		If it is set to false, the callback is continuously triggered with the period,
		independent of the value.
		
		It is furthermore possible to constrain the callback with thresholds.
		
		The `option`-parameter together with min/max sets a threshold for the :cb:`Temperature` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Threshold is turned off"
		 "'o'",    "Threshold is triggered when the value is *outside* the min and max values"
		 "'i'",    "Threshold is triggered when the value is *inside* or equal to the min and max values"
		 "'<'",    "Threshold is triggered when the value is smaller than the min value (max is ignored)"
		 "'>'",    "Threshold is triggered when the value is greater than the min value (max is ignored)"
		
		If the option is set to 'x' (threshold turned off) the callback is triggered with the fixed period.
		*/
		this.ipcon.sendRequest(this, BrickletPTCV2.FUNCTION_SET_TEMPERATURE_CALLBACK_CONFIGURATION, [period, valueHasToChange, option, min, max], 'I ? c i i', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getTemperatureCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the callback configuration as set by :func:`Set Temperature Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletPTCV2.FUNCTION_GET_TEMPERATURE_CALLBACK_CONFIGURATION, [], '', 22, 'I ? c i i', returnCallback, errorCallback, false, true);
	};
	this.getResistance = function(returnCallback, errorCallback) {
		/*
		Returns the value as measured by the MAX31865 precision delta-sigma ADC.
		
		The value can be converted with the following formulas:
		
		* Pt100:  resistance = (value * 390) / 32768
		* Pt1000: resistance = (value * 3900) / 32768
		
		
		If you want to get the value periodically, it is recommended to use the
		:cb:`Resistance` callback. You can set the callback configuration
		with :func:`Set Resistance Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletPTCV2.FUNCTION_GET_RESISTANCE, [], '', 12, 'i', returnCallback, errorCallback, false, true);
	};
	this.setResistanceCallbackConfiguration = function(period, valueHasToChange, option, min, max, returnCallback, errorCallback) {
		/*
		The period is the period with which the :cb:`Resistance` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		If the `value has to change`-parameter is set to true, the callback is only
		triggered after the value has changed. If the value didn't change
		within the period, the callback is triggered immediately on change.
		
		If it is set to false, the callback is continuously triggered with the period,
		independent of the value.
		
		It is furthermore possible to constrain the callback with thresholds.
		
		The `option`-parameter together with min/max sets a threshold for the :cb:`Resistance` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Threshold is turned off"
		 "'o'",    "Threshold is triggered when the value is *outside* the min and max values"
		 "'i'",    "Threshold is triggered when the value is *inside* or equal to the min and max values"
		 "'<'",    "Threshold is triggered when the value is smaller than the min value (max is ignored)"
		 "'>'",    "Threshold is triggered when the value is greater than the min value (max is ignored)"
		
		If the option is set to 'x' (threshold turned off) the callback is triggered with the fixed period.
		*/
		this.ipcon.sendRequest(this, BrickletPTCV2.FUNCTION_SET_RESISTANCE_CALLBACK_CONFIGURATION, [period, valueHasToChange, option, min, max], 'I ? c i i', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getResistanceCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the callback configuration as set by :func:`Set Resistance Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletPTCV2.FUNCTION_GET_RESISTANCE_CALLBACK_CONFIGURATION, [], '', 22, 'I ? c i i', returnCallback, errorCallback, false, true);
	};
	this.setNoiseRejectionFilter = function(filter, returnCallback, errorCallback) {
		/*
		Sets the noise rejection filter to either 50Hz (0) or 60Hz (1).
		Noise from 50Hz or 60Hz power sources (including
		harmonics of the AC power's fundamental frequency) is
		attenuated by 82dB.
		*/
		this.ipcon.sendRequest(this, BrickletPTCV2.FUNCTION_SET_NOISE_REJECTION_FILTER, [filter], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getNoiseRejectionFilter = function(returnCallback, errorCallback) {
		/*
		Returns the noise rejection filter option as set by
		:func:`Set Noise Rejection Filter`
		*/
		this.ipcon.sendRequest(this, BrickletPTCV2.FUNCTION_GET_NOISE_REJECTION_FILTER, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.isSensorConnected = function(returnCallback, errorCallback) {
		/*
		Returns *true* if the sensor is connected correctly.
		
		If this function
		returns *false*, there is either no Pt100 or Pt1000 sensor connected,
		the sensor is connected incorrectly or the sensor itself is faulty.
		
		If you want to get the status automatically, it is recommended to use the
		:cb:`Sensor Connected` callback. You can set the callback configuration
		with :func:`Set Sensor Connected Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletPTCV2.FUNCTION_IS_SENSOR_CONNECTED, [], '', 9, '?', returnCallback, errorCallback, false, true);
	};
	this.setWireMode = function(mode, returnCallback, errorCallback) {
		/*
		Sets the wire mode of the sensor. Possible values are 2, 3 and 4 which
		correspond to 2-, 3- and 4-wire sensors. The value has to match the jumper
		configuration on the Bricklet.
		*/
		this.ipcon.sendRequest(this, BrickletPTCV2.FUNCTION_SET_WIRE_MODE, [mode], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getWireMode = function(returnCallback, errorCallback) {
		/*
		Returns the wire mode as set by :func:`Set Wire Mode`
		*/
		this.ipcon.sendRequest(this, BrickletPTCV2.FUNCTION_GET_WIRE_MODE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setMovingAverageConfiguration = function(movingAverageLengthResistance, movingAverageLengthTemperature, returnCallback, errorCallback) {
		/*
		Sets the length of a `moving averaging <https://en.wikipedia.org/wiki/Moving_average>`__
		for the resistance and temperature.
		
		Setting the length to 1 will turn the averaging off. With less
		averaging, there is more noise on the data.
		
		New data is gathered every 20ms. With a moving average of length 1000 the resulting
		averaging window has a length of 20s. If you want to do long term measurements the longest
		moving average will give the cleanest results.
		
		The default values match the non-changeable averaging settings of the old PTC Bricklet 1.0
		*/
		this.ipcon.sendRequest(this, BrickletPTCV2.FUNCTION_SET_MOVING_AVERAGE_CONFIGURATION, [movingAverageLengthResistance, movingAverageLengthTemperature], 'H H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getMovingAverageConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the moving average configuration as set by :func:`Set Moving Average Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletPTCV2.FUNCTION_GET_MOVING_AVERAGE_CONFIGURATION, [], '', 12, 'H H', returnCallback, errorCallback, false, true);
	};
	this.setSensorConnectedCallbackConfiguration = function(enabled, returnCallback, errorCallback) {
		/*
		If you enable this callback, the :cb:`Sensor Connected` callback is triggered
		every time a Pt sensor is connected/disconnected.
		*/
		this.ipcon.sendRequest(this, BrickletPTCV2.FUNCTION_SET_SENSOR_CONNECTED_CALLBACK_CONFIGURATION, [enabled], '?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getSensorConnectedCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Sensor Connected Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletPTCV2.FUNCTION_GET_SENSOR_CONNECTED_CALLBACK_CONFIGURATION, [], '', 9, '?', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPErrorCount = function(returnCallback, errorCallback) {
		/*
		Returns the error count for the communication between Brick and Bricklet.
		
		The errors are divided into
		
		* ACK checksum errors,
		* message checksum errors,
		* framing errors and
		* overflow errors.
		
		The errors counts are for errors that occur on the Bricklet side. All
		Bricks have a similar function that returns the errors on the Brick side.
		*/
		this.ipcon.sendRequest(this, BrickletPTCV2.FUNCTION_GET_SPITFP_ERROR_COUNT, [], '', 24, 'I I I I', returnCallback, errorCallback, false, true);
	};
	this.setBootloaderMode = function(mode, returnCallback, errorCallback) {
		/*
		Sets the bootloader mode and returns the status after the requested
		mode change was instigated.
		
		You can change from bootloader mode to firmware mode and vice versa. A change
		from bootloader mode to firmware mode will only take place if the entry function,
		device identifier and CRC are present and correct.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletPTCV2.FUNCTION_SET_BOOTLOADER_MODE, [mode], 'B', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getBootloaderMode = function(returnCallback, errorCallback) {
		/*
		Returns the current bootloader mode, see :func:`Set Bootloader Mode`.
		*/
		this.ipcon.sendRequest(this, BrickletPTCV2.FUNCTION_GET_BOOTLOADER_MODE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setWriteFirmwarePointer = function(pointer, returnCallback, errorCallback) {
		/*
		Sets the firmware pointer for :func:`Write Firmware`. The pointer has
		to be increased by chunks of size 64. The data is written to flash
		every 4 chunks (which equals to one page of size 256).
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletPTCV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER, [pointer], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeFirmware = function(data, returnCallback, errorCallback) {
		/*
		Writes 64 Bytes of firmware at the position as written by
		:func:`Set Write Firmware Pointer` before. The firmware is written
		to flash every 4 chunks.
		
		You can only write firmware in bootloader mode.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletPTCV2.FUNCTION_WRITE_FIRMWARE, [data], 'B64', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setStatusLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Sets the status LED configuration. By default the LED shows
		communication traffic between Brick and Bricklet, it flickers once
		for every 10 received data packets.
		
		You can also turn the LED permanently on/off or show a heartbeat.
		
		If the Bricklet is in bootloader mode, the LED is will show heartbeat by default.
		*/
		this.ipcon.sendRequest(this, BrickletPTCV2.FUNCTION_SET_STATUS_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getStatusLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Status LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletPTCV2.FUNCTION_GET_STATUS_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getChipTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature as measured inside the microcontroller. The
		value returned is not the ambient temperature!
		
		The temperature is only proportional to the real temperature and it has bad
		accuracy. Practically it is only useful as an indicator for
		temperature changes.
		*/
		this.ipcon.sendRequest(this, BrickletPTCV2.FUNCTION_GET_CHIP_TEMPERATURE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.reset = function(returnCallback, errorCallback) {
		/*
		Calling this function will reset the Bricklet. All configurations
		will be lost.
		
		After a reset you have to create new device objects,
		calling functions on the existing ones will result in
		undefined behavior!
		*/
		this.ipcon.sendRequest(this, BrickletPTCV2.FUNCTION_RESET, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeUID = function(uid, returnCallback, errorCallback) {
		/*
		Writes a new UID into flash. If you want to set a new UID
		you have to decode the Base58 encoded UID string into an
		integer first.
		
		We recommend that you use Brick Viewer to change the UID.
		*/
		this.ipcon.sendRequest(this, BrickletPTCV2.FUNCTION_WRITE_UID, [uid], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.readUID = function(returnCallback, errorCallback) {
		/*
		Returns the current UID as an integer. Encode as
		Base58 to get the usual string version.
		*/
		this.ipcon.sendRequest(this, BrickletPTCV2.FUNCTION_READ_UID, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletPTCV2.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletPTCV2;

},{"./Device":279,"./IPConnection":280}],237:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletParticulateMatter.DEVICE_IDENTIFIER = 2110;
BrickletParticulateMatter.DEVICE_DISPLAY_NAME = 'Particulate Matter Bricklet';
BrickletParticulateMatter.CALLBACK_PM_CONCENTRATION = 10;
BrickletParticulateMatter.CALLBACK_PM_COUNT = 11;
BrickletParticulateMatter.FUNCTION_GET_PM_CONCENTRATION = 1;
BrickletParticulateMatter.FUNCTION_GET_PM_COUNT = 2;
BrickletParticulateMatter.FUNCTION_SET_ENABLE = 3;
BrickletParticulateMatter.FUNCTION_GET_ENABLE = 4;
BrickletParticulateMatter.FUNCTION_GET_SENSOR_INFO = 5;
BrickletParticulateMatter.FUNCTION_SET_PM_CONCENTRATION_CALLBACK_CONFIGURATION = 6;
BrickletParticulateMatter.FUNCTION_GET_PM_CONCENTRATION_CALLBACK_CONFIGURATION = 7;
BrickletParticulateMatter.FUNCTION_SET_PM_COUNT_CALLBACK_CONFIGURATION = 8;
BrickletParticulateMatter.FUNCTION_GET_PM_COUNT_CALLBACK_CONFIGURATION = 9;
BrickletParticulateMatter.FUNCTION_GET_SPITFP_ERROR_COUNT = 234;
BrickletParticulateMatter.FUNCTION_SET_BOOTLOADER_MODE = 235;
BrickletParticulateMatter.FUNCTION_GET_BOOTLOADER_MODE = 236;
BrickletParticulateMatter.FUNCTION_SET_WRITE_FIRMWARE_POINTER = 237;
BrickletParticulateMatter.FUNCTION_WRITE_FIRMWARE = 238;
BrickletParticulateMatter.FUNCTION_SET_STATUS_LED_CONFIG = 239;
BrickletParticulateMatter.FUNCTION_GET_STATUS_LED_CONFIG = 240;
BrickletParticulateMatter.FUNCTION_GET_CHIP_TEMPERATURE = 242;
BrickletParticulateMatter.FUNCTION_RESET = 243;
BrickletParticulateMatter.FUNCTION_WRITE_UID = 248;
BrickletParticulateMatter.FUNCTION_READ_UID = 249;
BrickletParticulateMatter.FUNCTION_GET_IDENTITY = 255;
BrickletParticulateMatter.BOOTLOADER_MODE_BOOTLOADER = 0;
BrickletParticulateMatter.BOOTLOADER_MODE_FIRMWARE = 1;
BrickletParticulateMatter.BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT = 2;
BrickletParticulateMatter.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT = 3;
BrickletParticulateMatter.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT = 4;
BrickletParticulateMatter.BOOTLOADER_STATUS_OK = 0;
BrickletParticulateMatter.BOOTLOADER_STATUS_INVALID_MODE = 1;
BrickletParticulateMatter.BOOTLOADER_STATUS_NO_CHANGE = 2;
BrickletParticulateMatter.BOOTLOADER_STATUS_ENTRY_FUNCTION_NOT_PRESENT = 3;
BrickletParticulateMatter.BOOTLOADER_STATUS_DEVICE_IDENTIFIER_INCORRECT = 4;
BrickletParticulateMatter.BOOTLOADER_STATUS_CRC_MISMATCH = 5;
BrickletParticulateMatter.STATUS_LED_CONFIG_OFF = 0;
BrickletParticulateMatter.STATUS_LED_CONFIG_ON = 1;
BrickletParticulateMatter.STATUS_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletParticulateMatter.STATUS_LED_CONFIG_SHOW_STATUS = 3;

function BrickletParticulateMatter(uid, ipcon) {
	//Measures Particulate Matter concentration (PM1.0, PM2.5 and PM10)

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletParticulateMatter.DEVICE_IDENTIFIER, BrickletParticulateMatter.DEVICE_DISPLAY_NAME);
	BrickletParticulateMatter.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickletParticulateMatter.FUNCTION_GET_PM_CONCENTRATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletParticulateMatter.FUNCTION_GET_PM_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletParticulateMatter.FUNCTION_SET_ENABLE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletParticulateMatter.FUNCTION_GET_ENABLE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletParticulateMatter.FUNCTION_GET_SENSOR_INFO] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletParticulateMatter.FUNCTION_SET_PM_CONCENTRATION_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletParticulateMatter.FUNCTION_GET_PM_CONCENTRATION_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletParticulateMatter.FUNCTION_SET_PM_COUNT_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletParticulateMatter.FUNCTION_GET_PM_COUNT_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletParticulateMatter.FUNCTION_GET_SPITFP_ERROR_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletParticulateMatter.FUNCTION_SET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletParticulateMatter.FUNCTION_GET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletParticulateMatter.FUNCTION_SET_WRITE_FIRMWARE_POINTER] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletParticulateMatter.FUNCTION_WRITE_FIRMWARE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletParticulateMatter.FUNCTION_SET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletParticulateMatter.FUNCTION_GET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletParticulateMatter.FUNCTION_GET_CHIP_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletParticulateMatter.FUNCTION_RESET] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletParticulateMatter.FUNCTION_WRITE_UID] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletParticulateMatter.FUNCTION_READ_UID] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletParticulateMatter.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletParticulateMatter.CALLBACK_PM_CONCENTRATION] = [14, 'H H H'];
	this.callbackFormats[BrickletParticulateMatter.CALLBACK_PM_COUNT] = [20, 'H H H H H H'];



	this.getPMConcentration = function(returnCallback, errorCallback) {
		/*
		Returns the particulate matter concentration, broken down as:
		
		* PM\ :sub:`1.0`\ ,
		* PM\ :sub:`2.5`\  and
		* PM\ :sub:`10.0`\ .
		
		If the sensor is disabled (see :func:`Set Enable`) then the last known good
		values from the sensor are returned.
		
		If you want to get the values periodically, it is recommended to use the
		:cb:`PM Concentration` callback. You can set the callback configuration
		with :func:`Set PM Concentration Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletParticulateMatter.FUNCTION_GET_PM_CONCENTRATION, [], '', 14, 'H H H', returnCallback, errorCallback, false, true);
	};
	this.getPMCount = function(returnCallback, errorCallback) {
		/*
		Returns the number of particulates in 100 ml of air, broken down by their
		diameter:
		
		* greater 0.3µm,
		* greater 0.5µm,
		* greater 1.0µm,
		* greater 2.5µm,
		* greater 5.0µm and
		* greater 10.0µm.
		
		If the sensor is disabled (see :func:`Set Enable`) then the last known good
		value from the sensor is returned.
		
		If you want to get the values periodically, it is recommended to use the
		:cb:`PM Count` callback. You can set the callback configuration
		with :func:`Set PM Count Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletParticulateMatter.FUNCTION_GET_PM_COUNT, [], '', 20, 'H H H H H H', returnCallback, errorCallback, false, true);
	};
	this.setEnable = function(enable, returnCallback, errorCallback) {
		/*
		Enables/Disables the fan and the laser diode of the sensors.
		
		The sensor takes about 30 seconds after it is enabled to settle and produce stable
		values.
		
		The laser diode has a lifetime of about 8000 hours. If you want to measure in
		an interval with a long idle time (e.g. hourly) you should turn the
		laser diode off between the measurements.
		*/
		this.ipcon.sendRequest(this, BrickletParticulateMatter.FUNCTION_SET_ENABLE, [enable], '?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getEnable = function(returnCallback, errorCallback) {
		/*
		Returns the state of the sensor as set by :func:`Set Enable`.
		*/
		this.ipcon.sendRequest(this, BrickletParticulateMatter.FUNCTION_GET_ENABLE, [], '', 9, '?', returnCallback, errorCallback, false, true);
	};
	this.getSensorInfo = function(returnCallback, errorCallback) {
		/*
		Returns information about the sensor:
		
		* the sensor version number,
		* the last error code reported by the sensor (0 means no error) and
		* the number of framing and checksum errors that occurred in the communication
		  with the sensor.
		*/
		this.ipcon.sendRequest(this, BrickletParticulateMatter.FUNCTION_GET_SENSOR_INFO, [], '', 12, 'B B B B', returnCallback, errorCallback, false, true);
	};
	this.setPMConcentrationCallbackConfiguration = function(period, valueHasToChange, returnCallback, errorCallback) {
		/*
		The period is the period with which the :cb:`PM Concentration`
		callback is triggered periodically. A value of 0 turns the callback off.
		
		If the `value has to change`-parameter is set to true, the callback is only
		triggered after the value has changed. If the value didn't change within the
		period, the callback is triggered immediately on change.
		
		If it is set to false, the callback is continuously triggered with the period,
		independent of the value.
		*/
		this.ipcon.sendRequest(this, BrickletParticulateMatter.FUNCTION_SET_PM_CONCENTRATION_CALLBACK_CONFIGURATION, [period, valueHasToChange], 'I ?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getPMConcentrationCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the callback configuration as set by
		:func:`Set PM Concentration Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletParticulateMatter.FUNCTION_GET_PM_CONCENTRATION_CALLBACK_CONFIGURATION, [], '', 13, 'I ?', returnCallback, errorCallback, false, true);
	};
	this.setPMCountCallbackConfiguration = function(period, valueHasToChange, returnCallback, errorCallback) {
		/*
		The period is the period with which the :cb:`PM Count` callback
		is triggered periodically. A value of 0 turns the callback off.
		
		If the `value has to change`-parameter is set to true, the callback is only
		triggered after the value has changed. If the value didn't change within the
		period, the callback is triggered immediately on change.
		
		If it is set to false, the callback is continuously triggered with the period,
		independent of the value.
		*/
		this.ipcon.sendRequest(this, BrickletParticulateMatter.FUNCTION_SET_PM_COUNT_CALLBACK_CONFIGURATION, [period, valueHasToChange], 'I ?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getPMCountCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the callback configuration as set by
		:func:`Set PM Count Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletParticulateMatter.FUNCTION_GET_PM_COUNT_CALLBACK_CONFIGURATION, [], '', 13, 'I ?', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPErrorCount = function(returnCallback, errorCallback) {
		/*
		Returns the error count for the communication between Brick and Bricklet.
		
		The errors are divided into
		
		* ACK checksum errors,
		* message checksum errors,
		* framing errors and
		* overflow errors.
		
		The errors counts are for errors that occur on the Bricklet side. All
		Bricks have a similar function that returns the errors on the Brick side.
		*/
		this.ipcon.sendRequest(this, BrickletParticulateMatter.FUNCTION_GET_SPITFP_ERROR_COUNT, [], '', 24, 'I I I I', returnCallback, errorCallback, false, true);
	};
	this.setBootloaderMode = function(mode, returnCallback, errorCallback) {
		/*
		Sets the bootloader mode and returns the status after the requested
		mode change was instigated.
		
		You can change from bootloader mode to firmware mode and vice versa. A change
		from bootloader mode to firmware mode will only take place if the entry function,
		device identifier and CRC are present and correct.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletParticulateMatter.FUNCTION_SET_BOOTLOADER_MODE, [mode], 'B', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getBootloaderMode = function(returnCallback, errorCallback) {
		/*
		Returns the current bootloader mode, see :func:`Set Bootloader Mode`.
		*/
		this.ipcon.sendRequest(this, BrickletParticulateMatter.FUNCTION_GET_BOOTLOADER_MODE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setWriteFirmwarePointer = function(pointer, returnCallback, errorCallback) {
		/*
		Sets the firmware pointer for :func:`Write Firmware`. The pointer has
		to be increased by chunks of size 64. The data is written to flash
		every 4 chunks (which equals to one page of size 256).
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletParticulateMatter.FUNCTION_SET_WRITE_FIRMWARE_POINTER, [pointer], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeFirmware = function(data, returnCallback, errorCallback) {
		/*
		Writes 64 Bytes of firmware at the position as written by
		:func:`Set Write Firmware Pointer` before. The firmware is written
		to flash every 4 chunks.
		
		You can only write firmware in bootloader mode.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletParticulateMatter.FUNCTION_WRITE_FIRMWARE, [data], 'B64', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setStatusLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Sets the status LED configuration. By default the LED shows
		communication traffic between Brick and Bricklet, it flickers once
		for every 10 received data packets.
		
		You can also turn the LED permanently on/off or show a heartbeat.
		
		If the Bricklet is in bootloader mode, the LED is will show heartbeat by default.
		*/
		this.ipcon.sendRequest(this, BrickletParticulateMatter.FUNCTION_SET_STATUS_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getStatusLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Status LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletParticulateMatter.FUNCTION_GET_STATUS_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getChipTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature as measured inside the microcontroller. The
		value returned is not the ambient temperature!
		
		The temperature is only proportional to the real temperature and it has bad
		accuracy. Practically it is only useful as an indicator for
		temperature changes.
		*/
		this.ipcon.sendRequest(this, BrickletParticulateMatter.FUNCTION_GET_CHIP_TEMPERATURE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.reset = function(returnCallback, errorCallback) {
		/*
		Calling this function will reset the Bricklet. All configurations
		will be lost.
		
		After a reset you have to create new device objects,
		calling functions on the existing ones will result in
		undefined behavior!
		*/
		this.ipcon.sendRequest(this, BrickletParticulateMatter.FUNCTION_RESET, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeUID = function(uid, returnCallback, errorCallback) {
		/*
		Writes a new UID into flash. If you want to set a new UID
		you have to decode the Base58 encoded UID string into an
		integer first.
		
		We recommend that you use Brick Viewer to change the UID.
		*/
		this.ipcon.sendRequest(this, BrickletParticulateMatter.FUNCTION_WRITE_UID, [uid], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.readUID = function(returnCallback, errorCallback) {
		/*
		Returns the current UID as an integer. Encode as
		Base58 to get the usual string version.
		*/
		this.ipcon.sendRequest(this, BrickletParticulateMatter.FUNCTION_READ_UID, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletParticulateMatter.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletParticulateMatter;

},{"./Device":279,"./IPConnection":280}],238:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletPerformanceDC.DEVICE_IDENTIFIER = 2156;
BrickletPerformanceDC.DEVICE_DISPLAY_NAME = 'Performance DC Bricklet';
BrickletPerformanceDC.CALLBACK_EMERGENCY_SHUTDOWN = 35;
BrickletPerformanceDC.CALLBACK_VELOCITY_REACHED = 36;
BrickletPerformanceDC.CALLBACK_CURRENT_VELOCITY = 37;
BrickletPerformanceDC.CALLBACK_GPIO_STATE = 38;
BrickletPerformanceDC.FUNCTION_SET_ENABLED = 1;
BrickletPerformanceDC.FUNCTION_GET_ENABLED = 2;
BrickletPerformanceDC.FUNCTION_SET_VELOCITY = 3;
BrickletPerformanceDC.FUNCTION_GET_VELOCITY = 4;
BrickletPerformanceDC.FUNCTION_GET_CURRENT_VELOCITY = 5;
BrickletPerformanceDC.FUNCTION_SET_MOTION = 6;
BrickletPerformanceDC.FUNCTION_GET_MOTION = 7;
BrickletPerformanceDC.FUNCTION_FULL_BRAKE = 8;
BrickletPerformanceDC.FUNCTION_SET_DRIVE_MODE = 9;
BrickletPerformanceDC.FUNCTION_GET_DRIVE_MODE = 10;
BrickletPerformanceDC.FUNCTION_SET_PWM_FREQUENCY = 11;
BrickletPerformanceDC.FUNCTION_GET_PWM_FREQUENCY = 12;
BrickletPerformanceDC.FUNCTION_GET_POWER_STATISTICS = 13;
BrickletPerformanceDC.FUNCTION_SET_THERMAL_SHUTDOWN = 14;
BrickletPerformanceDC.FUNCTION_GET_THERMAL_SHUTDOWN = 15;
BrickletPerformanceDC.FUNCTION_SET_GPIO_CONFIGURATION = 16;
BrickletPerformanceDC.FUNCTION_GET_GPIO_CONFIGURATION = 17;
BrickletPerformanceDC.FUNCTION_SET_GPIO_ACTION = 18;
BrickletPerformanceDC.FUNCTION_GET_GPIO_ACTION = 19;
BrickletPerformanceDC.FUNCTION_GET_GPIO_STATE = 20;
BrickletPerformanceDC.FUNCTION_SET_ERROR_LED_CONFIG = 21;
BrickletPerformanceDC.FUNCTION_GET_ERROR_LED_CONFIG = 22;
BrickletPerformanceDC.FUNCTION_SET_CW_LED_CONFIG = 23;
BrickletPerformanceDC.FUNCTION_GET_CW_LED_CONFIG = 24;
BrickletPerformanceDC.FUNCTION_SET_CCW_LED_CONFIG = 25;
BrickletPerformanceDC.FUNCTION_GET_CCW_LED_CONFIG = 26;
BrickletPerformanceDC.FUNCTION_SET_GPIO_LED_CONFIG = 27;
BrickletPerformanceDC.FUNCTION_GET_GPIO_LED_CONFIG = 28;
BrickletPerformanceDC.FUNCTION_SET_EMERGENCY_SHUTDOWN_CALLBACK_CONFIGURATION = 29;
BrickletPerformanceDC.FUNCTION_GET_EMERGENCY_SHUTDOWN_CALLBACK_CONFIGURATION = 30;
BrickletPerformanceDC.FUNCTION_SET_VELOCITY_REACHED_CALLBACK_CONFIGURATION = 31;
BrickletPerformanceDC.FUNCTION_GET_VELOCITY_REACHED_CALLBACK_CONFIGURATION = 32;
BrickletPerformanceDC.FUNCTION_SET_CURRENT_VELOCITY_CALLBACK_CONFIGURATION = 33;
BrickletPerformanceDC.FUNCTION_GET_CURRENT_VELOCITY_CALLBACK_CONFIGURATION = 34;
BrickletPerformanceDC.FUNCTION_GET_SPITFP_ERROR_COUNT = 234;
BrickletPerformanceDC.FUNCTION_SET_BOOTLOADER_MODE = 235;
BrickletPerformanceDC.FUNCTION_GET_BOOTLOADER_MODE = 236;
BrickletPerformanceDC.FUNCTION_SET_WRITE_FIRMWARE_POINTER = 237;
BrickletPerformanceDC.FUNCTION_WRITE_FIRMWARE = 238;
BrickletPerformanceDC.FUNCTION_SET_STATUS_LED_CONFIG = 239;
BrickletPerformanceDC.FUNCTION_GET_STATUS_LED_CONFIG = 240;
BrickletPerformanceDC.FUNCTION_GET_CHIP_TEMPERATURE = 242;
BrickletPerformanceDC.FUNCTION_RESET = 243;
BrickletPerformanceDC.FUNCTION_WRITE_UID = 248;
BrickletPerformanceDC.FUNCTION_READ_UID = 249;
BrickletPerformanceDC.FUNCTION_GET_IDENTITY = 255;
BrickletPerformanceDC.DRIVE_MODE_DRIVE_BRAKE = 0;
BrickletPerformanceDC.DRIVE_MODE_DRIVE_COAST = 1;
BrickletPerformanceDC.GPIO_ACTION_NONE = 0;
BrickletPerformanceDC.GPIO_ACTION_NORMAL_STOP_RISING_EDGE = 1;
BrickletPerformanceDC.GPIO_ACTION_NORMAL_STOP_FALLING_EDGE = 2;
BrickletPerformanceDC.GPIO_ACTION_FULL_BRAKE_RISING_EDGE = 4;
BrickletPerformanceDC.GPIO_ACTION_FULL_BRAKE_FALLING_EDGE = 8;
BrickletPerformanceDC.GPIO_ACTION_CALLBACK_RISING_EDGE = 16;
BrickletPerformanceDC.GPIO_ACTION_CALLBACK_FALLING_EDGE = 32;
BrickletPerformanceDC.ERROR_LED_CONFIG_OFF = 0;
BrickletPerformanceDC.ERROR_LED_CONFIG_ON = 1;
BrickletPerformanceDC.ERROR_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletPerformanceDC.ERROR_LED_CONFIG_SHOW_ERROR = 3;
BrickletPerformanceDC.CW_LED_CONFIG_OFF = 0;
BrickletPerformanceDC.CW_LED_CONFIG_ON = 1;
BrickletPerformanceDC.CW_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletPerformanceDC.CW_LED_CONFIG_SHOW_CW_AS_FORWARD = 3;
BrickletPerformanceDC.CW_LED_CONFIG_SHOW_CW_AS_BACKWARD = 4;
BrickletPerformanceDC.CCW_LED_CONFIG_OFF = 0;
BrickletPerformanceDC.CCW_LED_CONFIG_ON = 1;
BrickletPerformanceDC.CCW_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletPerformanceDC.CCW_LED_CONFIG_SHOW_CCW_AS_FORWARD = 3;
BrickletPerformanceDC.CCW_LED_CONFIG_SHOW_CCW_AS_BACKWARD = 4;
BrickletPerformanceDC.GPIO_LED_CONFIG_OFF = 0;
BrickletPerformanceDC.GPIO_LED_CONFIG_ON = 1;
BrickletPerformanceDC.GPIO_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletPerformanceDC.GPIO_LED_CONFIG_SHOW_GPIO_ACTIVE_HIGH = 3;
BrickletPerformanceDC.GPIO_LED_CONFIG_SHOW_GPIO_ACTIVE_LOW = 4;
BrickletPerformanceDC.BOOTLOADER_MODE_BOOTLOADER = 0;
BrickletPerformanceDC.BOOTLOADER_MODE_FIRMWARE = 1;
BrickletPerformanceDC.BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT = 2;
BrickletPerformanceDC.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT = 3;
BrickletPerformanceDC.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT = 4;
BrickletPerformanceDC.BOOTLOADER_STATUS_OK = 0;
BrickletPerformanceDC.BOOTLOADER_STATUS_INVALID_MODE = 1;
BrickletPerformanceDC.BOOTLOADER_STATUS_NO_CHANGE = 2;
BrickletPerformanceDC.BOOTLOADER_STATUS_ENTRY_FUNCTION_NOT_PRESENT = 3;
BrickletPerformanceDC.BOOTLOADER_STATUS_DEVICE_IDENTIFIER_INCORRECT = 4;
BrickletPerformanceDC.BOOTLOADER_STATUS_CRC_MISMATCH = 5;
BrickletPerformanceDC.STATUS_LED_CONFIG_OFF = 0;
BrickletPerformanceDC.STATUS_LED_CONFIG_ON = 1;
BrickletPerformanceDC.STATUS_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletPerformanceDC.STATUS_LED_CONFIG_SHOW_STATUS = 3;

function BrickletPerformanceDC(uid, ipcon) {
	//Drives one brushed DC motor with up to 36V and 10A

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletPerformanceDC.DEVICE_IDENTIFIER, BrickletPerformanceDC.DEVICE_DISPLAY_NAME);
	BrickletPerformanceDC.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 1];
	this.responseExpected[BrickletPerformanceDC.FUNCTION_SET_ENABLED] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletPerformanceDC.FUNCTION_GET_ENABLED] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletPerformanceDC.FUNCTION_SET_VELOCITY] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletPerformanceDC.FUNCTION_GET_VELOCITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletPerformanceDC.FUNCTION_GET_CURRENT_VELOCITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletPerformanceDC.FUNCTION_SET_MOTION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletPerformanceDC.FUNCTION_GET_MOTION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletPerformanceDC.FUNCTION_FULL_BRAKE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletPerformanceDC.FUNCTION_SET_DRIVE_MODE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletPerformanceDC.FUNCTION_GET_DRIVE_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletPerformanceDC.FUNCTION_SET_PWM_FREQUENCY] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletPerformanceDC.FUNCTION_GET_PWM_FREQUENCY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletPerformanceDC.FUNCTION_GET_POWER_STATISTICS] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletPerformanceDC.FUNCTION_SET_THERMAL_SHUTDOWN] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletPerformanceDC.FUNCTION_GET_THERMAL_SHUTDOWN] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletPerformanceDC.FUNCTION_SET_GPIO_CONFIGURATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletPerformanceDC.FUNCTION_GET_GPIO_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletPerformanceDC.FUNCTION_SET_GPIO_ACTION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletPerformanceDC.FUNCTION_GET_GPIO_ACTION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletPerformanceDC.FUNCTION_GET_GPIO_STATE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletPerformanceDC.FUNCTION_SET_ERROR_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletPerformanceDC.FUNCTION_GET_ERROR_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletPerformanceDC.FUNCTION_SET_CW_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletPerformanceDC.FUNCTION_GET_CW_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletPerformanceDC.FUNCTION_SET_CCW_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletPerformanceDC.FUNCTION_GET_CCW_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletPerformanceDC.FUNCTION_SET_GPIO_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletPerformanceDC.FUNCTION_GET_GPIO_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletPerformanceDC.FUNCTION_SET_EMERGENCY_SHUTDOWN_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletPerformanceDC.FUNCTION_GET_EMERGENCY_SHUTDOWN_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletPerformanceDC.FUNCTION_SET_VELOCITY_REACHED_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletPerformanceDC.FUNCTION_GET_VELOCITY_REACHED_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletPerformanceDC.FUNCTION_SET_CURRENT_VELOCITY_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletPerformanceDC.FUNCTION_GET_CURRENT_VELOCITY_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletPerformanceDC.FUNCTION_GET_SPITFP_ERROR_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletPerformanceDC.FUNCTION_SET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletPerformanceDC.FUNCTION_GET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletPerformanceDC.FUNCTION_SET_WRITE_FIRMWARE_POINTER] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletPerformanceDC.FUNCTION_WRITE_FIRMWARE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletPerformanceDC.FUNCTION_SET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletPerformanceDC.FUNCTION_GET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletPerformanceDC.FUNCTION_GET_CHIP_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletPerformanceDC.FUNCTION_RESET] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletPerformanceDC.FUNCTION_WRITE_UID] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletPerformanceDC.FUNCTION_READ_UID] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletPerformanceDC.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletPerformanceDC.CALLBACK_EMERGENCY_SHUTDOWN] = [8, ''];
	this.callbackFormats[BrickletPerformanceDC.CALLBACK_VELOCITY_REACHED] = [10, 'h'];
	this.callbackFormats[BrickletPerformanceDC.CALLBACK_CURRENT_VELOCITY] = [10, 'h'];
	this.callbackFormats[BrickletPerformanceDC.CALLBACK_GPIO_STATE] = [9, '?2'];



	this.setEnabled = function(enabled, returnCallback, errorCallback) {
		/*
		Enables/Disables the driver chip. The driver parameters can be configured
		(velocity, acceleration, etc) before it is enabled.
		*/
		this.ipcon.sendRequest(this, BrickletPerformanceDC.FUNCTION_SET_ENABLED, [enabled], '?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getEnabled = function(returnCallback, errorCallback) {
		/*
		Returns *true* if the driver chip is enabled, *false* otherwise.
		*/
		this.ipcon.sendRequest(this, BrickletPerformanceDC.FUNCTION_GET_ENABLED, [], '', 9, '?', returnCallback, errorCallback, false, true);
	};
	this.setVelocity = function(velocity, returnCallback, errorCallback) {
		/*
		Sets the velocity of the motor. Whereas -32767 is full speed backward,
		0 is stop and 32767 is full speed forward. Depending on the
		acceleration (see :func:`Set Motion`), the motor is not immediately
		brought to the velocity but smoothly accelerated.
		
		The velocity describes the duty cycle of the PWM with which the motor is
		controlled, e.g. a velocity of 3277 sets a PWM with a 10% duty cycle.
		You can not only control the duty cycle of the PWM but also the frequency,
		see :func:`Set PWM Frequency`.
		*/
		this.ipcon.sendRequest(this, BrickletPerformanceDC.FUNCTION_SET_VELOCITY, [velocity], 'h', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getVelocity = function(returnCallback, errorCallback) {
		/*
		Returns the velocity as set by :func:`Set Velocity`.
		*/
		this.ipcon.sendRequest(this, BrickletPerformanceDC.FUNCTION_GET_VELOCITY, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.getCurrentVelocity = function(returnCallback, errorCallback) {
		/*
		Returns the *current* velocity of the motor. This value is different
		from :func:`Get Velocity` whenever the motor is currently accelerating
		to a goal set by :func:`Set Velocity`.
		*/
		this.ipcon.sendRequest(this, BrickletPerformanceDC.FUNCTION_GET_CURRENT_VELOCITY, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.setMotion = function(acceleration, deceleration, returnCallback, errorCallback) {
		/*
		Sets the acceleration and deceleration of the motor. It is given in *velocity/s*.
		An acceleration of 10000 means, that every second the velocity is increased
		by 10000 (or about 30% duty cycle).
		
		For example: If the current velocity is 0 and you want to accelerate to a
		velocity of 16000 (about 50% duty cycle) in 10 seconds, you should set
		an acceleration of 1600.
		
		If acceleration and deceleration is set to 0, there is no speed ramping, i.e. a
		new velocity is immediately given to the motor.
		*/
		this.ipcon.sendRequest(this, BrickletPerformanceDC.FUNCTION_SET_MOTION, [acceleration, deceleration], 'H H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getMotion = function(returnCallback, errorCallback) {
		/*
		Returns the acceleration/deceleration as set by :func:`Set Motion`.
		*/
		this.ipcon.sendRequest(this, BrickletPerformanceDC.FUNCTION_GET_MOTION, [], '', 12, 'H H', returnCallback, errorCallback, false, true);
	};
	this.fullBrake = function(returnCallback, errorCallback) {
		/*
		Executes an active full brake.
		
		.. warning::
		 This function is for emergency purposes,
		 where an immediate brake is necessary. Depending on the current velocity and
		 the strength of the motor, a full brake can be quite violent.
		
		Call :func:`Set Velocity` with 0 if you just want to stop the motor.
		*/
		this.ipcon.sendRequest(this, BrickletPerformanceDC.FUNCTION_FULL_BRAKE, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.setDriveMode = function(mode, returnCallback, errorCallback) {
		/*
		Sets the drive mode. Possible modes are:
		
		* 0 = Drive/Brake
		* 1 = Drive/Coast
		
		These modes are different kinds of motor controls.
		
		In Drive/Brake mode, the motor is always either driving or braking. There
		is no freewheeling. Advantages are: A more linear correlation between
		PWM and velocity, more exact accelerations and the possibility to drive
		with slower velocities.
		
		In Drive/Coast mode, the motor is always either driving or freewheeling.
		Advantages are: Less current consumption and less demands on the motor and
		driver chip.
		*/
		this.ipcon.sendRequest(this, BrickletPerformanceDC.FUNCTION_SET_DRIVE_MODE, [mode], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getDriveMode = function(returnCallback, errorCallback) {
		/*
		Returns the drive mode, as set by :func:`Set Drive Mode`.
		*/
		this.ipcon.sendRequest(this, BrickletPerformanceDC.FUNCTION_GET_DRIVE_MODE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setPWMFrequency = function(frequency, returnCallback, errorCallback) {
		/*
		Sets the frequency of the PWM with which the motor is driven.
		Often a high frequency
		is less noisy and the motor runs smoother. However, with a low frequency
		there are less switches and therefore fewer switching losses. Also with
		most motors lower frequencies enable higher torque.
		
		If you have no idea what all this means, just ignore this function and use
		the default frequency, it will very likely work fine.
		*/
		this.ipcon.sendRequest(this, BrickletPerformanceDC.FUNCTION_SET_PWM_FREQUENCY, [frequency], 'H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getPWMFrequency = function(returnCallback, errorCallback) {
		/*
		Returns the PWM frequency as set by :func:`Set PWM Frequency`.
		*/
		this.ipcon.sendRequest(this, BrickletPerformanceDC.FUNCTION_GET_PWM_FREQUENCY, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.getPowerStatistics = function(returnCallback, errorCallback) {
		/*
		Returns input voltage, current usage and temperature of the driver.
		*/
		this.ipcon.sendRequest(this, BrickletPerformanceDC.FUNCTION_GET_POWER_STATISTICS, [], '', 14, 'H H h', returnCallback, errorCallback, false, true);
	};
	this.setThermalShutdown = function(temperature, returnCallback, errorCallback) {
		/*
		Sets a temperature threshold that is used for thermal shutdown.
		
		Additionally to this user defined threshold the driver chip will shut down at a
		temperature of 150°C.
		
		If a thermal shutdown is triggered the driver is disabled and has to be
		explicitly re-enabled with :func:`Set Enabled`.
		*/
		this.ipcon.sendRequest(this, BrickletPerformanceDC.FUNCTION_SET_THERMAL_SHUTDOWN, [temperature], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getThermalShutdown = function(returnCallback, errorCallback) {
		/*
		Returns the thermal shutdown temperature as set by :func:`Set Thermal Shutdown`.
		*/
		this.ipcon.sendRequest(this, BrickletPerformanceDC.FUNCTION_GET_THERMAL_SHUTDOWN, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setGPIOConfiguration = function(channel, debounce, stopDeceleration, returnCallback, errorCallback) {
		/*
		Sets the GPIO configuration for the given channel.
		You can configure a debounce and the deceleration that is used if the action is
		configured as ``normal stop``. See :func:`Set GPIO Action`.
		*/
		this.ipcon.sendRequest(this, BrickletPerformanceDC.FUNCTION_SET_GPIO_CONFIGURATION, [channel, debounce, stopDeceleration], 'B H H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getGPIOConfiguration = function(channel, returnCallback, errorCallback) {
		/*
		Returns the GPIO configuration for a channel as set by :func:`Set GPIO Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletPerformanceDC.FUNCTION_GET_GPIO_CONFIGURATION, [channel], 'B', 12, 'H H', returnCallback, errorCallback, false, true);
	};
	this.setGPIOAction = function(channel, action, returnCallback, errorCallback) {
		/*
		Sets the GPIO action for the given channel.
		
		The action can be a normal stop, a full brake or a callback. Each for a rising
		edge or falling edge. The actions are a bitmask they can be used at the same time.
		You can for example trigger a full brake and a callback at the same time or for
		rising and falling edge.
		
		The deceleration speed for the normal stop can be configured with
		:func:`Set GPIO Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletPerformanceDC.FUNCTION_SET_GPIO_ACTION, [channel, action], 'B I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getGPIOAction = function(channel, returnCallback, errorCallback) {
		/*
		Returns the GPIO action for a channel as set by :func:`Set GPIO Action`.
		*/
		this.ipcon.sendRequest(this, BrickletPerformanceDC.FUNCTION_GET_GPIO_ACTION, [channel], 'B', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getGPIOState = function(returnCallback, errorCallback) {
		/*
		Returns the GPIO state for both channels. True if the state is ``high`` and
		false if the state is ``low``.
		*/
		this.ipcon.sendRequest(this, BrickletPerformanceDC.FUNCTION_GET_GPIO_STATE, [], '', 9, '?2', returnCallback, errorCallback, false, true);
	};
	this.setErrorLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Configures the error LED to be either turned off, turned on, blink in
		heartbeat mode or show an error.
		
		If the LED is configured to show errors it has three different states:
		
		* Off: No error present.
		* 1s interval blinking: Input voltage too low (below 6V).
		* 250ms interval blinking: Overtemperature or overcurrent.
		*/
		this.ipcon.sendRequest(this, BrickletPerformanceDC.FUNCTION_SET_ERROR_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getErrorLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the LED configuration as set by :func:`Set Error LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletPerformanceDC.FUNCTION_GET_ERROR_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setCWLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Configures the CW LED to be either turned off, turned on, blink in
		heartbeat mode or if the motor turn clockwise.
		*/
		this.ipcon.sendRequest(this, BrickletPerformanceDC.FUNCTION_SET_CW_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getCWLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the LED configuration as set by :func:`Set CW LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletPerformanceDC.FUNCTION_GET_CW_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setCCWLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Configures the CCW LED to be either turned off, turned on, blink in
		heartbeat mode or if the motor turn counter-clockwise.
		*/
		this.ipcon.sendRequest(this, BrickletPerformanceDC.FUNCTION_SET_CCW_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getCCWLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the LED configuration as set by :func:`Set CCW LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletPerformanceDC.FUNCTION_GET_CCW_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setGPIOLEDConfig = function(channel, config, returnCallback, errorCallback) {
		/*
		Configures the GPIO LED to be either turned off, turned on, blink in
		heartbeat mode or the GPIO state.
		
		The GPIO LED can be configured for both channels.
		*/
		this.ipcon.sendRequest(this, BrickletPerformanceDC.FUNCTION_SET_GPIO_LED_CONFIG, [channel, config], 'B B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getGPIOLEDConfig = function(channel, returnCallback, errorCallback) {
		/*
		Returns the LED configuration as set by :func:`Set GPIO LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletPerformanceDC.FUNCTION_GET_GPIO_LED_CONFIG, [channel], 'B', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setEmergencyShutdownCallbackConfiguration = function(enabled, returnCallback, errorCallback) {
		/*
		Enable/Disable :cb:`Emergency Shutdown` callback.
		*/
		this.ipcon.sendRequest(this, BrickletPerformanceDC.FUNCTION_SET_EMERGENCY_SHUTDOWN_CALLBACK_CONFIGURATION, [enabled], '?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getEmergencyShutdownCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the callback configuration as set by
		:func:`Set Emergency Shutdown Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletPerformanceDC.FUNCTION_GET_EMERGENCY_SHUTDOWN_CALLBACK_CONFIGURATION, [], '', 9, '?', returnCallback, errorCallback, false, true);
	};
	this.setVelocityReachedCallbackConfiguration = function(enabled, returnCallback, errorCallback) {
		/*
		Enable/Disable :cb:`Velocity Reached` callback.
		*/
		this.ipcon.sendRequest(this, BrickletPerformanceDC.FUNCTION_SET_VELOCITY_REACHED_CALLBACK_CONFIGURATION, [enabled], '?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getVelocityReachedCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the callback configuration as set by
		:func:`Set Velocity Reached Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletPerformanceDC.FUNCTION_GET_VELOCITY_REACHED_CALLBACK_CONFIGURATION, [], '', 9, '?', returnCallback, errorCallback, false, true);
	};
	this.setCurrentVelocityCallbackConfiguration = function(period, valueHasToChange, returnCallback, errorCallback) {
		/*
		The period is the period with which the :cb:`Current Velocity`
		callback is triggered periodically. A value of 0 turns the callback off.
		
		If the `value has to change`-parameter is set to true, the callback is only
		triggered after the value has changed. If the value didn't change within the
		period, the callback is triggered immediately on change.
		
		If it is set to false, the callback is continuously triggered with the period,
		independent of the value.
		*/
		this.ipcon.sendRequest(this, BrickletPerformanceDC.FUNCTION_SET_CURRENT_VELOCITY_CALLBACK_CONFIGURATION, [period, valueHasToChange], 'I ?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getCurrentVelocityCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the callback configuration as set by
		:func:`Set Current Velocity Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletPerformanceDC.FUNCTION_GET_CURRENT_VELOCITY_CALLBACK_CONFIGURATION, [], '', 13, 'I ?', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPErrorCount = function(returnCallback, errorCallback) {
		/*
		Returns the error count for the communication between Brick and Bricklet.
		
		The errors are divided into
		
		* ACK checksum errors,
		* message checksum errors,
		* framing errors and
		* overflow errors.
		
		The errors counts are for errors that occur on the Bricklet side. All
		Bricks have a similar function that returns the errors on the Brick side.
		*/
		this.ipcon.sendRequest(this, BrickletPerformanceDC.FUNCTION_GET_SPITFP_ERROR_COUNT, [], '', 24, 'I I I I', returnCallback, errorCallback, false, true);
	};
	this.setBootloaderMode = function(mode, returnCallback, errorCallback) {
		/*
		Sets the bootloader mode and returns the status after the requested
		mode change was instigated.
		
		You can change from bootloader mode to firmware mode and vice versa. A change
		from bootloader mode to firmware mode will only take place if the entry function,
		device identifier and CRC are present and correct.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletPerformanceDC.FUNCTION_SET_BOOTLOADER_MODE, [mode], 'B', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getBootloaderMode = function(returnCallback, errorCallback) {
		/*
		Returns the current bootloader mode, see :func:`Set Bootloader Mode`.
		*/
		this.ipcon.sendRequest(this, BrickletPerformanceDC.FUNCTION_GET_BOOTLOADER_MODE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setWriteFirmwarePointer = function(pointer, returnCallback, errorCallback) {
		/*
		Sets the firmware pointer for :func:`Write Firmware`. The pointer has
		to be increased by chunks of size 64. The data is written to flash
		every 4 chunks (which equals to one page of size 256).
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletPerformanceDC.FUNCTION_SET_WRITE_FIRMWARE_POINTER, [pointer], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeFirmware = function(data, returnCallback, errorCallback) {
		/*
		Writes 64 Bytes of firmware at the position as written by
		:func:`Set Write Firmware Pointer` before. The firmware is written
		to flash every 4 chunks.
		
		You can only write firmware in bootloader mode.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletPerformanceDC.FUNCTION_WRITE_FIRMWARE, [data], 'B64', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setStatusLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Sets the status LED configuration. By default the LED shows
		communication traffic between Brick and Bricklet, it flickers once
		for every 10 received data packets.
		
		You can also turn the LED permanently on/off or show a heartbeat.
		
		If the Bricklet is in bootloader mode, the LED is will show heartbeat by default.
		*/
		this.ipcon.sendRequest(this, BrickletPerformanceDC.FUNCTION_SET_STATUS_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getStatusLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Status LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletPerformanceDC.FUNCTION_GET_STATUS_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getChipTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature as measured inside the microcontroller. The
		value returned is not the ambient temperature!
		
		The temperature is only proportional to the real temperature and it has bad
		accuracy. Practically it is only useful as an indicator for
		temperature changes.
		*/
		this.ipcon.sendRequest(this, BrickletPerformanceDC.FUNCTION_GET_CHIP_TEMPERATURE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.reset = function(returnCallback, errorCallback) {
		/*
		Calling this function will reset the Bricklet. All configurations
		will be lost.
		
		After a reset you have to create new device objects,
		calling functions on the existing ones will result in
		undefined behavior!
		*/
		this.ipcon.sendRequest(this, BrickletPerformanceDC.FUNCTION_RESET, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeUID = function(uid, returnCallback, errorCallback) {
		/*
		Writes a new UID into flash. If you want to set a new UID
		you have to decode the Base58 encoded UID string into an
		integer first.
		
		We recommend that you use Brick Viewer to change the UID.
		*/
		this.ipcon.sendRequest(this, BrickletPerformanceDC.FUNCTION_WRITE_UID, [uid], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.readUID = function(returnCallback, errorCallback) {
		/*
		Returns the current UID as an integer. Encode as
		Base58 to get the usual string version.
		*/
		this.ipcon.sendRequest(this, BrickletPerformanceDC.FUNCTION_READ_UID, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletPerformanceDC.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletPerformanceDC;

},{"./Device":279,"./IPConnection":280}],239:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletPiezoBuzzer.DEVICE_IDENTIFIER = 214;
BrickletPiezoBuzzer.DEVICE_DISPLAY_NAME = 'Piezo Buzzer Bricklet';
BrickletPiezoBuzzer.CALLBACK_BEEP_FINISHED = 3;
BrickletPiezoBuzzer.CALLBACK_MORSE_CODE_FINISHED = 4;
BrickletPiezoBuzzer.FUNCTION_BEEP = 1;
BrickletPiezoBuzzer.FUNCTION_MORSE_CODE = 2;
BrickletPiezoBuzzer.FUNCTION_GET_IDENTITY = 255;

function BrickletPiezoBuzzer(uid, ipcon) {
	//Creates 1kHz beep

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletPiezoBuzzer.DEVICE_IDENTIFIER, BrickletPiezoBuzzer.DEVICE_DISPLAY_NAME);
	BrickletPiezoBuzzer.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickletPiezoBuzzer.FUNCTION_BEEP] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletPiezoBuzzer.FUNCTION_MORSE_CODE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletPiezoBuzzer.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletPiezoBuzzer.CALLBACK_BEEP_FINISHED] = [8, ''];
	this.callbackFormats[BrickletPiezoBuzzer.CALLBACK_MORSE_CODE_FINISHED] = [8, ''];



	this.beep = function(duration, returnCallback, errorCallback) {
		/*
		Beeps for the given duration.
		*/
		this.ipcon.sendRequest(this, BrickletPiezoBuzzer.FUNCTION_BEEP, [duration], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.morseCode = function(morse, returnCallback, errorCallback) {
		/*
		Sets morse code that will be played by the piezo buzzer. The morse code
		is given as a string consisting of "." (dot), "-" (minus) and " " (space)
		for *dits*, *dahs* and *pauses*. Every other character is ignored.
		
		For example: If you set the string "...---...", the piezo buzzer will beep
		nine times with the durations "short short short long long long short
		short short".
		*/
		this.ipcon.sendRequest(this, BrickletPiezoBuzzer.FUNCTION_MORSE_CODE, [morse], 's60', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletPiezoBuzzer.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletPiezoBuzzer;

},{"./Device":279,"./IPConnection":280}],240:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletPiezoSpeaker.DEVICE_IDENTIFIER = 242;
BrickletPiezoSpeaker.DEVICE_DISPLAY_NAME = 'Piezo Speaker Bricklet';
BrickletPiezoSpeaker.CALLBACK_BEEP_FINISHED = 4;
BrickletPiezoSpeaker.CALLBACK_MORSE_CODE_FINISHED = 5;
BrickletPiezoSpeaker.FUNCTION_BEEP = 1;
BrickletPiezoSpeaker.FUNCTION_MORSE_CODE = 2;
BrickletPiezoSpeaker.FUNCTION_CALIBRATE = 3;
BrickletPiezoSpeaker.FUNCTION_GET_IDENTITY = 255;
BrickletPiezoSpeaker.BEEP_DURATION_OFF = 0;
BrickletPiezoSpeaker.BEEP_DURATION_INFINITE = 4294967295;

function BrickletPiezoSpeaker(uid, ipcon) {
	//Creates beep with configurable frequency

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletPiezoSpeaker.DEVICE_IDENTIFIER, BrickletPiezoSpeaker.DEVICE_DISPLAY_NAME);
	BrickletPiezoSpeaker.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickletPiezoSpeaker.FUNCTION_BEEP] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletPiezoSpeaker.FUNCTION_MORSE_CODE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletPiezoSpeaker.FUNCTION_CALIBRATE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletPiezoSpeaker.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletPiezoSpeaker.CALLBACK_BEEP_FINISHED] = [8, ''];
	this.callbackFormats[BrickletPiezoSpeaker.CALLBACK_MORSE_CODE_FINISHED] = [8, ''];



	this.beep = function(duration, frequency, returnCallback, errorCallback) {
		/*
		Beeps with the given frequency for the given duration.
		
		.. versionchanged:: 2.0.2$nbsp;(Plugin)
		   A duration of 0 stops the current beep if any, the frequency parameter is
		   ignored. A duration of 4294967295 results in an infinite beep.
		
		The Piezo Speaker Bricklet can only approximate the frequency, it will play
		the best possible match by applying the calibration (see :func:`Calibrate`).
		*/
		this.ipcon.sendRequest(this, BrickletPiezoSpeaker.FUNCTION_BEEP, [duration, frequency], 'I H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.morseCode = function(morse, frequency, returnCallback, errorCallback) {
		/*
		Sets morse code that will be played by the piezo buzzer. The morse code
		is given as a string consisting of "." (dot), "-" (minus) and " " (space)
		for *dits*, *dahs* and *pauses*. Every other character is ignored.
		
		For example: If you set the string "...---...", the piezo buzzer will beep
		nine times with the durations "short short short long long long short
		short short".
		*/
		this.ipcon.sendRequest(this, BrickletPiezoSpeaker.FUNCTION_MORSE_CODE, [morse, frequency], 's60 H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.calibrate = function(returnCallback, errorCallback) {
		/*
		The Piezo Speaker Bricklet can play 512 different tones. This function
		plays each tone and measures the exact frequency back. The result is a
		mapping between setting value and frequency. This mapping is stored
		in the EEPROM and loaded on startup.
		
		The Bricklet should come calibrated, you only need to call this
		function (once) every time you reflash the Bricklet plugin.
		
		Returns *true* after the calibration finishes.
		*/
		this.ipcon.sendRequest(this, BrickletPiezoSpeaker.FUNCTION_CALIBRATE, [], '', 9, '?', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletPiezoSpeaker.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletPiezoSpeaker;

},{"./Device":279,"./IPConnection":280}],241:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletPiezoSpeakerV2.DEVICE_IDENTIFIER = 2145;
BrickletPiezoSpeakerV2.DEVICE_DISPLAY_NAME = 'Piezo Speaker Bricklet 2.0';
BrickletPiezoSpeakerV2.CALLBACK_BEEP_FINISHED = 7;
BrickletPiezoSpeakerV2.CALLBACK_ALARM_FINISHED = 8;
BrickletPiezoSpeakerV2.FUNCTION_SET_BEEP = 1;
BrickletPiezoSpeakerV2.FUNCTION_GET_BEEP = 2;
BrickletPiezoSpeakerV2.FUNCTION_SET_ALARM = 3;
BrickletPiezoSpeakerV2.FUNCTION_GET_ALARM = 4;
BrickletPiezoSpeakerV2.FUNCTION_UPDATE_VOLUME = 5;
BrickletPiezoSpeakerV2.FUNCTION_UPDATE_FREQUENCY = 6;
BrickletPiezoSpeakerV2.FUNCTION_GET_SPITFP_ERROR_COUNT = 234;
BrickletPiezoSpeakerV2.FUNCTION_SET_BOOTLOADER_MODE = 235;
BrickletPiezoSpeakerV2.FUNCTION_GET_BOOTLOADER_MODE = 236;
BrickletPiezoSpeakerV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER = 237;
BrickletPiezoSpeakerV2.FUNCTION_WRITE_FIRMWARE = 238;
BrickletPiezoSpeakerV2.FUNCTION_SET_STATUS_LED_CONFIG = 239;
BrickletPiezoSpeakerV2.FUNCTION_GET_STATUS_LED_CONFIG = 240;
BrickletPiezoSpeakerV2.FUNCTION_GET_CHIP_TEMPERATURE = 242;
BrickletPiezoSpeakerV2.FUNCTION_RESET = 243;
BrickletPiezoSpeakerV2.FUNCTION_WRITE_UID = 248;
BrickletPiezoSpeakerV2.FUNCTION_READ_UID = 249;
BrickletPiezoSpeakerV2.FUNCTION_GET_IDENTITY = 255;
BrickletPiezoSpeakerV2.BEEP_DURATION_OFF = 0;
BrickletPiezoSpeakerV2.BEEP_DURATION_INFINITE = 4294967295;
BrickletPiezoSpeakerV2.ALARM_DURATION_OFF = 0;
BrickletPiezoSpeakerV2.ALARM_DURATION_INFINITE = 4294967295;
BrickletPiezoSpeakerV2.BOOTLOADER_MODE_BOOTLOADER = 0;
BrickletPiezoSpeakerV2.BOOTLOADER_MODE_FIRMWARE = 1;
BrickletPiezoSpeakerV2.BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT = 2;
BrickletPiezoSpeakerV2.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT = 3;
BrickletPiezoSpeakerV2.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT = 4;
BrickletPiezoSpeakerV2.BOOTLOADER_STATUS_OK = 0;
BrickletPiezoSpeakerV2.BOOTLOADER_STATUS_INVALID_MODE = 1;
BrickletPiezoSpeakerV2.BOOTLOADER_STATUS_NO_CHANGE = 2;
BrickletPiezoSpeakerV2.BOOTLOADER_STATUS_ENTRY_FUNCTION_NOT_PRESENT = 3;
BrickletPiezoSpeakerV2.BOOTLOADER_STATUS_DEVICE_IDENTIFIER_INCORRECT = 4;
BrickletPiezoSpeakerV2.BOOTLOADER_STATUS_CRC_MISMATCH = 5;
BrickletPiezoSpeakerV2.STATUS_LED_CONFIG_OFF = 0;
BrickletPiezoSpeakerV2.STATUS_LED_CONFIG_ON = 1;
BrickletPiezoSpeakerV2.STATUS_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletPiezoSpeakerV2.STATUS_LED_CONFIG_SHOW_STATUS = 3;

function BrickletPiezoSpeakerV2(uid, ipcon) {
	//Creates beep and alarm with configurable volume and frequency

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletPiezoSpeakerV2.DEVICE_IDENTIFIER, BrickletPiezoSpeakerV2.DEVICE_DISPLAY_NAME);
	BrickletPiezoSpeakerV2.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickletPiezoSpeakerV2.FUNCTION_SET_BEEP] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletPiezoSpeakerV2.FUNCTION_GET_BEEP] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletPiezoSpeakerV2.FUNCTION_SET_ALARM] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletPiezoSpeakerV2.FUNCTION_GET_ALARM] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletPiezoSpeakerV2.FUNCTION_UPDATE_VOLUME] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletPiezoSpeakerV2.FUNCTION_UPDATE_FREQUENCY] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletPiezoSpeakerV2.FUNCTION_GET_SPITFP_ERROR_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletPiezoSpeakerV2.FUNCTION_SET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletPiezoSpeakerV2.FUNCTION_GET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletPiezoSpeakerV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletPiezoSpeakerV2.FUNCTION_WRITE_FIRMWARE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletPiezoSpeakerV2.FUNCTION_SET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletPiezoSpeakerV2.FUNCTION_GET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletPiezoSpeakerV2.FUNCTION_GET_CHIP_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletPiezoSpeakerV2.FUNCTION_RESET] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletPiezoSpeakerV2.FUNCTION_WRITE_UID] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletPiezoSpeakerV2.FUNCTION_READ_UID] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletPiezoSpeakerV2.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletPiezoSpeakerV2.CALLBACK_BEEP_FINISHED] = [8, ''];
	this.callbackFormats[BrickletPiezoSpeakerV2.CALLBACK_ALARM_FINISHED] = [8, ''];



	this.setBeep = function(frequency, volume, duration, returnCallback, errorCallback) {
		/*
		Beeps with the given frequency and volume for the duration.
		
		A duration of 0 stops the current beep if any is ongoing.
		A duration of 4294967295 results in an infinite beep.
		*/
		this.ipcon.sendRequest(this, BrickletPiezoSpeakerV2.FUNCTION_SET_BEEP, [frequency, volume, duration], 'H B I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getBeep = function(returnCallback, errorCallback) {
		/*
		Returns the last beep settings as set by :func:`Set Beep`. If a beep is currently
		running it also returns the remaining duration of the beep.
		
		If the frequency or volume is updated during a beep (with :func:`Update Frequency`
		or :func:`Update Volume`) this function returns the updated value.
		*/
		this.ipcon.sendRequest(this, BrickletPiezoSpeakerV2.FUNCTION_GET_BEEP, [], '', 19, 'H B I I', returnCallback, errorCallback, false, true);
	};
	this.setAlarm = function(startFrequency, endFrequency, stepSize, stepDelay, volume, duration, returnCallback, errorCallback) {
		/*
		Creates an alarm (a tone that goes back and force between two specified frequencies).
		
		The following parameters can be set:
		
		* Start Frequency: Start frequency of the alarm.
		* End Frequency: End frequency of the alarm.
		* Step Size: Size of one step of the sweep between the start/end frequencies.
		* Step Delay: Delay between two steps (duration of time that one tone is used in a sweep).
		* Duration: Duration of the alarm.
		
		A duration of 0 stops the current alarm if any is ongoing.
		A duration of 4294967295 results in an infinite alarm.
		
		Below you can find two sets of example settings that you can try out. You can use
		these as a starting point to find an alarm signal that suits your application.
		
		Example 1: 10 seconds of loud annoying fast alarm
		
		* Start Frequency = 800
		* End Frequency = 2000
		* Step Size = 10
		* Step Delay = 1
		* Volume = 10
		* Duration = 10000
		
		Example 2: 10 seconds of soft siren sound with slow build-up
		
		* Start Frequency = 250
		* End Frequency = 750
		* Step Size = 1
		* Step Delay = 5
		* Volume = 0
		* Duration = 10000
		
		The following conditions must be met:
		
		* Start Frequency: has to be smaller than end frequency
		* End Frequency: has to be bigger than start frequency
		* Step Size: has to be small enough to fit into the frequency range
		* Step Delay: has to be small enough to fit into the duration
		*/
		this.ipcon.sendRequest(this, BrickletPiezoSpeakerV2.FUNCTION_SET_ALARM, [startFrequency, endFrequency, stepSize, stepDelay, volume, duration], 'H H H H B I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getAlarm = function(returnCallback, errorCallback) {
		/*
		Returns the last alarm settings as set by :func:`Set Alarm`. If an alarm is currently
		running it also returns the remaining duration of the alarm as well as the
		current frequency of the alarm.
		
		If the volume is updated during an alarm (with :func:`Update Volume`)
		this function returns the updated value.
		*/
		this.ipcon.sendRequest(this, BrickletPiezoSpeakerV2.FUNCTION_GET_ALARM, [], '', 27, 'H H H H B I I H', returnCallback, errorCallback, false, true);
	};
	this.updateVolume = function(volume, returnCallback, errorCallback) {
		/*
		Updates the volume of an ongoing beep or alarm.
		*/
		this.ipcon.sendRequest(this, BrickletPiezoSpeakerV2.FUNCTION_UPDATE_VOLUME, [volume], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.updateFrequency = function(frequency, returnCallback, errorCallback) {
		/*
		Updates the frequency of an ongoing beep.
		*/
		this.ipcon.sendRequest(this, BrickletPiezoSpeakerV2.FUNCTION_UPDATE_FREQUENCY, [frequency], 'H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPErrorCount = function(returnCallback, errorCallback) {
		/*
		Returns the error count for the communication between Brick and Bricklet.
		
		The errors are divided into
		
		* ACK checksum errors,
		* message checksum errors,
		* framing errors and
		* overflow errors.
		
		The errors counts are for errors that occur on the Bricklet side. All
		Bricks have a similar function that returns the errors on the Brick side.
		*/
		this.ipcon.sendRequest(this, BrickletPiezoSpeakerV2.FUNCTION_GET_SPITFP_ERROR_COUNT, [], '', 24, 'I I I I', returnCallback, errorCallback, false, true);
	};
	this.setBootloaderMode = function(mode, returnCallback, errorCallback) {
		/*
		Sets the bootloader mode and returns the status after the requested
		mode change was instigated.
		
		You can change from bootloader mode to firmware mode and vice versa. A change
		from bootloader mode to firmware mode will only take place if the entry function,
		device identifier and CRC are present and correct.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletPiezoSpeakerV2.FUNCTION_SET_BOOTLOADER_MODE, [mode], 'B', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getBootloaderMode = function(returnCallback, errorCallback) {
		/*
		Returns the current bootloader mode, see :func:`Set Bootloader Mode`.
		*/
		this.ipcon.sendRequest(this, BrickletPiezoSpeakerV2.FUNCTION_GET_BOOTLOADER_MODE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setWriteFirmwarePointer = function(pointer, returnCallback, errorCallback) {
		/*
		Sets the firmware pointer for :func:`Write Firmware`. The pointer has
		to be increased by chunks of size 64. The data is written to flash
		every 4 chunks (which equals to one page of size 256).
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletPiezoSpeakerV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER, [pointer], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeFirmware = function(data, returnCallback, errorCallback) {
		/*
		Writes 64 Bytes of firmware at the position as written by
		:func:`Set Write Firmware Pointer` before. The firmware is written
		to flash every 4 chunks.
		
		You can only write firmware in bootloader mode.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletPiezoSpeakerV2.FUNCTION_WRITE_FIRMWARE, [data], 'B64', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setStatusLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Sets the status LED configuration. By default the LED shows
		communication traffic between Brick and Bricklet, it flickers once
		for every 10 received data packets.
		
		You can also turn the LED permanently on/off or show a heartbeat.
		
		If the Bricklet is in bootloader mode, the LED is will show heartbeat by default.
		*/
		this.ipcon.sendRequest(this, BrickletPiezoSpeakerV2.FUNCTION_SET_STATUS_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getStatusLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Status LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletPiezoSpeakerV2.FUNCTION_GET_STATUS_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getChipTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature as measured inside the microcontroller. The
		value returned is not the ambient temperature!
		
		The temperature is only proportional to the real temperature and it has bad
		accuracy. Practically it is only useful as an indicator for
		temperature changes.
		*/
		this.ipcon.sendRequest(this, BrickletPiezoSpeakerV2.FUNCTION_GET_CHIP_TEMPERATURE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.reset = function(returnCallback, errorCallback) {
		/*
		Calling this function will reset the Bricklet. All configurations
		will be lost.
		
		After a reset you have to create new device objects,
		calling functions on the existing ones will result in
		undefined behavior!
		*/
		this.ipcon.sendRequest(this, BrickletPiezoSpeakerV2.FUNCTION_RESET, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeUID = function(uid, returnCallback, errorCallback) {
		/*
		Writes a new UID into flash. If you want to set a new UID
		you have to decode the Base58 encoded UID string into an
		integer first.
		
		We recommend that you use Brick Viewer to change the UID.
		*/
		this.ipcon.sendRequest(this, BrickletPiezoSpeakerV2.FUNCTION_WRITE_UID, [uid], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.readUID = function(returnCallback, errorCallback) {
		/*
		Returns the current UID as an integer. Encode as
		Base58 to get the usual string version.
		*/
		this.ipcon.sendRequest(this, BrickletPiezoSpeakerV2.FUNCTION_READ_UID, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletPiezoSpeakerV2.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletPiezoSpeakerV2;

},{"./Device":279,"./IPConnection":280}],242:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletRGBLED.DEVICE_IDENTIFIER = 271;
BrickletRGBLED.DEVICE_DISPLAY_NAME = 'RGB LED Bricklet';
BrickletRGBLED.FUNCTION_SET_RGB_VALUE = 1;
BrickletRGBLED.FUNCTION_GET_RGB_VALUE = 2;
BrickletRGBLED.FUNCTION_GET_IDENTITY = 255;

function BrickletRGBLED(uid, ipcon) {
	//Controls one RGB LED

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletRGBLED.DEVICE_IDENTIFIER, BrickletRGBLED.DEVICE_DISPLAY_NAME);
	BrickletRGBLED.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickletRGBLED.FUNCTION_SET_RGB_VALUE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletRGBLED.FUNCTION_GET_RGB_VALUE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRGBLED.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;



	this.setRGBValue = function(r, g, b, returnCallback, errorCallback) {
		/*
		Sets the *r*, *g* and *b* values for the LED.
		*/
		this.ipcon.sendRequest(this, BrickletRGBLED.FUNCTION_SET_RGB_VALUE, [r, g, b], 'B B B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getRGBValue = function(returnCallback, errorCallback) {
		/*
		Returns the *r*, *g* and *b* values of the LED as set by :func:`Set RGB Value`.
		*/
		this.ipcon.sendRequest(this, BrickletRGBLED.FUNCTION_GET_RGB_VALUE, [], '', 11, 'B B B', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletRGBLED.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletRGBLED;

},{"./Device":279,"./IPConnection":280}],243:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletRGBLEDButton.DEVICE_IDENTIFIER = 282;
BrickletRGBLEDButton.DEVICE_DISPLAY_NAME = 'RGB LED Button Bricklet';
BrickletRGBLEDButton.CALLBACK_BUTTON_STATE_CHANGED = 4;
BrickletRGBLEDButton.FUNCTION_SET_COLOR = 1;
BrickletRGBLEDButton.FUNCTION_GET_COLOR = 2;
BrickletRGBLEDButton.FUNCTION_GET_BUTTON_STATE = 3;
BrickletRGBLEDButton.FUNCTION_SET_COLOR_CALIBRATION = 5;
BrickletRGBLEDButton.FUNCTION_GET_COLOR_CALIBRATION = 6;
BrickletRGBLEDButton.FUNCTION_GET_SPITFP_ERROR_COUNT = 234;
BrickletRGBLEDButton.FUNCTION_SET_BOOTLOADER_MODE = 235;
BrickletRGBLEDButton.FUNCTION_GET_BOOTLOADER_MODE = 236;
BrickletRGBLEDButton.FUNCTION_SET_WRITE_FIRMWARE_POINTER = 237;
BrickletRGBLEDButton.FUNCTION_WRITE_FIRMWARE = 238;
BrickletRGBLEDButton.FUNCTION_SET_STATUS_LED_CONFIG = 239;
BrickletRGBLEDButton.FUNCTION_GET_STATUS_LED_CONFIG = 240;
BrickletRGBLEDButton.FUNCTION_GET_CHIP_TEMPERATURE = 242;
BrickletRGBLEDButton.FUNCTION_RESET = 243;
BrickletRGBLEDButton.FUNCTION_WRITE_UID = 248;
BrickletRGBLEDButton.FUNCTION_READ_UID = 249;
BrickletRGBLEDButton.FUNCTION_GET_IDENTITY = 255;
BrickletRGBLEDButton.BUTTON_STATE_PRESSED = 0;
BrickletRGBLEDButton.BUTTON_STATE_RELEASED = 1;
BrickletRGBLEDButton.BOOTLOADER_MODE_BOOTLOADER = 0;
BrickletRGBLEDButton.BOOTLOADER_MODE_FIRMWARE = 1;
BrickletRGBLEDButton.BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT = 2;
BrickletRGBLEDButton.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT = 3;
BrickletRGBLEDButton.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT = 4;
BrickletRGBLEDButton.BOOTLOADER_STATUS_OK = 0;
BrickletRGBLEDButton.BOOTLOADER_STATUS_INVALID_MODE = 1;
BrickletRGBLEDButton.BOOTLOADER_STATUS_NO_CHANGE = 2;
BrickletRGBLEDButton.BOOTLOADER_STATUS_ENTRY_FUNCTION_NOT_PRESENT = 3;
BrickletRGBLEDButton.BOOTLOADER_STATUS_DEVICE_IDENTIFIER_INCORRECT = 4;
BrickletRGBLEDButton.BOOTLOADER_STATUS_CRC_MISMATCH = 5;
BrickletRGBLEDButton.STATUS_LED_CONFIG_OFF = 0;
BrickletRGBLEDButton.STATUS_LED_CONFIG_ON = 1;
BrickletRGBLEDButton.STATUS_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletRGBLEDButton.STATUS_LED_CONFIG_SHOW_STATUS = 3;

function BrickletRGBLEDButton(uid, ipcon) {
	//Push button with built-in RGB LED

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletRGBLEDButton.DEVICE_IDENTIFIER, BrickletRGBLEDButton.DEVICE_DISPLAY_NAME);
	BrickletRGBLEDButton.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickletRGBLEDButton.FUNCTION_SET_COLOR] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletRGBLEDButton.FUNCTION_GET_COLOR] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRGBLEDButton.FUNCTION_GET_BUTTON_STATE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRGBLEDButton.FUNCTION_SET_COLOR_CALIBRATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletRGBLEDButton.FUNCTION_GET_COLOR_CALIBRATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRGBLEDButton.FUNCTION_GET_SPITFP_ERROR_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRGBLEDButton.FUNCTION_SET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRGBLEDButton.FUNCTION_GET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRGBLEDButton.FUNCTION_SET_WRITE_FIRMWARE_POINTER] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletRGBLEDButton.FUNCTION_WRITE_FIRMWARE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRGBLEDButton.FUNCTION_SET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletRGBLEDButton.FUNCTION_GET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRGBLEDButton.FUNCTION_GET_CHIP_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRGBLEDButton.FUNCTION_RESET] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletRGBLEDButton.FUNCTION_WRITE_UID] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletRGBLEDButton.FUNCTION_READ_UID] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRGBLEDButton.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletRGBLEDButton.CALLBACK_BUTTON_STATE_CHANGED] = [9, 'B'];



	this.setColor = function(red, green, blue, returnCallback, errorCallback) {
		/*
		Sets the color of the LED.
		*/
		this.ipcon.sendRequest(this, BrickletRGBLEDButton.FUNCTION_SET_COLOR, [red, green, blue], 'B B B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getColor = function(returnCallback, errorCallback) {
		/*
		Returns the LED color as set by :func:`Set Color`.
		*/
		this.ipcon.sendRequest(this, BrickletRGBLEDButton.FUNCTION_GET_COLOR, [], '', 11, 'B B B', returnCallback, errorCallback, false, true);
	};
	this.getButtonState = function(returnCallback, errorCallback) {
		/*
		Returns the current state of the button (either pressed or released).
		*/
		this.ipcon.sendRequest(this, BrickletRGBLEDButton.FUNCTION_GET_BUTTON_STATE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setColorCalibration = function(red, green, blue, returnCallback, errorCallback) {
		/*
		Sets a color calibration. Some colors appear brighter then others,
		so a calibration may be necessary for uniform colors.
		
		The calibration is saved in flash. You don't need to call this
		function on every startup.
		*/
		this.ipcon.sendRequest(this, BrickletRGBLEDButton.FUNCTION_SET_COLOR_CALIBRATION, [red, green, blue], 'B B B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getColorCalibration = function(returnCallback, errorCallback) {
		/*
		Returns the color calibration as set by :func:`Set Color Calibration`.
		*/
		this.ipcon.sendRequest(this, BrickletRGBLEDButton.FUNCTION_GET_COLOR_CALIBRATION, [], '', 11, 'B B B', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPErrorCount = function(returnCallback, errorCallback) {
		/*
		Returns the error count for the communication between Brick and Bricklet.
		
		The errors are divided into
		
		* ACK checksum errors,
		* message checksum errors,
		* framing errors and
		* overflow errors.
		
		The errors counts are for errors that occur on the Bricklet side. All
		Bricks have a similar function that returns the errors on the Brick side.
		*/
		this.ipcon.sendRequest(this, BrickletRGBLEDButton.FUNCTION_GET_SPITFP_ERROR_COUNT, [], '', 24, 'I I I I', returnCallback, errorCallback, false, true);
	};
	this.setBootloaderMode = function(mode, returnCallback, errorCallback) {
		/*
		Sets the bootloader mode and returns the status after the requested
		mode change was instigated.
		
		You can change from bootloader mode to firmware mode and vice versa. A change
		from bootloader mode to firmware mode will only take place if the entry function,
		device identifier and CRC are present and correct.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletRGBLEDButton.FUNCTION_SET_BOOTLOADER_MODE, [mode], 'B', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getBootloaderMode = function(returnCallback, errorCallback) {
		/*
		Returns the current bootloader mode, see :func:`Set Bootloader Mode`.
		*/
		this.ipcon.sendRequest(this, BrickletRGBLEDButton.FUNCTION_GET_BOOTLOADER_MODE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setWriteFirmwarePointer = function(pointer, returnCallback, errorCallback) {
		/*
		Sets the firmware pointer for :func:`Write Firmware`. The pointer has
		to be increased by chunks of size 64. The data is written to flash
		every 4 chunks (which equals to one page of size 256).
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletRGBLEDButton.FUNCTION_SET_WRITE_FIRMWARE_POINTER, [pointer], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeFirmware = function(data, returnCallback, errorCallback) {
		/*
		Writes 64 Bytes of firmware at the position as written by
		:func:`Set Write Firmware Pointer` before. The firmware is written
		to flash every 4 chunks.
		
		You can only write firmware in bootloader mode.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletRGBLEDButton.FUNCTION_WRITE_FIRMWARE, [data], 'B64', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setStatusLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Sets the status LED configuration. By default the LED shows
		communication traffic between Brick and Bricklet, it flickers once
		for every 10 received data packets.
		
		You can also turn the LED permanently on/off or show a heartbeat.
		
		If the Bricklet is in bootloader mode, the LED is will show heartbeat by default.
		*/
		this.ipcon.sendRequest(this, BrickletRGBLEDButton.FUNCTION_SET_STATUS_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getStatusLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Status LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletRGBLEDButton.FUNCTION_GET_STATUS_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getChipTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature as measured inside the microcontroller. The
		value returned is not the ambient temperature!
		
		The temperature is only proportional to the real temperature and it has bad
		accuracy. Practically it is only useful as an indicator for
		temperature changes.
		*/
		this.ipcon.sendRequest(this, BrickletRGBLEDButton.FUNCTION_GET_CHIP_TEMPERATURE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.reset = function(returnCallback, errorCallback) {
		/*
		Calling this function will reset the Bricklet. All configurations
		will be lost.
		
		After a reset you have to create new device objects,
		calling functions on the existing ones will result in
		undefined behavior!
		*/
		this.ipcon.sendRequest(this, BrickletRGBLEDButton.FUNCTION_RESET, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeUID = function(uid, returnCallback, errorCallback) {
		/*
		Writes a new UID into flash. If you want to set a new UID
		you have to decode the Base58 encoded UID string into an
		integer first.
		
		We recommend that you use Brick Viewer to change the UID.
		*/
		this.ipcon.sendRequest(this, BrickletRGBLEDButton.FUNCTION_WRITE_UID, [uid], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.readUID = function(returnCallback, errorCallback) {
		/*
		Returns the current UID as an integer. Encode as
		Base58 to get the usual string version.
		*/
		this.ipcon.sendRequest(this, BrickletRGBLEDButton.FUNCTION_READ_UID, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletRGBLEDButton.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletRGBLEDButton;

},{"./Device":279,"./IPConnection":280}],244:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletRGBLEDMatrix.DEVICE_IDENTIFIER = 272;
BrickletRGBLEDMatrix.DEVICE_DISPLAY_NAME = 'RGB LED Matrix Bricklet';
BrickletRGBLEDMatrix.CALLBACK_FRAME_STARTED = 11;
BrickletRGBLEDMatrix.FUNCTION_SET_RED = 1;
BrickletRGBLEDMatrix.FUNCTION_GET_RED = 2;
BrickletRGBLEDMatrix.FUNCTION_SET_GREEN = 3;
BrickletRGBLEDMatrix.FUNCTION_GET_GREEN = 4;
BrickletRGBLEDMatrix.FUNCTION_SET_BLUE = 5;
BrickletRGBLEDMatrix.FUNCTION_GET_BLUE = 6;
BrickletRGBLEDMatrix.FUNCTION_SET_FRAME_DURATION = 7;
BrickletRGBLEDMatrix.FUNCTION_GET_FRAME_DURATION = 8;
BrickletRGBLEDMatrix.FUNCTION_DRAW_FRAME = 9;
BrickletRGBLEDMatrix.FUNCTION_GET_SUPPLY_VOLTAGE = 10;
BrickletRGBLEDMatrix.FUNCTION_GET_SPITFP_ERROR_COUNT = 234;
BrickletRGBLEDMatrix.FUNCTION_SET_BOOTLOADER_MODE = 235;
BrickletRGBLEDMatrix.FUNCTION_GET_BOOTLOADER_MODE = 236;
BrickletRGBLEDMatrix.FUNCTION_SET_WRITE_FIRMWARE_POINTER = 237;
BrickletRGBLEDMatrix.FUNCTION_WRITE_FIRMWARE = 238;
BrickletRGBLEDMatrix.FUNCTION_SET_STATUS_LED_CONFIG = 239;
BrickletRGBLEDMatrix.FUNCTION_GET_STATUS_LED_CONFIG = 240;
BrickletRGBLEDMatrix.FUNCTION_GET_CHIP_TEMPERATURE = 242;
BrickletRGBLEDMatrix.FUNCTION_RESET = 243;
BrickletRGBLEDMatrix.FUNCTION_WRITE_UID = 248;
BrickletRGBLEDMatrix.FUNCTION_READ_UID = 249;
BrickletRGBLEDMatrix.FUNCTION_GET_IDENTITY = 255;
BrickletRGBLEDMatrix.BOOTLOADER_MODE_BOOTLOADER = 0;
BrickletRGBLEDMatrix.BOOTLOADER_MODE_FIRMWARE = 1;
BrickletRGBLEDMatrix.BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT = 2;
BrickletRGBLEDMatrix.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT = 3;
BrickletRGBLEDMatrix.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT = 4;
BrickletRGBLEDMatrix.BOOTLOADER_STATUS_OK = 0;
BrickletRGBLEDMatrix.BOOTLOADER_STATUS_INVALID_MODE = 1;
BrickletRGBLEDMatrix.BOOTLOADER_STATUS_NO_CHANGE = 2;
BrickletRGBLEDMatrix.BOOTLOADER_STATUS_ENTRY_FUNCTION_NOT_PRESENT = 3;
BrickletRGBLEDMatrix.BOOTLOADER_STATUS_DEVICE_IDENTIFIER_INCORRECT = 4;
BrickletRGBLEDMatrix.BOOTLOADER_STATUS_CRC_MISMATCH = 5;
BrickletRGBLEDMatrix.STATUS_LED_CONFIG_OFF = 0;
BrickletRGBLEDMatrix.STATUS_LED_CONFIG_ON = 1;
BrickletRGBLEDMatrix.STATUS_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletRGBLEDMatrix.STATUS_LED_CONFIG_SHOW_STATUS = 3;

function BrickletRGBLEDMatrix(uid, ipcon) {
	//RGB LED Matrix with 8x8 pixel

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletRGBLEDMatrix.DEVICE_IDENTIFIER, BrickletRGBLEDMatrix.DEVICE_DISPLAY_NAME);
	BrickletRGBLEDMatrix.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickletRGBLEDMatrix.FUNCTION_SET_RED] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletRGBLEDMatrix.FUNCTION_GET_RED] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRGBLEDMatrix.FUNCTION_SET_GREEN] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletRGBLEDMatrix.FUNCTION_GET_GREEN] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRGBLEDMatrix.FUNCTION_SET_BLUE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletRGBLEDMatrix.FUNCTION_GET_BLUE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRGBLEDMatrix.FUNCTION_SET_FRAME_DURATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletRGBLEDMatrix.FUNCTION_GET_FRAME_DURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRGBLEDMatrix.FUNCTION_DRAW_FRAME] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletRGBLEDMatrix.FUNCTION_GET_SUPPLY_VOLTAGE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRGBLEDMatrix.FUNCTION_GET_SPITFP_ERROR_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRGBLEDMatrix.FUNCTION_SET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRGBLEDMatrix.FUNCTION_GET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRGBLEDMatrix.FUNCTION_SET_WRITE_FIRMWARE_POINTER] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletRGBLEDMatrix.FUNCTION_WRITE_FIRMWARE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRGBLEDMatrix.FUNCTION_SET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletRGBLEDMatrix.FUNCTION_GET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRGBLEDMatrix.FUNCTION_GET_CHIP_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRGBLEDMatrix.FUNCTION_RESET] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletRGBLEDMatrix.FUNCTION_WRITE_UID] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletRGBLEDMatrix.FUNCTION_READ_UID] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRGBLEDMatrix.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletRGBLEDMatrix.CALLBACK_FRAME_STARTED] = [12, 'I'];



	this.setRed = function(red, returnCallback, errorCallback) {
		/*
		Sets the 64 red LED values of the matrix.
		*/
		this.ipcon.sendRequest(this, BrickletRGBLEDMatrix.FUNCTION_SET_RED, [red], 'B64', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getRed = function(returnCallback, errorCallback) {
		/*
		Returns the red LED values as set by :func:`Set Red`.
		*/
		this.ipcon.sendRequest(this, BrickletRGBLEDMatrix.FUNCTION_GET_RED, [], '', 72, 'B64', returnCallback, errorCallback, false, true);
	};
	this.setGreen = function(green, returnCallback, errorCallback) {
		/*
		Sets the 64 green LED values of the matrix.
		*/
		this.ipcon.sendRequest(this, BrickletRGBLEDMatrix.FUNCTION_SET_GREEN, [green], 'B64', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getGreen = function(returnCallback, errorCallback) {
		/*
		Returns the green LED values as set by :func:`Set Green`.
		*/
		this.ipcon.sendRequest(this, BrickletRGBLEDMatrix.FUNCTION_GET_GREEN, [], '', 72, 'B64', returnCallback, errorCallback, false, true);
	};
	this.setBlue = function(blue, returnCallback, errorCallback) {
		/*
		Sets the 64 blue LED values of the matrix.
		*/
		this.ipcon.sendRequest(this, BrickletRGBLEDMatrix.FUNCTION_SET_BLUE, [blue], 'B64', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getBlue = function(returnCallback, errorCallback) {
		/*
		Returns the blue LED values as set by :func:`Set Blue`.
		*/
		this.ipcon.sendRequest(this, BrickletRGBLEDMatrix.FUNCTION_GET_BLUE, [], '', 72, 'B64', returnCallback, errorCallback, false, true);
	};
	this.setFrameDuration = function(frameDuration, returnCallback, errorCallback) {
		/*
		Sets the frame duration.
		
		Example: If you want to achieve 20 frames per second, you should
		set the frame duration to 50ms (50ms * 20 = 1 second).
		
		Set this value to 0 to turn the automatic frame write mechanism off.
		
		Approach:
		
		* Call :func:`Set Frame Duration` with value > 0.
		* Set LED values for first frame with :func:`Set Red`, :func:`Set Green`, :func:`Set Blue`.
		* Wait for :cb:`Frame Started` callback.
		* Set LED values for second frame with :func:`Set Red`, :func:`Set Green`, :func:`Set Blue`.
		* Wait for :cb:`Frame Started` callback.
		* and so on.
		
		For frame duration of 0 see :func:`Draw Frame`.
		*/
		this.ipcon.sendRequest(this, BrickletRGBLEDMatrix.FUNCTION_SET_FRAME_DURATION, [frameDuration], 'H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getFrameDuration = function(returnCallback, errorCallback) {
		/*
		Returns the frame duration as set by :func:`Set Frame Duration`.
		*/
		this.ipcon.sendRequest(this, BrickletRGBLEDMatrix.FUNCTION_GET_FRAME_DURATION, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.drawFrame = function(returnCallback, errorCallback) {
		/*
		If you set the frame duration to 0 (see :func:`Set Frame Duration`), you can use this
		function to transfer the frame to the matrix.
		
		Approach:
		
		* Call :func:`Set Frame Duration` with 0.
		* Set LED values for first frame with :func:`Set Red`, :func:`Set Green`, :func:`Set Blue`.
		* Call :func:`Draw Frame`.
		* Wait for :cb:`Frame Started` callback.
		* Set LED values for second frame with :func:`Set Red`, :func:`Set Green`, :func:`Set Blue`.
		* Call :func:`Draw Frame`.
		* Wait for :cb:`Frame Started` callback.
		* and so on.
		*/
		this.ipcon.sendRequest(this, BrickletRGBLEDMatrix.FUNCTION_DRAW_FRAME, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getSupplyVoltage = function(returnCallback, errorCallback) {
		/*
		Returns the current supply voltage of the Bricklet.
		*/
		this.ipcon.sendRequest(this, BrickletRGBLEDMatrix.FUNCTION_GET_SUPPLY_VOLTAGE, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPErrorCount = function(returnCallback, errorCallback) {
		/*
		Returns the error count for the communication between Brick and Bricklet.
		
		The errors are divided into
		
		* ACK checksum errors,
		* message checksum errors,
		* framing errors and
		* overflow errors.
		
		The errors counts are for errors that occur on the Bricklet side. All
		Bricks have a similar function that returns the errors on the Brick side.
		*/
		this.ipcon.sendRequest(this, BrickletRGBLEDMatrix.FUNCTION_GET_SPITFP_ERROR_COUNT, [], '', 24, 'I I I I', returnCallback, errorCallback, false, true);
	};
	this.setBootloaderMode = function(mode, returnCallback, errorCallback) {
		/*
		Sets the bootloader mode and returns the status after the requested
		mode change was instigated.
		
		You can change from bootloader mode to firmware mode and vice versa. A change
		from bootloader mode to firmware mode will only take place if the entry function,
		device identifier and CRC are present and correct.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletRGBLEDMatrix.FUNCTION_SET_BOOTLOADER_MODE, [mode], 'B', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getBootloaderMode = function(returnCallback, errorCallback) {
		/*
		Returns the current bootloader mode, see :func:`Set Bootloader Mode`.
		*/
		this.ipcon.sendRequest(this, BrickletRGBLEDMatrix.FUNCTION_GET_BOOTLOADER_MODE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setWriteFirmwarePointer = function(pointer, returnCallback, errorCallback) {
		/*
		Sets the firmware pointer for :func:`Write Firmware`. The pointer has
		to be increased by chunks of size 64. The data is written to flash
		every 4 chunks (which equals to one page of size 256).
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletRGBLEDMatrix.FUNCTION_SET_WRITE_FIRMWARE_POINTER, [pointer], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeFirmware = function(data, returnCallback, errorCallback) {
		/*
		Writes 64 Bytes of firmware at the position as written by
		:func:`Set Write Firmware Pointer` before. The firmware is written
		to flash every 4 chunks.
		
		You can only write firmware in bootloader mode.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletRGBLEDMatrix.FUNCTION_WRITE_FIRMWARE, [data], 'B64', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setStatusLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Sets the status LED configuration. By default the LED shows
		communication traffic between Brick and Bricklet, it flickers once
		for every 10 received data packets.
		
		You can also turn the LED permanently on/off or show a heartbeat.
		
		If the Bricklet is in bootloader mode, the LED is will show heartbeat by default.
		*/
		this.ipcon.sendRequest(this, BrickletRGBLEDMatrix.FUNCTION_SET_STATUS_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getStatusLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Status LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletRGBLEDMatrix.FUNCTION_GET_STATUS_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getChipTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature as measured inside the microcontroller. The
		value returned is not the ambient temperature!
		
		The temperature is only proportional to the real temperature and it has bad
		accuracy. Practically it is only useful as an indicator for
		temperature changes.
		*/
		this.ipcon.sendRequest(this, BrickletRGBLEDMatrix.FUNCTION_GET_CHIP_TEMPERATURE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.reset = function(returnCallback, errorCallback) {
		/*
		Calling this function will reset the Bricklet. All configurations
		will be lost.
		
		After a reset you have to create new device objects,
		calling functions on the existing ones will result in
		undefined behavior!
		*/
		this.ipcon.sendRequest(this, BrickletRGBLEDMatrix.FUNCTION_RESET, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeUID = function(uid, returnCallback, errorCallback) {
		/*
		Writes a new UID into flash. If you want to set a new UID
		you have to decode the Base58 encoded UID string into an
		integer first.
		
		We recommend that you use Brick Viewer to change the UID.
		*/
		this.ipcon.sendRequest(this, BrickletRGBLEDMatrix.FUNCTION_WRITE_UID, [uid], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.readUID = function(returnCallback, errorCallback) {
		/*
		Returns the current UID as an integer. Encode as
		Base58 to get the usual string version.
		*/
		this.ipcon.sendRequest(this, BrickletRGBLEDMatrix.FUNCTION_READ_UID, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletRGBLEDMatrix.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletRGBLEDMatrix;

},{"./Device":279,"./IPConnection":280}],245:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletRGBLEDV2.DEVICE_IDENTIFIER = 2127;
BrickletRGBLEDV2.DEVICE_DISPLAY_NAME = 'RGB LED Bricklet 2.0';
BrickletRGBLEDV2.FUNCTION_SET_RGB_VALUE = 1;
BrickletRGBLEDV2.FUNCTION_GET_RGB_VALUE = 2;
BrickletRGBLEDV2.FUNCTION_GET_SPITFP_ERROR_COUNT = 234;
BrickletRGBLEDV2.FUNCTION_SET_BOOTLOADER_MODE = 235;
BrickletRGBLEDV2.FUNCTION_GET_BOOTLOADER_MODE = 236;
BrickletRGBLEDV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER = 237;
BrickletRGBLEDV2.FUNCTION_WRITE_FIRMWARE = 238;
BrickletRGBLEDV2.FUNCTION_SET_STATUS_LED_CONFIG = 239;
BrickletRGBLEDV2.FUNCTION_GET_STATUS_LED_CONFIG = 240;
BrickletRGBLEDV2.FUNCTION_GET_CHIP_TEMPERATURE = 242;
BrickletRGBLEDV2.FUNCTION_RESET = 243;
BrickletRGBLEDV2.FUNCTION_WRITE_UID = 248;
BrickletRGBLEDV2.FUNCTION_READ_UID = 249;
BrickletRGBLEDV2.FUNCTION_GET_IDENTITY = 255;
BrickletRGBLEDV2.BOOTLOADER_MODE_BOOTLOADER = 0;
BrickletRGBLEDV2.BOOTLOADER_MODE_FIRMWARE = 1;
BrickletRGBLEDV2.BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT = 2;
BrickletRGBLEDV2.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT = 3;
BrickletRGBLEDV2.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT = 4;
BrickletRGBLEDV2.BOOTLOADER_STATUS_OK = 0;
BrickletRGBLEDV2.BOOTLOADER_STATUS_INVALID_MODE = 1;
BrickletRGBLEDV2.BOOTLOADER_STATUS_NO_CHANGE = 2;
BrickletRGBLEDV2.BOOTLOADER_STATUS_ENTRY_FUNCTION_NOT_PRESENT = 3;
BrickletRGBLEDV2.BOOTLOADER_STATUS_DEVICE_IDENTIFIER_INCORRECT = 4;
BrickletRGBLEDV2.BOOTLOADER_STATUS_CRC_MISMATCH = 5;
BrickletRGBLEDV2.STATUS_LED_CONFIG_OFF = 0;
BrickletRGBLEDV2.STATUS_LED_CONFIG_ON = 1;
BrickletRGBLEDV2.STATUS_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletRGBLEDV2.STATUS_LED_CONFIG_SHOW_STATUS = 3;

function BrickletRGBLEDV2(uid, ipcon) {
	//Controls one RGB LED

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletRGBLEDV2.DEVICE_IDENTIFIER, BrickletRGBLEDV2.DEVICE_DISPLAY_NAME);
	BrickletRGBLEDV2.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickletRGBLEDV2.FUNCTION_SET_RGB_VALUE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletRGBLEDV2.FUNCTION_GET_RGB_VALUE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRGBLEDV2.FUNCTION_GET_SPITFP_ERROR_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRGBLEDV2.FUNCTION_SET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRGBLEDV2.FUNCTION_GET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRGBLEDV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletRGBLEDV2.FUNCTION_WRITE_FIRMWARE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRGBLEDV2.FUNCTION_SET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletRGBLEDV2.FUNCTION_GET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRGBLEDV2.FUNCTION_GET_CHIP_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRGBLEDV2.FUNCTION_RESET] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletRGBLEDV2.FUNCTION_WRITE_UID] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletRGBLEDV2.FUNCTION_READ_UID] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRGBLEDV2.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;



	this.setRGBValue = function(r, g, b, returnCallback, errorCallback) {
		/*
		Sets the *r*, *g* and *b* values for the LED.
		*/
		this.ipcon.sendRequest(this, BrickletRGBLEDV2.FUNCTION_SET_RGB_VALUE, [r, g, b], 'B B B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getRGBValue = function(returnCallback, errorCallback) {
		/*
		Returns the *r*, *g* and *b* values of the LED as set by :func:`Set RGB Value`.
		*/
		this.ipcon.sendRequest(this, BrickletRGBLEDV2.FUNCTION_GET_RGB_VALUE, [], '', 11, 'B B B', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPErrorCount = function(returnCallback, errorCallback) {
		/*
		Returns the error count for the communication between Brick and Bricklet.
		
		The errors are divided into
		
		* ACK checksum errors,
		* message checksum errors,
		* framing errors and
		* overflow errors.
		
		The errors counts are for errors that occur on the Bricklet side. All
		Bricks have a similar function that returns the errors on the Brick side.
		*/
		this.ipcon.sendRequest(this, BrickletRGBLEDV2.FUNCTION_GET_SPITFP_ERROR_COUNT, [], '', 24, 'I I I I', returnCallback, errorCallback, false, true);
	};
	this.setBootloaderMode = function(mode, returnCallback, errorCallback) {
		/*
		Sets the bootloader mode and returns the status after the requested
		mode change was instigated.
		
		You can change from bootloader mode to firmware mode and vice versa. A change
		from bootloader mode to firmware mode will only take place if the entry function,
		device identifier and CRC are present and correct.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletRGBLEDV2.FUNCTION_SET_BOOTLOADER_MODE, [mode], 'B', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getBootloaderMode = function(returnCallback, errorCallback) {
		/*
		Returns the current bootloader mode, see :func:`Set Bootloader Mode`.
		*/
		this.ipcon.sendRequest(this, BrickletRGBLEDV2.FUNCTION_GET_BOOTLOADER_MODE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setWriteFirmwarePointer = function(pointer, returnCallback, errorCallback) {
		/*
		Sets the firmware pointer for :func:`Write Firmware`. The pointer has
		to be increased by chunks of size 64. The data is written to flash
		every 4 chunks (which equals to one page of size 256).
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletRGBLEDV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER, [pointer], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeFirmware = function(data, returnCallback, errorCallback) {
		/*
		Writes 64 Bytes of firmware at the position as written by
		:func:`Set Write Firmware Pointer` before. The firmware is written
		to flash every 4 chunks.
		
		You can only write firmware in bootloader mode.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletRGBLEDV2.FUNCTION_WRITE_FIRMWARE, [data], 'B64', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setStatusLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Sets the status LED configuration. By default the LED shows
		communication traffic between Brick and Bricklet, it flickers once
		for every 10 received data packets.
		
		You can also turn the LED permanently on/off or show a heartbeat.
		
		If the Bricklet is in bootloader mode, the LED is will show heartbeat by default.
		*/
		this.ipcon.sendRequest(this, BrickletRGBLEDV2.FUNCTION_SET_STATUS_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getStatusLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Status LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletRGBLEDV2.FUNCTION_GET_STATUS_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getChipTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature as measured inside the microcontroller. The
		value returned is not the ambient temperature!
		
		The temperature is only proportional to the real temperature and it has bad
		accuracy. Practically it is only useful as an indicator for
		temperature changes.
		*/
		this.ipcon.sendRequest(this, BrickletRGBLEDV2.FUNCTION_GET_CHIP_TEMPERATURE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.reset = function(returnCallback, errorCallback) {
		/*
		Calling this function will reset the Bricklet. All configurations
		will be lost.
		
		After a reset you have to create new device objects,
		calling functions on the existing ones will result in
		undefined behavior!
		*/
		this.ipcon.sendRequest(this, BrickletRGBLEDV2.FUNCTION_RESET, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeUID = function(uid, returnCallback, errorCallback) {
		/*
		Writes a new UID into flash. If you want to set a new UID
		you have to decode the Base58 encoded UID string into an
		integer first.
		
		We recommend that you use Brick Viewer to change the UID.
		*/
		this.ipcon.sendRequest(this, BrickletRGBLEDV2.FUNCTION_WRITE_UID, [uid], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.readUID = function(returnCallback, errorCallback) {
		/*
		Returns the current UID as an integer. Encode as
		Base58 to get the usual string version.
		*/
		this.ipcon.sendRequest(this, BrickletRGBLEDV2.FUNCTION_READ_UID, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletRGBLEDV2.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletRGBLEDV2;

},{"./Device":279,"./IPConnection":280}],246:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletRS232.DEVICE_IDENTIFIER = 254;
BrickletRS232.DEVICE_DISPLAY_NAME = 'RS232 Bricklet';
BrickletRS232.CALLBACK_READ = 8;
BrickletRS232.CALLBACK_ERROR = 9;
BrickletRS232.CALLBACK_FRAME_READABLE = 13;
BrickletRS232.CALLBACK_READ_CALLBACK = 8; // for backward compatibility
BrickletRS232.CALLBACK_ERROR_CALLBACK = 9; // for backward compatibility
BrickletRS232.FUNCTION_WRITE = 1;
BrickletRS232.FUNCTION_READ = 2;
BrickletRS232.FUNCTION_ENABLE_READ_CALLBACK = 3;
BrickletRS232.FUNCTION_DISABLE_READ_CALLBACK = 4;
BrickletRS232.FUNCTION_IS_READ_CALLBACK_ENABLED = 5;
BrickletRS232.FUNCTION_SET_CONFIGURATION = 6;
BrickletRS232.FUNCTION_GET_CONFIGURATION = 7;
BrickletRS232.FUNCTION_SET_BREAK_CONDITION = 10;
BrickletRS232.FUNCTION_SET_FRAME_READABLE_CALLBACK_CONFIGURATION = 11;
BrickletRS232.FUNCTION_GET_FRAME_READABLE_CALLBACK_CONFIGURATION = 12;
BrickletRS232.FUNCTION_READ_FRAME = 14;
BrickletRS232.FUNCTION_GET_IDENTITY = 255;
BrickletRS232.BAUDRATE_300 = 0;
BrickletRS232.BAUDRATE_600 = 1;
BrickletRS232.BAUDRATE_1200 = 2;
BrickletRS232.BAUDRATE_2400 = 3;
BrickletRS232.BAUDRATE_4800 = 4;
BrickletRS232.BAUDRATE_9600 = 5;
BrickletRS232.BAUDRATE_14400 = 6;
BrickletRS232.BAUDRATE_19200 = 7;
BrickletRS232.BAUDRATE_28800 = 8;
BrickletRS232.BAUDRATE_38400 = 9;
BrickletRS232.BAUDRATE_57600 = 10;
BrickletRS232.BAUDRATE_115200 = 11;
BrickletRS232.BAUDRATE_230400 = 12;
BrickletRS232.PARITY_NONE = 0;
BrickletRS232.PARITY_ODD = 1;
BrickletRS232.PARITY_EVEN = 2;
BrickletRS232.PARITY_FORCED_PARITY_1 = 3;
BrickletRS232.PARITY_FORCED_PARITY_0 = 4;
BrickletRS232.STOPBITS_1 = 1;
BrickletRS232.STOPBITS_2 = 2;
BrickletRS232.WORDLENGTH_5 = 5;
BrickletRS232.WORDLENGTH_6 = 6;
BrickletRS232.WORDLENGTH_7 = 7;
BrickletRS232.WORDLENGTH_8 = 8;
BrickletRS232.HARDWARE_FLOWCONTROL_OFF = 0;
BrickletRS232.HARDWARE_FLOWCONTROL_ON = 1;
BrickletRS232.SOFTWARE_FLOWCONTROL_OFF = 0;
BrickletRS232.SOFTWARE_FLOWCONTROL_ON = 1;
BrickletRS232.ERROR_OVERRUN = 1;
BrickletRS232.ERROR_PARITY = 2;
BrickletRS232.ERROR_FRAMING = 4;

function BrickletRS232(uid, ipcon) {
	//Communicates with RS232 devices

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletRS232.DEVICE_IDENTIFIER, BrickletRS232.DEVICE_DISPLAY_NAME);
	BrickletRS232.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 3];
	this.responseExpected[BrickletRS232.FUNCTION_WRITE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRS232.FUNCTION_READ] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRS232.FUNCTION_ENABLE_READ_CALLBACK] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletRS232.FUNCTION_DISABLE_READ_CALLBACK] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletRS232.FUNCTION_IS_READ_CALLBACK_ENABLED] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRS232.FUNCTION_SET_CONFIGURATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletRS232.FUNCTION_GET_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRS232.FUNCTION_SET_BREAK_CONDITION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletRS232.FUNCTION_SET_FRAME_READABLE_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletRS232.FUNCTION_GET_FRAME_READABLE_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRS232.FUNCTION_READ_FRAME] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRS232.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletRS232.CALLBACK_READ] = [69, 'c60 B'];
	this.callbackFormats[BrickletRS232.CALLBACK_ERROR] = [9, 'B'];
	this.callbackFormats[BrickletRS232.CALLBACK_FRAME_READABLE] = [9, 'B'];



	this.write = function(message, length, returnCallback, errorCallback) {
		/*
		Writes a string of up to 60 characters to the RS232 interface. The string
		can be binary data, ASCII or similar is not necessary.
		
		The length of the string has to be given as an additional parameter.
		
		The return value is the number of bytes that could be written.
		
		See :func:`Set Configuration` for configuration possibilities
		regarding baudrate, parity and so on.
		*/
		this.ipcon.sendRequest(this, BrickletRS232.FUNCTION_WRITE, [message, length], 'c60 B', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.read = function(returnCallback, errorCallback) {
		/*
		Returns the currently buffered message. The maximum length
		of message is 60. If the returned length is 0, no new data was available.
		
		Instead of polling with this function, you can also use
		callbacks. See :func:`Enable Read Callback` and :cb:`Read` callback.
		*/
		this.ipcon.sendRequest(this, BrickletRS232.FUNCTION_READ, [], '', 69, 'c60 B', returnCallback, errorCallback, false, true);
	};
	this.enableReadCallback = function(returnCallback, errorCallback) {
		/*
		Enables the :cb:`Read` callback. This will disable the :cb:`Frame Readable` callback.
		
		By default the callback is disabled.
		*/
		this.ipcon.sendRequest(this, BrickletRS232.FUNCTION_ENABLE_READ_CALLBACK, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.disableReadCallback = function(returnCallback, errorCallback) {
		/*
		Disables the :cb:`Read` callback.
		
		By default the callback is disabled.
		*/
		this.ipcon.sendRequest(this, BrickletRS232.FUNCTION_DISABLE_READ_CALLBACK, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.isReadCallbackEnabled = function(returnCallback, errorCallback) {
		/*
		Returns *true* if the :cb:`Read` callback is enabled,
		*false* otherwise.
		*/
		this.ipcon.sendRequest(this, BrickletRS232.FUNCTION_IS_READ_CALLBACK_ENABLED, [], '', 9, '?', returnCallback, errorCallback, false, true);
	};
	this.setConfiguration = function(baudrate, parity, stopbits, wordlength, hardwareFlowcontrol, softwareFlowcontrol, returnCallback, errorCallback) {
		/*
		Sets the configuration for the RS232 communication.
		
		Hard-/Software flow control can either be on or off but not both simultaneously on.
		*/
		this.ipcon.sendRequest(this, BrickletRS232.FUNCTION_SET_CONFIGURATION, [baudrate, parity, stopbits, wordlength, hardwareFlowcontrol, softwareFlowcontrol], 'B B B B B B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletRS232.FUNCTION_GET_CONFIGURATION, [], '', 14, 'B B B B B B', returnCallback, errorCallback, false, true);
	};
	this.setBreakCondition = function(breakTime, returnCallback, errorCallback) {
		/*
		Sets a break condition (the TX output is forced to a logic 0 state).
		The parameter sets the hold-time of the break condition.
		
		.. versionadded:: 2.0.2$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletRS232.FUNCTION_SET_BREAK_CONDITION, [breakTime], 'H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.setFrameReadableCallbackConfiguration = function(frameSize, returnCallback, errorCallback) {
		/*
		Configures the :cb:`Frame Readable` callback. The frame size is the number of bytes, that have to be readable to trigger the callback.
		A frame size of 0 disables the callback. A frame size greater than 0 enables the callback and disables the :cb:`Read` callback.
		
		By default the callback is disabled.
		
		.. versionadded:: 2.0.4$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletRS232.FUNCTION_SET_FRAME_READABLE_CALLBACK_CONFIGURATION, [frameSize], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getFrameReadableCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the callback configuration as set by :func:`Set Frame Readable Callback Configuration`.
		
		.. versionadded:: 2.0.4$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletRS232.FUNCTION_GET_FRAME_READABLE_CALLBACK_CONFIGURATION, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.readFrame = function(returnCallback, errorCallback) {
		/*
		Returns up to one frame of bytes from the read buffer.
		The frame size is configured with :func:`Set Frame Readable Callback Configuration`.
		If the returned length is 0, no new data was available.
		
		.. versionadded:: 2.0.4$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletRS232.FUNCTION_READ_FRAME, [], '', 69, 'c60 B', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletRS232.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletRS232;

},{"./Device":279,"./IPConnection":280}],247:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletRS232V2.DEVICE_IDENTIFIER = 2108;
BrickletRS232V2.DEVICE_DISPLAY_NAME = 'RS232 Bricklet 2.0';
BrickletRS232V2.CALLBACK_READ_LOW_LEVEL = 12;
BrickletRS232V2.CALLBACK_ERROR_COUNT = 13;
BrickletRS232V2.CALLBACK_FRAME_READABLE = 16;
BrickletRS232V2.CALLBACK_READ = -12;
BrickletRS232V2.FUNCTION_WRITE_LOW_LEVEL = 1;
BrickletRS232V2.FUNCTION_READ_LOW_LEVEL = 2;
BrickletRS232V2.FUNCTION_ENABLE_READ_CALLBACK = 3;
BrickletRS232V2.FUNCTION_DISABLE_READ_CALLBACK = 4;
BrickletRS232V2.FUNCTION_IS_READ_CALLBACK_ENABLED = 5;
BrickletRS232V2.FUNCTION_SET_CONFIGURATION = 6;
BrickletRS232V2.FUNCTION_GET_CONFIGURATION = 7;
BrickletRS232V2.FUNCTION_SET_BUFFER_CONFIG = 8;
BrickletRS232V2.FUNCTION_GET_BUFFER_CONFIG = 9;
BrickletRS232V2.FUNCTION_GET_BUFFER_STATUS = 10;
BrickletRS232V2.FUNCTION_GET_ERROR_COUNT = 11;
BrickletRS232V2.FUNCTION_SET_FRAME_READABLE_CALLBACK_CONFIGURATION = 14;
BrickletRS232V2.FUNCTION_GET_FRAME_READABLE_CALLBACK_CONFIGURATION = 15;
BrickletRS232V2.FUNCTION_GET_SPITFP_ERROR_COUNT = 234;
BrickletRS232V2.FUNCTION_SET_BOOTLOADER_MODE = 235;
BrickletRS232V2.FUNCTION_GET_BOOTLOADER_MODE = 236;
BrickletRS232V2.FUNCTION_SET_WRITE_FIRMWARE_POINTER = 237;
BrickletRS232V2.FUNCTION_WRITE_FIRMWARE = 238;
BrickletRS232V2.FUNCTION_SET_STATUS_LED_CONFIG = 239;
BrickletRS232V2.FUNCTION_GET_STATUS_LED_CONFIG = 240;
BrickletRS232V2.FUNCTION_GET_CHIP_TEMPERATURE = 242;
BrickletRS232V2.FUNCTION_RESET = 243;
BrickletRS232V2.FUNCTION_WRITE_UID = 248;
BrickletRS232V2.FUNCTION_READ_UID = 249;
BrickletRS232V2.FUNCTION_GET_IDENTITY = 255;
BrickletRS232V2.PARITY_NONE = 0;
BrickletRS232V2.PARITY_ODD = 1;
BrickletRS232V2.PARITY_EVEN = 2;
BrickletRS232V2.STOPBITS_1 = 1;
BrickletRS232V2.STOPBITS_2 = 2;
BrickletRS232V2.WORDLENGTH_5 = 5;
BrickletRS232V2.WORDLENGTH_6 = 6;
BrickletRS232V2.WORDLENGTH_7 = 7;
BrickletRS232V2.WORDLENGTH_8 = 8;
BrickletRS232V2.FLOWCONTROL_OFF = 0;
BrickletRS232V2.FLOWCONTROL_SOFTWARE = 1;
BrickletRS232V2.FLOWCONTROL_HARDWARE = 2;
BrickletRS232V2.BOOTLOADER_MODE_BOOTLOADER = 0;
BrickletRS232V2.BOOTLOADER_MODE_FIRMWARE = 1;
BrickletRS232V2.BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT = 2;
BrickletRS232V2.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT = 3;
BrickletRS232V2.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT = 4;
BrickletRS232V2.BOOTLOADER_STATUS_OK = 0;
BrickletRS232V2.BOOTLOADER_STATUS_INVALID_MODE = 1;
BrickletRS232V2.BOOTLOADER_STATUS_NO_CHANGE = 2;
BrickletRS232V2.BOOTLOADER_STATUS_ENTRY_FUNCTION_NOT_PRESENT = 3;
BrickletRS232V2.BOOTLOADER_STATUS_DEVICE_IDENTIFIER_INCORRECT = 4;
BrickletRS232V2.BOOTLOADER_STATUS_CRC_MISMATCH = 5;
BrickletRS232V2.STATUS_LED_CONFIG_OFF = 0;
BrickletRS232V2.STATUS_LED_CONFIG_ON = 1;
BrickletRS232V2.STATUS_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletRS232V2.STATUS_LED_CONFIG_SHOW_STATUS = 3;

function BrickletRS232V2(uid, ipcon) {
	//Communicates with RS232 devices

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletRS232V2.DEVICE_IDENTIFIER, BrickletRS232V2.DEVICE_DISPLAY_NAME);
	BrickletRS232V2.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 1];
	this.responseExpected[BrickletRS232V2.FUNCTION_WRITE_LOW_LEVEL] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRS232V2.FUNCTION_READ_LOW_LEVEL] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRS232V2.FUNCTION_ENABLE_READ_CALLBACK] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletRS232V2.FUNCTION_DISABLE_READ_CALLBACK] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletRS232V2.FUNCTION_IS_READ_CALLBACK_ENABLED] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRS232V2.FUNCTION_SET_CONFIGURATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletRS232V2.FUNCTION_GET_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRS232V2.FUNCTION_SET_BUFFER_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletRS232V2.FUNCTION_GET_BUFFER_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRS232V2.FUNCTION_GET_BUFFER_STATUS] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRS232V2.FUNCTION_GET_ERROR_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRS232V2.FUNCTION_SET_FRAME_READABLE_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletRS232V2.FUNCTION_GET_FRAME_READABLE_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRS232V2.FUNCTION_GET_SPITFP_ERROR_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRS232V2.FUNCTION_SET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRS232V2.FUNCTION_GET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRS232V2.FUNCTION_SET_WRITE_FIRMWARE_POINTER] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletRS232V2.FUNCTION_WRITE_FIRMWARE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRS232V2.FUNCTION_SET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletRS232V2.FUNCTION_GET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRS232V2.FUNCTION_GET_CHIP_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRS232V2.FUNCTION_RESET] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletRS232V2.FUNCTION_WRITE_UID] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletRS232V2.FUNCTION_READ_UID] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRS232V2.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletRS232V2.CALLBACK_READ_LOW_LEVEL] = [72, 'H H c60'];
	this.callbackFormats[BrickletRS232V2.CALLBACK_ERROR_COUNT] = [16, 'I I'];
	this.callbackFormats[BrickletRS232V2.CALLBACK_FRAME_READABLE] = [10, 'H'];

	this.highLevelCallbacks[BrickletRS232V2.CALLBACK_READ] = [['streamLength', 'streamChunkOffset', 'streamChunkData'], {'fixedLength': null, 'singleChunk': false}, null];

	this.streamStateObjects[BrickletRS232V2.FUNCTION_WRITE_LOW_LEVEL] = {
		'dataMapping': ['streamChunkWritten'],
		'dataMappingStreamIn': ['streamLength', 'streamChunkOffset', 'streamChunkData'],
		'streamProperties': {
			'fixedLength': null,
			'singleChunk': false,
			'shortWrite': true
		},
		'responseProperties': {
			'running': false,
			'runningSubcall': false,
			'runningSubcallOOS': false,
			'waitingFirstChunk': true,
			'timeout': null,
			'data': [],
			'streamInChunkOffset': 0,
			'streamInChunkLength': 0,
			'streamInResponseEmpty': false,
			'streamInWritten': 0,
			'streamInLLParams': null,
			'responseHandler': null,
			'packFormatString': 'H H c60',
			'unpackFormatString': 'B',
			'returnCB': null,
			'errorCB': null,
			'callQueue': []
		}
	};
	this.streamStateObjects[BrickletRS232V2.FUNCTION_READ_LOW_LEVEL] = {
		'dataMapping': ['streamLength', 'streamChunkOffset', 'streamChunkData'],
		'dataMappingStreamIn': [],
		'streamProperties': {
			'fixedLength': null,
			'singleChunk': false,
			'shortWrite': false
		},
		'responseProperties': {
			'running': false,
			'runningSubcall': false,
			'runningSubcallOOS': false,
			'waitingFirstChunk': true,
			'timeout': null,
			'data': [],
			'streamInChunkOffset': 0,
			'streamInChunkLength': 0,
			'streamInResponseEmpty': true,
			'streamInWritten': 0,
			'streamInLLParams': null,
			'responseHandler': null,
			'packFormatString': 'H',
			'unpackFormatString': 'H H c60',
			'returnCB': null,
			'errorCB': null,
			'callQueue': []
		}
	};

	this.writeLowLevel = function(messageLength, messageChunkOffset, messageChunkData, returnCallback, errorCallback) {
		/*
		Writes characters to the RS232 interface. The characters can be binary data,
		ASCII or similar is not necessary.
		
		The return value is the number of characters that were written.
		
		See :func:`Set Configuration` for configuration possibilities
		regarding baud rate, parity and so on.
		*/
		this.ipcon.sendRequest(this, BrickletRS232V2.FUNCTION_WRITE_LOW_LEVEL, [messageLength, messageChunkOffset, messageChunkData], 'H H c60', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.readLowLevel = function(length, returnCallback, errorCallback) {
		/*
		Returns up to *length* characters from receive buffer.
		
		Instead of polling with this function, you can also use
		callbacks. But note that this function will return available
		data only when the read callback is disabled.
		See :func:`Enable Read Callback` and :cb:`Read` callback.
		*/
		this.ipcon.sendRequest(this, BrickletRS232V2.FUNCTION_READ_LOW_LEVEL, [length], 'H', 72, 'H H c60', returnCallback, errorCallback, false, true);
	};
	this.enableReadCallback = function(returnCallback, errorCallback) {
		/*
		Enables the :cb:`Read` callback. This will disable the :cb:`Frame Readable` callback.
		
		By default the callback is disabled.
		*/
		this.ipcon.sendRequest(this, BrickletRS232V2.FUNCTION_ENABLE_READ_CALLBACK, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.disableReadCallback = function(returnCallback, errorCallback) {
		/*
		Disables the :cb:`Read` callback.
		
		By default the callback is disabled.
		*/
		this.ipcon.sendRequest(this, BrickletRS232V2.FUNCTION_DISABLE_READ_CALLBACK, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.isReadCallbackEnabled = function(returnCallback, errorCallback) {
		/*
		Returns *true* if the :cb:`Read` callback is enabled,
		*false* otherwise.
		*/
		this.ipcon.sendRequest(this, BrickletRS232V2.FUNCTION_IS_READ_CALLBACK_ENABLED, [], '', 9, '?', returnCallback, errorCallback, false, true);
	};
	this.setConfiguration = function(baudrate, parity, stopbits, wordlength, flowcontrol, returnCallback, errorCallback) {
		/*
		Sets the configuration for the RS232 communication.
		*/
		this.ipcon.sendRequest(this, BrickletRS232V2.FUNCTION_SET_CONFIGURATION, [baudrate, parity, stopbits, wordlength, flowcontrol], 'I B B B B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletRS232V2.FUNCTION_GET_CONFIGURATION, [], '', 16, 'I B B B B', returnCallback, errorCallback, false, true);
	};
	this.setBufferConfig = function(sendBufferSize, receiveBufferSize, returnCallback, errorCallback) {
		/*
		Sets the send and receive buffer size in byte. In total the buffers have to be
		10240 byte (10KiB) in size, the minimum buffer size is 1024 byte (1KiB) for each.
		
		The current buffer content is lost if this function is called.
		
		The send buffer holds data that is given by :func:`Write` and
		can not be written yet. The receive buffer holds data that is
		received through RS232 but could not yet be send to the
		user, either by :func:`Read` or through :cb:`Read` callback.
		*/
		this.ipcon.sendRequest(this, BrickletRS232V2.FUNCTION_SET_BUFFER_CONFIG, [sendBufferSize, receiveBufferSize], 'H H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getBufferConfig = function(returnCallback, errorCallback) {
		/*
		Returns the buffer configuration as set by :func:`Set Buffer Config`.
		*/
		this.ipcon.sendRequest(this, BrickletRS232V2.FUNCTION_GET_BUFFER_CONFIG, [], '', 12, 'H H', returnCallback, errorCallback, false, true);
	};
	this.getBufferStatus = function(returnCallback, errorCallback) {
		/*
		Returns the currently used bytes for the send and received buffer.
		
		See :func:`Set Buffer Config` for buffer size configuration.
		*/
		this.ipcon.sendRequest(this, BrickletRS232V2.FUNCTION_GET_BUFFER_STATUS, [], '', 12, 'H H', returnCallback, errorCallback, false, true);
	};
	this.getErrorCount = function(returnCallback, errorCallback) {
		/*
		Returns the current number of overrun and parity errors.
		*/
		this.ipcon.sendRequest(this, BrickletRS232V2.FUNCTION_GET_ERROR_COUNT, [], '', 16, 'I I', returnCallback, errorCallback, false, true);
	};
	this.setFrameReadableCallbackConfiguration = function(frameSize, returnCallback, errorCallback) {
		/*
		Configures the :cb:`Frame Readable` callback. The frame size is the number of bytes, that have to be readable to trigger the callback.
		A frame size of 0 disables the callback. A frame size greater than 0 enables the callback and disables the :cb:`Read` callback.
		
		By default the callback is disabled.
		
		.. versionadded:: 2.0.3$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletRS232V2.FUNCTION_SET_FRAME_READABLE_CALLBACK_CONFIGURATION, [frameSize], 'H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getFrameReadableCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the callback configuration as set by :func:`Set Frame Readable Callback Configuration`.
		
		.. versionadded:: 2.0.3$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletRS232V2.FUNCTION_GET_FRAME_READABLE_CALLBACK_CONFIGURATION, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPErrorCount = function(returnCallback, errorCallback) {
		/*
		Returns the error count for the communication between Brick and Bricklet.
		
		The errors are divided into
		
		* ACK checksum errors,
		* message checksum errors,
		* framing errors and
		* overflow errors.
		
		The errors counts are for errors that occur on the Bricklet side. All
		Bricks have a similar function that returns the errors on the Brick side.
		*/
		this.ipcon.sendRequest(this, BrickletRS232V2.FUNCTION_GET_SPITFP_ERROR_COUNT, [], '', 24, 'I I I I', returnCallback, errorCallback, false, true);
	};
	this.setBootloaderMode = function(mode, returnCallback, errorCallback) {
		/*
		Sets the bootloader mode and returns the status after the requested
		mode change was instigated.
		
		You can change from bootloader mode to firmware mode and vice versa. A change
		from bootloader mode to firmware mode will only take place if the entry function,
		device identifier and CRC are present and correct.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletRS232V2.FUNCTION_SET_BOOTLOADER_MODE, [mode], 'B', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getBootloaderMode = function(returnCallback, errorCallback) {
		/*
		Returns the current bootloader mode, see :func:`Set Bootloader Mode`.
		*/
		this.ipcon.sendRequest(this, BrickletRS232V2.FUNCTION_GET_BOOTLOADER_MODE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setWriteFirmwarePointer = function(pointer, returnCallback, errorCallback) {
		/*
		Sets the firmware pointer for :func:`Write Firmware`. The pointer has
		to be increased by chunks of size 64. The data is written to flash
		every 4 chunks (which equals to one page of size 256).
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletRS232V2.FUNCTION_SET_WRITE_FIRMWARE_POINTER, [pointer], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeFirmware = function(data, returnCallback, errorCallback) {
		/*
		Writes 64 Bytes of firmware at the position as written by
		:func:`Set Write Firmware Pointer` before. The firmware is written
		to flash every 4 chunks.
		
		You can only write firmware in bootloader mode.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletRS232V2.FUNCTION_WRITE_FIRMWARE, [data], 'B64', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setStatusLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Sets the status LED configuration. By default the LED shows
		communication traffic between Brick and Bricklet, it flickers once
		for every 10 received data packets.
		
		You can also turn the LED permanently on/off or show a heartbeat.
		
		If the Bricklet is in bootloader mode, the LED is will show heartbeat by default.
		*/
		this.ipcon.sendRequest(this, BrickletRS232V2.FUNCTION_SET_STATUS_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getStatusLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Status LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletRS232V2.FUNCTION_GET_STATUS_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getChipTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature as measured inside the microcontroller. The
		value returned is not the ambient temperature!
		
		The temperature is only proportional to the real temperature and it has bad
		accuracy. Practically it is only useful as an indicator for
		temperature changes.
		*/
		this.ipcon.sendRequest(this, BrickletRS232V2.FUNCTION_GET_CHIP_TEMPERATURE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.reset = function(returnCallback, errorCallback) {
		/*
		Calling this function will reset the Bricklet. All configurations
		will be lost.
		
		After a reset you have to create new device objects,
		calling functions on the existing ones will result in
		undefined behavior!
		*/
		this.ipcon.sendRequest(this, BrickletRS232V2.FUNCTION_RESET, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeUID = function(uid, returnCallback, errorCallback) {
		/*
		Writes a new UID into flash. If you want to set a new UID
		you have to decode the Base58 encoded UID string into an
		integer first.
		
		We recommend that you use Brick Viewer to change the UID.
		*/
		this.ipcon.sendRequest(this, BrickletRS232V2.FUNCTION_WRITE_UID, [uid], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.readUID = function(returnCallback, errorCallback) {
		/*
		Returns the current UID as an integer. Encode as
		Base58 to get the usual string version.
		*/
		this.ipcon.sendRequest(this, BrickletRS232V2.FUNCTION_READ_UID, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletRS232V2.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};
	this.write = function(message, returnCallback, errorCallback) {
		/*
		Writes characters to the RS232 interface. The characters can be binary data,
		ASCII or similar is not necessary.
		
		The return value is the number of characters that were written.
		
		See :func:`Set Configuration` for configuration possibilities
		regarding baud rate, parity and so on.
		*/

		var messageLength = 0;
		var messageChunkData = [];
		var messageChunkOffset = 0;
		var streamStateObject = this.streamStateObjects[1];

		if (message.length > 65535) {
			if (errorCallback !== null){
				errorCallback(IPConnection.ERROR_INVALID_PARAMETER);
			}

			this.resetStreamStateObject(streamStateObject);

			if (streamStateObject['responseProperties']['callQueue'].length > 0) {
				streamStateObject['responseProperties']['callQueue'].shift()(device);
			}

			return;
		}

		if (!this.getResponseExpected(1)) {
			if (streamStateObject['streamProperties']['fixedLength']) {
				messageLength = streamStateObject['streamProperties']['fixedLength'];
			}
			else {
				messageLength = message.length;
			}

			if (streamStateObject['streamProperties']['singleChunk']) {
				messageChunkData =
					this.ipcon.createChunkData(message, 0, 60, '\0');

				this.ipcon.sendRequest(this,
				                       BrickletRS232V2.FUNCTION_WRITE_LOW_LEVEL,
				                       [messageLength, messageChunkOffset, messageChunkData],
				                       'H H c60',
				                       9,
				                       'B',
				                       returnCallback,
				                       errorCallback,
				                       false,
				                       true);
			}
			else {
				while (messageChunkOffset < message.length) {
					messageChunkData =
						this.ipcon.createChunkData(message, messageChunkOffset, 60, '\0');

					this.ipcon.sendRequest(this,
					                       BrickletRS232V2.FUNCTION_WRITE_LOW_LEVEL,
					                       [messageLength, messageChunkOffset, messageChunkData],
					                       'H H c60',
					                       9,
					                       'B',
					                       returnCallback,
					                       errorCallback,
					                       false,
					                       true);

					messageChunkOffset += 60;
				}
			}

			if (returnCallback) {
				returnCallback();
			}
		}
		else {
			var responseHandler = null;
			var functionToQueue = null;

			if (streamStateObject['responseProperties']['responseHandler'] === null) {
				responseHandler = function (device, fid, packetResponse) {
					var result = [];
					var payload = null;
					var llvalues = null;
					var packetErrorFlag = 0;
					var rolesMappedData = [];
					var shortWriteWritten = -1;
					var streamStateObject = device.streamStateObjects[fid];
					var responseEmpty = streamStateObject['responseProperties']['streamInResponseEmpty'];
					var messageLength = 0;
					var messageChunkData = [];
					var messageChunkOffset = 0;

					function doNextLLCall() {
						messageLength = streamStateObject['responseProperties']['data'].length;
						messageChunkData =
							device.ipcon.createChunkData(streamStateObject['responseProperties']['data'],
							                             streamStateObject['responseProperties']['streamInChunkOffset'],
							                             streamStateObject['responseProperties']['streamInChunkLength'],
							                             '\0');
						messageChunkOffset = streamStateObject['responseProperties']['streamInChunkOffset'];

						for (var i = 0; i < streamStateObject['dataMappingStreamIn'].length; i++) {
							if (streamStateObject['dataMappingStreamIn'][i] === null) {
								continue;
							}

							if (streamStateObject['dataMappingStreamIn'][i].endsWith('Length')) {
								streamStateObject['responseProperties']['streamInLLParams'][i] = messageLength;
							}
							else if (streamStateObject['dataMappingStreamIn'][i].endsWith('Offset')) {
								streamStateObject['responseProperties']['streamInLLParams'][i] = messageChunkOffset;
							}
							else if (streamStateObject['dataMappingStreamIn'][i].endsWith('Data')) {
								streamStateObject['responseProperties']['streamInLLParams'][i] = messageChunkData;
							}
						}

						device.ipcon.sendRequest(device,
						                         BrickletRS232V2.FUNCTION_WRITE_LOW_LEVEL,
						                         streamStateObject['responseProperties']['streamInLLParams'],
						                         'H H c60',
						                         9,
						                         'B',
						                         returnCallback,
						                         errorCallback,
						                         true,
						                         true);

						streamStateObject['responseProperties']['streamInChunkOffset'] += 60;
					}

					function handleStreamInDone() {
						if (streamStateObject['responseProperties']['returnCB']) {
							if (streamStateObject['streamProperties']['shortWrite']) {
								for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
									if (streamStateObject['dataMapping'][i].endsWith('Written')) {
										result[i] = streamStateObject['responseProperties']['streamInWritten'];
										break;
									}
								}
							}

							if (!responseEmpty) {
								streamStateObject['responseProperties']['returnCB'].apply(device, result);
							}
							else {
								streamStateObject['responseProperties']['returnCB'].apply(device);
							}
						}

						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}
					}

					if (!streamStateObject) {
						return;
					}

					packetErrorFlag = device.ipcon.getEFromPacket(packetResponse);

					if (packetErrorFlag !== 0) {
						if (streamStateObject['responseProperties']['errorCB'] !== undefined) {
							if (packetErrorFlag === 1) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_INVALID_PARAMETER);
							}
							else if (packetErrorFlag === 2) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_FUNCTION_NOT_SUPPORTED);
							}
							else {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_UNKNOWN_ERROR);
							}
						}

						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}

						return;
					}

					if (responseEmpty) {
						if (streamStateObject['streamProperties']['singleChunk']) {
							handleStreamInDone();

							return;
						}

						if (streamStateObject['responseProperties']['streamInChunkOffset'] < streamStateObject['responseProperties']['data'].length) {
							doNextLLCall();
						}
						else {
							handleStreamInDone();
						}
					}
					else {
						payload = device.ipcon.getPayloadFromPacket(packetResponse);
						llvalues = device.ipcon.unpack(payload,
						                               streamStateObject['responseProperties']['unpackFormatString']);

						if (!payload || !llvalues) {
							device.resetStreamStateObject(streamStateObject);

							if (streamStateObject['responseProperties']['callQueue'].length > 0) {
								streamStateObject['responseProperties']['callQueue'].shift()(device);
							}

							return;
						}

						for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
							result.push(llvalues[i]);
						}

						if (streamStateObject['streamProperties']['singleChunk']) {
							if (streamStateObject['responseProperties']['returnCB']) {
								streamStateObject['responseProperties']['returnCB'].apply(device, result);
							}

							device.resetStreamStateObject(streamStateObject);

							if (streamStateObject['responseProperties']['callQueue'].length > 0) {
								streamStateObject['responseProperties']['callQueue'].shift()(device);
							}

							return;
						}

						if (streamStateObject['streamProperties']['shortWrite']) {
							for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
								if (streamStateObject['dataMapping'][i].endsWith('Written')) {
									shortWriteWritten = llvalues[i];
									streamStateObject['responseProperties']['streamInWritten'] += shortWriteWritten;
									break;
								}
							}
							if ((shortWriteWritten !== -1) && (shortWriteWritten < 60)) {
								// Either last chunk or short write
								handleStreamInDone();
								return;
							}
						}

						if (streamStateObject['responseProperties']['streamInChunkOffset'] < streamStateObject['responseProperties']['data'].length) {
							doNextLLCall();
						}
						else {
							handleStreamInDone();
						}
					}
				};

				streamStateObject['responseProperties']['responseHandler'] = responseHandler;
			}

			if (!streamStateObject['responseProperties']['running']) {
				streamStateObject['responseProperties']['running'] = true;
				streamStateObject['responseProperties']['returnCB'] = returnCallback;
				streamStateObject['responseProperties']['errorCB'] = errorCallback;
				streamStateObject['responseProperties']['data'].length = 0;
				streamStateObject['responseProperties']['data'].push.apply(streamStateObject['responseProperties']['data'],
				                                                           message);

				if (streamStateObject['streamProperties']['fixedLength']) {
					messageLength = streamStateObject['streamProperties']['fixedLength'];
				}
				else {
					messageLength = message.length;
				}

				messageChunkOffset = 0;
				messageChunkData =
					this.ipcon.createChunkData(message, 0, 60, '\0');

				streamStateObject['responseProperties']['streamInChunkOffset'] = 60;
				streamStateObject['responseProperties']['streamInChunkLength'] = 60;
				streamStateObject['responseProperties']['streamInLLParams'] = [messageLength, messageChunkOffset, messageChunkData];

				this.ipcon.sendRequest(this,
				                       BrickletRS232V2.FUNCTION_WRITE_LOW_LEVEL,
				                       [messageLength, messageChunkOffset, messageChunkData],
				                       'H H c60',
				                       9,
				                       'B',
				                       returnCallback,
				                       errorCallback,
				                       true,
				                       true);
			}
			else {
				functionToQueue = function (device) {
					device.write.call(device, message, returnCallback, errorCallback);
				}

				streamStateObject['responseProperties']['callQueue'].push(functionToQueue);
			}
		}
	};

	this.read = function(length, returnCallback, errorCallback) {
		/*
		Returns up to *length* characters from receive buffer.
		
		Instead of polling with this function, you can also use
		callbacks. But note that this function will return available
		data only when the read callback is disabled.
		See :func:`Enable Read Callback` and :cb:`Read` callback.
		*/
		var responseHandler = null;
		var functionToQueue = null;
		var streamStateObject = this.streamStateObjects[2];
		if (streamStateObject['responseProperties']['responseHandler'] === null) {
			responseHandler = 
				function (device, fid, packetResponse) {
					var result = [];
					var llvalues = null;
					var packetErrorFlag = 0;
					var rolesMappedData = [];
					var messageLength = null;
					var messageChunkData = null;
					var messageOutOfSync = false;
					var streamStateObject = device.streamStateObjects[fid];
					var messageChunkOffset = null;
					var payload = device.ipcon.getPayloadFromPacket(packetResponse);

					packetErrorFlag = device.ipcon.getEFromPacket(packetResponse);

					if (packetErrorFlag !== 0) {
						if (streamStateObject['responseProperties']['errorCB'] !== undefined) {
							if (packetErrorFlag === 1) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_INVALID_PARAMETER);
							}
							else if (packetErrorFlag === 2) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_FUNCTION_NOT_SUPPORTED);
							}
							else {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_UNKNOWN_ERROR);
							}
						}

						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}

						return;
					}

					if (payload.length === 0) {
						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}

						return;
					}

					llvalues = device.ipcon.unpack(payload,
					                               streamStateObject['responseProperties']['unpackFormatString']);

					for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
						if (streamStateObject['dataMapping'][i] === 'streamChunkData') {
							messageChunkData = llvalues[i];
						}
						else if (streamStateObject['dataMapping'][i] === 'streamChunkOffset') {
							messageChunkOffset = llvalues[i];
						}
					}

					for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
						if (streamStateObject['dataMapping'][i] === 'streamLength') {
							messageLength = llvalues[i];
							break;
						}
					}

					function handleOOS() {
						if ((messageChunkOffset + 60) < messageLength) {
							streamStateObject['responseProperties']['runningSubcallOOS'] = true;
							device.ipcon.sendRequest(device, BrickletRS232V2.FUNCTION_READ_LOW_LEVEL, [length], 'H', 72, 'H H c60', streamStateObject['responseProperties']['returnCB'], streamStateObject['responseProperties']['errorCB'], true, true);

							return;
						}

						if (streamStateObject['responseProperties']['errorCB']) {
							streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_STREAM_OUT_OF_SYNC);
						}

						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}
					}

					if (streamStateObject['responseProperties']['waitingFirstChunk']) {
						streamStateObject['responseProperties']['waitingFirstChunk'] = false;
						messageOutOfSync = (messageChunkOffset !== 0);
						streamStateObject['responseProperties']['data'] = messageChunkData;
					}

					if (!streamStateObject['responseProperties']['runningSubcallOOS']) {
						if (!streamStateObject['responseProperties']['runningSubcall']) {
							if (!messageOutOfSync &&
							    (streamStateObject['responseProperties']['data'].length < messageLength)) {
							        streamStateObject['responseProperties']['runningSubcall'] = true;
							        device.ipcon.sendRequest(device, BrickletRS232V2.FUNCTION_READ_LOW_LEVEL, [length], 'H', 72, 'H H c60', streamStateObject['responseProperties']['returnCB'], streamStateObject['responseProperties']['errorCB'], true, true);

							        return;
							}
						}
						else {
							messageOutOfSync =
								(messageChunkOffset !== streamStateObject['responseProperties']['data'].length);

							if (!messageOutOfSync &&
								(streamStateObject['responseProperties']['data'].length < messageLength)) {
									streamStateObject['responseProperties']['data'] =
										streamStateObject['responseProperties']['data'].concat(messageChunkData);

									if (streamStateObject['responseProperties']['data'].length >= messageLength) {
										streamStateObject['responseProperties']['data'] =
											streamStateObject['responseProperties']['data'].splice(0, messageLength);
									}
									else {
										device.ipcon.sendRequest(device, BrickletRS232V2.FUNCTION_READ_LOW_LEVEL, [length], 'H', 72, 'H H c60', streamStateObject['responseProperties']['returnCB'], streamStateObject['responseProperties']['errorCB'], true, true);

										return;
									}
							}
						}
					}
					else{
						handleOOS();

						return;
					}

					if (messageOutOfSync) { // Discard remaining stream to bring it back in-sync
						handleOOS();

						return;
					}

					if (streamStateObject['responseProperties']['returnCB']) {
						for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
							rolesMappedData.push({'role': streamStateObject['dataMapping'][i], 'llvalue': llvalues[i]});
						}

						for (var i = 0; i < rolesMappedData.length; i++) {
							if (rolesMappedData[i]['role'] === 'streamChunkData') {
								result.push(streamStateObject['responseProperties']['data'].splice(0, messageLength));
							}
							else if (rolesMappedData[i]['role'] === null) {
								result.push(rolesMappedData[i]['llvalue']);
							}
						}

						streamStateObject['responseProperties']['returnCB'].apply(device, result);
					}

					device.resetStreamStateObject(streamStateObject);

					if (streamStateObject['responseProperties']['callQueue'].length > 0) {
						streamStateObject['responseProperties']['callQueue'].shift()(device);
					}
					
				};

			streamStateObject['responseProperties']['responseHandler'] = responseHandler;
		}
		if (!streamStateObject['responseProperties']['running']) {
			streamStateObject['responseProperties']['running'] = true;
			streamStateObject['responseProperties']['returnCB'] = returnCallback;
			streamStateObject['responseProperties']['errorCB'] = errorCallback;
			this.ipcon.sendRequest(this,
			                       BrickletRS232V2.FUNCTION_READ_LOW_LEVEL,
			                       [length],
			                       'H',
			                       72,
			                       'H H c60',
			                       returnCallback,
			                       errorCallback,
			                       true,
			                       true);
		}
		else {
			functionToQueue = function (device) {
				device.read.call(device, length, returnCallback, errorCallback);
			}
			streamStateObject['responseProperties']['callQueue'].push(functionToQueue);
		}
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletRS232V2;

},{"./Device":279,"./IPConnection":280}],248:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletRS485.DEVICE_IDENTIFIER = 277;
BrickletRS485.DEVICE_DISPLAY_NAME = 'RS485 Bricklet';
BrickletRS485.CALLBACK_READ_LOW_LEVEL = 41;
BrickletRS485.CALLBACK_ERROR_COUNT = 42;
BrickletRS485.CALLBACK_MODBUS_SLAVE_READ_COILS_REQUEST = 43;
BrickletRS485.CALLBACK_MODBUS_MASTER_READ_COILS_RESPONSE_LOW_LEVEL = 44;
BrickletRS485.CALLBACK_MODBUS_SLAVE_READ_HOLDING_REGISTERS_REQUEST = 45;
BrickletRS485.CALLBACK_MODBUS_MASTER_READ_HOLDING_REGISTERS_RESPONSE_LOW_LEVEL = 46;
BrickletRS485.CALLBACK_MODBUS_SLAVE_WRITE_SINGLE_COIL_REQUEST = 47;
BrickletRS485.CALLBACK_MODBUS_MASTER_WRITE_SINGLE_COIL_RESPONSE = 48;
BrickletRS485.CALLBACK_MODBUS_SLAVE_WRITE_SINGLE_REGISTER_REQUEST = 49;
BrickletRS485.CALLBACK_MODBUS_MASTER_WRITE_SINGLE_REGISTER_RESPONSE = 50;
BrickletRS485.CALLBACK_MODBUS_SLAVE_WRITE_MULTIPLE_COILS_REQUEST_LOW_LEVEL = 51;
BrickletRS485.CALLBACK_MODBUS_MASTER_WRITE_MULTIPLE_COILS_RESPONSE = 52;
BrickletRS485.CALLBACK_MODBUS_SLAVE_WRITE_MULTIPLE_REGISTERS_REQUEST_LOW_LEVEL = 53;
BrickletRS485.CALLBACK_MODBUS_MASTER_WRITE_MULTIPLE_REGISTERS_RESPONSE = 54;
BrickletRS485.CALLBACK_MODBUS_SLAVE_READ_DISCRETE_INPUTS_REQUEST = 55;
BrickletRS485.CALLBACK_MODBUS_MASTER_READ_DISCRETE_INPUTS_RESPONSE_LOW_LEVEL = 56;
BrickletRS485.CALLBACK_MODBUS_SLAVE_READ_INPUT_REGISTERS_REQUEST = 57;
BrickletRS485.CALLBACK_MODBUS_MASTER_READ_INPUT_REGISTERS_RESPONSE_LOW_LEVEL = 58;
BrickletRS485.CALLBACK_FRAME_READABLE = 61;
BrickletRS485.CALLBACK_READ = -41;
BrickletRS485.CALLBACK_MODBUS_MASTER_READ_COILS_RESPONSE = -44;
BrickletRS485.CALLBACK_MODBUS_MASTER_READ_HOLDING_REGISTERS_RESPONSE = -46;
BrickletRS485.CALLBACK_MODBUS_SLAVE_WRITE_MULTIPLE_COILS_REQUEST = -51;
BrickletRS485.CALLBACK_MODBUS_SLAVE_WRITE_MULTIPLE_REGISTERS_REQUEST = -53;
BrickletRS485.CALLBACK_MODBUS_MASTER_READ_DISCRETE_INPUTS_RESPONSE = -56;
BrickletRS485.CALLBACK_MODBUS_MASTER_READ_INPUT_REGISTERS_RESPONSE = -58;
BrickletRS485.FUNCTION_WRITE_LOW_LEVEL = 1;
BrickletRS485.FUNCTION_READ_LOW_LEVEL = 2;
BrickletRS485.FUNCTION_ENABLE_READ_CALLBACK = 3;
BrickletRS485.FUNCTION_DISABLE_READ_CALLBACK = 4;
BrickletRS485.FUNCTION_IS_READ_CALLBACK_ENABLED = 5;
BrickletRS485.FUNCTION_SET_RS485_CONFIGURATION = 6;
BrickletRS485.FUNCTION_GET_RS485_CONFIGURATION = 7;
BrickletRS485.FUNCTION_SET_MODBUS_CONFIGURATION = 8;
BrickletRS485.FUNCTION_GET_MODBUS_CONFIGURATION = 9;
BrickletRS485.FUNCTION_SET_MODE = 10;
BrickletRS485.FUNCTION_GET_MODE = 11;
BrickletRS485.FUNCTION_SET_COMMUNICATION_LED_CONFIG = 12;
BrickletRS485.FUNCTION_GET_COMMUNICATION_LED_CONFIG = 13;
BrickletRS485.FUNCTION_SET_ERROR_LED_CONFIG = 14;
BrickletRS485.FUNCTION_GET_ERROR_LED_CONFIG = 15;
BrickletRS485.FUNCTION_SET_BUFFER_CONFIG = 16;
BrickletRS485.FUNCTION_GET_BUFFER_CONFIG = 17;
BrickletRS485.FUNCTION_GET_BUFFER_STATUS = 18;
BrickletRS485.FUNCTION_ENABLE_ERROR_COUNT_CALLBACK = 19;
BrickletRS485.FUNCTION_DISABLE_ERROR_COUNT_CALLBACK = 20;
BrickletRS485.FUNCTION_IS_ERROR_COUNT_CALLBACK_ENABLED = 21;
BrickletRS485.FUNCTION_GET_ERROR_COUNT = 22;
BrickletRS485.FUNCTION_GET_MODBUS_COMMON_ERROR_COUNT = 23;
BrickletRS485.FUNCTION_MODBUS_SLAVE_REPORT_EXCEPTION = 24;
BrickletRS485.FUNCTION_MODBUS_SLAVE_ANSWER_READ_COILS_REQUEST_LOW_LEVEL = 25;
BrickletRS485.FUNCTION_MODBUS_MASTER_READ_COILS = 26;
BrickletRS485.FUNCTION_MODBUS_SLAVE_ANSWER_READ_HOLDING_REGISTERS_REQUEST_LOW_LEVEL = 27;
BrickletRS485.FUNCTION_MODBUS_MASTER_READ_HOLDING_REGISTERS = 28;
BrickletRS485.FUNCTION_MODBUS_SLAVE_ANSWER_WRITE_SINGLE_COIL_REQUEST = 29;
BrickletRS485.FUNCTION_MODBUS_MASTER_WRITE_SINGLE_COIL = 30;
BrickletRS485.FUNCTION_MODBUS_SLAVE_ANSWER_WRITE_SINGLE_REGISTER_REQUEST = 31;
BrickletRS485.FUNCTION_MODBUS_MASTER_WRITE_SINGLE_REGISTER = 32;
BrickletRS485.FUNCTION_MODBUS_SLAVE_ANSWER_WRITE_MULTIPLE_COILS_REQUEST = 33;
BrickletRS485.FUNCTION_MODBUS_MASTER_WRITE_MULTIPLE_COILS_LOW_LEVEL = 34;
BrickletRS485.FUNCTION_MODBUS_SLAVE_ANSWER_WRITE_MULTIPLE_REGISTERS_REQUEST = 35;
BrickletRS485.FUNCTION_MODBUS_MASTER_WRITE_MULTIPLE_REGISTERS_LOW_LEVEL = 36;
BrickletRS485.FUNCTION_MODBUS_SLAVE_ANSWER_READ_DISCRETE_INPUTS_REQUEST_LOW_LEVEL = 37;
BrickletRS485.FUNCTION_MODBUS_MASTER_READ_DISCRETE_INPUTS = 38;
BrickletRS485.FUNCTION_MODBUS_SLAVE_ANSWER_READ_INPUT_REGISTERS_REQUEST_LOW_LEVEL = 39;
BrickletRS485.FUNCTION_MODBUS_MASTER_READ_INPUT_REGISTERS = 40;
BrickletRS485.FUNCTION_SET_FRAME_READABLE_CALLBACK_CONFIGURATION = 59;
BrickletRS485.FUNCTION_GET_FRAME_READABLE_CALLBACK_CONFIGURATION = 60;
BrickletRS485.FUNCTION_GET_SPITFP_ERROR_COUNT = 234;
BrickletRS485.FUNCTION_SET_BOOTLOADER_MODE = 235;
BrickletRS485.FUNCTION_GET_BOOTLOADER_MODE = 236;
BrickletRS485.FUNCTION_SET_WRITE_FIRMWARE_POINTER = 237;
BrickletRS485.FUNCTION_WRITE_FIRMWARE = 238;
BrickletRS485.FUNCTION_SET_STATUS_LED_CONFIG = 239;
BrickletRS485.FUNCTION_GET_STATUS_LED_CONFIG = 240;
BrickletRS485.FUNCTION_GET_CHIP_TEMPERATURE = 242;
BrickletRS485.FUNCTION_RESET = 243;
BrickletRS485.FUNCTION_WRITE_UID = 248;
BrickletRS485.FUNCTION_READ_UID = 249;
BrickletRS485.FUNCTION_GET_IDENTITY = 255;
BrickletRS485.PARITY_NONE = 0;
BrickletRS485.PARITY_ODD = 1;
BrickletRS485.PARITY_EVEN = 2;
BrickletRS485.STOPBITS_1 = 1;
BrickletRS485.STOPBITS_2 = 2;
BrickletRS485.WORDLENGTH_5 = 5;
BrickletRS485.WORDLENGTH_6 = 6;
BrickletRS485.WORDLENGTH_7 = 7;
BrickletRS485.WORDLENGTH_8 = 8;
BrickletRS485.DUPLEX_HALF = 0;
BrickletRS485.DUPLEX_FULL = 1;
BrickletRS485.MODE_RS485 = 0;
BrickletRS485.MODE_MODBUS_MASTER_RTU = 1;
BrickletRS485.MODE_MODBUS_SLAVE_RTU = 2;
BrickletRS485.COMMUNICATION_LED_CONFIG_OFF = 0;
BrickletRS485.COMMUNICATION_LED_CONFIG_ON = 1;
BrickletRS485.COMMUNICATION_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletRS485.COMMUNICATION_LED_CONFIG_SHOW_COMMUNICATION = 3;
BrickletRS485.ERROR_LED_CONFIG_OFF = 0;
BrickletRS485.ERROR_LED_CONFIG_ON = 1;
BrickletRS485.ERROR_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletRS485.ERROR_LED_CONFIG_SHOW_ERROR = 3;
BrickletRS485.EXCEPTION_CODE_TIMEOUT = -1;
BrickletRS485.EXCEPTION_CODE_SUCCESS = 0;
BrickletRS485.EXCEPTION_CODE_ILLEGAL_FUNCTION = 1;
BrickletRS485.EXCEPTION_CODE_ILLEGAL_DATA_ADDRESS = 2;
BrickletRS485.EXCEPTION_CODE_ILLEGAL_DATA_VALUE = 3;
BrickletRS485.EXCEPTION_CODE_SLAVE_DEVICE_FAILURE = 4;
BrickletRS485.EXCEPTION_CODE_ACKNOWLEDGE = 5;
BrickletRS485.EXCEPTION_CODE_SLAVE_DEVICE_BUSY = 6;
BrickletRS485.EXCEPTION_CODE_MEMORY_PARITY_ERROR = 8;
BrickletRS485.EXCEPTION_CODE_GATEWAY_PATH_UNAVAILABLE = 10;
BrickletRS485.EXCEPTION_CODE_GATEWAY_TARGET_DEVICE_FAILED_TO_RESPOND = 11;
BrickletRS485.BOOTLOADER_MODE_BOOTLOADER = 0;
BrickletRS485.BOOTLOADER_MODE_FIRMWARE = 1;
BrickletRS485.BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT = 2;
BrickletRS485.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT = 3;
BrickletRS485.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT = 4;
BrickletRS485.BOOTLOADER_STATUS_OK = 0;
BrickletRS485.BOOTLOADER_STATUS_INVALID_MODE = 1;
BrickletRS485.BOOTLOADER_STATUS_NO_CHANGE = 2;
BrickletRS485.BOOTLOADER_STATUS_ENTRY_FUNCTION_NOT_PRESENT = 3;
BrickletRS485.BOOTLOADER_STATUS_DEVICE_IDENTIFIER_INCORRECT = 4;
BrickletRS485.BOOTLOADER_STATUS_CRC_MISMATCH = 5;
BrickletRS485.STATUS_LED_CONFIG_OFF = 0;
BrickletRS485.STATUS_LED_CONFIG_ON = 1;
BrickletRS485.STATUS_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletRS485.STATUS_LED_CONFIG_SHOW_STATUS = 3;

function BrickletRS485(uid, ipcon) {
	//Communicates with RS485/Modbus devices with full- or half-duplex

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletRS485.DEVICE_IDENTIFIER, BrickletRS485.DEVICE_DISPLAY_NAME);
	BrickletRS485.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 1];
	this.responseExpected[BrickletRS485.FUNCTION_WRITE_LOW_LEVEL] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRS485.FUNCTION_READ_LOW_LEVEL] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRS485.FUNCTION_ENABLE_READ_CALLBACK] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletRS485.FUNCTION_DISABLE_READ_CALLBACK] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletRS485.FUNCTION_IS_READ_CALLBACK_ENABLED] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRS485.FUNCTION_SET_RS485_CONFIGURATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletRS485.FUNCTION_GET_RS485_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRS485.FUNCTION_SET_MODBUS_CONFIGURATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletRS485.FUNCTION_GET_MODBUS_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRS485.FUNCTION_SET_MODE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletRS485.FUNCTION_GET_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRS485.FUNCTION_SET_COMMUNICATION_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletRS485.FUNCTION_GET_COMMUNICATION_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRS485.FUNCTION_SET_ERROR_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletRS485.FUNCTION_GET_ERROR_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRS485.FUNCTION_SET_BUFFER_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletRS485.FUNCTION_GET_BUFFER_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRS485.FUNCTION_GET_BUFFER_STATUS] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRS485.FUNCTION_ENABLE_ERROR_COUNT_CALLBACK] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletRS485.FUNCTION_DISABLE_ERROR_COUNT_CALLBACK] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletRS485.FUNCTION_IS_ERROR_COUNT_CALLBACK_ENABLED] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRS485.FUNCTION_GET_ERROR_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRS485.FUNCTION_GET_MODBUS_COMMON_ERROR_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRS485.FUNCTION_MODBUS_SLAVE_REPORT_EXCEPTION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletRS485.FUNCTION_MODBUS_SLAVE_ANSWER_READ_COILS_REQUEST_LOW_LEVEL] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletRS485.FUNCTION_MODBUS_MASTER_READ_COILS] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRS485.FUNCTION_MODBUS_SLAVE_ANSWER_READ_HOLDING_REGISTERS_REQUEST_LOW_LEVEL] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletRS485.FUNCTION_MODBUS_MASTER_READ_HOLDING_REGISTERS] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRS485.FUNCTION_MODBUS_SLAVE_ANSWER_WRITE_SINGLE_COIL_REQUEST] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletRS485.FUNCTION_MODBUS_MASTER_WRITE_SINGLE_COIL] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRS485.FUNCTION_MODBUS_SLAVE_ANSWER_WRITE_SINGLE_REGISTER_REQUEST] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletRS485.FUNCTION_MODBUS_MASTER_WRITE_SINGLE_REGISTER] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRS485.FUNCTION_MODBUS_SLAVE_ANSWER_WRITE_MULTIPLE_COILS_REQUEST] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletRS485.FUNCTION_MODBUS_MASTER_WRITE_MULTIPLE_COILS_LOW_LEVEL] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRS485.FUNCTION_MODBUS_SLAVE_ANSWER_WRITE_MULTIPLE_REGISTERS_REQUEST] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletRS485.FUNCTION_MODBUS_MASTER_WRITE_MULTIPLE_REGISTERS_LOW_LEVEL] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRS485.FUNCTION_MODBUS_SLAVE_ANSWER_READ_DISCRETE_INPUTS_REQUEST_LOW_LEVEL] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletRS485.FUNCTION_MODBUS_MASTER_READ_DISCRETE_INPUTS] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRS485.FUNCTION_MODBUS_SLAVE_ANSWER_READ_INPUT_REGISTERS_REQUEST_LOW_LEVEL] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletRS485.FUNCTION_MODBUS_MASTER_READ_INPUT_REGISTERS] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRS485.FUNCTION_SET_FRAME_READABLE_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletRS485.FUNCTION_GET_FRAME_READABLE_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRS485.FUNCTION_GET_SPITFP_ERROR_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRS485.FUNCTION_SET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRS485.FUNCTION_GET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRS485.FUNCTION_SET_WRITE_FIRMWARE_POINTER] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletRS485.FUNCTION_WRITE_FIRMWARE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRS485.FUNCTION_SET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletRS485.FUNCTION_GET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRS485.FUNCTION_GET_CHIP_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRS485.FUNCTION_RESET] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletRS485.FUNCTION_WRITE_UID] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletRS485.FUNCTION_READ_UID] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRS485.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletRS485.CALLBACK_READ_LOW_LEVEL] = [72, 'H H c60'];
	this.callbackFormats[BrickletRS485.CALLBACK_ERROR_COUNT] = [16, 'I I'];
	this.callbackFormats[BrickletRS485.CALLBACK_MODBUS_SLAVE_READ_COILS_REQUEST] = [15, 'B I H'];
	this.callbackFormats[BrickletRS485.CALLBACK_MODBUS_MASTER_READ_COILS_RESPONSE_LOW_LEVEL] = [72, 'B b H H ?464'];
	this.callbackFormats[BrickletRS485.CALLBACK_MODBUS_SLAVE_READ_HOLDING_REGISTERS_REQUEST] = [15, 'B I H'];
	this.callbackFormats[BrickletRS485.CALLBACK_MODBUS_MASTER_READ_HOLDING_REGISTERS_RESPONSE_LOW_LEVEL] = [72, 'B b H H H29'];
	this.callbackFormats[BrickletRS485.CALLBACK_MODBUS_SLAVE_WRITE_SINGLE_COIL_REQUEST] = [14, 'B I ?'];
	this.callbackFormats[BrickletRS485.CALLBACK_MODBUS_MASTER_WRITE_SINGLE_COIL_RESPONSE] = [10, 'B b'];
	this.callbackFormats[BrickletRS485.CALLBACK_MODBUS_SLAVE_WRITE_SINGLE_REGISTER_REQUEST] = [15, 'B I H'];
	this.callbackFormats[BrickletRS485.CALLBACK_MODBUS_MASTER_WRITE_SINGLE_REGISTER_RESPONSE] = [10, 'B b'];
	this.callbackFormats[BrickletRS485.CALLBACK_MODBUS_SLAVE_WRITE_MULTIPLE_COILS_REQUEST_LOW_LEVEL] = [72, 'B I H H ?440'];
	this.callbackFormats[BrickletRS485.CALLBACK_MODBUS_MASTER_WRITE_MULTIPLE_COILS_RESPONSE] = [10, 'B b'];
	this.callbackFormats[BrickletRS485.CALLBACK_MODBUS_SLAVE_WRITE_MULTIPLE_REGISTERS_REQUEST_LOW_LEVEL] = [71, 'B I H H H27'];
	this.callbackFormats[BrickletRS485.CALLBACK_MODBUS_MASTER_WRITE_MULTIPLE_REGISTERS_RESPONSE] = [10, 'B b'];
	this.callbackFormats[BrickletRS485.CALLBACK_MODBUS_SLAVE_READ_DISCRETE_INPUTS_REQUEST] = [15, 'B I H'];
	this.callbackFormats[BrickletRS485.CALLBACK_MODBUS_MASTER_READ_DISCRETE_INPUTS_RESPONSE_LOW_LEVEL] = [72, 'B b H H ?464'];
	this.callbackFormats[BrickletRS485.CALLBACK_MODBUS_SLAVE_READ_INPUT_REGISTERS_REQUEST] = [15, 'B I H'];
	this.callbackFormats[BrickletRS485.CALLBACK_MODBUS_MASTER_READ_INPUT_REGISTERS_RESPONSE_LOW_LEVEL] = [72, 'B b H H H29'];
	this.callbackFormats[BrickletRS485.CALLBACK_FRAME_READABLE] = [10, 'H'];

	this.highLevelCallbacks[BrickletRS485.CALLBACK_READ] = [['streamLength', 'streamChunkOffset', 'streamChunkData'], {'fixedLength': null, 'singleChunk': false}, null];
	this.highLevelCallbacks[BrickletRS485.CALLBACK_MODBUS_MASTER_READ_COILS_RESPONSE] = [[null, null, 'streamLength', 'streamChunkOffset', 'streamChunkData'], {'fixedLength': null, 'singleChunk': false}, null];
	this.highLevelCallbacks[BrickletRS485.CALLBACK_MODBUS_MASTER_READ_HOLDING_REGISTERS_RESPONSE] = [[null, null, 'streamLength', 'streamChunkOffset', 'streamChunkData'], {'fixedLength': null, 'singleChunk': false}, null];
	this.highLevelCallbacks[BrickletRS485.CALLBACK_MODBUS_SLAVE_WRITE_MULTIPLE_COILS_REQUEST] = [[null, null, 'streamLength', 'streamChunkOffset', 'streamChunkData'], {'fixedLength': null, 'singleChunk': false}, null];
	this.highLevelCallbacks[BrickletRS485.CALLBACK_MODBUS_SLAVE_WRITE_MULTIPLE_REGISTERS_REQUEST] = [[null, null, 'streamLength', 'streamChunkOffset', 'streamChunkData'], {'fixedLength': null, 'singleChunk': false}, null];
	this.highLevelCallbacks[BrickletRS485.CALLBACK_MODBUS_MASTER_READ_DISCRETE_INPUTS_RESPONSE] = [[null, null, 'streamLength', 'streamChunkOffset', 'streamChunkData'], {'fixedLength': null, 'singleChunk': false}, null];
	this.highLevelCallbacks[BrickletRS485.CALLBACK_MODBUS_MASTER_READ_INPUT_REGISTERS_RESPONSE] = [[null, null, 'streamLength', 'streamChunkOffset', 'streamChunkData'], {'fixedLength': null, 'singleChunk': false}, null];

	this.streamStateObjects[BrickletRS485.FUNCTION_WRITE_LOW_LEVEL] = {
		'dataMapping': ['streamChunkWritten'],
		'dataMappingStreamIn': ['streamLength', 'streamChunkOffset', 'streamChunkData'],
		'streamProperties': {
			'fixedLength': null,
			'singleChunk': false,
			'shortWrite': true
		},
		'responseProperties': {
			'running': false,
			'runningSubcall': false,
			'runningSubcallOOS': false,
			'waitingFirstChunk': true,
			'timeout': null,
			'data': [],
			'streamInChunkOffset': 0,
			'streamInChunkLength': 0,
			'streamInResponseEmpty': false,
			'streamInWritten': 0,
			'streamInLLParams': null,
			'responseHandler': null,
			'packFormatString': 'H H c60',
			'unpackFormatString': 'B',
			'returnCB': null,
			'errorCB': null,
			'callQueue': []
		}
	};
	this.streamStateObjects[BrickletRS485.FUNCTION_READ_LOW_LEVEL] = {
		'dataMapping': ['streamLength', 'streamChunkOffset', 'streamChunkData'],
		'dataMappingStreamIn': [],
		'streamProperties': {
			'fixedLength': null,
			'singleChunk': false,
			'shortWrite': false
		},
		'responseProperties': {
			'running': false,
			'runningSubcall': false,
			'runningSubcallOOS': false,
			'waitingFirstChunk': true,
			'timeout': null,
			'data': [],
			'streamInChunkOffset': 0,
			'streamInChunkLength': 0,
			'streamInResponseEmpty': true,
			'streamInWritten': 0,
			'streamInLLParams': null,
			'responseHandler': null,
			'packFormatString': 'H',
			'unpackFormatString': 'H H c60',
			'returnCB': null,
			'errorCB': null,
			'callQueue': []
		}
	};
	this.streamStateObjects[BrickletRS485.FUNCTION_MODBUS_SLAVE_ANSWER_READ_COILS_REQUEST_LOW_LEVEL] = {
		'dataMapping': [],
		'dataMappingStreamIn': [null, 'streamLength', 'streamChunkOffset', 'streamChunkData'],
		'streamProperties': {
			'fixedLength': null,
			'singleChunk': false,
			'shortWrite': false
		},
		'responseProperties': {
			'running': false,
			'runningSubcall': false,
			'runningSubcallOOS': false,
			'waitingFirstChunk': true,
			'timeout': null,
			'data': [],
			'streamInChunkOffset': 0,
			'streamInChunkLength': 0,
			'streamInResponseEmpty': true,
			'streamInWritten': 0,
			'streamInLLParams': null,
			'responseHandler': null,
			'packFormatString': 'B H H ?472',
			'unpackFormatString': '',
			'returnCB': null,
			'errorCB': null,
			'callQueue': []
		}
	};
	this.streamStateObjects[BrickletRS485.FUNCTION_MODBUS_SLAVE_ANSWER_READ_HOLDING_REGISTERS_REQUEST_LOW_LEVEL] = {
		'dataMapping': [],
		'dataMappingStreamIn': [null, 'streamLength', 'streamChunkOffset', 'streamChunkData'],
		'streamProperties': {
			'fixedLength': null,
			'singleChunk': false,
			'shortWrite': false
		},
		'responseProperties': {
			'running': false,
			'runningSubcall': false,
			'runningSubcallOOS': false,
			'waitingFirstChunk': true,
			'timeout': null,
			'data': [],
			'streamInChunkOffset': 0,
			'streamInChunkLength': 0,
			'streamInResponseEmpty': true,
			'streamInWritten': 0,
			'streamInLLParams': null,
			'responseHandler': null,
			'packFormatString': 'B H H H29',
			'unpackFormatString': '',
			'returnCB': null,
			'errorCB': null,
			'callQueue': []
		}
	};
	this.streamStateObjects[BrickletRS485.FUNCTION_MODBUS_MASTER_WRITE_MULTIPLE_COILS_LOW_LEVEL] = {
		'dataMapping': [null],
		'dataMappingStreamIn': [null, null, 'streamLength', 'streamChunkOffset', 'streamChunkData'],
		'streamProperties': {
			'fixedLength': null,
			'singleChunk': false,
			'shortWrite': false
		},
		'responseProperties': {
			'running': false,
			'runningSubcall': false,
			'runningSubcallOOS': false,
			'waitingFirstChunk': true,
			'timeout': null,
			'data': [],
			'streamInChunkOffset': 0,
			'streamInChunkLength': 0,
			'streamInResponseEmpty': false,
			'streamInWritten': 0,
			'streamInLLParams': null,
			'responseHandler': null,
			'packFormatString': 'B I H H ?440',
			'unpackFormatString': 'B',
			'returnCB': null,
			'errorCB': null,
			'callQueue': []
		}
	};
	this.streamStateObjects[BrickletRS485.FUNCTION_MODBUS_MASTER_WRITE_MULTIPLE_REGISTERS_LOW_LEVEL] = {
		'dataMapping': [null],
		'dataMappingStreamIn': [null, null, 'streamLength', 'streamChunkOffset', 'streamChunkData'],
		'streamProperties': {
			'fixedLength': null,
			'singleChunk': false,
			'shortWrite': false
		},
		'responseProperties': {
			'running': false,
			'runningSubcall': false,
			'runningSubcallOOS': false,
			'waitingFirstChunk': true,
			'timeout': null,
			'data': [],
			'streamInChunkOffset': 0,
			'streamInChunkLength': 0,
			'streamInResponseEmpty': false,
			'streamInWritten': 0,
			'streamInLLParams': null,
			'responseHandler': null,
			'packFormatString': 'B I H H H27',
			'unpackFormatString': 'B',
			'returnCB': null,
			'errorCB': null,
			'callQueue': []
		}
	};
	this.streamStateObjects[BrickletRS485.FUNCTION_MODBUS_SLAVE_ANSWER_READ_DISCRETE_INPUTS_REQUEST_LOW_LEVEL] = {
		'dataMapping': [],
		'dataMappingStreamIn': [null, 'streamLength', 'streamChunkOffset', 'streamChunkData'],
		'streamProperties': {
			'fixedLength': null,
			'singleChunk': false,
			'shortWrite': false
		},
		'responseProperties': {
			'running': false,
			'runningSubcall': false,
			'runningSubcallOOS': false,
			'waitingFirstChunk': true,
			'timeout': null,
			'data': [],
			'streamInChunkOffset': 0,
			'streamInChunkLength': 0,
			'streamInResponseEmpty': true,
			'streamInWritten': 0,
			'streamInLLParams': null,
			'responseHandler': null,
			'packFormatString': 'B H H ?472',
			'unpackFormatString': '',
			'returnCB': null,
			'errorCB': null,
			'callQueue': []
		}
	};
	this.streamStateObjects[BrickletRS485.FUNCTION_MODBUS_SLAVE_ANSWER_READ_INPUT_REGISTERS_REQUEST_LOW_LEVEL] = {
		'dataMapping': [],
		'dataMappingStreamIn': [null, 'streamLength', 'streamChunkOffset', 'streamChunkData'],
		'streamProperties': {
			'fixedLength': null,
			'singleChunk': false,
			'shortWrite': false
		},
		'responseProperties': {
			'running': false,
			'runningSubcall': false,
			'runningSubcallOOS': false,
			'waitingFirstChunk': true,
			'timeout': null,
			'data': [],
			'streamInChunkOffset': 0,
			'streamInChunkLength': 0,
			'streamInResponseEmpty': true,
			'streamInWritten': 0,
			'streamInLLParams': null,
			'responseHandler': null,
			'packFormatString': 'B H H H29',
			'unpackFormatString': '',
			'returnCB': null,
			'errorCB': null,
			'callQueue': []
		}
	};

	this.writeLowLevel = function(messageLength, messageChunkOffset, messageChunkData, returnCallback, errorCallback) {
		/*
		Writes characters to the RS485 interface. The characters can be binary data,
		ASCII or similar is not necessary.
		
		The return value is the number of characters that were written.
		
		See :func:`Set RS485 Configuration` for configuration possibilities
		regarding baudrate, parity and so on.
		*/
		this.ipcon.sendRequest(this, BrickletRS485.FUNCTION_WRITE_LOW_LEVEL, [messageLength, messageChunkOffset, messageChunkData], 'H H c60', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.readLowLevel = function(length, returnCallback, errorCallback) {
		/*
		Returns up to *length* characters from receive buffer.
		
		Instead of polling with this function, you can also use
		callbacks. But note that this function will return available
		data only when the read callback is disabled.
		See :func:`Enable Read Callback` and :cb:`Read` callback.
		*/
		this.ipcon.sendRequest(this, BrickletRS485.FUNCTION_READ_LOW_LEVEL, [length], 'H', 72, 'H H c60', returnCallback, errorCallback, false, true);
	};
	this.enableReadCallback = function(returnCallback, errorCallback) {
		/*
		Enables the :cb:`Read` callback. This will disable the :cb:`Frame Readable` callback.
		
		By default the callback is disabled.
		*/
		this.ipcon.sendRequest(this, BrickletRS485.FUNCTION_ENABLE_READ_CALLBACK, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.disableReadCallback = function(returnCallback, errorCallback) {
		/*
		Disables the :cb:`Read` callback.
		
		By default the callback is disabled.
		*/
		this.ipcon.sendRequest(this, BrickletRS485.FUNCTION_DISABLE_READ_CALLBACK, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.isReadCallbackEnabled = function(returnCallback, errorCallback) {
		/*
		Returns *true* if the :cb:`Read` callback is enabled,
		*false* otherwise.
		*/
		this.ipcon.sendRequest(this, BrickletRS485.FUNCTION_IS_READ_CALLBACK_ENABLED, [], '', 9, '?', returnCallback, errorCallback, false, true);
	};
	this.setRS485Configuration = function(baudrate, parity, stopbits, wordlength, duplex, returnCallback, errorCallback) {
		/*
		Sets the configuration for the RS485 communication.
		*/
		this.ipcon.sendRequest(this, BrickletRS485.FUNCTION_SET_RS485_CONFIGURATION, [baudrate, parity, stopbits, wordlength, duplex], 'I B B B B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getRS485Configuration = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set RS485 Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletRS485.FUNCTION_GET_RS485_CONFIGURATION, [], '', 16, 'I B B B B', returnCallback, errorCallback, false, true);
	};
	this.setModbusConfiguration = function(slaveAddress, masterRequestTimeout, returnCallback, errorCallback) {
		/*
		Sets the configuration for the RS485 Modbus communication. Available options:
		
		* Slave Address: Address to be used as the Modbus slave address in Modbus slave mode. Valid Modbus slave address range is 1 to 247.
		* Master Request Timeout: Specifies how long the master should wait for a response from a slave when in Modbus master mode.
		*/
		this.ipcon.sendRequest(this, BrickletRS485.FUNCTION_SET_MODBUS_CONFIGURATION, [slaveAddress, masterRequestTimeout], 'B I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getModbusConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Modbus Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletRS485.FUNCTION_GET_MODBUS_CONFIGURATION, [], '', 13, 'B I', returnCallback, errorCallback, false, true);
	};
	this.setMode = function(mode, returnCallback, errorCallback) {
		/*
		Sets the mode of the Bricklet in which it operates. Available options are
		
		* RS485,
		* Modbus Master RTU and
		* Modbus Slave RTU.
		*/
		this.ipcon.sendRequest(this, BrickletRS485.FUNCTION_SET_MODE, [mode], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getMode = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Mode`.
		*/
		this.ipcon.sendRequest(this, BrickletRS485.FUNCTION_GET_MODE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setCommunicationLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Sets the communication LED configuration. By default the LED shows RS485
		communication traffic by flickering.
		
		You can also turn the LED permanently on/off or show a heartbeat.
		
		If the Bricklet is in bootloader mode, the LED is off.
		*/
		this.ipcon.sendRequest(this, BrickletRS485.FUNCTION_SET_COMMUNICATION_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getCommunicationLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Communication LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletRS485.FUNCTION_GET_COMMUNICATION_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setErrorLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Sets the error LED configuration.
		
		By default the error LED turns on if there is any error (see :cb:`Error Count`
		callback). If you call this function with the SHOW ERROR option again, the LED
		will turn off until the next error occurs.
		
		You can also turn the LED permanently on/off or show a heartbeat.
		
		If the Bricklet is in bootloader mode, the LED is off.
		*/
		this.ipcon.sendRequest(this, BrickletRS485.FUNCTION_SET_ERROR_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getErrorLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Error LED Config`.
		*/
		this.ipcon.sendRequest(this, BrickletRS485.FUNCTION_GET_ERROR_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setBufferConfig = function(sendBufferSize, receiveBufferSize, returnCallback, errorCallback) {
		/*
		Sets the send and receive buffer size in byte. In sum there is
		10240 byte (10KiB) buffer available and the minimum buffer size
		is 1024 byte (1KiB) for both.
		
		The current buffer content is lost if this function is called.
		
		The send buffer holds data that was given by :func:`Write` and
		could not be written yet. The receive buffer holds data that is
		received through RS485 but could not yet be send to the
		user, either by :func:`Read` or through :cb:`Read` callback.
		*/
		this.ipcon.sendRequest(this, BrickletRS485.FUNCTION_SET_BUFFER_CONFIG, [sendBufferSize, receiveBufferSize], 'H H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getBufferConfig = function(returnCallback, errorCallback) {
		/*
		Returns the buffer configuration as set by :func:`Set Buffer Config`.
		*/
		this.ipcon.sendRequest(this, BrickletRS485.FUNCTION_GET_BUFFER_CONFIG, [], '', 12, 'H H', returnCallback, errorCallback, false, true);
	};
	this.getBufferStatus = function(returnCallback, errorCallback) {
		/*
		Returns the currently used bytes for the send and received buffer.
		
		See :func:`Set Buffer Config` for buffer size configuration.
		*/
		this.ipcon.sendRequest(this, BrickletRS485.FUNCTION_GET_BUFFER_STATUS, [], '', 12, 'H H', returnCallback, errorCallback, false, true);
	};
	this.enableErrorCountCallback = function(returnCallback, errorCallback) {
		/*
		Enables the :cb:`Error Count` callback.
		
		By default the callback is disabled.
		*/
		this.ipcon.sendRequest(this, BrickletRS485.FUNCTION_ENABLE_ERROR_COUNT_CALLBACK, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.disableErrorCountCallback = function(returnCallback, errorCallback) {
		/*
		Disables the :cb:`Error Count` callback.
		
		By default the callback is disabled.
		*/
		this.ipcon.sendRequest(this, BrickletRS485.FUNCTION_DISABLE_ERROR_COUNT_CALLBACK, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.isErrorCountCallbackEnabled = function(returnCallback, errorCallback) {
		/*
		Returns *true* if the :cb:`Error Count` callback is enabled,
		*false* otherwise.
		*/
		this.ipcon.sendRequest(this, BrickletRS485.FUNCTION_IS_ERROR_COUNT_CALLBACK_ENABLED, [], '', 9, '?', returnCallback, errorCallback, false, true);
	};
	this.getErrorCount = function(returnCallback, errorCallback) {
		/*
		Returns the current number of overrun and parity errors.
		*/
		this.ipcon.sendRequest(this, BrickletRS485.FUNCTION_GET_ERROR_COUNT, [], '', 16, 'I I', returnCallback, errorCallback, false, true);
	};
	this.getModbusCommonErrorCount = function(returnCallback, errorCallback) {
		/*
		Returns the current number of errors occurred in Modbus mode.
		
		* Timeout Error Count: Number of timeouts occurred.
		* Checksum Error Count: Number of failures due to Modbus frame CRC16 checksum mismatch.
		* Frame Too Big Error Count: Number of times frames were rejected because they exceeded maximum Modbus frame size which is 256 bytes.
		* Illegal Function Error Count: Number of errors when an unimplemented or illegal function is requested. This corresponds to Modbus exception code 1.
		* Illegal Data Address Error Count: Number of errors due to invalid data address. This corresponds to Modbus exception code 2.
		* Illegal Data Value Error Count: Number of errors due to invalid data value. This corresponds to Modbus exception code 3.
		* Slave Device Failure Error Count: Number of errors occurred on the slave device which were unrecoverable. This corresponds to Modbus exception code 4.
		*/
		this.ipcon.sendRequest(this, BrickletRS485.FUNCTION_GET_MODBUS_COMMON_ERROR_COUNT, [], '', 36, 'I I I I I I I', returnCallback, errorCallback, false, true);
	};
	this.modbusSlaveReportException = function(requestID, exceptionCode, returnCallback, errorCallback) {
		/*
		In Modbus slave mode this function can be used to report a Modbus exception for
		a Modbus master request.
		
		* Request ID: Request ID of the request received by the slave.
		* Exception Code: Modbus exception code to report to the Modbus master.
		*/
		this.ipcon.sendRequest(this, BrickletRS485.FUNCTION_MODBUS_SLAVE_REPORT_EXCEPTION, [requestID, exceptionCode], 'B b', 0, '', returnCallback, errorCallback, false, true);
	};
	this.modbusSlaveAnswerReadCoilsRequestLowLevel = function(requestID, coilsLength, coilsChunkOffset, coilsChunkData, returnCallback, errorCallback) {
		/*
		In Modbus slave mode this function can be used to answer a master request to
		read coils.
		
		* Request ID: Request ID of the corresponding request that is being answered.
		* Coils: Data that is to be sent to the Modbus master for the corresponding request.
		
		This function must be called from the :cb:`Modbus Slave Read Coils Request` callback
		with the Request ID as provided by the argument of the callback.
		*/
		this.ipcon.sendRequest(this, BrickletRS485.FUNCTION_MODBUS_SLAVE_ANSWER_READ_COILS_REQUEST_LOW_LEVEL, [requestID, coilsLength, coilsChunkOffset, coilsChunkData], 'B H H ?472', 0, '', returnCallback, errorCallback, false, true);
	};
	this.modbusMasterReadCoils = function(slaveAddress, startingAddress, count, returnCallback, errorCallback) {
		/*
		In Modbus master mode this function can be used to read coils from a slave. This
		function creates a Modbus function code 1 request.
		
		* Slave Address: Address of the target Modbus slave.
		* Starting Address: Number of the first coil to read. For backwards compatibility reasons this parameter is called Starting Address. It is not an address, but instead a coil number in the range of 1 to 65536.
		* Count: Number of coils to read.
		
		Upon success the function will return a non-zero request ID which will represent
		the current request initiated by the Modbus master. In case of failure the returned
		request ID will be 0.
		
		When successful this function will also invoke the :cb:`Modbus Master Read Coils Response`
		callback. In this callback the Request ID provided by the callback argument must be
		matched with the Request ID returned from this function to verify that the callback
		is indeed for a particular request.
		*/
		this.ipcon.sendRequest(this, BrickletRS485.FUNCTION_MODBUS_MASTER_READ_COILS, [slaveAddress, startingAddress, count], 'B I H', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.modbusSlaveAnswerReadHoldingRegistersRequestLowLevel = function(requestID, holdingRegistersLength, holdingRegistersChunkOffset, holdingRegistersChunkData, returnCallback, errorCallback) {
		/*
		In Modbus slave mode this function can be used to answer a master request to
		read holding registers.
		
		* Request ID: Request ID of the corresponding request that is being answered.
		* Holding Registers: Data that is to be sent to the Modbus master for the corresponding request.
		
		This function must be called from the :cb:`Modbus Slave Read Holding Registers Request`
		callback with the Request ID as provided by the argument of the callback.
		*/
		this.ipcon.sendRequest(this, BrickletRS485.FUNCTION_MODBUS_SLAVE_ANSWER_READ_HOLDING_REGISTERS_REQUEST_LOW_LEVEL, [requestID, holdingRegistersLength, holdingRegistersChunkOffset, holdingRegistersChunkData], 'B H H H29', 0, '', returnCallback, errorCallback, false, true);
	};
	this.modbusMasterReadHoldingRegisters = function(slaveAddress, startingAddress, count, returnCallback, errorCallback) {
		/*
		In Modbus master mode this function can be used to read holding registers from a slave.
		This function creates a Modbus function code 3 request.
		
		* Slave Address: Address of the target Modbus slave.
		* Starting Address: Number of the first holding register to read. For backwards compatibility reasons this parameter is called Starting Address. It is not an address, but instead a holding register number in the range of 1 to 65536. The prefix digit 4 (for holding register) is implicit and must be omitted.
		* Count: Number of holding registers to read.
		
		Upon success the function will return a non-zero request ID which will represent
		the current request initiated by the Modbus master. In case of failure the returned
		request ID will be 0.
		
		When successful this function will also invoke the :cb:`Modbus Master Read Holding Registers Response`
		callback. In this callback the Request ID provided by the callback argument must be matched
		with the Request ID returned from this function to verify that the callback is indeed for a
		particular request.
		*/
		this.ipcon.sendRequest(this, BrickletRS485.FUNCTION_MODBUS_MASTER_READ_HOLDING_REGISTERS, [slaveAddress, startingAddress, count], 'B I H', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.modbusSlaveAnswerWriteSingleCoilRequest = function(requestID, returnCallback, errorCallback) {
		/*
		In Modbus slave mode this function can be used to answer a master request to
		write a single coil.
		
		* Request ID: Request ID of the corresponding request that is being answered.
		
		This function must be called from the :cb:`Modbus Slave Write Single Coil Request`
		callback with the Request ID as provided by the arguments of the callback.
		*/
		this.ipcon.sendRequest(this, BrickletRS485.FUNCTION_MODBUS_SLAVE_ANSWER_WRITE_SINGLE_COIL_REQUEST, [requestID], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.modbusMasterWriteSingleCoil = function(slaveAddress, coilAddress, coilValue, returnCallback, errorCallback) {
		/*
		In Modbus master mode this function can be used to write a single coil of a slave.
		This function creates a Modbus function code 5 request.
		
		* Slave Address: Address of the target Modbus slave.
		* Coil Address: Number of the coil to be written. For backwards compatibility reasons, this parameter is called Starting Address. It is not an address, but instead a coil number in the range of 1 to 65536.
		* Coil Value: Value to be written.
		
		Upon success the function will return a non-zero request ID which will represent
		the current request initiated by the Modbus master. In case of failure the returned
		request ID will be 0.
		
		When successful this function will also invoke the :cb:`Modbus Master Write Single Coil Response`
		callback. In this callback the Request ID provided by the callback argument must be matched
		with the Request ID returned from this function to verify that the callback is indeed for a
		particular request.
		*/
		this.ipcon.sendRequest(this, BrickletRS485.FUNCTION_MODBUS_MASTER_WRITE_SINGLE_COIL, [slaveAddress, coilAddress, coilValue], 'B I ?', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.modbusSlaveAnswerWriteSingleRegisterRequest = function(requestID, returnCallback, errorCallback) {
		/*
		In Modbus slave mode this function can be used to answer a master request to
		write a single register.
		
		* Request ID: Request ID of the corresponding request that is being answered.
		
		This function must be called from the :cb:`Modbus Slave Write Single Register Request`
		callback with the Request ID, Register Address and Register Value as provided by
		the arguments of the callback.
		*/
		this.ipcon.sendRequest(this, BrickletRS485.FUNCTION_MODBUS_SLAVE_ANSWER_WRITE_SINGLE_REGISTER_REQUEST, [requestID], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.modbusMasterWriteSingleRegister = function(slaveAddress, registerAddress, registerValue, returnCallback, errorCallback) {
		/*
		In Modbus master mode this function can be used to write a single holding register of a
		slave. This function creates a Modbus function code 6 request.
		
		* Slave Address: Address of the target Modbus slave.
		* Register Address: Number of the holding register to be written. For backwards compatibility reasons, this parameter is called Starting Address. It is not an address, but instead a holding register number in the range of 1 to 65536. The prefix digit 4 (for holding register) is implicit and must be omitted.
		* Register Value: Value to be written.
		
		Upon success the function will return a non-zero request ID which will represent
		the current request initiated by the Modbus master. In case of failure the returned
		request ID will be 0.
		
		When successful this function will also invoke the :cb:`Modbus Master Write Single Register Response`
		callback. In this callback the Request ID provided by the callback argument must be matched
		with the Request ID returned from this function to verify that the callback is indeed for a
		particular request.
		*/
		this.ipcon.sendRequest(this, BrickletRS485.FUNCTION_MODBUS_MASTER_WRITE_SINGLE_REGISTER, [slaveAddress, registerAddress, registerValue], 'B I H', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.modbusSlaveAnswerWriteMultipleCoilsRequest = function(requestID, returnCallback, errorCallback) {
		/*
		In Modbus slave mode this function can be used to answer a master request to
		write multiple coils.
		
		* Request ID: Request ID of the corresponding request that is being answered.
		
		This function must be called from the :cb:`Modbus Slave Write Multiple Coils Request`
		callback with the Request ID of the callback.
		*/
		this.ipcon.sendRequest(this, BrickletRS485.FUNCTION_MODBUS_SLAVE_ANSWER_WRITE_MULTIPLE_COILS_REQUEST, [requestID], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.modbusMasterWriteMultipleCoilsLowLevel = function(slaveAddress, startingAddress, coilsLength, coilsChunkOffset, coilsChunkData, returnCallback, errorCallback) {
		/*
		In Modbus master mode this function can be used to write multiple coils of a slave.
		This function creates a Modbus function code 15 request.
		
		* Slave Address: Address of the target Modbus slave.
		* Starting Address: Number of the first coil to write. For backwards compatibility reasons, this parameter is called Starting Address.It is not an address, but instead a coil number in the range of 1 to 65536.
		
		Upon success the function will return a non-zero request ID which will represent
		the current request initiated by the Modbus master. In case of failure the returned
		request ID will be 0.
		
		When successful this function will also invoke the :cb:`Modbus Master Write Multiple Coils Response`
		callback. In this callback the Request ID provided by the callback argument must be matched
		with the Request ID returned from this function to verify that the callback is indeed for a
		particular request.
		*/
		this.ipcon.sendRequest(this, BrickletRS485.FUNCTION_MODBUS_MASTER_WRITE_MULTIPLE_COILS_LOW_LEVEL, [slaveAddress, startingAddress, coilsLength, coilsChunkOffset, coilsChunkData], 'B I H H ?440', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.modbusSlaveAnswerWriteMultipleRegistersRequest = function(requestID, returnCallback, errorCallback) {
		/*
		In Modbus slave mode this function can be used to answer a master request to
		write multiple registers.
		
		* Request ID: Request ID of the corresponding request that is being answered.
		
		This function must be called from the :cb:`Modbus Slave Write Multiple Registers Request`
		callback with the Request ID of the callback.
		*/
		this.ipcon.sendRequest(this, BrickletRS485.FUNCTION_MODBUS_SLAVE_ANSWER_WRITE_MULTIPLE_REGISTERS_REQUEST, [requestID], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.modbusMasterWriteMultipleRegistersLowLevel = function(slaveAddress, startingAddress, registersLength, registersChunkOffset, registersChunkData, returnCallback, errorCallback) {
		/*
		In Modbus master mode this function can be used to write multiple registers of a slave.
		This function creates a Modbus function code 16 request.
		
		* Slave Address: Address of the target Modbus slave.
		* Starting Address: Number of the first holding register to write. For backwards compatibility reasons, this parameter is called Starting Address. It is not an address, but instead a holding register number in the range of 1 to 65536. The prefix digit 4 (for holding register) is implicit and must be omitted.
		
		Upon success the function will return a non-zero request ID which will represent
		the current request initiated by the Modbus master. In case of failure the returned
		request ID will be 0.
		
		When successful this function will also invoke the :cb:`Modbus Master Write Multiple Registers Response`
		callback. In this callback the Request ID provided by the callback argument must be matched
		with the Request ID returned from this function to verify that the callback is indeed for a
		particular request.
		*/
		this.ipcon.sendRequest(this, BrickletRS485.FUNCTION_MODBUS_MASTER_WRITE_MULTIPLE_REGISTERS_LOW_LEVEL, [slaveAddress, startingAddress, registersLength, registersChunkOffset, registersChunkData], 'B I H H H27', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.modbusSlaveAnswerReadDiscreteInputsRequestLowLevel = function(requestID, discreteInputsLength, discreteInputsChunkOffset, discreteInputsChunkData, returnCallback, errorCallback) {
		/*
		In Modbus slave mode this function can be used to answer a master request to
		read discrete inputs.
		
		* Request ID: Request ID of the corresponding request that is being answered.
		* Discrete Inputs: Data that is to be sent to the Modbus master for the corresponding request.
		
		This function must be called from the :cb:`Modbus Slave Read Discrete Inputs Request`
		callback with the Request ID as provided by the argument of the callback.
		*/
		this.ipcon.sendRequest(this, BrickletRS485.FUNCTION_MODBUS_SLAVE_ANSWER_READ_DISCRETE_INPUTS_REQUEST_LOW_LEVEL, [requestID, discreteInputsLength, discreteInputsChunkOffset, discreteInputsChunkData], 'B H H ?472', 0, '', returnCallback, errorCallback, false, true);
	};
	this.modbusMasterReadDiscreteInputs = function(slaveAddress, startingAddress, count, returnCallback, errorCallback) {
		/*
		In Modbus master mode this function can be used to read discrete inputs from a slave.
		This function creates a Modbus function code 2 request.
		
		* Slave Address: Address of the target Modbus slave.
		* Starting Address: Number of the first discrete input to read. For backwards compatibility reasons, this parameter is called Starting Address. It is not an address, but instead a discrete input number in the range of 1 to 65536. The prefix digit 1 (for discrete input) is implicit and must be omitted.
		* Count: Number of discrete inputs to read.
		
		Upon success the function will return a non-zero request ID which will represent
		the current request initiated by the Modbus master. In case of failure the returned
		request ID will be 0.
		
		When successful this function will also invoke the :cb:`Modbus Master Read Discrete Inputs Response`
		callback. In this callback the Request ID provided by the callback argument must be matched
		with the Request ID returned from this function to verify that the callback is indeed for a
		particular request.
		*/
		this.ipcon.sendRequest(this, BrickletRS485.FUNCTION_MODBUS_MASTER_READ_DISCRETE_INPUTS, [slaveAddress, startingAddress, count], 'B I H', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.modbusSlaveAnswerReadInputRegistersRequestLowLevel = function(requestID, inputRegistersLength, inputRegistersChunkOffset, inputRegistersChunkData, returnCallback, errorCallback) {
		/*
		In Modbus slave mode this function can be used to answer a master request to
		read input registers.
		
		* Request ID: Request ID of the corresponding request that is being answered.
		* Input Registers: Data that is to be sent to the Modbus master for the corresponding request.
		
		This function must be called from the :cb:`Modbus Slave Read Input Registers Request` callback
		with the Request ID as provided by the argument of the callback.
		*/
		this.ipcon.sendRequest(this, BrickletRS485.FUNCTION_MODBUS_SLAVE_ANSWER_READ_INPUT_REGISTERS_REQUEST_LOW_LEVEL, [requestID, inputRegistersLength, inputRegistersChunkOffset, inputRegistersChunkData], 'B H H H29', 0, '', returnCallback, errorCallback, false, true);
	};
	this.modbusMasterReadInputRegisters = function(slaveAddress, startingAddress, count, returnCallback, errorCallback) {
		/*
		In Modbus master mode this function can be used to read input registers from a slave.
		This function creates a Modbus function code 4 request.
		
		* Slave Address: Address of the target Modbus slave.
		* Starting Address: Number of the first input register to read. For backwards compatibility reasons, this parameter is called Starting Address. It is not an address, but instead an input register number in the range of 1 to 65536. The prefix digit 3 (for input register) is implicit and must be omitted.
		* Count: Number of input registers to read.
		
		Upon success the function will return a non-zero request ID which will represent
		the current request initiated by the Modbus master. In case of failure the returned
		request ID will be 0.
		
		When successful this function will also invoke the :cb:`Modbus Master Read Input Registers Response`
		callback. In this callback the Request ID provided by the callback argument must be matched
		with the Request ID returned from this function to verify that the callback is indeed for a
		particular request.
		*/
		this.ipcon.sendRequest(this, BrickletRS485.FUNCTION_MODBUS_MASTER_READ_INPUT_REGISTERS, [slaveAddress, startingAddress, count], 'B I H', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setFrameReadableCallbackConfiguration = function(frameSize, returnCallback, errorCallback) {
		/*
		Configures the :cb:`Frame Readable` callback. The frame size is the number of bytes, that have to be readable to trigger the callback.
		A frame size of 0 disables the callback. A frame size greater than 0 enables the callback and disables the :cb:`Read` callback.
		
		By default the callback is disabled.
		
		.. versionadded:: 2.0.5$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletRS485.FUNCTION_SET_FRAME_READABLE_CALLBACK_CONFIGURATION, [frameSize], 'H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getFrameReadableCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the callback configuration as set by :func:`Set Frame Readable Callback Configuration`.
		
		.. versionadded:: 2.0.5$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletRS485.FUNCTION_GET_FRAME_READABLE_CALLBACK_CONFIGURATION, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPErrorCount = function(returnCallback, errorCallback) {
		/*
		Returns the error count for the communication between Brick and Bricklet.
		
		The errors are divided into
		
		* ACK checksum errors,
		* message checksum errors,
		* framing errors and
		* overflow errors.
		
		The errors counts are for errors that occur on the Bricklet side. All
		Bricks have a similar function that returns the errors on the Brick side.
		*/
		this.ipcon.sendRequest(this, BrickletRS485.FUNCTION_GET_SPITFP_ERROR_COUNT, [], '', 24, 'I I I I', returnCallback, errorCallback, false, true);
	};
	this.setBootloaderMode = function(mode, returnCallback, errorCallback) {
		/*
		Sets the bootloader mode and returns the status after the requested
		mode change was instigated.
		
		You can change from bootloader mode to firmware mode and vice versa. A change
		from bootloader mode to firmware mode will only take place if the entry function,
		device identifier and CRC are present and correct.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletRS485.FUNCTION_SET_BOOTLOADER_MODE, [mode], 'B', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getBootloaderMode = function(returnCallback, errorCallback) {
		/*
		Returns the current bootloader mode, see :func:`Set Bootloader Mode`.
		*/
		this.ipcon.sendRequest(this, BrickletRS485.FUNCTION_GET_BOOTLOADER_MODE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setWriteFirmwarePointer = function(pointer, returnCallback, errorCallback) {
		/*
		Sets the firmware pointer for :func:`Write Firmware`. The pointer has
		to be increased by chunks of size 64. The data is written to flash
		every 4 chunks (which equals to one page of size 256).
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletRS485.FUNCTION_SET_WRITE_FIRMWARE_POINTER, [pointer], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeFirmware = function(data, returnCallback, errorCallback) {
		/*
		Writes 64 Bytes of firmware at the position as written by
		:func:`Set Write Firmware Pointer` before. The firmware is written
		to flash every 4 chunks.
		
		You can only write firmware in bootloader mode.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletRS485.FUNCTION_WRITE_FIRMWARE, [data], 'B64', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setStatusLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Sets the status LED configuration. By default the LED shows
		communication traffic between Brick and Bricklet, it flickers once
		for every 10 received data packets.
		
		You can also turn the LED permanently on/off or show a heartbeat.
		
		If the Bricklet is in bootloader mode, the LED is will show heartbeat by default.
		*/
		this.ipcon.sendRequest(this, BrickletRS485.FUNCTION_SET_STATUS_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getStatusLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Status LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletRS485.FUNCTION_GET_STATUS_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getChipTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature as measured inside the microcontroller. The
		value returned is not the ambient temperature!
		
		The temperature is only proportional to the real temperature and it has bad
		accuracy. Practically it is only useful as an indicator for
		temperature changes.
		*/
		this.ipcon.sendRequest(this, BrickletRS485.FUNCTION_GET_CHIP_TEMPERATURE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.reset = function(returnCallback, errorCallback) {
		/*
		Calling this function will reset the Bricklet. All configurations
		will be lost.
		
		After a reset you have to create new device objects,
		calling functions on the existing ones will result in
		undefined behavior!
		*/
		this.ipcon.sendRequest(this, BrickletRS485.FUNCTION_RESET, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeUID = function(uid, returnCallback, errorCallback) {
		/*
		Writes a new UID into flash. If you want to set a new UID
		you have to decode the Base58 encoded UID string into an
		integer first.
		
		We recommend that you use Brick Viewer to change the UID.
		*/
		this.ipcon.sendRequest(this, BrickletRS485.FUNCTION_WRITE_UID, [uid], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.readUID = function(returnCallback, errorCallback) {
		/*
		Returns the current UID as an integer. Encode as
		Base58 to get the usual string version.
		*/
		this.ipcon.sendRequest(this, BrickletRS485.FUNCTION_READ_UID, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletRS485.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};
	this.write = function(message, returnCallback, errorCallback) {
		/*
		Writes characters to the RS485 interface. The characters can be binary data,
		ASCII or similar is not necessary.
		
		The return value is the number of characters that were written.
		
		See :func:`Set RS485 Configuration` for configuration possibilities
		regarding baudrate, parity and so on.
		*/

		var messageLength = 0;
		var messageChunkData = [];
		var messageChunkOffset = 0;
		var streamStateObject = this.streamStateObjects[1];

		if (message.length > 65535) {
			if (errorCallback !== null){
				errorCallback(IPConnection.ERROR_INVALID_PARAMETER);
			}

			this.resetStreamStateObject(streamStateObject);

			if (streamStateObject['responseProperties']['callQueue'].length > 0) {
				streamStateObject['responseProperties']['callQueue'].shift()(device);
			}

			return;
		}

		if (!this.getResponseExpected(1)) {
			if (streamStateObject['streamProperties']['fixedLength']) {
				messageLength = streamStateObject['streamProperties']['fixedLength'];
			}
			else {
				messageLength = message.length;
			}

			if (streamStateObject['streamProperties']['singleChunk']) {
				messageChunkData =
					this.ipcon.createChunkData(message, 0, 60, '\0');

				this.ipcon.sendRequest(this,
				                       BrickletRS485.FUNCTION_WRITE_LOW_LEVEL,
				                       [messageLength, messageChunkOffset, messageChunkData],
				                       'H H c60',
				                       9,
				                       'B',
				                       returnCallback,
				                       errorCallback,
				                       false,
				                       true);
			}
			else {
				while (messageChunkOffset < message.length) {
					messageChunkData =
						this.ipcon.createChunkData(message, messageChunkOffset, 60, '\0');

					this.ipcon.sendRequest(this,
					                       BrickletRS485.FUNCTION_WRITE_LOW_LEVEL,
					                       [messageLength, messageChunkOffset, messageChunkData],
					                       'H H c60',
					                       9,
					                       'B',
					                       returnCallback,
					                       errorCallback,
					                       false,
					                       true);

					messageChunkOffset += 60;
				}
			}

			if (returnCallback) {
				returnCallback();
			}
		}
		else {
			var responseHandler = null;
			var functionToQueue = null;

			if (streamStateObject['responseProperties']['responseHandler'] === null) {
				responseHandler = function (device, fid, packetResponse) {
					var result = [];
					var payload = null;
					var llvalues = null;
					var packetErrorFlag = 0;
					var rolesMappedData = [];
					var shortWriteWritten = -1;
					var streamStateObject = device.streamStateObjects[fid];
					var responseEmpty = streamStateObject['responseProperties']['streamInResponseEmpty'];
					var messageLength = 0;
					var messageChunkData = [];
					var messageChunkOffset = 0;

					function doNextLLCall() {
						messageLength = streamStateObject['responseProperties']['data'].length;
						messageChunkData =
							device.ipcon.createChunkData(streamStateObject['responseProperties']['data'],
							                             streamStateObject['responseProperties']['streamInChunkOffset'],
							                             streamStateObject['responseProperties']['streamInChunkLength'],
							                             '\0');
						messageChunkOffset = streamStateObject['responseProperties']['streamInChunkOffset'];

						for (var i = 0; i < streamStateObject['dataMappingStreamIn'].length; i++) {
							if (streamStateObject['dataMappingStreamIn'][i] === null) {
								continue;
							}

							if (streamStateObject['dataMappingStreamIn'][i].endsWith('Length')) {
								streamStateObject['responseProperties']['streamInLLParams'][i] = messageLength;
							}
							else if (streamStateObject['dataMappingStreamIn'][i].endsWith('Offset')) {
								streamStateObject['responseProperties']['streamInLLParams'][i] = messageChunkOffset;
							}
							else if (streamStateObject['dataMappingStreamIn'][i].endsWith('Data')) {
								streamStateObject['responseProperties']['streamInLLParams'][i] = messageChunkData;
							}
						}

						device.ipcon.sendRequest(device,
						                         BrickletRS485.FUNCTION_WRITE_LOW_LEVEL,
						                         streamStateObject['responseProperties']['streamInLLParams'],
						                         'H H c60',
						                         9,
						                         'B',
						                         returnCallback,
						                         errorCallback,
						                         true,
						                         true);

						streamStateObject['responseProperties']['streamInChunkOffset'] += 60;
					}

					function handleStreamInDone() {
						if (streamStateObject['responseProperties']['returnCB']) {
							if (streamStateObject['streamProperties']['shortWrite']) {
								for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
									if (streamStateObject['dataMapping'][i].endsWith('Written')) {
										result[i] = streamStateObject['responseProperties']['streamInWritten'];
										break;
									}
								}
							}

							if (!responseEmpty) {
								streamStateObject['responseProperties']['returnCB'].apply(device, result);
							}
							else {
								streamStateObject['responseProperties']['returnCB'].apply(device);
							}
						}

						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}
					}

					if (!streamStateObject) {
						return;
					}

					packetErrorFlag = device.ipcon.getEFromPacket(packetResponse);

					if (packetErrorFlag !== 0) {
						if (streamStateObject['responseProperties']['errorCB'] !== undefined) {
							if (packetErrorFlag === 1) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_INVALID_PARAMETER);
							}
							else if (packetErrorFlag === 2) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_FUNCTION_NOT_SUPPORTED);
							}
							else {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_UNKNOWN_ERROR);
							}
						}

						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}

						return;
					}

					if (responseEmpty) {
						if (streamStateObject['streamProperties']['singleChunk']) {
							handleStreamInDone();

							return;
						}

						if (streamStateObject['responseProperties']['streamInChunkOffset'] < streamStateObject['responseProperties']['data'].length) {
							doNextLLCall();
						}
						else {
							handleStreamInDone();
						}
					}
					else {
						payload = device.ipcon.getPayloadFromPacket(packetResponse);
						llvalues = device.ipcon.unpack(payload,
						                               streamStateObject['responseProperties']['unpackFormatString']);

						if (!payload || !llvalues) {
							device.resetStreamStateObject(streamStateObject);

							if (streamStateObject['responseProperties']['callQueue'].length > 0) {
								streamStateObject['responseProperties']['callQueue'].shift()(device);
							}

							return;
						}

						for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
							result.push(llvalues[i]);
						}

						if (streamStateObject['streamProperties']['singleChunk']) {
							if (streamStateObject['responseProperties']['returnCB']) {
								streamStateObject['responseProperties']['returnCB'].apply(device, result);
							}

							device.resetStreamStateObject(streamStateObject);

							if (streamStateObject['responseProperties']['callQueue'].length > 0) {
								streamStateObject['responseProperties']['callQueue'].shift()(device);
							}

							return;
						}

						if (streamStateObject['streamProperties']['shortWrite']) {
							for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
								if (streamStateObject['dataMapping'][i].endsWith('Written')) {
									shortWriteWritten = llvalues[i];
									streamStateObject['responseProperties']['streamInWritten'] += shortWriteWritten;
									break;
								}
							}
							if ((shortWriteWritten !== -1) && (shortWriteWritten < 60)) {
								// Either last chunk or short write
								handleStreamInDone();
								return;
							}
						}

						if (streamStateObject['responseProperties']['streamInChunkOffset'] < streamStateObject['responseProperties']['data'].length) {
							doNextLLCall();
						}
						else {
							handleStreamInDone();
						}
					}
				};

				streamStateObject['responseProperties']['responseHandler'] = responseHandler;
			}

			if (!streamStateObject['responseProperties']['running']) {
				streamStateObject['responseProperties']['running'] = true;
				streamStateObject['responseProperties']['returnCB'] = returnCallback;
				streamStateObject['responseProperties']['errorCB'] = errorCallback;
				streamStateObject['responseProperties']['data'].length = 0;
				streamStateObject['responseProperties']['data'].push.apply(streamStateObject['responseProperties']['data'],
				                                                           message);

				if (streamStateObject['streamProperties']['fixedLength']) {
					messageLength = streamStateObject['streamProperties']['fixedLength'];
				}
				else {
					messageLength = message.length;
				}

				messageChunkOffset = 0;
				messageChunkData =
					this.ipcon.createChunkData(message, 0, 60, '\0');

				streamStateObject['responseProperties']['streamInChunkOffset'] = 60;
				streamStateObject['responseProperties']['streamInChunkLength'] = 60;
				streamStateObject['responseProperties']['streamInLLParams'] = [messageLength, messageChunkOffset, messageChunkData];

				this.ipcon.sendRequest(this,
				                       BrickletRS485.FUNCTION_WRITE_LOW_LEVEL,
				                       [messageLength, messageChunkOffset, messageChunkData],
				                       'H H c60',
				                       9,
				                       'B',
				                       returnCallback,
				                       errorCallback,
				                       true,
				                       true);
			}
			else {
				functionToQueue = function (device) {
					device.write.call(device, message, returnCallback, errorCallback);
				}

				streamStateObject['responseProperties']['callQueue'].push(functionToQueue);
			}
		}
	};

	this.read = function(length, returnCallback, errorCallback) {
		/*
		Returns up to *length* characters from receive buffer.
		
		Instead of polling with this function, you can also use
		callbacks. But note that this function will return available
		data only when the read callback is disabled.
		See :func:`Enable Read Callback` and :cb:`Read` callback.
		*/
		var responseHandler = null;
		var functionToQueue = null;
		var streamStateObject = this.streamStateObjects[2];
		if (streamStateObject['responseProperties']['responseHandler'] === null) {
			responseHandler = 
				function (device, fid, packetResponse) {
					var result = [];
					var llvalues = null;
					var packetErrorFlag = 0;
					var rolesMappedData = [];
					var messageLength = null;
					var messageChunkData = null;
					var messageOutOfSync = false;
					var streamStateObject = device.streamStateObjects[fid];
					var messageChunkOffset = null;
					var payload = device.ipcon.getPayloadFromPacket(packetResponse);

					packetErrorFlag = device.ipcon.getEFromPacket(packetResponse);

					if (packetErrorFlag !== 0) {
						if (streamStateObject['responseProperties']['errorCB'] !== undefined) {
							if (packetErrorFlag === 1) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_INVALID_PARAMETER);
							}
							else if (packetErrorFlag === 2) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_FUNCTION_NOT_SUPPORTED);
							}
							else {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_UNKNOWN_ERROR);
							}
						}

						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}

						return;
					}

					if (payload.length === 0) {
						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}

						return;
					}

					llvalues = device.ipcon.unpack(payload,
					                               streamStateObject['responseProperties']['unpackFormatString']);

					for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
						if (streamStateObject['dataMapping'][i] === 'streamChunkData') {
							messageChunkData = llvalues[i];
						}
						else if (streamStateObject['dataMapping'][i] === 'streamChunkOffset') {
							messageChunkOffset = llvalues[i];
						}
					}

					for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
						if (streamStateObject['dataMapping'][i] === 'streamLength') {
							messageLength = llvalues[i];
							break;
						}
					}

					function handleOOS() {
						if ((messageChunkOffset + 60) < messageLength) {
							streamStateObject['responseProperties']['runningSubcallOOS'] = true;
							device.ipcon.sendRequest(device, BrickletRS485.FUNCTION_READ_LOW_LEVEL, [length], 'H', 72, 'H H c60', streamStateObject['responseProperties']['returnCB'], streamStateObject['responseProperties']['errorCB'], true, true);

							return;
						}

						if (streamStateObject['responseProperties']['errorCB']) {
							streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_STREAM_OUT_OF_SYNC);
						}

						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}
					}

					if (streamStateObject['responseProperties']['waitingFirstChunk']) {
						streamStateObject['responseProperties']['waitingFirstChunk'] = false;
						messageOutOfSync = (messageChunkOffset !== 0);
						streamStateObject['responseProperties']['data'] = messageChunkData;
					}

					if (!streamStateObject['responseProperties']['runningSubcallOOS']) {
						if (!streamStateObject['responseProperties']['runningSubcall']) {
							if (!messageOutOfSync &&
							    (streamStateObject['responseProperties']['data'].length < messageLength)) {
							        streamStateObject['responseProperties']['runningSubcall'] = true;
							        device.ipcon.sendRequest(device, BrickletRS485.FUNCTION_READ_LOW_LEVEL, [length], 'H', 72, 'H H c60', streamStateObject['responseProperties']['returnCB'], streamStateObject['responseProperties']['errorCB'], true, true);

							        return;
							}
						}
						else {
							messageOutOfSync =
								(messageChunkOffset !== streamStateObject['responseProperties']['data'].length);

							if (!messageOutOfSync &&
								(streamStateObject['responseProperties']['data'].length < messageLength)) {
									streamStateObject['responseProperties']['data'] =
										streamStateObject['responseProperties']['data'].concat(messageChunkData);

									if (streamStateObject['responseProperties']['data'].length >= messageLength) {
										streamStateObject['responseProperties']['data'] =
											streamStateObject['responseProperties']['data'].splice(0, messageLength);
									}
									else {
										device.ipcon.sendRequest(device, BrickletRS485.FUNCTION_READ_LOW_LEVEL, [length], 'H', 72, 'H H c60', streamStateObject['responseProperties']['returnCB'], streamStateObject['responseProperties']['errorCB'], true, true);

										return;
									}
							}
						}
					}
					else{
						handleOOS();

						return;
					}

					if (messageOutOfSync) { // Discard remaining stream to bring it back in-sync
						handleOOS();

						return;
					}

					if (streamStateObject['responseProperties']['returnCB']) {
						for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
							rolesMappedData.push({'role': streamStateObject['dataMapping'][i], 'llvalue': llvalues[i]});
						}

						for (var i = 0; i < rolesMappedData.length; i++) {
							if (rolesMappedData[i]['role'] === 'streamChunkData') {
								result.push(streamStateObject['responseProperties']['data'].splice(0, messageLength));
							}
							else if (rolesMappedData[i]['role'] === null) {
								result.push(rolesMappedData[i]['llvalue']);
							}
						}

						streamStateObject['responseProperties']['returnCB'].apply(device, result);
					}

					device.resetStreamStateObject(streamStateObject);

					if (streamStateObject['responseProperties']['callQueue'].length > 0) {
						streamStateObject['responseProperties']['callQueue'].shift()(device);
					}
					
				};

			streamStateObject['responseProperties']['responseHandler'] = responseHandler;
		}
		if (!streamStateObject['responseProperties']['running']) {
			streamStateObject['responseProperties']['running'] = true;
			streamStateObject['responseProperties']['returnCB'] = returnCallback;
			streamStateObject['responseProperties']['errorCB'] = errorCallback;
			this.ipcon.sendRequest(this,
			                       BrickletRS485.FUNCTION_READ_LOW_LEVEL,
			                       [length],
			                       'H',
			                       72,
			                       'H H c60',
			                       returnCallback,
			                       errorCallback,
			                       true,
			                       true);
		}
		else {
			functionToQueue = function (device) {
				device.read.call(device, length, returnCallback, errorCallback);
			}
			streamStateObject['responseProperties']['callQueue'].push(functionToQueue);
		}
	};
	this.modbusSlaveAnswerReadCoilsRequest = function(requestID, coils, returnCallback, errorCallback) {
		/*
		In Modbus slave mode this function can be used to answer a master request to
		read coils.
		
		* Request ID: Request ID of the corresponding request that is being answered.
		* Coils: Data that is to be sent to the Modbus master for the corresponding request.
		
		This function must be called from the :cb:`Modbus Slave Read Coils Request` callback
		with the Request ID as provided by the argument of the callback.
		*/

		var coilsLength = 0;
		var coilsChunkData = [];
		var coilsChunkOffset = 0;
		var streamStateObject = this.streamStateObjects[25];

		if (coils.length > 65535) {
			if (errorCallback !== null){
				errorCallback(IPConnection.ERROR_INVALID_PARAMETER);
			}

			this.resetStreamStateObject(streamStateObject);

			if (streamStateObject['responseProperties']['callQueue'].length > 0) {
				streamStateObject['responseProperties']['callQueue'].shift()(device);
			}

			return;
		}

		if (!this.getResponseExpected(25)) {
			if (streamStateObject['streamProperties']['fixedLength']) {
				coilsLength = streamStateObject['streamProperties']['fixedLength'];
			}
			else {
				coilsLength = coils.length;
			}

			if (streamStateObject['streamProperties']['singleChunk']) {
				coilsChunkData =
					this.ipcon.createChunkData(coils, 0, 472, '\0');

				this.ipcon.sendRequest(this,
				                       BrickletRS485.FUNCTION_MODBUS_SLAVE_ANSWER_READ_COILS_REQUEST_LOW_LEVEL,
				                       [requestID, coilsLength, coilsChunkOffset, coilsChunkData],
				                       'B H H ?472',
				                       0,
				                       '',
				                       returnCallback,
				                       errorCallback,
				                       false,
				                       true);
			}
			else {
				while (coilsChunkOffset < coils.length) {
					coilsChunkData =
						this.ipcon.createChunkData(coils, coilsChunkOffset, 472, '\0');

					this.ipcon.sendRequest(this,
					                       BrickletRS485.FUNCTION_MODBUS_SLAVE_ANSWER_READ_COILS_REQUEST_LOW_LEVEL,
					                       [requestID, coilsLength, coilsChunkOffset, coilsChunkData],
					                       'B H H ?472',
					                       0,
					                       '',
					                       returnCallback,
					                       errorCallback,
					                       false,
					                       true);

					coilsChunkOffset += 472;
				}
			}

			if (returnCallback) {
				returnCallback();
			}
		}
		else {
			var responseHandler = null;
			var functionToQueue = null;

			if (streamStateObject['responseProperties']['responseHandler'] === null) {
				responseHandler = function (device, fid, packetResponse) {
					var result = [];
					var payload = null;
					var llvalues = null;
					var packetErrorFlag = 0;
					var rolesMappedData = [];
					var shortWriteWritten = -1;
					var streamStateObject = device.streamStateObjects[fid];
					var responseEmpty = streamStateObject['responseProperties']['streamInResponseEmpty'];
					var coilsLength = 0;
					var coilsChunkData = [];
					var coilsChunkOffset = 0;

					function doNextLLCall() {
						coilsLength = streamStateObject['responseProperties']['data'].length;
						coilsChunkData =
							device.ipcon.createChunkData(streamStateObject['responseProperties']['data'],
							                             streamStateObject['responseProperties']['streamInChunkOffset'],
							                             streamStateObject['responseProperties']['streamInChunkLength'],
							                             '\0');
						coilsChunkOffset = streamStateObject['responseProperties']['streamInChunkOffset'];

						for (var i = 0; i < streamStateObject['dataMappingStreamIn'].length; i++) {
							if (streamStateObject['dataMappingStreamIn'][i] === null) {
								continue;
							}

							if (streamStateObject['dataMappingStreamIn'][i].endsWith('Length')) {
								streamStateObject['responseProperties']['streamInLLParams'][i] = coilsLength;
							}
							else if (streamStateObject['dataMappingStreamIn'][i].endsWith('Offset')) {
								streamStateObject['responseProperties']['streamInLLParams'][i] = coilsChunkOffset;
							}
							else if (streamStateObject['dataMappingStreamIn'][i].endsWith('Data')) {
								streamStateObject['responseProperties']['streamInLLParams'][i] = coilsChunkData;
							}
						}

						device.ipcon.sendRequest(device,
						                         BrickletRS485.FUNCTION_MODBUS_SLAVE_ANSWER_READ_COILS_REQUEST_LOW_LEVEL,
						                         streamStateObject['responseProperties']['streamInLLParams'],
						                         'B H H ?472',
						                         0,
						                         '',
						                         returnCallback,
						                         errorCallback,
						                         true,
						                         true);

						streamStateObject['responseProperties']['streamInChunkOffset'] += 472;
					}

					function handleStreamInDone() {
						if (streamStateObject['responseProperties']['returnCB']) {
							if (streamStateObject['streamProperties']['shortWrite']) {
								for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
									if (streamStateObject['dataMapping'][i].endsWith('Written')) {
										result[i] = streamStateObject['responseProperties']['streamInWritten'];
										break;
									}
								}
							}

							if (!responseEmpty) {
								streamStateObject['responseProperties']['returnCB'].apply(device, result);
							}
							else {
								streamStateObject['responseProperties']['returnCB'].apply(device);
							}
						}

						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}
					}

					if (!streamStateObject) {
						return;
					}

					packetErrorFlag = device.ipcon.getEFromPacket(packetResponse);

					if (packetErrorFlag !== 0) {
						if (streamStateObject['responseProperties']['errorCB'] !== undefined) {
							if (packetErrorFlag === 1) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_INVALID_PARAMETER);
							}
							else if (packetErrorFlag === 2) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_FUNCTION_NOT_SUPPORTED);
							}
							else {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_UNKNOWN_ERROR);
							}
						}

						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}

						return;
					}

					if (responseEmpty) {
						if (streamStateObject['streamProperties']['singleChunk']) {
							handleStreamInDone();

							return;
						}

						if (streamStateObject['responseProperties']['streamInChunkOffset'] < streamStateObject['responseProperties']['data'].length) {
							doNextLLCall();
						}
						else {
							handleStreamInDone();
						}
					}
					else {
						payload = device.ipcon.getPayloadFromPacket(packetResponse);
						llvalues = device.ipcon.unpack(payload,
						                               streamStateObject['responseProperties']['unpackFormatString']);

						if (!payload || !llvalues) {
							device.resetStreamStateObject(streamStateObject);

							if (streamStateObject['responseProperties']['callQueue'].length > 0) {
								streamStateObject['responseProperties']['callQueue'].shift()(device);
							}

							return;
						}

						for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
							result.push(llvalues[i]);
						}

						if (streamStateObject['streamProperties']['singleChunk']) {
							if (streamStateObject['responseProperties']['returnCB']) {
								streamStateObject['responseProperties']['returnCB'].apply(device, result);
							}

							device.resetStreamStateObject(streamStateObject);

							if (streamStateObject['responseProperties']['callQueue'].length > 0) {
								streamStateObject['responseProperties']['callQueue'].shift()(device);
							}

							return;
						}

						if (streamStateObject['streamProperties']['shortWrite']) {
							for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
								if (streamStateObject['dataMapping'][i].endsWith('Written')) {
									shortWriteWritten = llvalues[i];
									streamStateObject['responseProperties']['streamInWritten'] += shortWriteWritten;
									break;
								}
							}
							if ((shortWriteWritten !== -1) && (shortWriteWritten < 472)) {
								// Either last chunk or short write
								handleStreamInDone();
								return;
							}
						}

						if (streamStateObject['responseProperties']['streamInChunkOffset'] < streamStateObject['responseProperties']['data'].length) {
							doNextLLCall();
						}
						else {
							handleStreamInDone();
						}
					}
				};

				streamStateObject['responseProperties']['responseHandler'] = responseHandler;
			}

			if (!streamStateObject['responseProperties']['running']) {
				streamStateObject['responseProperties']['running'] = true;
				streamStateObject['responseProperties']['returnCB'] = returnCallback;
				streamStateObject['responseProperties']['errorCB'] = errorCallback;
				streamStateObject['responseProperties']['data'].length = 0;
				streamStateObject['responseProperties']['data'].push.apply(streamStateObject['responseProperties']['data'],
				                                                           coils);

				if (streamStateObject['streamProperties']['fixedLength']) {
					coilsLength = streamStateObject['streamProperties']['fixedLength'];
				}
				else {
					coilsLength = coils.length;
				}

				coilsChunkOffset = 0;
				coilsChunkData =
					this.ipcon.createChunkData(coils, 0, 472, '\0');

				streamStateObject['responseProperties']['streamInChunkOffset'] = 472;
				streamStateObject['responseProperties']['streamInChunkLength'] = 472;
				streamStateObject['responseProperties']['streamInLLParams'] = [requestID, coilsLength, coilsChunkOffset, coilsChunkData];

				this.ipcon.sendRequest(this,
				                       BrickletRS485.FUNCTION_MODBUS_SLAVE_ANSWER_READ_COILS_REQUEST_LOW_LEVEL,
				                       [requestID, coilsLength, coilsChunkOffset, coilsChunkData],
				                       'B H H ?472',
				                       0,
				                       '',
				                       returnCallback,
				                       errorCallback,
				                       true,
				                       true);
			}
			else {
				functionToQueue = function (device) {
					device.modbusSlaveAnswerReadCoilsRequest.call(device, requestID, coils, returnCallback, errorCallback);
				}

				streamStateObject['responseProperties']['callQueue'].push(functionToQueue);
			}
		}
	};
	this.modbusSlaveAnswerReadHoldingRegistersRequest = function(requestID, holdingRegisters, returnCallback, errorCallback) {
		/*
		In Modbus slave mode this function can be used to answer a master request to
		read holding registers.
		
		* Request ID: Request ID of the corresponding request that is being answered.
		* Holding Registers: Data that is to be sent to the Modbus master for the corresponding request.
		
		This function must be called from the :cb:`Modbus Slave Read Holding Registers Request`
		callback with the Request ID as provided by the argument of the callback.
		*/

		var holdingRegistersLength = 0;
		var holdingRegistersChunkData = [];
		var holdingRegistersChunkOffset = 0;
		var streamStateObject = this.streamStateObjects[27];

		if (holdingRegisters.length > 65535) {
			if (errorCallback !== null){
				errorCallback(IPConnection.ERROR_INVALID_PARAMETER);
			}

			this.resetStreamStateObject(streamStateObject);

			if (streamStateObject['responseProperties']['callQueue'].length > 0) {
				streamStateObject['responseProperties']['callQueue'].shift()(device);
			}

			return;
		}

		if (!this.getResponseExpected(27)) {
			if (streamStateObject['streamProperties']['fixedLength']) {
				holdingRegistersLength = streamStateObject['streamProperties']['fixedLength'];
			}
			else {
				holdingRegistersLength = holdingRegisters.length;
			}

			if (streamStateObject['streamProperties']['singleChunk']) {
				holdingRegistersChunkData =
					this.ipcon.createChunkData(holdingRegisters, 0, 29, '\0');

				this.ipcon.sendRequest(this,
				                       BrickletRS485.FUNCTION_MODBUS_SLAVE_ANSWER_READ_HOLDING_REGISTERS_REQUEST_LOW_LEVEL,
				                       [requestID, holdingRegistersLength, holdingRegistersChunkOffset, holdingRegistersChunkData],
				                       'B H H H29',
				                       0,
				                       '',
				                       returnCallback,
				                       errorCallback,
				                       false,
				                       true);
			}
			else {
				while (holdingRegistersChunkOffset < holdingRegisters.length) {
					holdingRegistersChunkData =
						this.ipcon.createChunkData(holdingRegisters, holdingRegistersChunkOffset, 29, '\0');

					this.ipcon.sendRequest(this,
					                       BrickletRS485.FUNCTION_MODBUS_SLAVE_ANSWER_READ_HOLDING_REGISTERS_REQUEST_LOW_LEVEL,
					                       [requestID, holdingRegistersLength, holdingRegistersChunkOffset, holdingRegistersChunkData],
					                       'B H H H29',
					                       0,
					                       '',
					                       returnCallback,
					                       errorCallback,
					                       false,
					                       true);

					holdingRegistersChunkOffset += 29;
				}
			}

			if (returnCallback) {
				returnCallback();
			}
		}
		else {
			var responseHandler = null;
			var functionToQueue = null;

			if (streamStateObject['responseProperties']['responseHandler'] === null) {
				responseHandler = function (device, fid, packetResponse) {
					var result = [];
					var payload = null;
					var llvalues = null;
					var packetErrorFlag = 0;
					var rolesMappedData = [];
					var shortWriteWritten = -1;
					var streamStateObject = device.streamStateObjects[fid];
					var responseEmpty = streamStateObject['responseProperties']['streamInResponseEmpty'];
					var holdingRegistersLength = 0;
					var holdingRegistersChunkData = [];
					var holdingRegistersChunkOffset = 0;

					function doNextLLCall() {
						holdingRegistersLength = streamStateObject['responseProperties']['data'].length;
						holdingRegistersChunkData =
							device.ipcon.createChunkData(streamStateObject['responseProperties']['data'],
							                             streamStateObject['responseProperties']['streamInChunkOffset'],
							                             streamStateObject['responseProperties']['streamInChunkLength'],
							                             '\0');
						holdingRegistersChunkOffset = streamStateObject['responseProperties']['streamInChunkOffset'];

						for (var i = 0; i < streamStateObject['dataMappingStreamIn'].length; i++) {
							if (streamStateObject['dataMappingStreamIn'][i] === null) {
								continue;
							}

							if (streamStateObject['dataMappingStreamIn'][i].endsWith('Length')) {
								streamStateObject['responseProperties']['streamInLLParams'][i] = holdingRegistersLength;
							}
							else if (streamStateObject['dataMappingStreamIn'][i].endsWith('Offset')) {
								streamStateObject['responseProperties']['streamInLLParams'][i] = holdingRegistersChunkOffset;
							}
							else if (streamStateObject['dataMappingStreamIn'][i].endsWith('Data')) {
								streamStateObject['responseProperties']['streamInLLParams'][i] = holdingRegistersChunkData;
							}
						}

						device.ipcon.sendRequest(device,
						                         BrickletRS485.FUNCTION_MODBUS_SLAVE_ANSWER_READ_HOLDING_REGISTERS_REQUEST_LOW_LEVEL,
						                         streamStateObject['responseProperties']['streamInLLParams'],
						                         'B H H H29',
						                         0,
						                         '',
						                         returnCallback,
						                         errorCallback,
						                         true,
						                         true);

						streamStateObject['responseProperties']['streamInChunkOffset'] += 29;
					}

					function handleStreamInDone() {
						if (streamStateObject['responseProperties']['returnCB']) {
							if (streamStateObject['streamProperties']['shortWrite']) {
								for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
									if (streamStateObject['dataMapping'][i].endsWith('Written')) {
										result[i] = streamStateObject['responseProperties']['streamInWritten'];
										break;
									}
								}
							}

							if (!responseEmpty) {
								streamStateObject['responseProperties']['returnCB'].apply(device, result);
							}
							else {
								streamStateObject['responseProperties']['returnCB'].apply(device);
							}
						}

						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}
					}

					if (!streamStateObject) {
						return;
					}

					packetErrorFlag = device.ipcon.getEFromPacket(packetResponse);

					if (packetErrorFlag !== 0) {
						if (streamStateObject['responseProperties']['errorCB'] !== undefined) {
							if (packetErrorFlag === 1) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_INVALID_PARAMETER);
							}
							else if (packetErrorFlag === 2) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_FUNCTION_NOT_SUPPORTED);
							}
							else {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_UNKNOWN_ERROR);
							}
						}

						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}

						return;
					}

					if (responseEmpty) {
						if (streamStateObject['streamProperties']['singleChunk']) {
							handleStreamInDone();

							return;
						}

						if (streamStateObject['responseProperties']['streamInChunkOffset'] < streamStateObject['responseProperties']['data'].length) {
							doNextLLCall();
						}
						else {
							handleStreamInDone();
						}
					}
					else {
						payload = device.ipcon.getPayloadFromPacket(packetResponse);
						llvalues = device.ipcon.unpack(payload,
						                               streamStateObject['responseProperties']['unpackFormatString']);

						if (!payload || !llvalues) {
							device.resetStreamStateObject(streamStateObject);

							if (streamStateObject['responseProperties']['callQueue'].length > 0) {
								streamStateObject['responseProperties']['callQueue'].shift()(device);
							}

							return;
						}

						for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
							result.push(llvalues[i]);
						}

						if (streamStateObject['streamProperties']['singleChunk']) {
							if (streamStateObject['responseProperties']['returnCB']) {
								streamStateObject['responseProperties']['returnCB'].apply(device, result);
							}

							device.resetStreamStateObject(streamStateObject);

							if (streamStateObject['responseProperties']['callQueue'].length > 0) {
								streamStateObject['responseProperties']['callQueue'].shift()(device);
							}

							return;
						}

						if (streamStateObject['streamProperties']['shortWrite']) {
							for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
								if (streamStateObject['dataMapping'][i].endsWith('Written')) {
									shortWriteWritten = llvalues[i];
									streamStateObject['responseProperties']['streamInWritten'] += shortWriteWritten;
									break;
								}
							}
							if ((shortWriteWritten !== -1) && (shortWriteWritten < 29)) {
								// Either last chunk or short write
								handleStreamInDone();
								return;
							}
						}

						if (streamStateObject['responseProperties']['streamInChunkOffset'] < streamStateObject['responseProperties']['data'].length) {
							doNextLLCall();
						}
						else {
							handleStreamInDone();
						}
					}
				};

				streamStateObject['responseProperties']['responseHandler'] = responseHandler;
			}

			if (!streamStateObject['responseProperties']['running']) {
				streamStateObject['responseProperties']['running'] = true;
				streamStateObject['responseProperties']['returnCB'] = returnCallback;
				streamStateObject['responseProperties']['errorCB'] = errorCallback;
				streamStateObject['responseProperties']['data'].length = 0;
				streamStateObject['responseProperties']['data'].push.apply(streamStateObject['responseProperties']['data'],
				                                                           holdingRegisters);

				if (streamStateObject['streamProperties']['fixedLength']) {
					holdingRegistersLength = streamStateObject['streamProperties']['fixedLength'];
				}
				else {
					holdingRegistersLength = holdingRegisters.length;
				}

				holdingRegistersChunkOffset = 0;
				holdingRegistersChunkData =
					this.ipcon.createChunkData(holdingRegisters, 0, 29, '\0');

				streamStateObject['responseProperties']['streamInChunkOffset'] = 29;
				streamStateObject['responseProperties']['streamInChunkLength'] = 29;
				streamStateObject['responseProperties']['streamInLLParams'] = [requestID, holdingRegistersLength, holdingRegistersChunkOffset, holdingRegistersChunkData];

				this.ipcon.sendRequest(this,
				                       BrickletRS485.FUNCTION_MODBUS_SLAVE_ANSWER_READ_HOLDING_REGISTERS_REQUEST_LOW_LEVEL,
				                       [requestID, holdingRegistersLength, holdingRegistersChunkOffset, holdingRegistersChunkData],
				                       'B H H H29',
				                       0,
				                       '',
				                       returnCallback,
				                       errorCallback,
				                       true,
				                       true);
			}
			else {
				functionToQueue = function (device) {
					device.modbusSlaveAnswerReadHoldingRegistersRequest.call(device, requestID, holdingRegisters, returnCallback, errorCallback);
				}

				streamStateObject['responseProperties']['callQueue'].push(functionToQueue);
			}
		}
	};
	this.modbusMasterWriteMultipleCoils = function(slaveAddress, startingAddress, coils, returnCallback, errorCallback) {
		/*
		In Modbus master mode this function can be used to write multiple coils of a slave.
		This function creates a Modbus function code 15 request.
		
		* Slave Address: Address of the target Modbus slave.
		* Starting Address: Number of the first coil to write. For backwards compatibility reasons, this parameter is called Starting Address.It is not an address, but instead a coil number in the range of 1 to 65536.
		
		Upon success the function will return a non-zero request ID which will represent
		the current request initiated by the Modbus master. In case of failure the returned
		request ID will be 0.
		
		When successful this function will also invoke the :cb:`Modbus Master Write Multiple Coils Response`
		callback. In this callback the Request ID provided by the callback argument must be matched
		with the Request ID returned from this function to verify that the callback is indeed for a
		particular request.
		*/

		var coilsLength = 0;
		var coilsChunkData = [];
		var coilsChunkOffset = 0;
		var streamStateObject = this.streamStateObjects[34];

		if (coils.length > 65535) {
			if (errorCallback !== null){
				errorCallback(IPConnection.ERROR_INVALID_PARAMETER);
			}

			this.resetStreamStateObject(streamStateObject);

			if (streamStateObject['responseProperties']['callQueue'].length > 0) {
				streamStateObject['responseProperties']['callQueue'].shift()(device);
			}

			return;
		}

		if (!this.getResponseExpected(34)) {
			if (streamStateObject['streamProperties']['fixedLength']) {
				coilsLength = streamStateObject['streamProperties']['fixedLength'];
			}
			else {
				coilsLength = coils.length;
			}

			if (streamStateObject['streamProperties']['singleChunk']) {
				coilsChunkData =
					this.ipcon.createChunkData(coils, 0, 440, '\0');

				this.ipcon.sendRequest(this,
				                       BrickletRS485.FUNCTION_MODBUS_MASTER_WRITE_MULTIPLE_COILS_LOW_LEVEL,
				                       [slaveAddress, startingAddress, coilsLength, coilsChunkOffset, coilsChunkData],
				                       'B I H H ?440',
				                       9,
				                       'B',
				                       returnCallback,
				                       errorCallback,
				                       false,
				                       true);
			}
			else {
				while (coilsChunkOffset < coils.length) {
					coilsChunkData =
						this.ipcon.createChunkData(coils, coilsChunkOffset, 440, '\0');

					this.ipcon.sendRequest(this,
					                       BrickletRS485.FUNCTION_MODBUS_MASTER_WRITE_MULTIPLE_COILS_LOW_LEVEL,
					                       [slaveAddress, startingAddress, coilsLength, coilsChunkOffset, coilsChunkData],
					                       'B I H H ?440',
					                       9,
					                       'B',
					                       returnCallback,
					                       errorCallback,
					                       false,
					                       true);

					coilsChunkOffset += 440;
				}
			}

			if (returnCallback) {
				returnCallback();
			}
		}
		else {
			var responseHandler = null;
			var functionToQueue = null;

			if (streamStateObject['responseProperties']['responseHandler'] === null) {
				responseHandler = function (device, fid, packetResponse) {
					var result = [];
					var payload = null;
					var llvalues = null;
					var packetErrorFlag = 0;
					var rolesMappedData = [];
					var shortWriteWritten = -1;
					var streamStateObject = device.streamStateObjects[fid];
					var responseEmpty = streamStateObject['responseProperties']['streamInResponseEmpty'];
					var coilsLength = 0;
					var coilsChunkData = [];
					var coilsChunkOffset = 0;

					function doNextLLCall() {
						coilsLength = streamStateObject['responseProperties']['data'].length;
						coilsChunkData =
							device.ipcon.createChunkData(streamStateObject['responseProperties']['data'],
							                             streamStateObject['responseProperties']['streamInChunkOffset'],
							                             streamStateObject['responseProperties']['streamInChunkLength'],
							                             '\0');
						coilsChunkOffset = streamStateObject['responseProperties']['streamInChunkOffset'];

						for (var i = 0; i < streamStateObject['dataMappingStreamIn'].length; i++) {
							if (streamStateObject['dataMappingStreamIn'][i] === null) {
								continue;
							}

							if (streamStateObject['dataMappingStreamIn'][i].endsWith('Length')) {
								streamStateObject['responseProperties']['streamInLLParams'][i] = coilsLength;
							}
							else if (streamStateObject['dataMappingStreamIn'][i].endsWith('Offset')) {
								streamStateObject['responseProperties']['streamInLLParams'][i] = coilsChunkOffset;
							}
							else if (streamStateObject['dataMappingStreamIn'][i].endsWith('Data')) {
								streamStateObject['responseProperties']['streamInLLParams'][i] = coilsChunkData;
							}
						}

						device.ipcon.sendRequest(device,
						                         BrickletRS485.FUNCTION_MODBUS_MASTER_WRITE_MULTIPLE_COILS_LOW_LEVEL,
						                         streamStateObject['responseProperties']['streamInLLParams'],
						                         'B I H H ?440',
						                         9,
						                         'B',
						                         returnCallback,
						                         errorCallback,
						                         true,
						                         true);

						streamStateObject['responseProperties']['streamInChunkOffset'] += 440;
					}

					function handleStreamInDone() {
						if (streamStateObject['responseProperties']['returnCB']) {
							if (streamStateObject['streamProperties']['shortWrite']) {
								for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
									if (streamStateObject['dataMapping'][i].endsWith('Written')) {
										result[i] = streamStateObject['responseProperties']['streamInWritten'];
										break;
									}
								}
							}

							if (!responseEmpty) {
								streamStateObject['responseProperties']['returnCB'].apply(device, result);
							}
							else {
								streamStateObject['responseProperties']['returnCB'].apply(device);
							}
						}

						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}
					}

					if (!streamStateObject) {
						return;
					}

					packetErrorFlag = device.ipcon.getEFromPacket(packetResponse);

					if (packetErrorFlag !== 0) {
						if (streamStateObject['responseProperties']['errorCB'] !== undefined) {
							if (packetErrorFlag === 1) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_INVALID_PARAMETER);
							}
							else if (packetErrorFlag === 2) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_FUNCTION_NOT_SUPPORTED);
							}
							else {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_UNKNOWN_ERROR);
							}
						}

						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}

						return;
					}

					if (responseEmpty) {
						if (streamStateObject['streamProperties']['singleChunk']) {
							handleStreamInDone();

							return;
						}

						if (streamStateObject['responseProperties']['streamInChunkOffset'] < streamStateObject['responseProperties']['data'].length) {
							doNextLLCall();
						}
						else {
							handleStreamInDone();
						}
					}
					else {
						payload = device.ipcon.getPayloadFromPacket(packetResponse);
						llvalues = device.ipcon.unpack(payload,
						                               streamStateObject['responseProperties']['unpackFormatString']);

						if (!payload || !llvalues) {
							device.resetStreamStateObject(streamStateObject);

							if (streamStateObject['responseProperties']['callQueue'].length > 0) {
								streamStateObject['responseProperties']['callQueue'].shift()(device);
							}

							return;
						}

						for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
							result.push(llvalues[i]);
						}

						if (streamStateObject['streamProperties']['singleChunk']) {
							if (streamStateObject['responseProperties']['returnCB']) {
								streamStateObject['responseProperties']['returnCB'].apply(device, result);
							}

							device.resetStreamStateObject(streamStateObject);

							if (streamStateObject['responseProperties']['callQueue'].length > 0) {
								streamStateObject['responseProperties']['callQueue'].shift()(device);
							}

							return;
						}

						if (streamStateObject['streamProperties']['shortWrite']) {
							for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
								if (streamStateObject['dataMapping'][i].endsWith('Written')) {
									shortWriteWritten = llvalues[i];
									streamStateObject['responseProperties']['streamInWritten'] += shortWriteWritten;
									break;
								}
							}
							if ((shortWriteWritten !== -1) && (shortWriteWritten < 440)) {
								// Either last chunk or short write
								handleStreamInDone();
								return;
							}
						}

						if (streamStateObject['responseProperties']['streamInChunkOffset'] < streamStateObject['responseProperties']['data'].length) {
							doNextLLCall();
						}
						else {
							handleStreamInDone();
						}
					}
				};

				streamStateObject['responseProperties']['responseHandler'] = responseHandler;
			}

			if (!streamStateObject['responseProperties']['running']) {
				streamStateObject['responseProperties']['running'] = true;
				streamStateObject['responseProperties']['returnCB'] = returnCallback;
				streamStateObject['responseProperties']['errorCB'] = errorCallback;
				streamStateObject['responseProperties']['data'].length = 0;
				streamStateObject['responseProperties']['data'].push.apply(streamStateObject['responseProperties']['data'],
				                                                           coils);

				if (streamStateObject['streamProperties']['fixedLength']) {
					coilsLength = streamStateObject['streamProperties']['fixedLength'];
				}
				else {
					coilsLength = coils.length;
				}

				coilsChunkOffset = 0;
				coilsChunkData =
					this.ipcon.createChunkData(coils, 0, 440, '\0');

				streamStateObject['responseProperties']['streamInChunkOffset'] = 440;
				streamStateObject['responseProperties']['streamInChunkLength'] = 440;
				streamStateObject['responseProperties']['streamInLLParams'] = [slaveAddress, startingAddress, coilsLength, coilsChunkOffset, coilsChunkData];

				this.ipcon.sendRequest(this,
				                       BrickletRS485.FUNCTION_MODBUS_MASTER_WRITE_MULTIPLE_COILS_LOW_LEVEL,
				                       [slaveAddress, startingAddress, coilsLength, coilsChunkOffset, coilsChunkData],
				                       'B I H H ?440',
				                       9,
				                       'B',
				                       returnCallback,
				                       errorCallback,
				                       true,
				                       true);
			}
			else {
				functionToQueue = function (device) {
					device.modbusMasterWriteMultipleCoils.call(device, slaveAddress, startingAddress, coils, returnCallback, errorCallback);
				}

				streamStateObject['responseProperties']['callQueue'].push(functionToQueue);
			}
		}
	};
	this.modbusMasterWriteMultipleRegisters = function(slaveAddress, startingAddress, registers, returnCallback, errorCallback) {
		/*
		In Modbus master mode this function can be used to write multiple registers of a slave.
		This function creates a Modbus function code 16 request.
		
		* Slave Address: Address of the target Modbus slave.
		* Starting Address: Number of the first holding register to write. For backwards compatibility reasons, this parameter is called Starting Address. It is not an address, but instead a holding register number in the range of 1 to 65536. The prefix digit 4 (for holding register) is implicit and must be omitted.
		
		Upon success the function will return a non-zero request ID which will represent
		the current request initiated by the Modbus master. In case of failure the returned
		request ID will be 0.
		
		When successful this function will also invoke the :cb:`Modbus Master Write Multiple Registers Response`
		callback. In this callback the Request ID provided by the callback argument must be matched
		with the Request ID returned from this function to verify that the callback is indeed for a
		particular request.
		*/

		var registersLength = 0;
		var registersChunkData = [];
		var registersChunkOffset = 0;
		var streamStateObject = this.streamStateObjects[36];

		if (registers.length > 65535) {
			if (errorCallback !== null){
				errorCallback(IPConnection.ERROR_INVALID_PARAMETER);
			}

			this.resetStreamStateObject(streamStateObject);

			if (streamStateObject['responseProperties']['callQueue'].length > 0) {
				streamStateObject['responseProperties']['callQueue'].shift()(device);
			}

			return;
		}

		if (!this.getResponseExpected(36)) {
			if (streamStateObject['streamProperties']['fixedLength']) {
				registersLength = streamStateObject['streamProperties']['fixedLength'];
			}
			else {
				registersLength = registers.length;
			}

			if (streamStateObject['streamProperties']['singleChunk']) {
				registersChunkData =
					this.ipcon.createChunkData(registers, 0, 27, '\0');

				this.ipcon.sendRequest(this,
				                       BrickletRS485.FUNCTION_MODBUS_MASTER_WRITE_MULTIPLE_REGISTERS_LOW_LEVEL,
				                       [slaveAddress, startingAddress, registersLength, registersChunkOffset, registersChunkData],
				                       'B I H H H27',
				                       9,
				                       'B',
				                       returnCallback,
				                       errorCallback,
				                       false,
				                       true);
			}
			else {
				while (registersChunkOffset < registers.length) {
					registersChunkData =
						this.ipcon.createChunkData(registers, registersChunkOffset, 27, '\0');

					this.ipcon.sendRequest(this,
					                       BrickletRS485.FUNCTION_MODBUS_MASTER_WRITE_MULTIPLE_REGISTERS_LOW_LEVEL,
					                       [slaveAddress, startingAddress, registersLength, registersChunkOffset, registersChunkData],
					                       'B I H H H27',
					                       9,
					                       'B',
					                       returnCallback,
					                       errorCallback,
					                       false,
					                       true);

					registersChunkOffset += 27;
				}
			}

			if (returnCallback) {
				returnCallback();
			}
		}
		else {
			var responseHandler = null;
			var functionToQueue = null;

			if (streamStateObject['responseProperties']['responseHandler'] === null) {
				responseHandler = function (device, fid, packetResponse) {
					var result = [];
					var payload = null;
					var llvalues = null;
					var packetErrorFlag = 0;
					var rolesMappedData = [];
					var shortWriteWritten = -1;
					var streamStateObject = device.streamStateObjects[fid];
					var responseEmpty = streamStateObject['responseProperties']['streamInResponseEmpty'];
					var registersLength = 0;
					var registersChunkData = [];
					var registersChunkOffset = 0;

					function doNextLLCall() {
						registersLength = streamStateObject['responseProperties']['data'].length;
						registersChunkData =
							device.ipcon.createChunkData(streamStateObject['responseProperties']['data'],
							                             streamStateObject['responseProperties']['streamInChunkOffset'],
							                             streamStateObject['responseProperties']['streamInChunkLength'],
							                             '\0');
						registersChunkOffset = streamStateObject['responseProperties']['streamInChunkOffset'];

						for (var i = 0; i < streamStateObject['dataMappingStreamIn'].length; i++) {
							if (streamStateObject['dataMappingStreamIn'][i] === null) {
								continue;
							}

							if (streamStateObject['dataMappingStreamIn'][i].endsWith('Length')) {
								streamStateObject['responseProperties']['streamInLLParams'][i] = registersLength;
							}
							else if (streamStateObject['dataMappingStreamIn'][i].endsWith('Offset')) {
								streamStateObject['responseProperties']['streamInLLParams'][i] = registersChunkOffset;
							}
							else if (streamStateObject['dataMappingStreamIn'][i].endsWith('Data')) {
								streamStateObject['responseProperties']['streamInLLParams'][i] = registersChunkData;
							}
						}

						device.ipcon.sendRequest(device,
						                         BrickletRS485.FUNCTION_MODBUS_MASTER_WRITE_MULTIPLE_REGISTERS_LOW_LEVEL,
						                         streamStateObject['responseProperties']['streamInLLParams'],
						                         'B I H H H27',
						                         9,
						                         'B',
						                         returnCallback,
						                         errorCallback,
						                         true,
						                         true);

						streamStateObject['responseProperties']['streamInChunkOffset'] += 27;
					}

					function handleStreamInDone() {
						if (streamStateObject['responseProperties']['returnCB']) {
							if (streamStateObject['streamProperties']['shortWrite']) {
								for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
									if (streamStateObject['dataMapping'][i].endsWith('Written')) {
										result[i] = streamStateObject['responseProperties']['streamInWritten'];
										break;
									}
								}
							}

							if (!responseEmpty) {
								streamStateObject['responseProperties']['returnCB'].apply(device, result);
							}
							else {
								streamStateObject['responseProperties']['returnCB'].apply(device);
							}
						}

						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}
					}

					if (!streamStateObject) {
						return;
					}

					packetErrorFlag = device.ipcon.getEFromPacket(packetResponse);

					if (packetErrorFlag !== 0) {
						if (streamStateObject['responseProperties']['errorCB'] !== undefined) {
							if (packetErrorFlag === 1) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_INVALID_PARAMETER);
							}
							else if (packetErrorFlag === 2) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_FUNCTION_NOT_SUPPORTED);
							}
							else {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_UNKNOWN_ERROR);
							}
						}

						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}

						return;
					}

					if (responseEmpty) {
						if (streamStateObject['streamProperties']['singleChunk']) {
							handleStreamInDone();

							return;
						}

						if (streamStateObject['responseProperties']['streamInChunkOffset'] < streamStateObject['responseProperties']['data'].length) {
							doNextLLCall();
						}
						else {
							handleStreamInDone();
						}
					}
					else {
						payload = device.ipcon.getPayloadFromPacket(packetResponse);
						llvalues = device.ipcon.unpack(payload,
						                               streamStateObject['responseProperties']['unpackFormatString']);

						if (!payload || !llvalues) {
							device.resetStreamStateObject(streamStateObject);

							if (streamStateObject['responseProperties']['callQueue'].length > 0) {
								streamStateObject['responseProperties']['callQueue'].shift()(device);
							}

							return;
						}

						for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
							result.push(llvalues[i]);
						}

						if (streamStateObject['streamProperties']['singleChunk']) {
							if (streamStateObject['responseProperties']['returnCB']) {
								streamStateObject['responseProperties']['returnCB'].apply(device, result);
							}

							device.resetStreamStateObject(streamStateObject);

							if (streamStateObject['responseProperties']['callQueue'].length > 0) {
								streamStateObject['responseProperties']['callQueue'].shift()(device);
							}

							return;
						}

						if (streamStateObject['streamProperties']['shortWrite']) {
							for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
								if (streamStateObject['dataMapping'][i].endsWith('Written')) {
									shortWriteWritten = llvalues[i];
									streamStateObject['responseProperties']['streamInWritten'] += shortWriteWritten;
									break;
								}
							}
							if ((shortWriteWritten !== -1) && (shortWriteWritten < 27)) {
								// Either last chunk or short write
								handleStreamInDone();
								return;
							}
						}

						if (streamStateObject['responseProperties']['streamInChunkOffset'] < streamStateObject['responseProperties']['data'].length) {
							doNextLLCall();
						}
						else {
							handleStreamInDone();
						}
					}
				};

				streamStateObject['responseProperties']['responseHandler'] = responseHandler;
			}

			if (!streamStateObject['responseProperties']['running']) {
				streamStateObject['responseProperties']['running'] = true;
				streamStateObject['responseProperties']['returnCB'] = returnCallback;
				streamStateObject['responseProperties']['errorCB'] = errorCallback;
				streamStateObject['responseProperties']['data'].length = 0;
				streamStateObject['responseProperties']['data'].push.apply(streamStateObject['responseProperties']['data'],
				                                                           registers);

				if (streamStateObject['streamProperties']['fixedLength']) {
					registersLength = streamStateObject['streamProperties']['fixedLength'];
				}
				else {
					registersLength = registers.length;
				}

				registersChunkOffset = 0;
				registersChunkData =
					this.ipcon.createChunkData(registers, 0, 27, '\0');

				streamStateObject['responseProperties']['streamInChunkOffset'] = 27;
				streamStateObject['responseProperties']['streamInChunkLength'] = 27;
				streamStateObject['responseProperties']['streamInLLParams'] = [slaveAddress, startingAddress, registersLength, registersChunkOffset, registersChunkData];

				this.ipcon.sendRequest(this,
				                       BrickletRS485.FUNCTION_MODBUS_MASTER_WRITE_MULTIPLE_REGISTERS_LOW_LEVEL,
				                       [slaveAddress, startingAddress, registersLength, registersChunkOffset, registersChunkData],
				                       'B I H H H27',
				                       9,
				                       'B',
				                       returnCallback,
				                       errorCallback,
				                       true,
				                       true);
			}
			else {
				functionToQueue = function (device) {
					device.modbusMasterWriteMultipleRegisters.call(device, slaveAddress, startingAddress, registers, returnCallback, errorCallback);
				}

				streamStateObject['responseProperties']['callQueue'].push(functionToQueue);
			}
		}
	};
	this.modbusSlaveAnswerReadDiscreteInputsRequest = function(requestID, discreteInputs, returnCallback, errorCallback) {
		/*
		In Modbus slave mode this function can be used to answer a master request to
		read discrete inputs.
		
		* Request ID: Request ID of the corresponding request that is being answered.
		* Discrete Inputs: Data that is to be sent to the Modbus master for the corresponding request.
		
		This function must be called from the :cb:`Modbus Slave Read Discrete Inputs Request`
		callback with the Request ID as provided by the argument of the callback.
		*/

		var discreteInputsLength = 0;
		var discreteInputsChunkData = [];
		var discreteInputsChunkOffset = 0;
		var streamStateObject = this.streamStateObjects[37];

		if (discreteInputs.length > 65535) {
			if (errorCallback !== null){
				errorCallback(IPConnection.ERROR_INVALID_PARAMETER);
			}

			this.resetStreamStateObject(streamStateObject);

			if (streamStateObject['responseProperties']['callQueue'].length > 0) {
				streamStateObject['responseProperties']['callQueue'].shift()(device);
			}

			return;
		}

		if (!this.getResponseExpected(37)) {
			if (streamStateObject['streamProperties']['fixedLength']) {
				discreteInputsLength = streamStateObject['streamProperties']['fixedLength'];
			}
			else {
				discreteInputsLength = discreteInputs.length;
			}

			if (streamStateObject['streamProperties']['singleChunk']) {
				discreteInputsChunkData =
					this.ipcon.createChunkData(discreteInputs, 0, 472, '\0');

				this.ipcon.sendRequest(this,
				                       BrickletRS485.FUNCTION_MODBUS_SLAVE_ANSWER_READ_DISCRETE_INPUTS_REQUEST_LOW_LEVEL,
				                       [requestID, discreteInputsLength, discreteInputsChunkOffset, discreteInputsChunkData],
				                       'B H H ?472',
				                       0,
				                       '',
				                       returnCallback,
				                       errorCallback,
				                       false,
				                       true);
			}
			else {
				while (discreteInputsChunkOffset < discreteInputs.length) {
					discreteInputsChunkData =
						this.ipcon.createChunkData(discreteInputs, discreteInputsChunkOffset, 472, '\0');

					this.ipcon.sendRequest(this,
					                       BrickletRS485.FUNCTION_MODBUS_SLAVE_ANSWER_READ_DISCRETE_INPUTS_REQUEST_LOW_LEVEL,
					                       [requestID, discreteInputsLength, discreteInputsChunkOffset, discreteInputsChunkData],
					                       'B H H ?472',
					                       0,
					                       '',
					                       returnCallback,
					                       errorCallback,
					                       false,
					                       true);

					discreteInputsChunkOffset += 472;
				}
			}

			if (returnCallback) {
				returnCallback();
			}
		}
		else {
			var responseHandler = null;
			var functionToQueue = null;

			if (streamStateObject['responseProperties']['responseHandler'] === null) {
				responseHandler = function (device, fid, packetResponse) {
					var result = [];
					var payload = null;
					var llvalues = null;
					var packetErrorFlag = 0;
					var rolesMappedData = [];
					var shortWriteWritten = -1;
					var streamStateObject = device.streamStateObjects[fid];
					var responseEmpty = streamStateObject['responseProperties']['streamInResponseEmpty'];
					var discreteInputsLength = 0;
					var discreteInputsChunkData = [];
					var discreteInputsChunkOffset = 0;

					function doNextLLCall() {
						discreteInputsLength = streamStateObject['responseProperties']['data'].length;
						discreteInputsChunkData =
							device.ipcon.createChunkData(streamStateObject['responseProperties']['data'],
							                             streamStateObject['responseProperties']['streamInChunkOffset'],
							                             streamStateObject['responseProperties']['streamInChunkLength'],
							                             '\0');
						discreteInputsChunkOffset = streamStateObject['responseProperties']['streamInChunkOffset'];

						for (var i = 0; i < streamStateObject['dataMappingStreamIn'].length; i++) {
							if (streamStateObject['dataMappingStreamIn'][i] === null) {
								continue;
							}

							if (streamStateObject['dataMappingStreamIn'][i].endsWith('Length')) {
								streamStateObject['responseProperties']['streamInLLParams'][i] = discreteInputsLength;
							}
							else if (streamStateObject['dataMappingStreamIn'][i].endsWith('Offset')) {
								streamStateObject['responseProperties']['streamInLLParams'][i] = discreteInputsChunkOffset;
							}
							else if (streamStateObject['dataMappingStreamIn'][i].endsWith('Data')) {
								streamStateObject['responseProperties']['streamInLLParams'][i] = discreteInputsChunkData;
							}
						}

						device.ipcon.sendRequest(device,
						                         BrickletRS485.FUNCTION_MODBUS_SLAVE_ANSWER_READ_DISCRETE_INPUTS_REQUEST_LOW_LEVEL,
						                         streamStateObject['responseProperties']['streamInLLParams'],
						                         'B H H ?472',
						                         0,
						                         '',
						                         returnCallback,
						                         errorCallback,
						                         true,
						                         true);

						streamStateObject['responseProperties']['streamInChunkOffset'] += 472;
					}

					function handleStreamInDone() {
						if (streamStateObject['responseProperties']['returnCB']) {
							if (streamStateObject['streamProperties']['shortWrite']) {
								for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
									if (streamStateObject['dataMapping'][i].endsWith('Written')) {
										result[i] = streamStateObject['responseProperties']['streamInWritten'];
										break;
									}
								}
							}

							if (!responseEmpty) {
								streamStateObject['responseProperties']['returnCB'].apply(device, result);
							}
							else {
								streamStateObject['responseProperties']['returnCB'].apply(device);
							}
						}

						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}
					}

					if (!streamStateObject) {
						return;
					}

					packetErrorFlag = device.ipcon.getEFromPacket(packetResponse);

					if (packetErrorFlag !== 0) {
						if (streamStateObject['responseProperties']['errorCB'] !== undefined) {
							if (packetErrorFlag === 1) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_INVALID_PARAMETER);
							}
							else if (packetErrorFlag === 2) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_FUNCTION_NOT_SUPPORTED);
							}
							else {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_UNKNOWN_ERROR);
							}
						}

						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}

						return;
					}

					if (responseEmpty) {
						if (streamStateObject['streamProperties']['singleChunk']) {
							handleStreamInDone();

							return;
						}

						if (streamStateObject['responseProperties']['streamInChunkOffset'] < streamStateObject['responseProperties']['data'].length) {
							doNextLLCall();
						}
						else {
							handleStreamInDone();
						}
					}
					else {
						payload = device.ipcon.getPayloadFromPacket(packetResponse);
						llvalues = device.ipcon.unpack(payload,
						                               streamStateObject['responseProperties']['unpackFormatString']);

						if (!payload || !llvalues) {
							device.resetStreamStateObject(streamStateObject);

							if (streamStateObject['responseProperties']['callQueue'].length > 0) {
								streamStateObject['responseProperties']['callQueue'].shift()(device);
							}

							return;
						}

						for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
							result.push(llvalues[i]);
						}

						if (streamStateObject['streamProperties']['singleChunk']) {
							if (streamStateObject['responseProperties']['returnCB']) {
								streamStateObject['responseProperties']['returnCB'].apply(device, result);
							}

							device.resetStreamStateObject(streamStateObject);

							if (streamStateObject['responseProperties']['callQueue'].length > 0) {
								streamStateObject['responseProperties']['callQueue'].shift()(device);
							}

							return;
						}

						if (streamStateObject['streamProperties']['shortWrite']) {
							for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
								if (streamStateObject['dataMapping'][i].endsWith('Written')) {
									shortWriteWritten = llvalues[i];
									streamStateObject['responseProperties']['streamInWritten'] += shortWriteWritten;
									break;
								}
							}
							if ((shortWriteWritten !== -1) && (shortWriteWritten < 472)) {
								// Either last chunk or short write
								handleStreamInDone();
								return;
							}
						}

						if (streamStateObject['responseProperties']['streamInChunkOffset'] < streamStateObject['responseProperties']['data'].length) {
							doNextLLCall();
						}
						else {
							handleStreamInDone();
						}
					}
				};

				streamStateObject['responseProperties']['responseHandler'] = responseHandler;
			}

			if (!streamStateObject['responseProperties']['running']) {
				streamStateObject['responseProperties']['running'] = true;
				streamStateObject['responseProperties']['returnCB'] = returnCallback;
				streamStateObject['responseProperties']['errorCB'] = errorCallback;
				streamStateObject['responseProperties']['data'].length = 0;
				streamStateObject['responseProperties']['data'].push.apply(streamStateObject['responseProperties']['data'],
				                                                           discreteInputs);

				if (streamStateObject['streamProperties']['fixedLength']) {
					discreteInputsLength = streamStateObject['streamProperties']['fixedLength'];
				}
				else {
					discreteInputsLength = discreteInputs.length;
				}

				discreteInputsChunkOffset = 0;
				discreteInputsChunkData =
					this.ipcon.createChunkData(discreteInputs, 0, 472, '\0');

				streamStateObject['responseProperties']['streamInChunkOffset'] = 472;
				streamStateObject['responseProperties']['streamInChunkLength'] = 472;
				streamStateObject['responseProperties']['streamInLLParams'] = [requestID, discreteInputsLength, discreteInputsChunkOffset, discreteInputsChunkData];

				this.ipcon.sendRequest(this,
				                       BrickletRS485.FUNCTION_MODBUS_SLAVE_ANSWER_READ_DISCRETE_INPUTS_REQUEST_LOW_LEVEL,
				                       [requestID, discreteInputsLength, discreteInputsChunkOffset, discreteInputsChunkData],
				                       'B H H ?472',
				                       0,
				                       '',
				                       returnCallback,
				                       errorCallback,
				                       true,
				                       true);
			}
			else {
				functionToQueue = function (device) {
					device.modbusSlaveAnswerReadDiscreteInputsRequest.call(device, requestID, discreteInputs, returnCallback, errorCallback);
				}

				streamStateObject['responseProperties']['callQueue'].push(functionToQueue);
			}
		}
	};
	this.modbusSlaveAnswerReadInputRegistersRequest = function(requestID, inputRegisters, returnCallback, errorCallback) {
		/*
		In Modbus slave mode this function can be used to answer a master request to
		read input registers.
		
		* Request ID: Request ID of the corresponding request that is being answered.
		* Input Registers: Data that is to be sent to the Modbus master for the corresponding request.
		
		This function must be called from the :cb:`Modbus Slave Read Input Registers Request` callback
		with the Request ID as provided by the argument of the callback.
		*/

		var inputRegistersLength = 0;
		var inputRegistersChunkData = [];
		var inputRegistersChunkOffset = 0;
		var streamStateObject = this.streamStateObjects[39];

		if (inputRegisters.length > 65535) {
			if (errorCallback !== null){
				errorCallback(IPConnection.ERROR_INVALID_PARAMETER);
			}

			this.resetStreamStateObject(streamStateObject);

			if (streamStateObject['responseProperties']['callQueue'].length > 0) {
				streamStateObject['responseProperties']['callQueue'].shift()(device);
			}

			return;
		}

		if (!this.getResponseExpected(39)) {
			if (streamStateObject['streamProperties']['fixedLength']) {
				inputRegistersLength = streamStateObject['streamProperties']['fixedLength'];
			}
			else {
				inputRegistersLength = inputRegisters.length;
			}

			if (streamStateObject['streamProperties']['singleChunk']) {
				inputRegistersChunkData =
					this.ipcon.createChunkData(inputRegisters, 0, 29, '\0');

				this.ipcon.sendRequest(this,
				                       BrickletRS485.FUNCTION_MODBUS_SLAVE_ANSWER_READ_INPUT_REGISTERS_REQUEST_LOW_LEVEL,
				                       [requestID, inputRegistersLength, inputRegistersChunkOffset, inputRegistersChunkData],
				                       'B H H H29',
				                       0,
				                       '',
				                       returnCallback,
				                       errorCallback,
				                       false,
				                       true);
			}
			else {
				while (inputRegistersChunkOffset < inputRegisters.length) {
					inputRegistersChunkData =
						this.ipcon.createChunkData(inputRegisters, inputRegistersChunkOffset, 29, '\0');

					this.ipcon.sendRequest(this,
					                       BrickletRS485.FUNCTION_MODBUS_SLAVE_ANSWER_READ_INPUT_REGISTERS_REQUEST_LOW_LEVEL,
					                       [requestID, inputRegistersLength, inputRegistersChunkOffset, inputRegistersChunkData],
					                       'B H H H29',
					                       0,
					                       '',
					                       returnCallback,
					                       errorCallback,
					                       false,
					                       true);

					inputRegistersChunkOffset += 29;
				}
			}

			if (returnCallback) {
				returnCallback();
			}
		}
		else {
			var responseHandler = null;
			var functionToQueue = null;

			if (streamStateObject['responseProperties']['responseHandler'] === null) {
				responseHandler = function (device, fid, packetResponse) {
					var result = [];
					var payload = null;
					var llvalues = null;
					var packetErrorFlag = 0;
					var rolesMappedData = [];
					var shortWriteWritten = -1;
					var streamStateObject = device.streamStateObjects[fid];
					var responseEmpty = streamStateObject['responseProperties']['streamInResponseEmpty'];
					var inputRegistersLength = 0;
					var inputRegistersChunkData = [];
					var inputRegistersChunkOffset = 0;

					function doNextLLCall() {
						inputRegistersLength = streamStateObject['responseProperties']['data'].length;
						inputRegistersChunkData =
							device.ipcon.createChunkData(streamStateObject['responseProperties']['data'],
							                             streamStateObject['responseProperties']['streamInChunkOffset'],
							                             streamStateObject['responseProperties']['streamInChunkLength'],
							                             '\0');
						inputRegistersChunkOffset = streamStateObject['responseProperties']['streamInChunkOffset'];

						for (var i = 0; i < streamStateObject['dataMappingStreamIn'].length; i++) {
							if (streamStateObject['dataMappingStreamIn'][i] === null) {
								continue;
							}

							if (streamStateObject['dataMappingStreamIn'][i].endsWith('Length')) {
								streamStateObject['responseProperties']['streamInLLParams'][i] = inputRegistersLength;
							}
							else if (streamStateObject['dataMappingStreamIn'][i].endsWith('Offset')) {
								streamStateObject['responseProperties']['streamInLLParams'][i] = inputRegistersChunkOffset;
							}
							else if (streamStateObject['dataMappingStreamIn'][i].endsWith('Data')) {
								streamStateObject['responseProperties']['streamInLLParams'][i] = inputRegistersChunkData;
							}
						}

						device.ipcon.sendRequest(device,
						                         BrickletRS485.FUNCTION_MODBUS_SLAVE_ANSWER_READ_INPUT_REGISTERS_REQUEST_LOW_LEVEL,
						                         streamStateObject['responseProperties']['streamInLLParams'],
						                         'B H H H29',
						                         0,
						                         '',
						                         returnCallback,
						                         errorCallback,
						                         true,
						                         true);

						streamStateObject['responseProperties']['streamInChunkOffset'] += 29;
					}

					function handleStreamInDone() {
						if (streamStateObject['responseProperties']['returnCB']) {
							if (streamStateObject['streamProperties']['shortWrite']) {
								for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
									if (streamStateObject['dataMapping'][i].endsWith('Written')) {
										result[i] = streamStateObject['responseProperties']['streamInWritten'];
										break;
									}
								}
							}

							if (!responseEmpty) {
								streamStateObject['responseProperties']['returnCB'].apply(device, result);
							}
							else {
								streamStateObject['responseProperties']['returnCB'].apply(device);
							}
						}

						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}
					}

					if (!streamStateObject) {
						return;
					}

					packetErrorFlag = device.ipcon.getEFromPacket(packetResponse);

					if (packetErrorFlag !== 0) {
						if (streamStateObject['responseProperties']['errorCB'] !== undefined) {
							if (packetErrorFlag === 1) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_INVALID_PARAMETER);
							}
							else if (packetErrorFlag === 2) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_FUNCTION_NOT_SUPPORTED);
							}
							else {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_UNKNOWN_ERROR);
							}
						}

						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}

						return;
					}

					if (responseEmpty) {
						if (streamStateObject['streamProperties']['singleChunk']) {
							handleStreamInDone();

							return;
						}

						if (streamStateObject['responseProperties']['streamInChunkOffset'] < streamStateObject['responseProperties']['data'].length) {
							doNextLLCall();
						}
						else {
							handleStreamInDone();
						}
					}
					else {
						payload = device.ipcon.getPayloadFromPacket(packetResponse);
						llvalues = device.ipcon.unpack(payload,
						                               streamStateObject['responseProperties']['unpackFormatString']);

						if (!payload || !llvalues) {
							device.resetStreamStateObject(streamStateObject);

							if (streamStateObject['responseProperties']['callQueue'].length > 0) {
								streamStateObject['responseProperties']['callQueue'].shift()(device);
							}

							return;
						}

						for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
							result.push(llvalues[i]);
						}

						if (streamStateObject['streamProperties']['singleChunk']) {
							if (streamStateObject['responseProperties']['returnCB']) {
								streamStateObject['responseProperties']['returnCB'].apply(device, result);
							}

							device.resetStreamStateObject(streamStateObject);

							if (streamStateObject['responseProperties']['callQueue'].length > 0) {
								streamStateObject['responseProperties']['callQueue'].shift()(device);
							}

							return;
						}

						if (streamStateObject['streamProperties']['shortWrite']) {
							for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
								if (streamStateObject['dataMapping'][i].endsWith('Written')) {
									shortWriteWritten = llvalues[i];
									streamStateObject['responseProperties']['streamInWritten'] += shortWriteWritten;
									break;
								}
							}
							if ((shortWriteWritten !== -1) && (shortWriteWritten < 29)) {
								// Either last chunk or short write
								handleStreamInDone();
								return;
							}
						}

						if (streamStateObject['responseProperties']['streamInChunkOffset'] < streamStateObject['responseProperties']['data'].length) {
							doNextLLCall();
						}
						else {
							handleStreamInDone();
						}
					}
				};

				streamStateObject['responseProperties']['responseHandler'] = responseHandler;
			}

			if (!streamStateObject['responseProperties']['running']) {
				streamStateObject['responseProperties']['running'] = true;
				streamStateObject['responseProperties']['returnCB'] = returnCallback;
				streamStateObject['responseProperties']['errorCB'] = errorCallback;
				streamStateObject['responseProperties']['data'].length = 0;
				streamStateObject['responseProperties']['data'].push.apply(streamStateObject['responseProperties']['data'],
				                                                           inputRegisters);

				if (streamStateObject['streamProperties']['fixedLength']) {
					inputRegistersLength = streamStateObject['streamProperties']['fixedLength'];
				}
				else {
					inputRegistersLength = inputRegisters.length;
				}

				inputRegistersChunkOffset = 0;
				inputRegistersChunkData =
					this.ipcon.createChunkData(inputRegisters, 0, 29, '\0');

				streamStateObject['responseProperties']['streamInChunkOffset'] = 29;
				streamStateObject['responseProperties']['streamInChunkLength'] = 29;
				streamStateObject['responseProperties']['streamInLLParams'] = [requestID, inputRegistersLength, inputRegistersChunkOffset, inputRegistersChunkData];

				this.ipcon.sendRequest(this,
				                       BrickletRS485.FUNCTION_MODBUS_SLAVE_ANSWER_READ_INPUT_REGISTERS_REQUEST_LOW_LEVEL,
				                       [requestID, inputRegistersLength, inputRegistersChunkOffset, inputRegistersChunkData],
				                       'B H H H29',
				                       0,
				                       '',
				                       returnCallback,
				                       errorCallback,
				                       true,
				                       true);
			}
			else {
				functionToQueue = function (device) {
					device.modbusSlaveAnswerReadInputRegistersRequest.call(device, requestID, inputRegisters, returnCallback, errorCallback);
				}

				streamStateObject['responseProperties']['callQueue'].push(functionToQueue);
			}
		}
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletRS485;

},{"./Device":279,"./IPConnection":280}],249:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletRealTimeClock.DEVICE_IDENTIFIER = 268;
BrickletRealTimeClock.DEVICE_DISPLAY_NAME = 'Real-Time Clock Bricklet';
BrickletRealTimeClock.CALLBACK_DATE_TIME = 10;
BrickletRealTimeClock.CALLBACK_ALARM = 11;
BrickletRealTimeClock.FUNCTION_SET_DATE_TIME = 1;
BrickletRealTimeClock.FUNCTION_GET_DATE_TIME = 2;
BrickletRealTimeClock.FUNCTION_GET_TIMESTAMP = 3;
BrickletRealTimeClock.FUNCTION_SET_OFFSET = 4;
BrickletRealTimeClock.FUNCTION_GET_OFFSET = 5;
BrickletRealTimeClock.FUNCTION_SET_DATE_TIME_CALLBACK_PERIOD = 6;
BrickletRealTimeClock.FUNCTION_GET_DATE_TIME_CALLBACK_PERIOD = 7;
BrickletRealTimeClock.FUNCTION_SET_ALARM = 8;
BrickletRealTimeClock.FUNCTION_GET_ALARM = 9;
BrickletRealTimeClock.FUNCTION_GET_IDENTITY = 255;
BrickletRealTimeClock.WEEKDAY_MONDAY = 1;
BrickletRealTimeClock.WEEKDAY_TUESDAY = 2;
BrickletRealTimeClock.WEEKDAY_WEDNESDAY = 3;
BrickletRealTimeClock.WEEKDAY_THURSDAY = 4;
BrickletRealTimeClock.WEEKDAY_FRIDAY = 5;
BrickletRealTimeClock.WEEKDAY_SATURDAY = 6;
BrickletRealTimeClock.WEEKDAY_SUNDAY = 7;
BrickletRealTimeClock.ALARM_MATCH_DISABLED = -1;
BrickletRealTimeClock.ALARM_INTERVAL_DISABLED = -1;

function BrickletRealTimeClock(uid, ipcon) {
	//Battery-backed real-time clock

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletRealTimeClock.DEVICE_IDENTIFIER, BrickletRealTimeClock.DEVICE_DISPLAY_NAME);
	BrickletRealTimeClock.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 1];
	this.responseExpected[BrickletRealTimeClock.FUNCTION_SET_DATE_TIME] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletRealTimeClock.FUNCTION_GET_DATE_TIME] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRealTimeClock.FUNCTION_GET_TIMESTAMP] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRealTimeClock.FUNCTION_SET_OFFSET] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletRealTimeClock.FUNCTION_GET_OFFSET] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRealTimeClock.FUNCTION_SET_DATE_TIME_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletRealTimeClock.FUNCTION_GET_DATE_TIME_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRealTimeClock.FUNCTION_SET_ALARM] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletRealTimeClock.FUNCTION_GET_ALARM] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRealTimeClock.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletRealTimeClock.CALLBACK_DATE_TIME] = [25, 'H B B B B B B B q'];
	this.callbackFormats[BrickletRealTimeClock.CALLBACK_ALARM] = [25, 'H B B B B B B B q'];



	this.setDateTime = function(year, month, day, hour, minute, second, centisecond, weekday, returnCallback, errorCallback) {
		/*
		Sets the current date (including weekday) and the current time.
		
		If the backup battery is installed then the real-time clock keeps date and
		time even if the Bricklet is not powered by a Brick.
		
		The real-time clock handles leap year and inserts the 29th of February
		accordingly. But leap seconds, time zones and daylight saving time are not
		handled.
		*/
		this.ipcon.sendRequest(this, BrickletRealTimeClock.FUNCTION_SET_DATE_TIME, [year, month, day, hour, minute, second, centisecond, weekday], 'H B B B B B B B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getDateTime = function(returnCallback, errorCallback) {
		/*
		Returns the current date (including weekday) and the current time of the
		real-time clock.
		*/
		this.ipcon.sendRequest(this, BrickletRealTimeClock.FUNCTION_GET_DATE_TIME, [], '', 17, 'H B B B B B B B', returnCallback, errorCallback, false, true);
	};
	this.getTimestamp = function(returnCallback, errorCallback) {
		/*
		Returns the current date and the time of the real-time clock.
		The timestamp has an effective resolution of hundredths of a
		second and is an offset to 2000-01-01 00:00:00.000.
		*/
		this.ipcon.sendRequest(this, BrickletRealTimeClock.FUNCTION_GET_TIMESTAMP, [], '', 16, 'q', returnCallback, errorCallback, false, true);
	};
	this.setOffset = function(offset, returnCallback, errorCallback) {
		/*
		Sets the offset the real-time clock should compensate for in 2.17 ppm steps
		between -277.76 ppm (-128) and +275.59 ppm (127).
		
		The real-time clock time can deviate from the actual time due to the frequency
		deviation of its 32.768 kHz crystal. Even without compensation (factory
		default) the resulting time deviation should be at most ±20 ppm (±52.6
		seconds per month).
		
		This deviation can be calculated by comparing the same duration measured by the
		real-time clock (``rtc_duration``) an accurate reference clock
		(``ref_duration``).
		
		For best results the configured offset should be set to 0 ppm first and then a
		duration of at least 6 hours should be measured.
		
		The new offset (``new_offset``) can be calculated from the currently configured
		offset (``current_offset``) and the measured durations as follow::
		
		  new_offset = current_offset - round(1000000 * (rtc_duration - ref_duration) / rtc_duration / 2.17)
		
		If you want to calculate the offset, then we recommend using the calibration
		dialog in Brick Viewer, instead of doing it manually.
		
		The offset is saved in the EEPROM of the Bricklet and only needs to be
		configured once.
		*/
		this.ipcon.sendRequest(this, BrickletRealTimeClock.FUNCTION_SET_OFFSET, [offset], 'b', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getOffset = function(returnCallback, errorCallback) {
		/*
		Returns the offset as set by :func:`Set Offset`.
		*/
		this.ipcon.sendRequest(this, BrickletRealTimeClock.FUNCTION_GET_OFFSET, [], '', 9, 'b', returnCallback, errorCallback, false, true);
	};
	this.setDateTimeCallbackPeriod = function(period, returnCallback, errorCallback) {
		/*
		Sets the period with which the :cb:`Date Time` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		The :cb:`Date Time` Callback is only triggered if the date or time changed
		since the last triggering.
		
		.. versionadded:: 2.0.1$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletRealTimeClock.FUNCTION_SET_DATE_TIME_CALLBACK_PERIOD, [period], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getDateTimeCallbackPeriod = function(returnCallback, errorCallback) {
		/*
		Returns the period as set by :func:`Set Date Time Callback Period`.
		
		.. versionadded:: 2.0.1$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletRealTimeClock.FUNCTION_GET_DATE_TIME_CALLBACK_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setAlarm = function(month, day, hour, minute, second, weekday, interval, returnCallback, errorCallback) {
		/*
		Configures a repeatable alarm. The :cb:`Alarm` callback is triggered if the
		current date and time matches the configured alarm.
		
		Setting a parameter to -1 means that it should be disabled and doesn't take part
		in the match. Setting all parameters to -1 disables the alarm completely.
		
		For example, to make the alarm trigger every day at 7:30 AM it can be
		configured as (-1, -1, 7, 30, -1, -1, -1). The hour is set to match 7 and the
		minute is set to match 30. The alarm is triggered if all enabled parameters
		match.
		
		The interval has a special role. It allows to make the alarm reconfigure itself.
		This is useful if you need a repeated alarm that cannot be expressed by matching
		the current date and time. For example, to make the alarm trigger every 23
		seconds it can be configured as (-1, -1, -1, -1, -1, -1, 23). Internally the
		Bricklet will take the current date and time, add 23 seconds to it and set the
		result as its alarm. The first alarm will be triggered 23 seconds after the
		call. Because the interval is not -1, the Bricklet will do the same again
		internally, take the current date and time, add 23 seconds to it and set that
		as its alarm. This results in a repeated alarm that triggers every 23 seconds.
		
		The interval can also be used in combination with the other parameters. For
		example, configuring the alarm as (-1, -1, 7, 30, -1, -1, 300) results in an
		alarm that triggers every day at 7:30 AM and is then repeated every 5 minutes.
		
		.. versionadded:: 2.0.1$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletRealTimeClock.FUNCTION_SET_ALARM, [month, day, hour, minute, second, weekday, interval], 'b b b b b b i', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getAlarm = function(returnCallback, errorCallback) {
		/*
		Returns the alarm configuration as set by :func:`Set Alarm`.
		
		.. versionadded:: 2.0.1$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletRealTimeClock.FUNCTION_GET_ALARM, [], '', 18, 'b b b b b b i', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletRealTimeClock.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletRealTimeClock;

},{"./Device":279,"./IPConnection":280}],250:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletRealTimeClockV2.DEVICE_IDENTIFIER = 2106;
BrickletRealTimeClockV2.DEVICE_DISPLAY_NAME = 'Real-Time Clock Bricklet 2.0';
BrickletRealTimeClockV2.CALLBACK_DATE_TIME = 10;
BrickletRealTimeClockV2.CALLBACK_ALARM = 11;
BrickletRealTimeClockV2.FUNCTION_SET_DATE_TIME = 1;
BrickletRealTimeClockV2.FUNCTION_GET_DATE_TIME = 2;
BrickletRealTimeClockV2.FUNCTION_GET_TIMESTAMP = 3;
BrickletRealTimeClockV2.FUNCTION_SET_OFFSET = 4;
BrickletRealTimeClockV2.FUNCTION_GET_OFFSET = 5;
BrickletRealTimeClockV2.FUNCTION_SET_DATE_TIME_CALLBACK_CONFIGURATION = 6;
BrickletRealTimeClockV2.FUNCTION_GET_DATE_TIME_CALLBACK_CONFIGURATION = 7;
BrickletRealTimeClockV2.FUNCTION_SET_ALARM = 8;
BrickletRealTimeClockV2.FUNCTION_GET_ALARM = 9;
BrickletRealTimeClockV2.FUNCTION_GET_SPITFP_ERROR_COUNT = 234;
BrickletRealTimeClockV2.FUNCTION_SET_BOOTLOADER_MODE = 235;
BrickletRealTimeClockV2.FUNCTION_GET_BOOTLOADER_MODE = 236;
BrickletRealTimeClockV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER = 237;
BrickletRealTimeClockV2.FUNCTION_WRITE_FIRMWARE = 238;
BrickletRealTimeClockV2.FUNCTION_SET_STATUS_LED_CONFIG = 239;
BrickletRealTimeClockV2.FUNCTION_GET_STATUS_LED_CONFIG = 240;
BrickletRealTimeClockV2.FUNCTION_GET_CHIP_TEMPERATURE = 242;
BrickletRealTimeClockV2.FUNCTION_RESET = 243;
BrickletRealTimeClockV2.FUNCTION_WRITE_UID = 248;
BrickletRealTimeClockV2.FUNCTION_READ_UID = 249;
BrickletRealTimeClockV2.FUNCTION_GET_IDENTITY = 255;
BrickletRealTimeClockV2.WEEKDAY_MONDAY = 1;
BrickletRealTimeClockV2.WEEKDAY_TUESDAY = 2;
BrickletRealTimeClockV2.WEEKDAY_WEDNESDAY = 3;
BrickletRealTimeClockV2.WEEKDAY_THURSDAY = 4;
BrickletRealTimeClockV2.WEEKDAY_FRIDAY = 5;
BrickletRealTimeClockV2.WEEKDAY_SATURDAY = 6;
BrickletRealTimeClockV2.WEEKDAY_SUNDAY = 7;
BrickletRealTimeClockV2.ALARM_MATCH_DISABLED = -1;
BrickletRealTimeClockV2.ALARM_INTERVAL_DISABLED = -1;
BrickletRealTimeClockV2.BOOTLOADER_MODE_BOOTLOADER = 0;
BrickletRealTimeClockV2.BOOTLOADER_MODE_FIRMWARE = 1;
BrickletRealTimeClockV2.BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT = 2;
BrickletRealTimeClockV2.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT = 3;
BrickletRealTimeClockV2.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT = 4;
BrickletRealTimeClockV2.BOOTLOADER_STATUS_OK = 0;
BrickletRealTimeClockV2.BOOTLOADER_STATUS_INVALID_MODE = 1;
BrickletRealTimeClockV2.BOOTLOADER_STATUS_NO_CHANGE = 2;
BrickletRealTimeClockV2.BOOTLOADER_STATUS_ENTRY_FUNCTION_NOT_PRESENT = 3;
BrickletRealTimeClockV2.BOOTLOADER_STATUS_DEVICE_IDENTIFIER_INCORRECT = 4;
BrickletRealTimeClockV2.BOOTLOADER_STATUS_CRC_MISMATCH = 5;
BrickletRealTimeClockV2.STATUS_LED_CONFIG_OFF = 0;
BrickletRealTimeClockV2.STATUS_LED_CONFIG_ON = 1;
BrickletRealTimeClockV2.STATUS_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletRealTimeClockV2.STATUS_LED_CONFIG_SHOW_STATUS = 3;

function BrickletRealTimeClockV2(uid, ipcon) {
	//Battery-backed real-time clock

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletRealTimeClockV2.DEVICE_IDENTIFIER, BrickletRealTimeClockV2.DEVICE_DISPLAY_NAME);
	BrickletRealTimeClockV2.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickletRealTimeClockV2.FUNCTION_SET_DATE_TIME] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletRealTimeClockV2.FUNCTION_GET_DATE_TIME] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRealTimeClockV2.FUNCTION_GET_TIMESTAMP] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRealTimeClockV2.FUNCTION_SET_OFFSET] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletRealTimeClockV2.FUNCTION_GET_OFFSET] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRealTimeClockV2.FUNCTION_SET_DATE_TIME_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletRealTimeClockV2.FUNCTION_GET_DATE_TIME_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRealTimeClockV2.FUNCTION_SET_ALARM] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletRealTimeClockV2.FUNCTION_GET_ALARM] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRealTimeClockV2.FUNCTION_GET_SPITFP_ERROR_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRealTimeClockV2.FUNCTION_SET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRealTimeClockV2.FUNCTION_GET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRealTimeClockV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletRealTimeClockV2.FUNCTION_WRITE_FIRMWARE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRealTimeClockV2.FUNCTION_SET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletRealTimeClockV2.FUNCTION_GET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRealTimeClockV2.FUNCTION_GET_CHIP_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRealTimeClockV2.FUNCTION_RESET] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletRealTimeClockV2.FUNCTION_WRITE_UID] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletRealTimeClockV2.FUNCTION_READ_UID] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRealTimeClockV2.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletRealTimeClockV2.CALLBACK_DATE_TIME] = [25, 'H B B B B B B B q'];
	this.callbackFormats[BrickletRealTimeClockV2.CALLBACK_ALARM] = [25, 'H B B B B B B B q'];



	this.setDateTime = function(year, month, day, hour, minute, second, centisecond, weekday, returnCallback, errorCallback) {
		/*
		Sets the current date (including weekday) and the current time.
		
		If the backup battery is installed then the real-time clock keeps date and
		time even if the Bricklet is not powered by a Brick.
		
		The real-time clock handles leap year and inserts the 29th of February
		accordingly. But leap seconds, time zones and daylight saving time are not
		handled.
		*/
		this.ipcon.sendRequest(this, BrickletRealTimeClockV2.FUNCTION_SET_DATE_TIME, [year, month, day, hour, minute, second, centisecond, weekday], 'H B B B B B B B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getDateTime = function(returnCallback, errorCallback) {
		/*
		Returns the current date (including weekday) and the current time of the
		real-time.
		
		The timestamp represents the current date and the the current time of the
		real-time clock converted to milliseconds and is an offset to 2000-01-01 00:00:00.0000.
		*/
		this.ipcon.sendRequest(this, BrickletRealTimeClockV2.FUNCTION_GET_DATE_TIME, [], '', 25, 'H B B B B B B B q', returnCallback, errorCallback, false, true);
	};
	this.getTimestamp = function(returnCallback, errorCallback) {
		/*
		Returns the current date and the time of the real-time clock converted to
		milliseconds. The timestamp has an effective resolution of hundredths of a
		second and is an offset to 2000-01-01 00:00:00.0000.
		*/
		this.ipcon.sendRequest(this, BrickletRealTimeClockV2.FUNCTION_GET_TIMESTAMP, [], '', 16, 'q', returnCallback, errorCallback, false, true);
	};
	this.setOffset = function(offset, returnCallback, errorCallback) {
		/*
		Sets the offset the real-time clock should compensate for in 2.17 ppm steps
		between -277.76 ppm (-128) and +275.59 ppm (127).
		
		The real-time clock time can deviate from the actual time due to the frequency
		deviation of its 32.768 kHz crystal. Even without compensation (factory
		default) the resulting time deviation should be at most ±20 ppm (±52.6
		seconds per month).
		
		This deviation can be calculated by comparing the same duration measured by the
		real-time clock (``rtc_duration``) an accurate reference clock
		(``ref_duration``).
		
		For best results the configured offset should be set to 0 ppm first and then a
		duration of at least 6 hours should be measured.
		
		The new offset (``new_offset``) can be calculated from the currently configured
		offset (``current_offset``) and the measured durations as follow::
		
		  new_offset = current_offset - round(1000000 * (rtc_duration - ref_duration) / rtc_duration / 2.17)
		
		If you want to calculate the offset, then we recommend using the calibration
		dialog in Brick Viewer, instead of doing it manually.
		
		The offset is saved in the EEPROM of the Bricklet and only needs to be
		configured once.
		*/
		this.ipcon.sendRequest(this, BrickletRealTimeClockV2.FUNCTION_SET_OFFSET, [offset], 'b', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getOffset = function(returnCallback, errorCallback) {
		/*
		Returns the offset as set by :func:`Set Offset`.
		*/
		this.ipcon.sendRequest(this, BrickletRealTimeClockV2.FUNCTION_GET_OFFSET, [], '', 9, 'b', returnCallback, errorCallback, false, true);
	};
	this.setDateTimeCallbackConfiguration = function(period, returnCallback, errorCallback) {
		/*
		Sets the period with which the :cb:`Date Time` callback is triggered
		periodically. A value of 0 turns the callback off.
		*/
		this.ipcon.sendRequest(this, BrickletRealTimeClockV2.FUNCTION_SET_DATE_TIME_CALLBACK_CONFIGURATION, [period], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getDateTimeCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the period as set by :func:`Set Date Time Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletRealTimeClockV2.FUNCTION_GET_DATE_TIME_CALLBACK_CONFIGURATION, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setAlarm = function(month, day, hour, minute, second, weekday, interval, returnCallback, errorCallback) {
		/*
		Configures a repeatable alarm. The :cb:`Alarm` callback is triggered if the
		current date and time matches the configured alarm.
		
		Setting a parameter to -1 means that it should be disabled and doesn't take part
		in the match. Setting all parameters to -1 disables the alarm completely.
		
		For example, to make the alarm trigger every day at 7:30 AM it can be
		configured as (-1, -1, 7, 30, -1, -1, -1). The hour is set to match 7 and the
		minute is set to match 30. The alarm is triggered if all enabled parameters
		match.
		
		The interval has a special role. It allows to make the alarm reconfigure itself.
		This is useful if you need a repeated alarm that cannot be expressed by matching
		the current date and time. For example, to make the alarm trigger every 23
		seconds it can be configured as (-1, -1, -1, -1, -1, -1, 23). Internally the
		Bricklet will take the current date and time, add 23 seconds to it and set the
		result as its alarm. The first alarm will be triggered 23 seconds after the
		call. Because the interval is not -1, the Bricklet will do the same again
		internally, take the current date and time, add 23 seconds to it and set that
		as its alarm. This results in a repeated alarm that triggers every 23 seconds.
		
		The interval can also be used in combination with the other parameters. For
		example, configuring the alarm as (-1, -1, 7, 30, -1, -1, 300) results in an
		alarm that triggers every day at 7:30 AM and is then repeated every 5 minutes.
		*/
		this.ipcon.sendRequest(this, BrickletRealTimeClockV2.FUNCTION_SET_ALARM, [month, day, hour, minute, second, weekday, interval], 'b b b b b b i', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getAlarm = function(returnCallback, errorCallback) {
		/*
		Returns the alarm configuration as set by :func:`Set Alarm`.
		*/
		this.ipcon.sendRequest(this, BrickletRealTimeClockV2.FUNCTION_GET_ALARM, [], '', 18, 'b b b b b b i', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPErrorCount = function(returnCallback, errorCallback) {
		/*
		Returns the error count for the communication between Brick and Bricklet.
		
		The errors are divided into
		
		* ACK checksum errors,
		* message checksum errors,
		* framing errors and
		* overflow errors.
		
		The errors counts are for errors that occur on the Bricklet side. All
		Bricks have a similar function that returns the errors on the Brick side.
		*/
		this.ipcon.sendRequest(this, BrickletRealTimeClockV2.FUNCTION_GET_SPITFP_ERROR_COUNT, [], '', 24, 'I I I I', returnCallback, errorCallback, false, true);
	};
	this.setBootloaderMode = function(mode, returnCallback, errorCallback) {
		/*
		Sets the bootloader mode and returns the status after the requested
		mode change was instigated.
		
		You can change from bootloader mode to firmware mode and vice versa. A change
		from bootloader mode to firmware mode will only take place if the entry function,
		device identifier and CRC are present and correct.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletRealTimeClockV2.FUNCTION_SET_BOOTLOADER_MODE, [mode], 'B', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getBootloaderMode = function(returnCallback, errorCallback) {
		/*
		Returns the current bootloader mode, see :func:`Set Bootloader Mode`.
		*/
		this.ipcon.sendRequest(this, BrickletRealTimeClockV2.FUNCTION_GET_BOOTLOADER_MODE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setWriteFirmwarePointer = function(pointer, returnCallback, errorCallback) {
		/*
		Sets the firmware pointer for :func:`Write Firmware`. The pointer has
		to be increased by chunks of size 64. The data is written to flash
		every 4 chunks (which equals to one page of size 256).
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletRealTimeClockV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER, [pointer], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeFirmware = function(data, returnCallback, errorCallback) {
		/*
		Writes 64 Bytes of firmware at the position as written by
		:func:`Set Write Firmware Pointer` before. The firmware is written
		to flash every 4 chunks.
		
		You can only write firmware in bootloader mode.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletRealTimeClockV2.FUNCTION_WRITE_FIRMWARE, [data], 'B64', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setStatusLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Sets the status LED configuration. By default the LED shows
		communication traffic between Brick and Bricklet, it flickers once
		for every 10 received data packets.
		
		You can also turn the LED permanently on/off or show a heartbeat.
		
		If the Bricklet is in bootloader mode, the LED is will show heartbeat by default.
		*/
		this.ipcon.sendRequest(this, BrickletRealTimeClockV2.FUNCTION_SET_STATUS_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getStatusLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Status LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletRealTimeClockV2.FUNCTION_GET_STATUS_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getChipTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature as measured inside the microcontroller. The
		value returned is not the ambient temperature!
		
		The temperature is only proportional to the real temperature and it has bad
		accuracy. Practically it is only useful as an indicator for
		temperature changes.
		*/
		this.ipcon.sendRequest(this, BrickletRealTimeClockV2.FUNCTION_GET_CHIP_TEMPERATURE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.reset = function(returnCallback, errorCallback) {
		/*
		Calling this function will reset the Bricklet. All configurations
		will be lost.
		
		After a reset you have to create new device objects,
		calling functions on the existing ones will result in
		undefined behavior!
		*/
		this.ipcon.sendRequest(this, BrickletRealTimeClockV2.FUNCTION_RESET, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeUID = function(uid, returnCallback, errorCallback) {
		/*
		Writes a new UID into flash. If you want to set a new UID
		you have to decode the Base58 encoded UID string into an
		integer first.
		
		We recommend that you use Brick Viewer to change the UID.
		*/
		this.ipcon.sendRequest(this, BrickletRealTimeClockV2.FUNCTION_WRITE_UID, [uid], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.readUID = function(returnCallback, errorCallback) {
		/*
		Returns the current UID as an integer. Encode as
		Base58 to get the usual string version.
		*/
		this.ipcon.sendRequest(this, BrickletRealTimeClockV2.FUNCTION_READ_UID, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletRealTimeClockV2.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletRealTimeClockV2;

},{"./Device":279,"./IPConnection":280}],251:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletRemoteSwitch.DEVICE_IDENTIFIER = 235;
BrickletRemoteSwitch.DEVICE_DISPLAY_NAME = 'Remote Switch Bricklet';
BrickletRemoteSwitch.CALLBACK_SWITCHING_DONE = 3;
BrickletRemoteSwitch.FUNCTION_SWITCH_SOCKET = 1;
BrickletRemoteSwitch.FUNCTION_GET_SWITCHING_STATE = 2;
BrickletRemoteSwitch.FUNCTION_SET_REPEATS = 4;
BrickletRemoteSwitch.FUNCTION_GET_REPEATS = 5;
BrickletRemoteSwitch.FUNCTION_SWITCH_SOCKET_A = 6;
BrickletRemoteSwitch.FUNCTION_SWITCH_SOCKET_B = 7;
BrickletRemoteSwitch.FUNCTION_DIM_SOCKET_B = 8;
BrickletRemoteSwitch.FUNCTION_SWITCH_SOCKET_C = 9;
BrickletRemoteSwitch.FUNCTION_GET_IDENTITY = 255;
BrickletRemoteSwitch.SWITCH_TO_OFF = 0;
BrickletRemoteSwitch.SWITCH_TO_ON = 1;
BrickletRemoteSwitch.SWITCHING_STATE_READY = 0;
BrickletRemoteSwitch.SWITCHING_STATE_BUSY = 1;

function BrickletRemoteSwitch(uid, ipcon) {
	//Controls remote mains switches

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletRemoteSwitch.DEVICE_IDENTIFIER, BrickletRemoteSwitch.DEVICE_DISPLAY_NAME);
	BrickletRemoteSwitch.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 1];
	this.responseExpected[BrickletRemoteSwitch.FUNCTION_SWITCH_SOCKET] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletRemoteSwitch.FUNCTION_GET_SWITCHING_STATE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRemoteSwitch.FUNCTION_SET_REPEATS] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletRemoteSwitch.FUNCTION_GET_REPEATS] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRemoteSwitch.FUNCTION_SWITCH_SOCKET_A] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletRemoteSwitch.FUNCTION_SWITCH_SOCKET_B] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletRemoteSwitch.FUNCTION_DIM_SOCKET_B] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletRemoteSwitch.FUNCTION_SWITCH_SOCKET_C] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletRemoteSwitch.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletRemoteSwitch.CALLBACK_SWITCHING_DONE] = [8, ''];



	this.switchSocket = function(houseCode, receiverCode, switchTo, returnCallback, errorCallback) {
		/*
		This function is deprecated, use :func:`Switch Socket A` instead.
		*/
		this.ipcon.sendRequest(this, BrickletRemoteSwitch.FUNCTION_SWITCH_SOCKET, [houseCode, receiverCode, switchTo], 'B B B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getSwitchingState = function(returnCallback, errorCallback) {
		/*
		Returns the current switching state. If the current state is busy, the
		Bricklet is currently sending a code to switch a socket. It will not
		accept any requests to switch sockets until the state changes to ready.
		
		How long the switching takes is dependent on the number of repeats, see
		:func:`Set Repeats`.
		*/
		this.ipcon.sendRequest(this, BrickletRemoteSwitch.FUNCTION_GET_SWITCHING_STATE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setRepeats = function(repeats, returnCallback, errorCallback) {
		/*
		Sets the number of times the code is sent when one of the switch socket
		functions is called. The repeats basically correspond to the amount of time
		that a button of the remote is pressed.
		
		Some dimmers are controlled by the length of a button pressed,
		this can be simulated by increasing the repeats.
		*/
		this.ipcon.sendRequest(this, BrickletRemoteSwitch.FUNCTION_SET_REPEATS, [repeats], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getRepeats = function(returnCallback, errorCallback) {
		/*
		Returns the number of repeats as set by :func:`Set Repeats`.
		*/
		this.ipcon.sendRequest(this, BrickletRemoteSwitch.FUNCTION_GET_REPEATS, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.switchSocketA = function(houseCode, receiverCode, switchTo, returnCallback, errorCallback) {
		/*
		To switch a type A socket you have to give the house code, receiver code and the
		state (on or off) you want to switch to.
		
		A detailed description on how you can figure out the house and receiver code
		can be found :ref:`here <remote_switch_bricklet_type_a_house_and_receiver_code>`.
		
		.. versionadded:: 2.0.1$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletRemoteSwitch.FUNCTION_SWITCH_SOCKET_A, [houseCode, receiverCode, switchTo], 'B B B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.switchSocketB = function(address, unit, switchTo, returnCallback, errorCallback) {
		/*
		To switch a type B socket you have to give the address, unit and the state
		(on or off) you want to switch to.
		
		To switch all devices with the same address use 255 for the unit.
		
		A detailed description on how you can teach a socket the address and unit can
		be found :ref:`here <remote_switch_bricklet_type_b_address_and_unit>`.
		
		.. versionadded:: 2.0.1$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletRemoteSwitch.FUNCTION_SWITCH_SOCKET_B, [address, unit, switchTo], 'I B B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.dimSocketB = function(address, unit, dimValue, returnCallback, errorCallback) {
		/*
		To control a type B dimmer you have to give the address, unit and the
		dim value you want to set the dimmer to.
		
		A detailed description on how you can teach a dimmer the address and unit can
		be found :ref:`here <remote_switch_bricklet_type_b_address_and_unit>`.
		
		.. versionadded:: 2.0.1$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletRemoteSwitch.FUNCTION_DIM_SOCKET_B, [address, unit, dimValue], 'I B B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.switchSocketC = function(systemCode, deviceCode, switchTo, returnCallback, errorCallback) {
		/*
		To switch a type C socket you have to give the system code, device code and the
		state (on or off) you want to switch to.
		
		A detailed description on how you can figure out the system and device code
		can be found :ref:`here <remote_switch_bricklet_type_c_system_and_device_code>`.
		
		.. versionadded:: 2.0.1$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletRemoteSwitch.FUNCTION_SWITCH_SOCKET_C, [systemCode, deviceCode, switchTo], 'c B B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletRemoteSwitch.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletRemoteSwitch;

},{"./Device":279,"./IPConnection":280}],252:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletRemoteSwitchV2.DEVICE_IDENTIFIER = 289;
BrickletRemoteSwitchV2.DEVICE_DISPLAY_NAME = 'Remote Switch Bricklet 2.0';
BrickletRemoteSwitchV2.CALLBACK_SWITCHING_DONE = 2;
BrickletRemoteSwitchV2.CALLBACK_REMOTE_STATUS_A = 14;
BrickletRemoteSwitchV2.CALLBACK_REMOTE_STATUS_B = 15;
BrickletRemoteSwitchV2.CALLBACK_REMOTE_STATUS_C = 16;
BrickletRemoteSwitchV2.FUNCTION_GET_SWITCHING_STATE = 1;
BrickletRemoteSwitchV2.FUNCTION_SET_REPEATS = 3;
BrickletRemoteSwitchV2.FUNCTION_GET_REPEATS = 4;
BrickletRemoteSwitchV2.FUNCTION_SWITCH_SOCKET_A = 5;
BrickletRemoteSwitchV2.FUNCTION_SWITCH_SOCKET_B = 6;
BrickletRemoteSwitchV2.FUNCTION_DIM_SOCKET_B = 7;
BrickletRemoteSwitchV2.FUNCTION_SWITCH_SOCKET_C = 8;
BrickletRemoteSwitchV2.FUNCTION_SET_REMOTE_CONFIGURATION = 9;
BrickletRemoteSwitchV2.FUNCTION_GET_REMOTE_CONFIGURATION = 10;
BrickletRemoteSwitchV2.FUNCTION_GET_REMOTE_STATUS_A = 11;
BrickletRemoteSwitchV2.FUNCTION_GET_REMOTE_STATUS_B = 12;
BrickletRemoteSwitchV2.FUNCTION_GET_REMOTE_STATUS_C = 13;
BrickletRemoteSwitchV2.FUNCTION_GET_SPITFP_ERROR_COUNT = 234;
BrickletRemoteSwitchV2.FUNCTION_SET_BOOTLOADER_MODE = 235;
BrickletRemoteSwitchV2.FUNCTION_GET_BOOTLOADER_MODE = 236;
BrickletRemoteSwitchV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER = 237;
BrickletRemoteSwitchV2.FUNCTION_WRITE_FIRMWARE = 238;
BrickletRemoteSwitchV2.FUNCTION_SET_STATUS_LED_CONFIG = 239;
BrickletRemoteSwitchV2.FUNCTION_GET_STATUS_LED_CONFIG = 240;
BrickletRemoteSwitchV2.FUNCTION_GET_CHIP_TEMPERATURE = 242;
BrickletRemoteSwitchV2.FUNCTION_RESET = 243;
BrickletRemoteSwitchV2.FUNCTION_WRITE_UID = 248;
BrickletRemoteSwitchV2.FUNCTION_READ_UID = 249;
BrickletRemoteSwitchV2.FUNCTION_GET_IDENTITY = 255;
BrickletRemoteSwitchV2.SWITCHING_STATE_READY = 0;
BrickletRemoteSwitchV2.SWITCHING_STATE_BUSY = 1;
BrickletRemoteSwitchV2.SWITCH_TO_OFF = 0;
BrickletRemoteSwitchV2.SWITCH_TO_ON = 1;
BrickletRemoteSwitchV2.REMOTE_TYPE_A = 0;
BrickletRemoteSwitchV2.REMOTE_TYPE_B = 1;
BrickletRemoteSwitchV2.REMOTE_TYPE_C = 2;
BrickletRemoteSwitchV2.BOOTLOADER_MODE_BOOTLOADER = 0;
BrickletRemoteSwitchV2.BOOTLOADER_MODE_FIRMWARE = 1;
BrickletRemoteSwitchV2.BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT = 2;
BrickletRemoteSwitchV2.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT = 3;
BrickletRemoteSwitchV2.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT = 4;
BrickletRemoteSwitchV2.BOOTLOADER_STATUS_OK = 0;
BrickletRemoteSwitchV2.BOOTLOADER_STATUS_INVALID_MODE = 1;
BrickletRemoteSwitchV2.BOOTLOADER_STATUS_NO_CHANGE = 2;
BrickletRemoteSwitchV2.BOOTLOADER_STATUS_ENTRY_FUNCTION_NOT_PRESENT = 3;
BrickletRemoteSwitchV2.BOOTLOADER_STATUS_DEVICE_IDENTIFIER_INCORRECT = 4;
BrickletRemoteSwitchV2.BOOTLOADER_STATUS_CRC_MISMATCH = 5;
BrickletRemoteSwitchV2.STATUS_LED_CONFIG_OFF = 0;
BrickletRemoteSwitchV2.STATUS_LED_CONFIG_ON = 1;
BrickletRemoteSwitchV2.STATUS_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletRemoteSwitchV2.STATUS_LED_CONFIG_SHOW_STATUS = 3;

function BrickletRemoteSwitchV2(uid, ipcon) {
	//Controls remote mains switches and receives signals from remotes

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletRemoteSwitchV2.DEVICE_IDENTIFIER, BrickletRemoteSwitchV2.DEVICE_DISPLAY_NAME);
	BrickletRemoteSwitchV2.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickletRemoteSwitchV2.FUNCTION_GET_SWITCHING_STATE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRemoteSwitchV2.FUNCTION_SET_REPEATS] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletRemoteSwitchV2.FUNCTION_GET_REPEATS] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRemoteSwitchV2.FUNCTION_SWITCH_SOCKET_A] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletRemoteSwitchV2.FUNCTION_SWITCH_SOCKET_B] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletRemoteSwitchV2.FUNCTION_DIM_SOCKET_B] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletRemoteSwitchV2.FUNCTION_SWITCH_SOCKET_C] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletRemoteSwitchV2.FUNCTION_SET_REMOTE_CONFIGURATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletRemoteSwitchV2.FUNCTION_GET_REMOTE_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRemoteSwitchV2.FUNCTION_GET_REMOTE_STATUS_A] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRemoteSwitchV2.FUNCTION_GET_REMOTE_STATUS_B] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRemoteSwitchV2.FUNCTION_GET_REMOTE_STATUS_C] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRemoteSwitchV2.FUNCTION_GET_SPITFP_ERROR_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRemoteSwitchV2.FUNCTION_SET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRemoteSwitchV2.FUNCTION_GET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRemoteSwitchV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletRemoteSwitchV2.FUNCTION_WRITE_FIRMWARE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRemoteSwitchV2.FUNCTION_SET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletRemoteSwitchV2.FUNCTION_GET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRemoteSwitchV2.FUNCTION_GET_CHIP_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRemoteSwitchV2.FUNCTION_RESET] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletRemoteSwitchV2.FUNCTION_WRITE_UID] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletRemoteSwitchV2.FUNCTION_READ_UID] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRemoteSwitchV2.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletRemoteSwitchV2.CALLBACK_SWITCHING_DONE] = [8, ''];
	this.callbackFormats[BrickletRemoteSwitchV2.CALLBACK_REMOTE_STATUS_A] = [13, 'B B B H'];
	this.callbackFormats[BrickletRemoteSwitchV2.CALLBACK_REMOTE_STATUS_B] = [17, 'I B B B H'];
	this.callbackFormats[BrickletRemoteSwitchV2.CALLBACK_REMOTE_STATUS_C] = [13, 'c B B H'];



	this.getSwitchingState = function(returnCallback, errorCallback) {
		/*
		Returns the current switching state. If the current state is busy, the
		Bricklet is currently sending a code to switch a socket. It will not
		accept any calls of switch socket functions until the state changes to ready.
		
		How long the switching takes is dependent on the number of repeats, see
		:func:`Set Repeats`.
		*/
		this.ipcon.sendRequest(this, BrickletRemoteSwitchV2.FUNCTION_GET_SWITCHING_STATE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setRepeats = function(repeats, returnCallback, errorCallback) {
		/*
		Sets the number of times the code is sent when one of the Switch Socket
		functions is called. The repeats basically correspond to the amount of time
		that a button of the remote is pressed.
		
		Some dimmers are controlled by the length of a button pressed,
		this can be simulated by increasing the repeats.
		*/
		this.ipcon.sendRequest(this, BrickletRemoteSwitchV2.FUNCTION_SET_REPEATS, [repeats], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getRepeats = function(returnCallback, errorCallback) {
		/*
		Returns the number of repeats as set by :func:`Set Repeats`.
		*/
		this.ipcon.sendRequest(this, BrickletRemoteSwitchV2.FUNCTION_GET_REPEATS, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.switchSocketA = function(houseCode, receiverCode, switchTo, returnCallback, errorCallback) {
		/*
		To switch a type A socket you have to give the house code, receiver code and the
		state (on or off) you want to switch to.
		
		A detailed description on how you can figure out the house and receiver code
		can be found :ref:`here <remote_switch_bricklet_type_a_house_and_receiver_code>`.
		*/
		this.ipcon.sendRequest(this, BrickletRemoteSwitchV2.FUNCTION_SWITCH_SOCKET_A, [houseCode, receiverCode, switchTo], 'B B B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.switchSocketB = function(address, unit, switchTo, returnCallback, errorCallback) {
		/*
		To switch a type B socket you have to give the address, unit and the state
		(on or off) you want to switch to.
		
		To switch all devices with the same address use 255 for the unit.
		
		A detailed description on how you can teach a socket the address and unit can
		be found :ref:`here <remote_switch_bricklet_type_b_address_and_unit>`.
		*/
		this.ipcon.sendRequest(this, BrickletRemoteSwitchV2.FUNCTION_SWITCH_SOCKET_B, [address, unit, switchTo], 'I B B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.dimSocketB = function(address, unit, dimValue, returnCallback, errorCallback) {
		/*
		To control a type B dimmer you have to give the address, unit and the
		dim value you want to set the dimmer to.
		
		A detailed description on how you can teach a dimmer the address and unit can
		be found :ref:`here <remote_switch_bricklet_type_b_address_and_unit>`.
		*/
		this.ipcon.sendRequest(this, BrickletRemoteSwitchV2.FUNCTION_DIM_SOCKET_B, [address, unit, dimValue], 'I B B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.switchSocketC = function(systemCode, deviceCode, switchTo, returnCallback, errorCallback) {
		/*
		To switch a type C socket you have to give the system code, device code and the
		state (on or off) you want to switch to.
		
		A detailed description on how you can figure out the system and device code
		can be found :ref:`here <remote_switch_bricklet_type_c_system_and_device_code>`.
		*/
		this.ipcon.sendRequest(this, BrickletRemoteSwitchV2.FUNCTION_SWITCH_SOCKET_C, [systemCode, deviceCode, switchTo], 'c B B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.setRemoteConfiguration = function(remoteType, minimumRepeats, callbackEnabled, returnCallback, errorCallback) {
		/*
		Sets the configuration for **receiving** data from a remote of type A, B or C.
		
		* Remote Type: A, B or C depending on the type of remote you want to receive.
		* Minimum Repeats: The minimum number of repeated data packets until the callback
		  is triggered (if enabled).
		* Callback Enabled: Enable or disable callback (see :cb:`Remote Status A` callback,
		  :cb:`Remote Status B` callback and :cb:`Remote Status C` callback).
		*/
		this.ipcon.sendRequest(this, BrickletRemoteSwitchV2.FUNCTION_SET_REMOTE_CONFIGURATION, [remoteType, minimumRepeats, callbackEnabled], 'B H ?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getRemoteConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the remote configuration as set by :func:`Set Remote Configuration`
		*/
		this.ipcon.sendRequest(this, BrickletRemoteSwitchV2.FUNCTION_GET_REMOTE_CONFIGURATION, [], '', 12, 'B H ?', returnCallback, errorCallback, false, true);
	};
	this.getRemoteStatusA = function(returnCallback, errorCallback) {
		/*
		Returns the house code, receiver code, switch state (on/off) and number of
		repeats for remote type A.
		
		Repeats == 0 means there was no button press. Repeats >= 1 means there
		was a button press with the specified house/receiver code. The repeats are the
		number of received identical data packets. The longer the button is pressed,
		the higher the repeat number.
		
		Use the callback to get this data automatically when a button is pressed,
		see :func:`Set Remote Configuration` and :cb:`Remote Status A` callback.
		*/
		this.ipcon.sendRequest(this, BrickletRemoteSwitchV2.FUNCTION_GET_REMOTE_STATUS_A, [], '', 13, 'B B B H', returnCallback, errorCallback, false, true);
	};
	this.getRemoteStatusB = function(returnCallback, errorCallback) {
		/*
		Returns the address (unique per remote), unit (button number), switch state
		(on/off) and number of repeats for remote type B.
		
		If the remote supports dimming the dim value is used instead of the switch state.
		
		If repeats=0 there was no button press. If repeats >= 1 there
		was a button press with the specified address/unit. The repeats are the number of received
		identical data packets. The longer the button is pressed, the higher the repeat number.
		
		Use the callback to get this data automatically when a button is pressed,
		see :func:`Set Remote Configuration` and :cb:`Remote Status B` callback.
		*/
		this.ipcon.sendRequest(this, BrickletRemoteSwitchV2.FUNCTION_GET_REMOTE_STATUS_B, [], '', 17, 'I B B B H', returnCallback, errorCallback, false, true);
	};
	this.getRemoteStatusC = function(returnCallback, errorCallback) {
		/*
		Returns the system code, device code, switch state (on/off) and number of repeats for
		remote type C.
		
		If repeats=0 there was no button press. If repeats >= 1 there
		was a button press with the specified system/device code. The repeats are the number of received
		identical data packets. The longer the button is pressed, the higher the repeat number.
		
		Use the callback to get this data automatically when a button is pressed,
		see :func:`Set Remote Configuration` and :cb:`Remote Status C` callback.
		*/
		this.ipcon.sendRequest(this, BrickletRemoteSwitchV2.FUNCTION_GET_REMOTE_STATUS_C, [], '', 13, 'c B B H', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPErrorCount = function(returnCallback, errorCallback) {
		/*
		Returns the error count for the communication between Brick and Bricklet.
		
		The errors are divided into
		
		* ACK checksum errors,
		* message checksum errors,
		* framing errors and
		* overflow errors.
		
		The errors counts are for errors that occur on the Bricklet side. All
		Bricks have a similar function that returns the errors on the Brick side.
		*/
		this.ipcon.sendRequest(this, BrickletRemoteSwitchV2.FUNCTION_GET_SPITFP_ERROR_COUNT, [], '', 24, 'I I I I', returnCallback, errorCallback, false, true);
	};
	this.setBootloaderMode = function(mode, returnCallback, errorCallback) {
		/*
		Sets the bootloader mode and returns the status after the requested
		mode change was instigated.
		
		You can change from bootloader mode to firmware mode and vice versa. A change
		from bootloader mode to firmware mode will only take place if the entry function,
		device identifier and CRC are present and correct.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletRemoteSwitchV2.FUNCTION_SET_BOOTLOADER_MODE, [mode], 'B', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getBootloaderMode = function(returnCallback, errorCallback) {
		/*
		Returns the current bootloader mode, see :func:`Set Bootloader Mode`.
		*/
		this.ipcon.sendRequest(this, BrickletRemoteSwitchV2.FUNCTION_GET_BOOTLOADER_MODE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setWriteFirmwarePointer = function(pointer, returnCallback, errorCallback) {
		/*
		Sets the firmware pointer for :func:`Write Firmware`. The pointer has
		to be increased by chunks of size 64. The data is written to flash
		every 4 chunks (which equals to one page of size 256).
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletRemoteSwitchV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER, [pointer], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeFirmware = function(data, returnCallback, errorCallback) {
		/*
		Writes 64 Bytes of firmware at the position as written by
		:func:`Set Write Firmware Pointer` before. The firmware is written
		to flash every 4 chunks.
		
		You can only write firmware in bootloader mode.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletRemoteSwitchV2.FUNCTION_WRITE_FIRMWARE, [data], 'B64', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setStatusLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Sets the status LED configuration. By default the LED shows
		communication traffic between Brick and Bricklet, it flickers once
		for every 10 received data packets.
		
		You can also turn the LED permanently on/off or show a heartbeat.
		
		If the Bricklet is in bootloader mode, the LED is will show heartbeat by default.
		*/
		this.ipcon.sendRequest(this, BrickletRemoteSwitchV2.FUNCTION_SET_STATUS_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getStatusLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Status LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletRemoteSwitchV2.FUNCTION_GET_STATUS_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getChipTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature as measured inside the microcontroller. The
		value returned is not the ambient temperature!
		
		The temperature is only proportional to the real temperature and it has bad
		accuracy. Practically it is only useful as an indicator for
		temperature changes.
		*/
		this.ipcon.sendRequest(this, BrickletRemoteSwitchV2.FUNCTION_GET_CHIP_TEMPERATURE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.reset = function(returnCallback, errorCallback) {
		/*
		Calling this function will reset the Bricklet. All configurations
		will be lost.
		
		After a reset you have to create new device objects,
		calling functions on the existing ones will result in
		undefined behavior!
		*/
		this.ipcon.sendRequest(this, BrickletRemoteSwitchV2.FUNCTION_RESET, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeUID = function(uid, returnCallback, errorCallback) {
		/*
		Writes a new UID into flash. If you want to set a new UID
		you have to decode the Base58 encoded UID string into an
		integer first.
		
		We recommend that you use Brick Viewer to change the UID.
		*/
		this.ipcon.sendRequest(this, BrickletRemoteSwitchV2.FUNCTION_WRITE_UID, [uid], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.readUID = function(returnCallback, errorCallback) {
		/*
		Returns the current UID as an integer. Encode as
		Base58 to get the usual string version.
		*/
		this.ipcon.sendRequest(this, BrickletRemoteSwitchV2.FUNCTION_READ_UID, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletRemoteSwitchV2.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletRemoteSwitchV2;

},{"./Device":279,"./IPConnection":280}],253:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletRotaryEncoder.DEVICE_IDENTIFIER = 236;
BrickletRotaryEncoder.DEVICE_DISPLAY_NAME = 'Rotary Encoder Bricklet';
BrickletRotaryEncoder.CALLBACK_COUNT = 8;
BrickletRotaryEncoder.CALLBACK_COUNT_REACHED = 9;
BrickletRotaryEncoder.CALLBACK_PRESSED = 11;
BrickletRotaryEncoder.CALLBACK_RELEASED = 12;
BrickletRotaryEncoder.FUNCTION_GET_COUNT = 1;
BrickletRotaryEncoder.FUNCTION_SET_COUNT_CALLBACK_PERIOD = 2;
BrickletRotaryEncoder.FUNCTION_GET_COUNT_CALLBACK_PERIOD = 3;
BrickletRotaryEncoder.FUNCTION_SET_COUNT_CALLBACK_THRESHOLD = 4;
BrickletRotaryEncoder.FUNCTION_GET_COUNT_CALLBACK_THRESHOLD = 5;
BrickletRotaryEncoder.FUNCTION_SET_DEBOUNCE_PERIOD = 6;
BrickletRotaryEncoder.FUNCTION_GET_DEBOUNCE_PERIOD = 7;
BrickletRotaryEncoder.FUNCTION_IS_PRESSED = 10;
BrickletRotaryEncoder.FUNCTION_GET_IDENTITY = 255;
BrickletRotaryEncoder.THRESHOLD_OPTION_OFF = 'x';
BrickletRotaryEncoder.THRESHOLD_OPTION_OUTSIDE = 'o';
BrickletRotaryEncoder.THRESHOLD_OPTION_INSIDE = 'i';
BrickletRotaryEncoder.THRESHOLD_OPTION_SMALLER = '<';
BrickletRotaryEncoder.THRESHOLD_OPTION_GREATER = '>';

function BrickletRotaryEncoder(uid, ipcon) {
	//360° rotary encoder with push-button

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletRotaryEncoder.DEVICE_IDENTIFIER, BrickletRotaryEncoder.DEVICE_DISPLAY_NAME);
	BrickletRotaryEncoder.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickletRotaryEncoder.FUNCTION_GET_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRotaryEncoder.FUNCTION_SET_COUNT_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletRotaryEncoder.FUNCTION_GET_COUNT_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRotaryEncoder.FUNCTION_SET_COUNT_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletRotaryEncoder.FUNCTION_GET_COUNT_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRotaryEncoder.FUNCTION_SET_DEBOUNCE_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletRotaryEncoder.FUNCTION_GET_DEBOUNCE_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRotaryEncoder.FUNCTION_IS_PRESSED] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRotaryEncoder.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletRotaryEncoder.CALLBACK_COUNT] = [12, 'i'];
	this.callbackFormats[BrickletRotaryEncoder.CALLBACK_COUNT_REACHED] = [12, 'i'];
	this.callbackFormats[BrickletRotaryEncoder.CALLBACK_PRESSED] = [8, ''];
	this.callbackFormats[BrickletRotaryEncoder.CALLBACK_RELEASED] = [8, ''];



	this.getCount = function(reset, returnCallback, errorCallback) {
		/*
		Returns the current count of the encoder. If you set reset
		to true, the count is set back to 0 directly after the
		current count is read.
		
		The encoder has 24 steps per rotation
		
		Turning the encoder to the left decrements the counter,
		so a negative count is possible.
		*/
		this.ipcon.sendRequest(this, BrickletRotaryEncoder.FUNCTION_GET_COUNT, [reset], '?', 12, 'i', returnCallback, errorCallback, false, true);
	};
	this.setCountCallbackPeriod = function(period, returnCallback, errorCallback) {
		/*
		Sets the period with which the :cb:`Count` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		The :cb:`Count` callback is only triggered if the count has changed since the
		last triggering.
		*/
		this.ipcon.sendRequest(this, BrickletRotaryEncoder.FUNCTION_SET_COUNT_CALLBACK_PERIOD, [period], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getCountCallbackPeriod = function(returnCallback, errorCallback) {
		/*
		Returns the period as set by :func:`Set Count Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletRotaryEncoder.FUNCTION_GET_COUNT_CALLBACK_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setCountCallbackThreshold = function(option, min, max, returnCallback, errorCallback) {
		/*
		Sets the thresholds for the :cb:`Count Reached` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Callback is turned off"
		 "'o'",    "Callback is triggered when the count is *outside* the min and max values"
		 "'i'",    "Callback is triggered when the count is *inside* the min and max values"
		 "'<'",    "Callback is triggered when the count is smaller than the min value (max is ignored)"
		 "'>'",    "Callback is triggered when the count is greater than the min value (max is ignored)"
		*/
		this.ipcon.sendRequest(this, BrickletRotaryEncoder.FUNCTION_SET_COUNT_CALLBACK_THRESHOLD, [option, min, max], 'c i i', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getCountCallbackThreshold = function(returnCallback, errorCallback) {
		/*
		Returns the threshold as set by :func:`Set Count Callback Threshold`.
		*/
		this.ipcon.sendRequest(this, BrickletRotaryEncoder.FUNCTION_GET_COUNT_CALLBACK_THRESHOLD, [], '', 17, 'c i i', returnCallback, errorCallback, false, true);
	};
	this.setDebouncePeriod = function(debounce, returnCallback, errorCallback) {
		/*
		Sets the period with which the threshold callback
		
		* :cb:`Count Reached`
		
		is triggered, if the thresholds
		
		* :func:`Set Count Callback Threshold`
		
		keeps being reached.
		*/
		this.ipcon.sendRequest(this, BrickletRotaryEncoder.FUNCTION_SET_DEBOUNCE_PERIOD, [debounce], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getDebouncePeriod = function(returnCallback, errorCallback) {
		/*
		Returns the debounce period as set by :func:`Set Debounce Period`.
		*/
		this.ipcon.sendRequest(this, BrickletRotaryEncoder.FUNCTION_GET_DEBOUNCE_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.isPressed = function(returnCallback, errorCallback) {
		/*
		Returns *true* if the button is pressed and *false* otherwise.
		
		It is recommended to use the :cb:`Pressed` and :cb:`Released` callbacks
		to handle the button.
		*/
		this.ipcon.sendRequest(this, BrickletRotaryEncoder.FUNCTION_IS_PRESSED, [], '', 9, '?', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletRotaryEncoder.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletRotaryEncoder;

},{"./Device":279,"./IPConnection":280}],254:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletRotaryEncoderV2.DEVICE_IDENTIFIER = 294;
BrickletRotaryEncoderV2.DEVICE_DISPLAY_NAME = 'Rotary Encoder Bricklet 2.0';
BrickletRotaryEncoderV2.CALLBACK_COUNT = 4;
BrickletRotaryEncoderV2.CALLBACK_PRESSED = 6;
BrickletRotaryEncoderV2.CALLBACK_RELEASED = 7;
BrickletRotaryEncoderV2.FUNCTION_GET_COUNT = 1;
BrickletRotaryEncoderV2.FUNCTION_SET_COUNT_CALLBACK_CONFIGURATION = 2;
BrickletRotaryEncoderV2.FUNCTION_GET_COUNT_CALLBACK_CONFIGURATION = 3;
BrickletRotaryEncoderV2.FUNCTION_IS_PRESSED = 5;
BrickletRotaryEncoderV2.FUNCTION_GET_SPITFP_ERROR_COUNT = 234;
BrickletRotaryEncoderV2.FUNCTION_SET_BOOTLOADER_MODE = 235;
BrickletRotaryEncoderV2.FUNCTION_GET_BOOTLOADER_MODE = 236;
BrickletRotaryEncoderV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER = 237;
BrickletRotaryEncoderV2.FUNCTION_WRITE_FIRMWARE = 238;
BrickletRotaryEncoderV2.FUNCTION_SET_STATUS_LED_CONFIG = 239;
BrickletRotaryEncoderV2.FUNCTION_GET_STATUS_LED_CONFIG = 240;
BrickletRotaryEncoderV2.FUNCTION_GET_CHIP_TEMPERATURE = 242;
BrickletRotaryEncoderV2.FUNCTION_RESET = 243;
BrickletRotaryEncoderV2.FUNCTION_WRITE_UID = 248;
BrickletRotaryEncoderV2.FUNCTION_READ_UID = 249;
BrickletRotaryEncoderV2.FUNCTION_GET_IDENTITY = 255;
BrickletRotaryEncoderV2.THRESHOLD_OPTION_OFF = 'x';
BrickletRotaryEncoderV2.THRESHOLD_OPTION_OUTSIDE = 'o';
BrickletRotaryEncoderV2.THRESHOLD_OPTION_INSIDE = 'i';
BrickletRotaryEncoderV2.THRESHOLD_OPTION_SMALLER = '<';
BrickletRotaryEncoderV2.THRESHOLD_OPTION_GREATER = '>';
BrickletRotaryEncoderV2.BOOTLOADER_MODE_BOOTLOADER = 0;
BrickletRotaryEncoderV2.BOOTLOADER_MODE_FIRMWARE = 1;
BrickletRotaryEncoderV2.BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT = 2;
BrickletRotaryEncoderV2.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT = 3;
BrickletRotaryEncoderV2.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT = 4;
BrickletRotaryEncoderV2.BOOTLOADER_STATUS_OK = 0;
BrickletRotaryEncoderV2.BOOTLOADER_STATUS_INVALID_MODE = 1;
BrickletRotaryEncoderV2.BOOTLOADER_STATUS_NO_CHANGE = 2;
BrickletRotaryEncoderV2.BOOTLOADER_STATUS_ENTRY_FUNCTION_NOT_PRESENT = 3;
BrickletRotaryEncoderV2.BOOTLOADER_STATUS_DEVICE_IDENTIFIER_INCORRECT = 4;
BrickletRotaryEncoderV2.BOOTLOADER_STATUS_CRC_MISMATCH = 5;
BrickletRotaryEncoderV2.STATUS_LED_CONFIG_OFF = 0;
BrickletRotaryEncoderV2.STATUS_LED_CONFIG_ON = 1;
BrickletRotaryEncoderV2.STATUS_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletRotaryEncoderV2.STATUS_LED_CONFIG_SHOW_STATUS = 3;

function BrickletRotaryEncoderV2(uid, ipcon) {
	//360° rotary encoder with push-button

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletRotaryEncoderV2.DEVICE_IDENTIFIER, BrickletRotaryEncoderV2.DEVICE_DISPLAY_NAME);
	BrickletRotaryEncoderV2.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 1];
	this.responseExpected[BrickletRotaryEncoderV2.FUNCTION_GET_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRotaryEncoderV2.FUNCTION_SET_COUNT_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletRotaryEncoderV2.FUNCTION_GET_COUNT_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRotaryEncoderV2.FUNCTION_IS_PRESSED] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRotaryEncoderV2.FUNCTION_GET_SPITFP_ERROR_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRotaryEncoderV2.FUNCTION_SET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRotaryEncoderV2.FUNCTION_GET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRotaryEncoderV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletRotaryEncoderV2.FUNCTION_WRITE_FIRMWARE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRotaryEncoderV2.FUNCTION_SET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletRotaryEncoderV2.FUNCTION_GET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRotaryEncoderV2.FUNCTION_GET_CHIP_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRotaryEncoderV2.FUNCTION_RESET] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletRotaryEncoderV2.FUNCTION_WRITE_UID] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletRotaryEncoderV2.FUNCTION_READ_UID] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRotaryEncoderV2.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletRotaryEncoderV2.CALLBACK_COUNT] = [12, 'i'];
	this.callbackFormats[BrickletRotaryEncoderV2.CALLBACK_PRESSED] = [8, ''];
	this.callbackFormats[BrickletRotaryEncoderV2.CALLBACK_RELEASED] = [8, ''];



	this.getCount = function(reset, returnCallback, errorCallback) {
		/*
		Returns the current count of the encoder. If you set reset
		to true, the count is set back to 0 directly after the
		current count is read.
		
		The encoder has 24 steps per rotation.
		
		Turning the encoder to the left decrements the counter,
		so a negative count is possible.
		
		
		If you want to get the value periodically, it is recommended to use the
		:cb:`Count` callback. You can set the callback configuration
		with :func:`Set Count Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletRotaryEncoderV2.FUNCTION_GET_COUNT, [reset], '?', 12, 'i', returnCallback, errorCallback, false, true);
	};
	this.setCountCallbackConfiguration = function(period, valueHasToChange, option, min, max, returnCallback, errorCallback) {
		/*
		The period is the period with which the :cb:`Count` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		If the `value has to change`-parameter is set to true, the callback is only
		triggered after the value has changed. If the value didn't change
		within the period, the callback is triggered immediately on change.
		
		If it is set to false, the callback is continuously triggered with the period,
		independent of the value.
		
		It is furthermore possible to constrain the callback with thresholds.
		
		The `option`-parameter together with min/max sets a threshold for the :cb:`Count` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Threshold is turned off"
		 "'o'",    "Threshold is triggered when the value is *outside* the min and max values"
		 "'i'",    "Threshold is triggered when the value is *inside* or equal to the min and max values"
		 "'<'",    "Threshold is triggered when the value is smaller than the min value (max is ignored)"
		 "'>'",    "Threshold is triggered when the value is greater than the min value (max is ignored)"
		
		If the option is set to 'x' (threshold turned off) the callback is triggered with the fixed period.
		*/
		this.ipcon.sendRequest(this, BrickletRotaryEncoderV2.FUNCTION_SET_COUNT_CALLBACK_CONFIGURATION, [period, valueHasToChange, option, min, max], 'I ? c i i', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getCountCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the callback configuration as set by :func:`Set Count Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletRotaryEncoderV2.FUNCTION_GET_COUNT_CALLBACK_CONFIGURATION, [], '', 22, 'I ? c i i', returnCallback, errorCallback, false, true);
	};
	this.isPressed = function(returnCallback, errorCallback) {
		/*
		Returns *true* if the button is pressed and *false* otherwise.
		
		It is recommended to use the :cb:`Pressed` and :cb:`Released` callbacks
		to handle the button.
		*/
		this.ipcon.sendRequest(this, BrickletRotaryEncoderV2.FUNCTION_IS_PRESSED, [], '', 9, '?', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPErrorCount = function(returnCallback, errorCallback) {
		/*
		Returns the error count for the communication between Brick and Bricklet.
		
		The errors are divided into
		
		* ACK checksum errors,
		* message checksum errors,
		* framing errors and
		* overflow errors.
		
		The errors counts are for errors that occur on the Bricklet side. All
		Bricks have a similar function that returns the errors on the Brick side.
		*/
		this.ipcon.sendRequest(this, BrickletRotaryEncoderV2.FUNCTION_GET_SPITFP_ERROR_COUNT, [], '', 24, 'I I I I', returnCallback, errorCallback, false, true);
	};
	this.setBootloaderMode = function(mode, returnCallback, errorCallback) {
		/*
		Sets the bootloader mode and returns the status after the requested
		mode change was instigated.
		
		You can change from bootloader mode to firmware mode and vice versa. A change
		from bootloader mode to firmware mode will only take place if the entry function,
		device identifier and CRC are present and correct.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletRotaryEncoderV2.FUNCTION_SET_BOOTLOADER_MODE, [mode], 'B', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getBootloaderMode = function(returnCallback, errorCallback) {
		/*
		Returns the current bootloader mode, see :func:`Set Bootloader Mode`.
		*/
		this.ipcon.sendRequest(this, BrickletRotaryEncoderV2.FUNCTION_GET_BOOTLOADER_MODE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setWriteFirmwarePointer = function(pointer, returnCallback, errorCallback) {
		/*
		Sets the firmware pointer for :func:`Write Firmware`. The pointer has
		to be increased by chunks of size 64. The data is written to flash
		every 4 chunks (which equals to one page of size 256).
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletRotaryEncoderV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER, [pointer], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeFirmware = function(data, returnCallback, errorCallback) {
		/*
		Writes 64 Bytes of firmware at the position as written by
		:func:`Set Write Firmware Pointer` before. The firmware is written
		to flash every 4 chunks.
		
		You can only write firmware in bootloader mode.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletRotaryEncoderV2.FUNCTION_WRITE_FIRMWARE, [data], 'B64', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setStatusLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Sets the status LED configuration. By default the LED shows
		communication traffic between Brick and Bricklet, it flickers once
		for every 10 received data packets.
		
		You can also turn the LED permanently on/off or show a heartbeat.
		
		If the Bricklet is in bootloader mode, the LED is will show heartbeat by default.
		*/
		this.ipcon.sendRequest(this, BrickletRotaryEncoderV2.FUNCTION_SET_STATUS_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getStatusLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Status LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletRotaryEncoderV2.FUNCTION_GET_STATUS_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getChipTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature as measured inside the microcontroller. The
		value returned is not the ambient temperature!
		
		The temperature is only proportional to the real temperature and it has bad
		accuracy. Practically it is only useful as an indicator for
		temperature changes.
		*/
		this.ipcon.sendRequest(this, BrickletRotaryEncoderV2.FUNCTION_GET_CHIP_TEMPERATURE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.reset = function(returnCallback, errorCallback) {
		/*
		Calling this function will reset the Bricklet. All configurations
		will be lost.
		
		After a reset you have to create new device objects,
		calling functions on the existing ones will result in
		undefined behavior!
		*/
		this.ipcon.sendRequest(this, BrickletRotaryEncoderV2.FUNCTION_RESET, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeUID = function(uid, returnCallback, errorCallback) {
		/*
		Writes a new UID into flash. If you want to set a new UID
		you have to decode the Base58 encoded UID string into an
		integer first.
		
		We recommend that you use Brick Viewer to change the UID.
		*/
		this.ipcon.sendRequest(this, BrickletRotaryEncoderV2.FUNCTION_WRITE_UID, [uid], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.readUID = function(returnCallback, errorCallback) {
		/*
		Returns the current UID as an integer. Encode as
		Base58 to get the usual string version.
		*/
		this.ipcon.sendRequest(this, BrickletRotaryEncoderV2.FUNCTION_READ_UID, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletRotaryEncoderV2.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletRotaryEncoderV2;

},{"./Device":279,"./IPConnection":280}],255:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletRotaryPoti.DEVICE_IDENTIFIER = 215;
BrickletRotaryPoti.DEVICE_DISPLAY_NAME = 'Rotary Poti Bricklet';
BrickletRotaryPoti.CALLBACK_POSITION = 13;
BrickletRotaryPoti.CALLBACK_ANALOG_VALUE = 14;
BrickletRotaryPoti.CALLBACK_POSITION_REACHED = 15;
BrickletRotaryPoti.CALLBACK_ANALOG_VALUE_REACHED = 16;
BrickletRotaryPoti.FUNCTION_GET_POSITION = 1;
BrickletRotaryPoti.FUNCTION_GET_ANALOG_VALUE = 2;
BrickletRotaryPoti.FUNCTION_SET_POSITION_CALLBACK_PERIOD = 3;
BrickletRotaryPoti.FUNCTION_GET_POSITION_CALLBACK_PERIOD = 4;
BrickletRotaryPoti.FUNCTION_SET_ANALOG_VALUE_CALLBACK_PERIOD = 5;
BrickletRotaryPoti.FUNCTION_GET_ANALOG_VALUE_CALLBACK_PERIOD = 6;
BrickletRotaryPoti.FUNCTION_SET_POSITION_CALLBACK_THRESHOLD = 7;
BrickletRotaryPoti.FUNCTION_GET_POSITION_CALLBACK_THRESHOLD = 8;
BrickletRotaryPoti.FUNCTION_SET_ANALOG_VALUE_CALLBACK_THRESHOLD = 9;
BrickletRotaryPoti.FUNCTION_GET_ANALOG_VALUE_CALLBACK_THRESHOLD = 10;
BrickletRotaryPoti.FUNCTION_SET_DEBOUNCE_PERIOD = 11;
BrickletRotaryPoti.FUNCTION_GET_DEBOUNCE_PERIOD = 12;
BrickletRotaryPoti.FUNCTION_GET_IDENTITY = 255;
BrickletRotaryPoti.THRESHOLD_OPTION_OFF = 'x';
BrickletRotaryPoti.THRESHOLD_OPTION_OUTSIDE = 'o';
BrickletRotaryPoti.THRESHOLD_OPTION_INSIDE = 'i';
BrickletRotaryPoti.THRESHOLD_OPTION_SMALLER = '<';
BrickletRotaryPoti.THRESHOLD_OPTION_GREATER = '>';

function BrickletRotaryPoti(uid, ipcon) {
	//300° rotary potentiometer

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletRotaryPoti.DEVICE_IDENTIFIER, BrickletRotaryPoti.DEVICE_DISPLAY_NAME);
	BrickletRotaryPoti.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickletRotaryPoti.FUNCTION_GET_POSITION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRotaryPoti.FUNCTION_GET_ANALOG_VALUE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRotaryPoti.FUNCTION_SET_POSITION_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletRotaryPoti.FUNCTION_GET_POSITION_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRotaryPoti.FUNCTION_SET_ANALOG_VALUE_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletRotaryPoti.FUNCTION_GET_ANALOG_VALUE_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRotaryPoti.FUNCTION_SET_POSITION_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletRotaryPoti.FUNCTION_GET_POSITION_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRotaryPoti.FUNCTION_SET_ANALOG_VALUE_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletRotaryPoti.FUNCTION_GET_ANALOG_VALUE_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRotaryPoti.FUNCTION_SET_DEBOUNCE_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletRotaryPoti.FUNCTION_GET_DEBOUNCE_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRotaryPoti.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletRotaryPoti.CALLBACK_POSITION] = [10, 'h'];
	this.callbackFormats[BrickletRotaryPoti.CALLBACK_ANALOG_VALUE] = [10, 'H'];
	this.callbackFormats[BrickletRotaryPoti.CALLBACK_POSITION_REACHED] = [10, 'h'];
	this.callbackFormats[BrickletRotaryPoti.CALLBACK_ANALOG_VALUE_REACHED] = [10, 'H'];



	this.getPosition = function(returnCallback, errorCallback) {
		/*
		Returns the position of the rotary potentiometer. The value is
		between -150° (turned left) and 150° (turned right).
		
		If you want to get the position periodically, it is recommended to use the
		:cb:`Position` callback and set the period with
		:func:`Set Position Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletRotaryPoti.FUNCTION_GET_POSITION, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.getAnalogValue = function(returnCallback, errorCallback) {
		/*
		Returns the value as read by a 12-bit analog-to-digital converter.
		
		.. note::
		 The value returned by :func:`Get Position` is averaged over several samples
		 to yield less noise, while :func:`Get Analog Value` gives back raw
		 unfiltered analog values. The only reason to use :func:`Get Analog Value` is,
		 if you need the full resolution of the analog-to-digital converter.
		
		If you want the analog value periodically, it is recommended to use the
		:cb:`Analog Value` callback and set the period with
		:func:`Set Analog Value Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletRotaryPoti.FUNCTION_GET_ANALOG_VALUE, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.setPositionCallbackPeriod = function(period, returnCallback, errorCallback) {
		/*
		Sets the period with which the :cb:`Position` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		The :cb:`Position` callback is only triggered if the position has changed since
		the last triggering.
		*/
		this.ipcon.sendRequest(this, BrickletRotaryPoti.FUNCTION_SET_POSITION_CALLBACK_PERIOD, [period], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getPositionCallbackPeriod = function(returnCallback, errorCallback) {
		/*
		Returns the period as set by :func:`Set Position Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletRotaryPoti.FUNCTION_GET_POSITION_CALLBACK_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setAnalogValueCallbackPeriod = function(period, returnCallback, errorCallback) {
		/*
		Sets the period with which the :cb:`Analog Value` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		The :cb:`Analog Value` callback is only triggered if the analog value has
		changed since the last triggering.
		*/
		this.ipcon.sendRequest(this, BrickletRotaryPoti.FUNCTION_SET_ANALOG_VALUE_CALLBACK_PERIOD, [period], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getAnalogValueCallbackPeriod = function(returnCallback, errorCallback) {
		/*
		Returns the period as set by :func:`Set Analog Value Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletRotaryPoti.FUNCTION_GET_ANALOG_VALUE_CALLBACK_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setPositionCallbackThreshold = function(option, min, max, returnCallback, errorCallback) {
		/*
		Sets the thresholds for the :cb:`Position Reached` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Callback is turned off"
		 "'o'",    "Callback is triggered when the position is *outside* the min and max values"
		 "'i'",    "Callback is triggered when the position is *inside* the min and max values"
		 "'<'",    "Callback is triggered when the position is smaller than the min value (max is ignored)"
		 "'>'",    "Callback is triggered when the position is greater than the min value (max is ignored)"
		*/
		this.ipcon.sendRequest(this, BrickletRotaryPoti.FUNCTION_SET_POSITION_CALLBACK_THRESHOLD, [option, min, max], 'c h h', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getPositionCallbackThreshold = function(returnCallback, errorCallback) {
		/*
		Returns the threshold as set by :func:`Set Position Callback Threshold`.
		*/
		this.ipcon.sendRequest(this, BrickletRotaryPoti.FUNCTION_GET_POSITION_CALLBACK_THRESHOLD, [], '', 13, 'c h h', returnCallback, errorCallback, false, true);
	};
	this.setAnalogValueCallbackThreshold = function(option, min, max, returnCallback, errorCallback) {
		/*
		Sets the thresholds for the :cb:`Analog Value Reached` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Callback is turned off"
		 "'o'",    "Callback is triggered when the analog value is *outside* the min and max values"
		 "'i'",    "Callback is triggered when the analog value is *inside* the min and max values"
		 "'<'",    "Callback is triggered when the analog value is smaller than the min value (max is ignored)"
		 "'>'",    "Callback is triggered when the analog value is greater than the min value (max is ignored)"
		*/
		this.ipcon.sendRequest(this, BrickletRotaryPoti.FUNCTION_SET_ANALOG_VALUE_CALLBACK_THRESHOLD, [option, min, max], 'c H H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getAnalogValueCallbackThreshold = function(returnCallback, errorCallback) {
		/*
		Returns the threshold as set by :func:`Set Analog Value Callback Threshold`.
		*/
		this.ipcon.sendRequest(this, BrickletRotaryPoti.FUNCTION_GET_ANALOG_VALUE_CALLBACK_THRESHOLD, [], '', 13, 'c H H', returnCallback, errorCallback, false, true);
	};
	this.setDebouncePeriod = function(debounce, returnCallback, errorCallback) {
		/*
		Sets the period with which the threshold callbacks
		
		* :cb:`Position Reached`,
		* :cb:`Analog Value Reached`
		
		are triggered, if the thresholds
		
		* :func:`Set Position Callback Threshold`,
		* :func:`Set Analog Value Callback Threshold`
		
		keep being reached.
		*/
		this.ipcon.sendRequest(this, BrickletRotaryPoti.FUNCTION_SET_DEBOUNCE_PERIOD, [debounce], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getDebouncePeriod = function(returnCallback, errorCallback) {
		/*
		Returns the debounce period as set by :func:`Set Debounce Period`.
		*/
		this.ipcon.sendRequest(this, BrickletRotaryPoti.FUNCTION_GET_DEBOUNCE_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletRotaryPoti.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletRotaryPoti;

},{"./Device":279,"./IPConnection":280}],256:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletRotaryPotiV2.DEVICE_IDENTIFIER = 2140;
BrickletRotaryPotiV2.DEVICE_DISPLAY_NAME = 'Rotary Poti Bricklet 2.0';
BrickletRotaryPotiV2.CALLBACK_POSITION = 4;
BrickletRotaryPotiV2.FUNCTION_GET_POSITION = 1;
BrickletRotaryPotiV2.FUNCTION_SET_POSITION_CALLBACK_CONFIGURATION = 2;
BrickletRotaryPotiV2.FUNCTION_GET_POSITION_CALLBACK_CONFIGURATION = 3;
BrickletRotaryPotiV2.FUNCTION_GET_SPITFP_ERROR_COUNT = 234;
BrickletRotaryPotiV2.FUNCTION_SET_BOOTLOADER_MODE = 235;
BrickletRotaryPotiV2.FUNCTION_GET_BOOTLOADER_MODE = 236;
BrickletRotaryPotiV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER = 237;
BrickletRotaryPotiV2.FUNCTION_WRITE_FIRMWARE = 238;
BrickletRotaryPotiV2.FUNCTION_SET_STATUS_LED_CONFIG = 239;
BrickletRotaryPotiV2.FUNCTION_GET_STATUS_LED_CONFIG = 240;
BrickletRotaryPotiV2.FUNCTION_GET_CHIP_TEMPERATURE = 242;
BrickletRotaryPotiV2.FUNCTION_RESET = 243;
BrickletRotaryPotiV2.FUNCTION_WRITE_UID = 248;
BrickletRotaryPotiV2.FUNCTION_READ_UID = 249;
BrickletRotaryPotiV2.FUNCTION_GET_IDENTITY = 255;
BrickletRotaryPotiV2.THRESHOLD_OPTION_OFF = 'x';
BrickletRotaryPotiV2.THRESHOLD_OPTION_OUTSIDE = 'o';
BrickletRotaryPotiV2.THRESHOLD_OPTION_INSIDE = 'i';
BrickletRotaryPotiV2.THRESHOLD_OPTION_SMALLER = '<';
BrickletRotaryPotiV2.THRESHOLD_OPTION_GREATER = '>';
BrickletRotaryPotiV2.BOOTLOADER_MODE_BOOTLOADER = 0;
BrickletRotaryPotiV2.BOOTLOADER_MODE_FIRMWARE = 1;
BrickletRotaryPotiV2.BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT = 2;
BrickletRotaryPotiV2.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT = 3;
BrickletRotaryPotiV2.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT = 4;
BrickletRotaryPotiV2.BOOTLOADER_STATUS_OK = 0;
BrickletRotaryPotiV2.BOOTLOADER_STATUS_INVALID_MODE = 1;
BrickletRotaryPotiV2.BOOTLOADER_STATUS_NO_CHANGE = 2;
BrickletRotaryPotiV2.BOOTLOADER_STATUS_ENTRY_FUNCTION_NOT_PRESENT = 3;
BrickletRotaryPotiV2.BOOTLOADER_STATUS_DEVICE_IDENTIFIER_INCORRECT = 4;
BrickletRotaryPotiV2.BOOTLOADER_STATUS_CRC_MISMATCH = 5;
BrickletRotaryPotiV2.STATUS_LED_CONFIG_OFF = 0;
BrickletRotaryPotiV2.STATUS_LED_CONFIG_ON = 1;
BrickletRotaryPotiV2.STATUS_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletRotaryPotiV2.STATUS_LED_CONFIG_SHOW_STATUS = 3;

function BrickletRotaryPotiV2(uid, ipcon) {
	//300° rotary potentiometer

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletRotaryPotiV2.DEVICE_IDENTIFIER, BrickletRotaryPotiV2.DEVICE_DISPLAY_NAME);
	BrickletRotaryPotiV2.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickletRotaryPotiV2.FUNCTION_GET_POSITION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRotaryPotiV2.FUNCTION_SET_POSITION_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletRotaryPotiV2.FUNCTION_GET_POSITION_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRotaryPotiV2.FUNCTION_GET_SPITFP_ERROR_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRotaryPotiV2.FUNCTION_SET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRotaryPotiV2.FUNCTION_GET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRotaryPotiV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletRotaryPotiV2.FUNCTION_WRITE_FIRMWARE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRotaryPotiV2.FUNCTION_SET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletRotaryPotiV2.FUNCTION_GET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRotaryPotiV2.FUNCTION_GET_CHIP_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRotaryPotiV2.FUNCTION_RESET] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletRotaryPotiV2.FUNCTION_WRITE_UID] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletRotaryPotiV2.FUNCTION_READ_UID] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletRotaryPotiV2.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletRotaryPotiV2.CALLBACK_POSITION] = [10, 'h'];



	this.getPosition = function(returnCallback, errorCallback) {
		/*
		Returns the position of the rotary potentiometer. The value is
		between -150° (turned left) and 150° (turned right).
		
		
		If you want to get the value periodically, it is recommended to use the
		:cb:`Position` callback. You can set the callback configuration
		with :func:`Set Position Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletRotaryPotiV2.FUNCTION_GET_POSITION, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.setPositionCallbackConfiguration = function(period, valueHasToChange, option, min, max, returnCallback, errorCallback) {
		/*
		The period is the period with which the :cb:`Position` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		If the `value has to change`-parameter is set to true, the callback is only
		triggered after the value has changed. If the value didn't change
		within the period, the callback is triggered immediately on change.
		
		If it is set to false, the callback is continuously triggered with the period,
		independent of the value.
		
		It is furthermore possible to constrain the callback with thresholds.
		
		The `option`-parameter together with min/max sets a threshold for the :cb:`Position` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Threshold is turned off"
		 "'o'",    "Threshold is triggered when the value is *outside* the min and max values"
		 "'i'",    "Threshold is triggered when the value is *inside* or equal to the min and max values"
		 "'<'",    "Threshold is triggered when the value is smaller than the min value (max is ignored)"
		 "'>'",    "Threshold is triggered when the value is greater than the min value (max is ignored)"
		
		If the option is set to 'x' (threshold turned off) the callback is triggered with the fixed period.
		*/
		this.ipcon.sendRequest(this, BrickletRotaryPotiV2.FUNCTION_SET_POSITION_CALLBACK_CONFIGURATION, [period, valueHasToChange, option, min, max], 'I ? c h h', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getPositionCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the callback configuration as set by :func:`Set Position Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletRotaryPotiV2.FUNCTION_GET_POSITION_CALLBACK_CONFIGURATION, [], '', 18, 'I ? c h h', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPErrorCount = function(returnCallback, errorCallback) {
		/*
		Returns the error count for the communication between Brick and Bricklet.
		
		The errors are divided into
		
		* ACK checksum errors,
		* message checksum errors,
		* framing errors and
		* overflow errors.
		
		The errors counts are for errors that occur on the Bricklet side. All
		Bricks have a similar function that returns the errors on the Brick side.
		*/
		this.ipcon.sendRequest(this, BrickletRotaryPotiV2.FUNCTION_GET_SPITFP_ERROR_COUNT, [], '', 24, 'I I I I', returnCallback, errorCallback, false, true);
	};
	this.setBootloaderMode = function(mode, returnCallback, errorCallback) {
		/*
		Sets the bootloader mode and returns the status after the requested
		mode change was instigated.
		
		You can change from bootloader mode to firmware mode and vice versa. A change
		from bootloader mode to firmware mode will only take place if the entry function,
		device identifier and CRC are present and correct.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletRotaryPotiV2.FUNCTION_SET_BOOTLOADER_MODE, [mode], 'B', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getBootloaderMode = function(returnCallback, errorCallback) {
		/*
		Returns the current bootloader mode, see :func:`Set Bootloader Mode`.
		*/
		this.ipcon.sendRequest(this, BrickletRotaryPotiV2.FUNCTION_GET_BOOTLOADER_MODE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setWriteFirmwarePointer = function(pointer, returnCallback, errorCallback) {
		/*
		Sets the firmware pointer for :func:`Write Firmware`. The pointer has
		to be increased by chunks of size 64. The data is written to flash
		every 4 chunks (which equals to one page of size 256).
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletRotaryPotiV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER, [pointer], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeFirmware = function(data, returnCallback, errorCallback) {
		/*
		Writes 64 Bytes of firmware at the position as written by
		:func:`Set Write Firmware Pointer` before. The firmware is written
		to flash every 4 chunks.
		
		You can only write firmware in bootloader mode.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletRotaryPotiV2.FUNCTION_WRITE_FIRMWARE, [data], 'B64', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setStatusLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Sets the status LED configuration. By default the LED shows
		communication traffic between Brick and Bricklet, it flickers once
		for every 10 received data packets.
		
		You can also turn the LED permanently on/off or show a heartbeat.
		
		If the Bricklet is in bootloader mode, the LED is will show heartbeat by default.
		*/
		this.ipcon.sendRequest(this, BrickletRotaryPotiV2.FUNCTION_SET_STATUS_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getStatusLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Status LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletRotaryPotiV2.FUNCTION_GET_STATUS_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getChipTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature as measured inside the microcontroller. The
		value returned is not the ambient temperature!
		
		The temperature is only proportional to the real temperature and it has bad
		accuracy. Practically it is only useful as an indicator for
		temperature changes.
		*/
		this.ipcon.sendRequest(this, BrickletRotaryPotiV2.FUNCTION_GET_CHIP_TEMPERATURE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.reset = function(returnCallback, errorCallback) {
		/*
		Calling this function will reset the Bricklet. All configurations
		will be lost.
		
		After a reset you have to create new device objects,
		calling functions on the existing ones will result in
		undefined behavior!
		*/
		this.ipcon.sendRequest(this, BrickletRotaryPotiV2.FUNCTION_RESET, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeUID = function(uid, returnCallback, errorCallback) {
		/*
		Writes a new UID into flash. If you want to set a new UID
		you have to decode the Base58 encoded UID string into an
		integer first.
		
		We recommend that you use Brick Viewer to change the UID.
		*/
		this.ipcon.sendRequest(this, BrickletRotaryPotiV2.FUNCTION_WRITE_UID, [uid], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.readUID = function(returnCallback, errorCallback) {
		/*
		Returns the current UID as an integer. Encode as
		Base58 to get the usual string version.
		*/
		this.ipcon.sendRequest(this, BrickletRotaryPotiV2.FUNCTION_READ_UID, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletRotaryPotiV2.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletRotaryPotiV2;

},{"./Device":279,"./IPConnection":280}],257:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletSegmentDisplay4x7.DEVICE_IDENTIFIER = 237;
BrickletSegmentDisplay4x7.DEVICE_DISPLAY_NAME = 'Segment Display 4x7 Bricklet';
BrickletSegmentDisplay4x7.CALLBACK_COUNTER_FINISHED = 5;
BrickletSegmentDisplay4x7.FUNCTION_SET_SEGMENTS = 1;
BrickletSegmentDisplay4x7.FUNCTION_GET_SEGMENTS = 2;
BrickletSegmentDisplay4x7.FUNCTION_START_COUNTER = 3;
BrickletSegmentDisplay4x7.FUNCTION_GET_COUNTER_VALUE = 4;
BrickletSegmentDisplay4x7.FUNCTION_GET_IDENTITY = 255;

function BrickletSegmentDisplay4x7(uid, ipcon) {
	//Four 7-segment displays with switchable colon

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletSegmentDisplay4x7.DEVICE_IDENTIFIER, BrickletSegmentDisplay4x7.DEVICE_DISPLAY_NAME);
	BrickletSegmentDisplay4x7.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickletSegmentDisplay4x7.FUNCTION_SET_SEGMENTS] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletSegmentDisplay4x7.FUNCTION_GET_SEGMENTS] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletSegmentDisplay4x7.FUNCTION_START_COUNTER] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletSegmentDisplay4x7.FUNCTION_GET_COUNTER_VALUE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletSegmentDisplay4x7.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletSegmentDisplay4x7.CALLBACK_COUNTER_FINISHED] = [8, ''];



	this.setSegments = function(segments, brightness, colon, returnCallback, errorCallback) {
		/*
		The 7-segment display can be set with bitmaps. Every bit controls one
		segment:
		
		.. image:: /Images/Bricklets/bricklet_segment_display_4x7_bit_order.png
		   :scale: 100 %
		   :alt: Bit order of one segment
		   :align: center
		
		For example to set a "5" you would want to activate segments 0, 2, 3, 5 and 6.
		This is represented by the number 0b01101101 = 0x6d = 109.
		
		The brightness can be set between 0 (dark) and 7 (bright). The colon
		parameter turns the colon of the display on or off.
		*/
		this.ipcon.sendRequest(this, BrickletSegmentDisplay4x7.FUNCTION_SET_SEGMENTS, [segments, brightness, colon], 'B4 B ?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getSegments = function(returnCallback, errorCallback) {
		/*
		Returns the segment, brightness and color data as set by
		:func:`Set Segments`.
		*/
		this.ipcon.sendRequest(this, BrickletSegmentDisplay4x7.FUNCTION_GET_SEGMENTS, [], '', 14, 'B4 B ?', returnCallback, errorCallback, false, true);
	};
	this.startCounter = function(valueFrom, valueTo, increment, length, returnCallback, errorCallback) {
		/*
		Starts a counter with the *from* value that counts to the *to*
		value with the each step incremented by *increment*.
		*length* is the pause between each increment.
		
		Example: If you set *from* to 0, *to* to 100, *increment* to 1 and
		*length* to 1000, a counter that goes from 0 to 100 with one second
		pause between each increment will be started.
		
		Using a negative increment allows to count backwards.
		
		You can stop the counter at every time by calling :func:`Set Segments`.
		*/
		this.ipcon.sendRequest(this, BrickletSegmentDisplay4x7.FUNCTION_START_COUNTER, [valueFrom, valueTo, increment, length], 'h h h I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getCounterValue = function(returnCallback, errorCallback) {
		/*
		Returns the counter value that is currently shown on the display.
		
		If there is no counter running a 0 will be returned.
		*/
		this.ipcon.sendRequest(this, BrickletSegmentDisplay4x7.FUNCTION_GET_COUNTER_VALUE, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletSegmentDisplay4x7.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletSegmentDisplay4x7;

},{"./Device":279,"./IPConnection":280}],258:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletSegmentDisplay4x7V2.DEVICE_IDENTIFIER = 2137;
BrickletSegmentDisplay4x7V2.DEVICE_DISPLAY_NAME = 'Segment Display 4x7 Bricklet 2.0';
BrickletSegmentDisplay4x7V2.CALLBACK_COUNTER_FINISHED = 10;
BrickletSegmentDisplay4x7V2.FUNCTION_SET_SEGMENTS = 1;
BrickletSegmentDisplay4x7V2.FUNCTION_GET_SEGMENTS = 2;
BrickletSegmentDisplay4x7V2.FUNCTION_SET_BRIGHTNESS = 3;
BrickletSegmentDisplay4x7V2.FUNCTION_GET_BRIGHTNESS = 4;
BrickletSegmentDisplay4x7V2.FUNCTION_SET_NUMERIC_VALUE = 5;
BrickletSegmentDisplay4x7V2.FUNCTION_SET_SELECTED_SEGMENT = 6;
BrickletSegmentDisplay4x7V2.FUNCTION_GET_SELECTED_SEGMENT = 7;
BrickletSegmentDisplay4x7V2.FUNCTION_START_COUNTER = 8;
BrickletSegmentDisplay4x7V2.FUNCTION_GET_COUNTER_VALUE = 9;
BrickletSegmentDisplay4x7V2.FUNCTION_GET_SPITFP_ERROR_COUNT = 234;
BrickletSegmentDisplay4x7V2.FUNCTION_SET_BOOTLOADER_MODE = 235;
BrickletSegmentDisplay4x7V2.FUNCTION_GET_BOOTLOADER_MODE = 236;
BrickletSegmentDisplay4x7V2.FUNCTION_SET_WRITE_FIRMWARE_POINTER = 237;
BrickletSegmentDisplay4x7V2.FUNCTION_WRITE_FIRMWARE = 238;
BrickletSegmentDisplay4x7V2.FUNCTION_SET_STATUS_LED_CONFIG = 239;
BrickletSegmentDisplay4x7V2.FUNCTION_GET_STATUS_LED_CONFIG = 240;
BrickletSegmentDisplay4x7V2.FUNCTION_GET_CHIP_TEMPERATURE = 242;
BrickletSegmentDisplay4x7V2.FUNCTION_RESET = 243;
BrickletSegmentDisplay4x7V2.FUNCTION_WRITE_UID = 248;
BrickletSegmentDisplay4x7V2.FUNCTION_READ_UID = 249;
BrickletSegmentDisplay4x7V2.FUNCTION_GET_IDENTITY = 255;
BrickletSegmentDisplay4x7V2.BOOTLOADER_MODE_BOOTLOADER = 0;
BrickletSegmentDisplay4x7V2.BOOTLOADER_MODE_FIRMWARE = 1;
BrickletSegmentDisplay4x7V2.BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT = 2;
BrickletSegmentDisplay4x7V2.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT = 3;
BrickletSegmentDisplay4x7V2.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT = 4;
BrickletSegmentDisplay4x7V2.BOOTLOADER_STATUS_OK = 0;
BrickletSegmentDisplay4x7V2.BOOTLOADER_STATUS_INVALID_MODE = 1;
BrickletSegmentDisplay4x7V2.BOOTLOADER_STATUS_NO_CHANGE = 2;
BrickletSegmentDisplay4x7V2.BOOTLOADER_STATUS_ENTRY_FUNCTION_NOT_PRESENT = 3;
BrickletSegmentDisplay4x7V2.BOOTLOADER_STATUS_DEVICE_IDENTIFIER_INCORRECT = 4;
BrickletSegmentDisplay4x7V2.BOOTLOADER_STATUS_CRC_MISMATCH = 5;
BrickletSegmentDisplay4x7V2.STATUS_LED_CONFIG_OFF = 0;
BrickletSegmentDisplay4x7V2.STATUS_LED_CONFIG_ON = 1;
BrickletSegmentDisplay4x7V2.STATUS_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletSegmentDisplay4x7V2.STATUS_LED_CONFIG_SHOW_STATUS = 3;

function BrickletSegmentDisplay4x7V2(uid, ipcon) {
	//Four 7-segment displays with switchable dots

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletSegmentDisplay4x7V2.DEVICE_IDENTIFIER, BrickletSegmentDisplay4x7V2.DEVICE_DISPLAY_NAME);
	BrickletSegmentDisplay4x7V2.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickletSegmentDisplay4x7V2.FUNCTION_SET_SEGMENTS] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletSegmentDisplay4x7V2.FUNCTION_GET_SEGMENTS] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletSegmentDisplay4x7V2.FUNCTION_SET_BRIGHTNESS] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletSegmentDisplay4x7V2.FUNCTION_GET_BRIGHTNESS] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletSegmentDisplay4x7V2.FUNCTION_SET_NUMERIC_VALUE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletSegmentDisplay4x7V2.FUNCTION_SET_SELECTED_SEGMENT] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletSegmentDisplay4x7V2.FUNCTION_GET_SELECTED_SEGMENT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletSegmentDisplay4x7V2.FUNCTION_START_COUNTER] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletSegmentDisplay4x7V2.FUNCTION_GET_COUNTER_VALUE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletSegmentDisplay4x7V2.FUNCTION_GET_SPITFP_ERROR_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletSegmentDisplay4x7V2.FUNCTION_SET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletSegmentDisplay4x7V2.FUNCTION_GET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletSegmentDisplay4x7V2.FUNCTION_SET_WRITE_FIRMWARE_POINTER] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletSegmentDisplay4x7V2.FUNCTION_WRITE_FIRMWARE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletSegmentDisplay4x7V2.FUNCTION_SET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletSegmentDisplay4x7V2.FUNCTION_GET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletSegmentDisplay4x7V2.FUNCTION_GET_CHIP_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletSegmentDisplay4x7V2.FUNCTION_RESET] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletSegmentDisplay4x7V2.FUNCTION_WRITE_UID] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletSegmentDisplay4x7V2.FUNCTION_READ_UID] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletSegmentDisplay4x7V2.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletSegmentDisplay4x7V2.CALLBACK_COUNTER_FINISHED] = [8, ''];



	this.setSegments = function(digit0, digit1, digit2, digit3, colon, tick, returnCallback, errorCallback) {
		/*
		Sets the segments of the Segment Display 4x7 Bricklet 2.0 segment-by-segment.
		
		The data is split into the four digits, two colon dots and the tick mark.
		
		The indices of the segments in the digit and colon parameters are as follows:
		
		.. image:: /Images/Bricklets/bricklet_segment_display_4x7_v2_segment_index.png
		   :scale: 100 %
		   :alt: Indices of segments
		   :align: center
		*/
		this.ipcon.sendRequest(this, BrickletSegmentDisplay4x7V2.FUNCTION_SET_SEGMENTS, [digit0, digit1, digit2, digit3, colon, tick], '?8 ?8 ?8 ?8 ?2 ?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getSegments = function(returnCallback, errorCallback) {
		/*
		Returns the segment data as set by :func:`Set Segments`.
		*/
		this.ipcon.sendRequest(this, BrickletSegmentDisplay4x7V2.FUNCTION_GET_SEGMENTS, [], '', 14, '?8 ?8 ?8 ?8 ?2 ?', returnCallback, errorCallback, false, true);
	};
	this.setBrightness = function(brightness, returnCallback, errorCallback) {
		/*
		The brightness can be set between 0 (dark) and 7 (bright).
		*/
		this.ipcon.sendRequest(this, BrickletSegmentDisplay4x7V2.FUNCTION_SET_BRIGHTNESS, [brightness], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getBrightness = function(returnCallback, errorCallback) {
		/*
		Returns the brightness as set by :func:`Set Brightness`.
		*/
		this.ipcon.sendRequest(this, BrickletSegmentDisplay4x7V2.FUNCTION_GET_BRIGHTNESS, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setNumericValue = function(value, returnCallback, errorCallback) {
		/*
		Sets a numeric value for each of the digits. They represent:
		
		* -2: minus sign
		* -1: blank
		* 0-9: 0-9
		* 10: A
		* 11: b
		* 12: C
		* 13: d
		* 14: E
		* 15: F
		
		Example: A call with [-2, -1, 4, 2] will result in a display of "- 42".
		*/
		this.ipcon.sendRequest(this, BrickletSegmentDisplay4x7V2.FUNCTION_SET_NUMERIC_VALUE, [value], 'b4', 0, '', returnCallback, errorCallback, false, true);
	};
	this.setSelectedSegment = function(segment, value, returnCallback, errorCallback) {
		/*
		Turns one specified segment on or off.
		
		The indices of the segments are as follows:
		
		.. image:: /Images/Bricklets/bricklet_segment_display_4x7_v2_selected_segment_index.png
		   :scale: 100 %
		   :alt: Indices of selected segments
		   :align: center
		*/
		this.ipcon.sendRequest(this, BrickletSegmentDisplay4x7V2.FUNCTION_SET_SELECTED_SEGMENT, [segment, value], 'B ?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getSelectedSegment = function(segment, returnCallback, errorCallback) {
		/*
		Returns the value of a single segment.
		*/
		this.ipcon.sendRequest(this, BrickletSegmentDisplay4x7V2.FUNCTION_GET_SELECTED_SEGMENT, [segment], 'B', 9, '?', returnCallback, errorCallback, false, true);
	};
	this.startCounter = function(valueFrom, valueTo, increment, length, returnCallback, errorCallback) {
		/*
		Starts a counter with the *from* value that counts to the *to*
		value with the each step incremented by *increment*.
		*length* is the pause between each increment.
		
		Example: If you set *from* to 0, *to* to 100, *increment* to 1 and
		*length* to 1000, a counter that goes from 0 to 100 with one second
		pause between each increment will be started.
		
		Using a negative *increment* allows to count backwards.
		
		You can stop the counter at every time by calling :func:`Set Segments`
		or :func:`Set Numeric Value`.
		*/
		this.ipcon.sendRequest(this, BrickletSegmentDisplay4x7V2.FUNCTION_START_COUNTER, [valueFrom, valueTo, increment, length], 'h h h I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getCounterValue = function(returnCallback, errorCallback) {
		/*
		Returns the counter value that is currently shown on the display.
		
		If there is no counter running a 0 will be returned.
		*/
		this.ipcon.sendRequest(this, BrickletSegmentDisplay4x7V2.FUNCTION_GET_COUNTER_VALUE, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPErrorCount = function(returnCallback, errorCallback) {
		/*
		Returns the error count for the communication between Brick and Bricklet.
		
		The errors are divided into
		
		* ACK checksum errors,
		* message checksum errors,
		* framing errors and
		* overflow errors.
		
		The errors counts are for errors that occur on the Bricklet side. All
		Bricks have a similar function that returns the errors on the Brick side.
		*/
		this.ipcon.sendRequest(this, BrickletSegmentDisplay4x7V2.FUNCTION_GET_SPITFP_ERROR_COUNT, [], '', 24, 'I I I I', returnCallback, errorCallback, false, true);
	};
	this.setBootloaderMode = function(mode, returnCallback, errorCallback) {
		/*
		Sets the bootloader mode and returns the status after the requested
		mode change was instigated.
		
		You can change from bootloader mode to firmware mode and vice versa. A change
		from bootloader mode to firmware mode will only take place if the entry function,
		device identifier and CRC are present and correct.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletSegmentDisplay4x7V2.FUNCTION_SET_BOOTLOADER_MODE, [mode], 'B', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getBootloaderMode = function(returnCallback, errorCallback) {
		/*
		Returns the current bootloader mode, see :func:`Set Bootloader Mode`.
		*/
		this.ipcon.sendRequest(this, BrickletSegmentDisplay4x7V2.FUNCTION_GET_BOOTLOADER_MODE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setWriteFirmwarePointer = function(pointer, returnCallback, errorCallback) {
		/*
		Sets the firmware pointer for :func:`Write Firmware`. The pointer has
		to be increased by chunks of size 64. The data is written to flash
		every 4 chunks (which equals to one page of size 256).
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletSegmentDisplay4x7V2.FUNCTION_SET_WRITE_FIRMWARE_POINTER, [pointer], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeFirmware = function(data, returnCallback, errorCallback) {
		/*
		Writes 64 Bytes of firmware at the position as written by
		:func:`Set Write Firmware Pointer` before. The firmware is written
		to flash every 4 chunks.
		
		You can only write firmware in bootloader mode.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletSegmentDisplay4x7V2.FUNCTION_WRITE_FIRMWARE, [data], 'B64', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setStatusLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Sets the status LED configuration. By default the LED shows
		communication traffic between Brick and Bricklet, it flickers once
		for every 10 received data packets.
		
		You can also turn the LED permanently on/off or show a heartbeat.
		
		If the Bricklet is in bootloader mode, the LED is will show heartbeat by default.
		*/
		this.ipcon.sendRequest(this, BrickletSegmentDisplay4x7V2.FUNCTION_SET_STATUS_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getStatusLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Status LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletSegmentDisplay4x7V2.FUNCTION_GET_STATUS_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getChipTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature as measured inside the microcontroller. The
		value returned is not the ambient temperature!
		
		The temperature is only proportional to the real temperature and it has bad
		accuracy. Practically it is only useful as an indicator for
		temperature changes.
		*/
		this.ipcon.sendRequest(this, BrickletSegmentDisplay4x7V2.FUNCTION_GET_CHIP_TEMPERATURE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.reset = function(returnCallback, errorCallback) {
		/*
		Calling this function will reset the Bricklet. All configurations
		will be lost.
		
		After a reset you have to create new device objects,
		calling functions on the existing ones will result in
		undefined behavior!
		*/
		this.ipcon.sendRequest(this, BrickletSegmentDisplay4x7V2.FUNCTION_RESET, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeUID = function(uid, returnCallback, errorCallback) {
		/*
		Writes a new UID into flash. If you want to set a new UID
		you have to decode the Base58 encoded UID string into an
		integer first.
		
		We recommend that you use Brick Viewer to change the UID.
		*/
		this.ipcon.sendRequest(this, BrickletSegmentDisplay4x7V2.FUNCTION_WRITE_UID, [uid], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.readUID = function(returnCallback, errorCallback) {
		/*
		Returns the current UID as an integer. Encode as
		Base58 to get the usual string version.
		*/
		this.ipcon.sendRequest(this, BrickletSegmentDisplay4x7V2.FUNCTION_READ_UID, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletSegmentDisplay4x7V2.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletSegmentDisplay4x7V2;

},{"./Device":279,"./IPConnection":280}],259:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletServoV2.DEVICE_IDENTIFIER = 2157;
BrickletServoV2.DEVICE_DISPLAY_NAME = 'Servo Bricklet 2.0';
BrickletServoV2.CALLBACK_POSITION_REACHED = 27;
BrickletServoV2.FUNCTION_GET_STATUS = 1;
BrickletServoV2.FUNCTION_SET_ENABLE = 2;
BrickletServoV2.FUNCTION_GET_ENABLED = 3;
BrickletServoV2.FUNCTION_SET_POSITION = 4;
BrickletServoV2.FUNCTION_GET_POSITION = 5;
BrickletServoV2.FUNCTION_GET_CURRENT_POSITION = 6;
BrickletServoV2.FUNCTION_GET_CURRENT_VELOCITY = 7;
BrickletServoV2.FUNCTION_SET_MOTION_CONFIGURATION = 8;
BrickletServoV2.FUNCTION_GET_MOTION_CONFIGURATION = 9;
BrickletServoV2.FUNCTION_SET_PULSE_WIDTH = 10;
BrickletServoV2.FUNCTION_GET_PULSE_WIDTH = 11;
BrickletServoV2.FUNCTION_SET_DEGREE = 12;
BrickletServoV2.FUNCTION_GET_DEGREE = 13;
BrickletServoV2.FUNCTION_SET_PERIOD = 14;
BrickletServoV2.FUNCTION_GET_PERIOD = 15;
BrickletServoV2.FUNCTION_GET_SERVO_CURRENT = 16;
BrickletServoV2.FUNCTION_SET_SERVO_CURRENT_CONFIGURATION = 17;
BrickletServoV2.FUNCTION_GET_SERVO_CURRENT_CONFIGURATION = 18;
BrickletServoV2.FUNCTION_SET_INPUT_VOLTAGE_CONFIGURATION = 19;
BrickletServoV2.FUNCTION_GET_INPUT_VOLTAGE_CONFIGURATION = 20;
BrickletServoV2.FUNCTION_GET_OVERALL_CURRENT = 21;
BrickletServoV2.FUNCTION_GET_INPUT_VOLTAGE = 22;
BrickletServoV2.FUNCTION_SET_CURRENT_CALIBRATION = 23;
BrickletServoV2.FUNCTION_GET_CURRENT_CALIBRATION = 24;
BrickletServoV2.FUNCTION_SET_POSITION_REACHED_CALLBACK_CONFIGURATION = 25;
BrickletServoV2.FUNCTION_GET_POSITION_REACHED_CALLBACK_CONFIGURATION = 26;
BrickletServoV2.FUNCTION_GET_SPITFP_ERROR_COUNT = 234;
BrickletServoV2.FUNCTION_SET_BOOTLOADER_MODE = 235;
BrickletServoV2.FUNCTION_GET_BOOTLOADER_MODE = 236;
BrickletServoV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER = 237;
BrickletServoV2.FUNCTION_WRITE_FIRMWARE = 238;
BrickletServoV2.FUNCTION_SET_STATUS_LED_CONFIG = 239;
BrickletServoV2.FUNCTION_GET_STATUS_LED_CONFIG = 240;
BrickletServoV2.FUNCTION_GET_CHIP_TEMPERATURE = 242;
BrickletServoV2.FUNCTION_RESET = 243;
BrickletServoV2.FUNCTION_WRITE_UID = 248;
BrickletServoV2.FUNCTION_READ_UID = 249;
BrickletServoV2.FUNCTION_GET_IDENTITY = 255;
BrickletServoV2.BOOTLOADER_MODE_BOOTLOADER = 0;
BrickletServoV2.BOOTLOADER_MODE_FIRMWARE = 1;
BrickletServoV2.BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT = 2;
BrickletServoV2.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT = 3;
BrickletServoV2.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT = 4;
BrickletServoV2.BOOTLOADER_STATUS_OK = 0;
BrickletServoV2.BOOTLOADER_STATUS_INVALID_MODE = 1;
BrickletServoV2.BOOTLOADER_STATUS_NO_CHANGE = 2;
BrickletServoV2.BOOTLOADER_STATUS_ENTRY_FUNCTION_NOT_PRESENT = 3;
BrickletServoV2.BOOTLOADER_STATUS_DEVICE_IDENTIFIER_INCORRECT = 4;
BrickletServoV2.BOOTLOADER_STATUS_CRC_MISMATCH = 5;
BrickletServoV2.STATUS_LED_CONFIG_OFF = 0;
BrickletServoV2.STATUS_LED_CONFIG_ON = 1;
BrickletServoV2.STATUS_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletServoV2.STATUS_LED_CONFIG_SHOW_STATUS = 3;

function BrickletServoV2(uid, ipcon) {
	//Drives up to 10 RC Servos

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletServoV2.DEVICE_IDENTIFIER, BrickletServoV2.DEVICE_DISPLAY_NAME);
	BrickletServoV2.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickletServoV2.FUNCTION_GET_STATUS] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletServoV2.FUNCTION_SET_ENABLE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletServoV2.FUNCTION_GET_ENABLED] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletServoV2.FUNCTION_SET_POSITION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletServoV2.FUNCTION_GET_POSITION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletServoV2.FUNCTION_GET_CURRENT_POSITION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletServoV2.FUNCTION_GET_CURRENT_VELOCITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletServoV2.FUNCTION_SET_MOTION_CONFIGURATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletServoV2.FUNCTION_GET_MOTION_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletServoV2.FUNCTION_SET_PULSE_WIDTH] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletServoV2.FUNCTION_GET_PULSE_WIDTH] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletServoV2.FUNCTION_SET_DEGREE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletServoV2.FUNCTION_GET_DEGREE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletServoV2.FUNCTION_SET_PERIOD] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletServoV2.FUNCTION_GET_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletServoV2.FUNCTION_GET_SERVO_CURRENT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletServoV2.FUNCTION_SET_SERVO_CURRENT_CONFIGURATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletServoV2.FUNCTION_GET_SERVO_CURRENT_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletServoV2.FUNCTION_SET_INPUT_VOLTAGE_CONFIGURATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletServoV2.FUNCTION_GET_INPUT_VOLTAGE_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletServoV2.FUNCTION_GET_OVERALL_CURRENT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletServoV2.FUNCTION_GET_INPUT_VOLTAGE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletServoV2.FUNCTION_SET_CURRENT_CALIBRATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletServoV2.FUNCTION_GET_CURRENT_CALIBRATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletServoV2.FUNCTION_SET_POSITION_REACHED_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletServoV2.FUNCTION_GET_POSITION_REACHED_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletServoV2.FUNCTION_GET_SPITFP_ERROR_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletServoV2.FUNCTION_SET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletServoV2.FUNCTION_GET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletServoV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletServoV2.FUNCTION_WRITE_FIRMWARE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletServoV2.FUNCTION_SET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletServoV2.FUNCTION_GET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletServoV2.FUNCTION_GET_CHIP_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletServoV2.FUNCTION_RESET] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletServoV2.FUNCTION_WRITE_UID] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletServoV2.FUNCTION_READ_UID] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletServoV2.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletServoV2.CALLBACK_POSITION_REACHED] = [12, 'H h'];



	this.getStatus = function(returnCallback, errorCallback) {
		/*
		Returns the status information of the Servo Bricklet 2.0.
		
		The status includes
		
		* for each channel if it is enabled or disabled,
		* for each channel the current position,
		* for each channel the current velocity,
		* for each channel the current usage and
		* the input voltage.
		
		Please note that the position and the velocity is a snapshot of the
		current position and velocity of the servo in motion.
		*/
		this.ipcon.sendRequest(this, BrickletServoV2.FUNCTION_GET_STATUS, [], '', 72, '?10 h10 h10 H10 H', returnCallback, errorCallback, false, true);
	};
	this.setEnable = function(servoChannel, enable, returnCallback, errorCallback) {
		/*
		Enables a servo channel (0 to 9). If a servo is enabled, the configured position,
		velocity, acceleration, etc. are applied immediately.
		*/
		this.ipcon.sendRequest(this, BrickletServoV2.FUNCTION_SET_ENABLE, [servoChannel, enable], 'H ?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getEnabled = function(servoChannel, returnCallback, errorCallback) {
		/*
		Returns *true* if the specified servo channel is enabled, *false* otherwise.
		*/
		this.ipcon.sendRequest(this, BrickletServoV2.FUNCTION_GET_ENABLED, [servoChannel], 'H', 9, '?', returnCallback, errorCallback, false, true);
	};
	this.setPosition = function(servoChannel, position, returnCallback, errorCallback) {
		/*
		Sets the position in °/100 for the specified servo channel.
		
		The default range of the position is -9000 to 9000, but it can be specified
		according to your servo with :func:`Set Degree`.
		
		If you want to control a linear servo or RC brushless motor controller or
		similar with the Servo Brick, you can also define lengths or speeds with
		:func:`Set Degree`.
		*/
		this.ipcon.sendRequest(this, BrickletServoV2.FUNCTION_SET_POSITION, [servoChannel, position], 'H h', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getPosition = function(servoChannel, returnCallback, errorCallback) {
		/*
		Returns the position of the specified servo channel as set by :func:`Set Position`.
		*/
		this.ipcon.sendRequest(this, BrickletServoV2.FUNCTION_GET_POSITION, [servoChannel], 'H', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.getCurrentPosition = function(servoChannel, returnCallback, errorCallback) {
		/*
		Returns the *current* position of the specified servo channel. This may not be the
		value of :func:`Set Position` if the servo is currently approaching a
		position goal.
		*/
		this.ipcon.sendRequest(this, BrickletServoV2.FUNCTION_GET_CURRENT_POSITION, [servoChannel], 'H', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.getCurrentVelocity = function(servoChannel, returnCallback, errorCallback) {
		/*
		Returns the *current* velocity of the specified servo channel. This may not be the
		velocity specified by :func:`Set Motion Configuration`. if the servo is
		currently approaching a velocity goal.
		*/
		this.ipcon.sendRequest(this, BrickletServoV2.FUNCTION_GET_CURRENT_VELOCITY, [servoChannel], 'H', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.setMotionConfiguration = function(servoChannel, velocity, acceleration, deceleration, returnCallback, errorCallback) {
		/*
		Sets the maximum velocity of the specified servo channel in °/100s as well as
		the acceleration and deceleration in °/100s²
		
		With a velocity of 0 °/100s the position will be set immediately (no velocity).
		
		With an acc-/deceleration of 0 °/100s² the velocity will be set immediately
		(no acc-/deceleration).
		*/
		this.ipcon.sendRequest(this, BrickletServoV2.FUNCTION_SET_MOTION_CONFIGURATION, [servoChannel, velocity, acceleration, deceleration], 'H I I I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getMotionConfiguration = function(servoChannel, returnCallback, errorCallback) {
		/*
		Returns the motion configuration as set by :func:`Set Motion Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletServoV2.FUNCTION_GET_MOTION_CONFIGURATION, [servoChannel], 'H', 20, 'I I I', returnCallback, errorCallback, false, true);
	};
	this.setPulseWidth = function(servoChannel, min, max, returnCallback, errorCallback) {
		/*
		Sets the minimum and maximum pulse width of the specified servo channel in µs.
		
		Usually, servos are controlled with a
		`PWM <https://en.wikipedia.org/wiki/Pulse-width_modulation>`__, whereby the
		length of the pulse controls the position of the servo. Every servo has
		different minimum and maximum pulse widths, these can be specified with
		this function.
		
		If you have a datasheet for your servo that specifies the minimum and
		maximum pulse width, you should set the values accordingly. If your servo
		comes without any datasheet you have to find the values via trial and error.
		
		Both values have a range from 1 to 65535 (unsigned 16-bit integer). The
		minimum must be smaller than the maximum.
		
		The default values are 1000µs (1ms) and 2000µs (2ms) for minimum and
		maximum pulse width.
		*/
		this.ipcon.sendRequest(this, BrickletServoV2.FUNCTION_SET_PULSE_WIDTH, [servoChannel, min, max], 'H I I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getPulseWidth = function(servoChannel, returnCallback, errorCallback) {
		/*
		Returns the minimum and maximum pulse width for the specified servo channel as set by
		:func:`Set Pulse Width`.
		*/
		this.ipcon.sendRequest(this, BrickletServoV2.FUNCTION_GET_PULSE_WIDTH, [servoChannel], 'H', 16, 'I I', returnCallback, errorCallback, false, true);
	};
	this.setDegree = function(servoChannel, min, max, returnCallback, errorCallback) {
		/*
		Sets the minimum and maximum degree for the specified servo channel (by default
		given as °/100).
		
		This only specifies the abstract values between which the minimum and maximum
		pulse width is scaled. For example: If you specify a pulse width of 1000µs
		to 2000µs and a degree range of -90° to 90°, a call of :func:`Set Position`
		with 0 will result in a pulse width of 1500µs
		(-90° = 1000µs, 90° = 2000µs, etc.).
		
		Possible usage:
		
		* The datasheet of your servo specifies a range of 200° with the middle position
		  at 110°. In this case you can set the minimum to -9000 and the maximum to 11000.
		* You measure a range of 220° on your servo and you don't have or need a middle
		  position. In this case you can set the minimum to 0 and the maximum to 22000.
		* You have a linear servo with a drive length of 20cm, In this case you could
		  set the minimum to 0 and the maximum to 20000. Now you can set the Position
		  with :func:`Set Position` with a resolution of cm/100. Also the velocity will
		  have a resolution of cm/100s and the acceleration will have a resolution of
		  cm/100s².
		* You don't care about units and just want the highest possible resolution. In
		  this case you should set the minimum to -32767 and the maximum to 32767.
		* You have a brushless motor with a maximum speed of 10000 rpm and want to
		  control it with a RC brushless motor controller. In this case you can set the
		  minimum to 0 and the maximum to 10000. :func:`Set Position` now controls the rpm.
		
		Both values have a possible range from -32767 to 32767
		(signed 16-bit integer). The minimum must be smaller than the maximum.
		
		The default values are -9000 and 9000 for the minimum and maximum degree.
		*/
		this.ipcon.sendRequest(this, BrickletServoV2.FUNCTION_SET_DEGREE, [servoChannel, min, max], 'H h h', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getDegree = function(servoChannel, returnCallback, errorCallback) {
		/*
		Returns the minimum and maximum degree for the specified servo channel as set by
		:func:`Set Degree`.
		*/
		this.ipcon.sendRequest(this, BrickletServoV2.FUNCTION_GET_DEGREE, [servoChannel], 'H', 12, 'h h', returnCallback, errorCallback, false, true);
	};
	this.setPeriod = function(servoChannel, period, returnCallback, errorCallback) {
		/*
		Sets the period of the specified servo channel in µs.
		
		Usually, servos are controlled with a
		`PWM <https://en.wikipedia.org/wiki/Pulse-width_modulation>`__. Different
		servos expect PWMs with different periods. Most servos run well with a
		period of about 20ms.
		
		If your servo comes with a datasheet that specifies a period, you should
		set it accordingly. If you don't have a datasheet and you have no idea
		what the correct period is, the default value (19.5ms) will most likely
		work fine.
		
		The minimum possible period is 1µs and the maximum is 1000000µs.
		
		The default value is 19.5ms (19500µs).
		*/
		this.ipcon.sendRequest(this, BrickletServoV2.FUNCTION_SET_PERIOD, [servoChannel, period], 'H I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getPeriod = function(servoChannel, returnCallback, errorCallback) {
		/*
		Returns the period for the specified servo channel as set by :func:`Set Period`.
		*/
		this.ipcon.sendRequest(this, BrickletServoV2.FUNCTION_GET_PERIOD, [servoChannel], 'H', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getServoCurrent = function(servoChannel, returnCallback, errorCallback) {
		/*
		Returns the current consumption of the specified servo channel in mA.
		*/
		this.ipcon.sendRequest(this, BrickletServoV2.FUNCTION_GET_SERVO_CURRENT, [servoChannel], 'H', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.setServoCurrentConfiguration = function(servoChannel, averagingDuration, returnCallback, errorCallback) {
		/*
		Sets the averaging duration of the current measurement for the specified servo channel in ms.
		*/
		this.ipcon.sendRequest(this, BrickletServoV2.FUNCTION_SET_SERVO_CURRENT_CONFIGURATION, [servoChannel, averagingDuration], 'H B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getServoCurrentConfiguration = function(servoChannel, returnCallback, errorCallback) {
		/*
		Returns the servo current configuration for the specified servo channel as set
		by :func:`Set Servo Current Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletServoV2.FUNCTION_GET_SERVO_CURRENT_CONFIGURATION, [servoChannel], 'H', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setInputVoltageConfiguration = function(averagingDuration, returnCallback, errorCallback) {
		/*
		Sets the averaging duration of the input voltage measurement for the specified servo channel in ms.
		*/
		this.ipcon.sendRequest(this, BrickletServoV2.FUNCTION_SET_INPUT_VOLTAGE_CONFIGURATION, [averagingDuration], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getInputVoltageConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the input voltage configuration as set by :func:`Set Input Voltage Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletServoV2.FUNCTION_GET_INPUT_VOLTAGE_CONFIGURATION, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getOverallCurrent = function(returnCallback, errorCallback) {
		/*
		Returns the current consumption of all servos together in mA.
		*/
		this.ipcon.sendRequest(this, BrickletServoV2.FUNCTION_GET_OVERALL_CURRENT, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.getInputVoltage = function(returnCallback, errorCallback) {
		/*
		Returns the input voltage in mV. The input voltage is
		given via the black power input connector on the Servo Brick.
		*/
		this.ipcon.sendRequest(this, BrickletServoV2.FUNCTION_GET_INPUT_VOLTAGE, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.setCurrentCalibration = function(offset, returnCallback, errorCallback) {
		/*
		Sets an offset value (in mA) for each channel.
		
		Note: On delivery the Servo Bricklet 2.0 is already calibrated.
		*/
		this.ipcon.sendRequest(this, BrickletServoV2.FUNCTION_SET_CURRENT_CALIBRATION, [offset], 'h10', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getCurrentCalibration = function(returnCallback, errorCallback) {
		/*
		Returns the current calibration as set by :func:`Set Current Calibration`.
		*/
		this.ipcon.sendRequest(this, BrickletServoV2.FUNCTION_GET_CURRENT_CALIBRATION, [], '', 28, 'h10', returnCallback, errorCallback, false, true);
	};
	this.setPositionReachedCallbackConfiguration = function(servoChannel, enabled, returnCallback, errorCallback) {
		/*
		Enable/Disable :cb:`Position Reached` callback.
		*/
		this.ipcon.sendRequest(this, BrickletServoV2.FUNCTION_SET_POSITION_REACHED_CALLBACK_CONFIGURATION, [servoChannel, enabled], 'H ?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getPositionReachedCallbackConfiguration = function(servoChannel, returnCallback, errorCallback) {
		/*
		Returns the callback configuration as set by
		:func:`Set Position Reached Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletServoV2.FUNCTION_GET_POSITION_REACHED_CALLBACK_CONFIGURATION, [servoChannel], 'H', 9, '?', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPErrorCount = function(returnCallback, errorCallback) {
		/*
		Returns the error count for the communication between Brick and Bricklet.
		
		The errors are divided into
		
		* ACK checksum errors,
		* message checksum errors,
		* framing errors and
		* overflow errors.
		
		The errors counts are for errors that occur on the Bricklet side. All
		Bricks have a similar function that returns the errors on the Brick side.
		*/
		this.ipcon.sendRequest(this, BrickletServoV2.FUNCTION_GET_SPITFP_ERROR_COUNT, [], '', 24, 'I I I I', returnCallback, errorCallback, false, true);
	};
	this.setBootloaderMode = function(mode, returnCallback, errorCallback) {
		/*
		Sets the bootloader mode and returns the status after the requested
		mode change was instigated.
		
		You can change from bootloader mode to firmware mode and vice versa. A change
		from bootloader mode to firmware mode will only take place if the entry function,
		device identifier and CRC are present and correct.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletServoV2.FUNCTION_SET_BOOTLOADER_MODE, [mode], 'B', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getBootloaderMode = function(returnCallback, errorCallback) {
		/*
		Returns the current bootloader mode, see :func:`Set Bootloader Mode`.
		*/
		this.ipcon.sendRequest(this, BrickletServoV2.FUNCTION_GET_BOOTLOADER_MODE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setWriteFirmwarePointer = function(pointer, returnCallback, errorCallback) {
		/*
		Sets the firmware pointer for :func:`Write Firmware`. The pointer has
		to be increased by chunks of size 64. The data is written to flash
		every 4 chunks (which equals to one page of size 256).
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletServoV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER, [pointer], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeFirmware = function(data, returnCallback, errorCallback) {
		/*
		Writes 64 Bytes of firmware at the position as written by
		:func:`Set Write Firmware Pointer` before. The firmware is written
		to flash every 4 chunks.
		
		You can only write firmware in bootloader mode.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletServoV2.FUNCTION_WRITE_FIRMWARE, [data], 'B64', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setStatusLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Sets the status LED configuration. By default the LED shows
		communication traffic between Brick and Bricklet, it flickers once
		for every 10 received data packets.
		
		You can also turn the LED permanently on/off or show a heartbeat.
		
		If the Bricklet is in bootloader mode, the LED is will show heartbeat by default.
		*/
		this.ipcon.sendRequest(this, BrickletServoV2.FUNCTION_SET_STATUS_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getStatusLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Status LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletServoV2.FUNCTION_GET_STATUS_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getChipTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature as measured inside the microcontroller. The
		value returned is not the ambient temperature!
		
		The temperature is only proportional to the real temperature and it has bad
		accuracy. Practically it is only useful as an indicator for
		temperature changes.
		*/
		this.ipcon.sendRequest(this, BrickletServoV2.FUNCTION_GET_CHIP_TEMPERATURE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.reset = function(returnCallback, errorCallback) {
		/*
		Calling this function will reset the Bricklet. All configurations
		will be lost.
		
		After a reset you have to create new device objects,
		calling functions on the existing ones will result in
		undefined behavior!
		*/
		this.ipcon.sendRequest(this, BrickletServoV2.FUNCTION_RESET, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeUID = function(uid, returnCallback, errorCallback) {
		/*
		Writes a new UID into flash. If you want to set a new UID
		you have to decode the Base58 encoded UID string into an
		integer first.
		
		We recommend that you use Brick Viewer to change the UID.
		*/
		this.ipcon.sendRequest(this, BrickletServoV2.FUNCTION_WRITE_UID, [uid], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.readUID = function(returnCallback, errorCallback) {
		/*
		Returns the current UID as an integer. Encode as
		Base58 to get the usual string version.
		*/
		this.ipcon.sendRequest(this, BrickletServoV2.FUNCTION_READ_UID, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletServoV2.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletServoV2;

},{"./Device":279,"./IPConnection":280}],260:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletSolidStateRelay.DEVICE_IDENTIFIER = 244;
BrickletSolidStateRelay.DEVICE_DISPLAY_NAME = 'Solid State Relay Bricklet';
BrickletSolidStateRelay.CALLBACK_MONOFLOP_DONE = 5;
BrickletSolidStateRelay.FUNCTION_SET_STATE = 1;
BrickletSolidStateRelay.FUNCTION_GET_STATE = 2;
BrickletSolidStateRelay.FUNCTION_SET_MONOFLOP = 3;
BrickletSolidStateRelay.FUNCTION_GET_MONOFLOP = 4;
BrickletSolidStateRelay.FUNCTION_GET_IDENTITY = 255;

function BrickletSolidStateRelay(uid, ipcon) {
	//Controls AC and DC Solid State Relays

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletSolidStateRelay.DEVICE_IDENTIFIER, BrickletSolidStateRelay.DEVICE_DISPLAY_NAME);
	BrickletSolidStateRelay.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickletSolidStateRelay.FUNCTION_SET_STATE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletSolidStateRelay.FUNCTION_GET_STATE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletSolidStateRelay.FUNCTION_SET_MONOFLOP] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletSolidStateRelay.FUNCTION_GET_MONOFLOP] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletSolidStateRelay.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletSolidStateRelay.CALLBACK_MONOFLOP_DONE] = [9, '?'];



	this.setState = function(state, returnCallback, errorCallback) {
		/*
		Sets the state of the relays *true* means on and *false* means off.
		
		A running monoflop timer will be aborted if this function is called.
		*/
		this.ipcon.sendRequest(this, BrickletSolidStateRelay.FUNCTION_SET_STATE, [state], '?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getState = function(returnCallback, errorCallback) {
		/*
		Returns the state of the relay, *true* means on and *false* means off.
		*/
		this.ipcon.sendRequest(this, BrickletSolidStateRelay.FUNCTION_GET_STATE, [], '', 9, '?', returnCallback, errorCallback, false, true);
	};
	this.setMonoflop = function(state, time, returnCallback, errorCallback) {
		/*
		The first parameter  is the desired state of the relay (*true* means on
		and *false* means off). The second parameter indicates the time that
		the relay should hold the state.
		
		If this function is called with the parameters (true, 1500):
		The relay will turn on and in 1.5s it will turn off again.
		
		A monoflop can be used as a failsafe mechanism. For example: Lets assume you
		have a RS485 bus and a Solid State Relay Bricklet connected to one of the slave
		stacks. You can now call this function every second, with a time parameter
		of two seconds. The relay will be on all the time. If now the RS485
		connection is lost, the relay will turn off in at most two seconds.
		*/
		this.ipcon.sendRequest(this, BrickletSolidStateRelay.FUNCTION_SET_MONOFLOP, [state, time], '? I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getMonoflop = function(returnCallback, errorCallback) {
		/*
		Returns the current state and the time as set by
		:func:`Set Monoflop` as well as the remaining time until the state flips.
		
		If the timer is not running currently, the remaining time will be returned
		as 0.
		*/
		this.ipcon.sendRequest(this, BrickletSolidStateRelay.FUNCTION_GET_MONOFLOP, [], '', 17, '? I I', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletSolidStateRelay.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletSolidStateRelay;

},{"./Device":279,"./IPConnection":280}],261:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletSolidStateRelayV2.DEVICE_IDENTIFIER = 296;
BrickletSolidStateRelayV2.DEVICE_DISPLAY_NAME = 'Solid State Relay Bricklet 2.0';
BrickletSolidStateRelayV2.CALLBACK_MONOFLOP_DONE = 5;
BrickletSolidStateRelayV2.FUNCTION_SET_STATE = 1;
BrickletSolidStateRelayV2.FUNCTION_GET_STATE = 2;
BrickletSolidStateRelayV2.FUNCTION_SET_MONOFLOP = 3;
BrickletSolidStateRelayV2.FUNCTION_GET_MONOFLOP = 4;
BrickletSolidStateRelayV2.FUNCTION_GET_SPITFP_ERROR_COUNT = 234;
BrickletSolidStateRelayV2.FUNCTION_SET_BOOTLOADER_MODE = 235;
BrickletSolidStateRelayV2.FUNCTION_GET_BOOTLOADER_MODE = 236;
BrickletSolidStateRelayV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER = 237;
BrickletSolidStateRelayV2.FUNCTION_WRITE_FIRMWARE = 238;
BrickletSolidStateRelayV2.FUNCTION_SET_STATUS_LED_CONFIG = 239;
BrickletSolidStateRelayV2.FUNCTION_GET_STATUS_LED_CONFIG = 240;
BrickletSolidStateRelayV2.FUNCTION_GET_CHIP_TEMPERATURE = 242;
BrickletSolidStateRelayV2.FUNCTION_RESET = 243;
BrickletSolidStateRelayV2.FUNCTION_WRITE_UID = 248;
BrickletSolidStateRelayV2.FUNCTION_READ_UID = 249;
BrickletSolidStateRelayV2.FUNCTION_GET_IDENTITY = 255;
BrickletSolidStateRelayV2.BOOTLOADER_MODE_BOOTLOADER = 0;
BrickletSolidStateRelayV2.BOOTLOADER_MODE_FIRMWARE = 1;
BrickletSolidStateRelayV2.BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT = 2;
BrickletSolidStateRelayV2.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT = 3;
BrickletSolidStateRelayV2.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT = 4;
BrickletSolidStateRelayV2.BOOTLOADER_STATUS_OK = 0;
BrickletSolidStateRelayV2.BOOTLOADER_STATUS_INVALID_MODE = 1;
BrickletSolidStateRelayV2.BOOTLOADER_STATUS_NO_CHANGE = 2;
BrickletSolidStateRelayV2.BOOTLOADER_STATUS_ENTRY_FUNCTION_NOT_PRESENT = 3;
BrickletSolidStateRelayV2.BOOTLOADER_STATUS_DEVICE_IDENTIFIER_INCORRECT = 4;
BrickletSolidStateRelayV2.BOOTLOADER_STATUS_CRC_MISMATCH = 5;
BrickletSolidStateRelayV2.STATUS_LED_CONFIG_OFF = 0;
BrickletSolidStateRelayV2.STATUS_LED_CONFIG_ON = 1;
BrickletSolidStateRelayV2.STATUS_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletSolidStateRelayV2.STATUS_LED_CONFIG_SHOW_STATUS = 3;

function BrickletSolidStateRelayV2(uid, ipcon) {
	//Controls AC and DC Solid State Relays

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletSolidStateRelayV2.DEVICE_IDENTIFIER, BrickletSolidStateRelayV2.DEVICE_DISPLAY_NAME);
	BrickletSolidStateRelayV2.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickletSolidStateRelayV2.FUNCTION_SET_STATE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletSolidStateRelayV2.FUNCTION_GET_STATE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletSolidStateRelayV2.FUNCTION_SET_MONOFLOP] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletSolidStateRelayV2.FUNCTION_GET_MONOFLOP] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletSolidStateRelayV2.FUNCTION_GET_SPITFP_ERROR_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletSolidStateRelayV2.FUNCTION_SET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletSolidStateRelayV2.FUNCTION_GET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletSolidStateRelayV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletSolidStateRelayV2.FUNCTION_WRITE_FIRMWARE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletSolidStateRelayV2.FUNCTION_SET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletSolidStateRelayV2.FUNCTION_GET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletSolidStateRelayV2.FUNCTION_GET_CHIP_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletSolidStateRelayV2.FUNCTION_RESET] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletSolidStateRelayV2.FUNCTION_WRITE_UID] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletSolidStateRelayV2.FUNCTION_READ_UID] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletSolidStateRelayV2.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletSolidStateRelayV2.CALLBACK_MONOFLOP_DONE] = [9, '?'];



	this.setState = function(state, returnCallback, errorCallback) {
		/*
		Sets the state of the relays *true* means on and *false* means off.
		
		A running monoflop timer will be aborted if this function is called.
		*/
		this.ipcon.sendRequest(this, BrickletSolidStateRelayV2.FUNCTION_SET_STATE, [state], '?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getState = function(returnCallback, errorCallback) {
		/*
		Returns the state of the relay, *true* means on and *false* means off.
		*/
		this.ipcon.sendRequest(this, BrickletSolidStateRelayV2.FUNCTION_GET_STATE, [], '', 9, '?', returnCallback, errorCallback, false, true);
	};
	this.setMonoflop = function(state, time, returnCallback, errorCallback) {
		/*
		The first parameter  is the desired state of the relay (*true* means on
		and *false* means off). The second parameter indicates the time that
		the relay should hold the state.
		
		If this function is called with the parameters (true, 1500):
		The relay will turn on and in 1.5s it will turn off again.
		
		A monoflop can be used as a failsafe mechanism. For example: Lets assume you
		have a RS485 bus and a Solid State Relay Bricklet connected to one of the slave
		stacks. You can now call this function every second, with a time parameter
		of two seconds. The relay will be on all the time. If now the RS485
		connection is lost, the relay will turn off in at most two seconds.
		*/
		this.ipcon.sendRequest(this, BrickletSolidStateRelayV2.FUNCTION_SET_MONOFLOP, [state, time], '? I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getMonoflop = function(returnCallback, errorCallback) {
		/*
		Returns the current state and the time as set by
		:func:`Set Monoflop` as well as the remaining time until the state flips.
		
		If the timer is not running currently, the remaining time will be returned
		as 0.
		*/
		this.ipcon.sendRequest(this, BrickletSolidStateRelayV2.FUNCTION_GET_MONOFLOP, [], '', 17, '? I I', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPErrorCount = function(returnCallback, errorCallback) {
		/*
		Returns the error count for the communication between Brick and Bricklet.
		
		The errors are divided into
		
		* ACK checksum errors,
		* message checksum errors,
		* framing errors and
		* overflow errors.
		
		The errors counts are for errors that occur on the Bricklet side. All
		Bricks have a similar function that returns the errors on the Brick side.
		*/
		this.ipcon.sendRequest(this, BrickletSolidStateRelayV2.FUNCTION_GET_SPITFP_ERROR_COUNT, [], '', 24, 'I I I I', returnCallback, errorCallback, false, true);
	};
	this.setBootloaderMode = function(mode, returnCallback, errorCallback) {
		/*
		Sets the bootloader mode and returns the status after the requested
		mode change was instigated.
		
		You can change from bootloader mode to firmware mode and vice versa. A change
		from bootloader mode to firmware mode will only take place if the entry function,
		device identifier and CRC are present and correct.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletSolidStateRelayV2.FUNCTION_SET_BOOTLOADER_MODE, [mode], 'B', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getBootloaderMode = function(returnCallback, errorCallback) {
		/*
		Returns the current bootloader mode, see :func:`Set Bootloader Mode`.
		*/
		this.ipcon.sendRequest(this, BrickletSolidStateRelayV2.FUNCTION_GET_BOOTLOADER_MODE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setWriteFirmwarePointer = function(pointer, returnCallback, errorCallback) {
		/*
		Sets the firmware pointer for :func:`Write Firmware`. The pointer has
		to be increased by chunks of size 64. The data is written to flash
		every 4 chunks (which equals to one page of size 256).
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletSolidStateRelayV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER, [pointer], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeFirmware = function(data, returnCallback, errorCallback) {
		/*
		Writes 64 Bytes of firmware at the position as written by
		:func:`Set Write Firmware Pointer` before. The firmware is written
		to flash every 4 chunks.
		
		You can only write firmware in bootloader mode.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletSolidStateRelayV2.FUNCTION_WRITE_FIRMWARE, [data], 'B64', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setStatusLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Sets the status LED configuration. By default the LED shows
		communication traffic between Brick and Bricklet, it flickers once
		for every 10 received data packets.
		
		You can also turn the LED permanently on/off or show a heartbeat.
		
		If the Bricklet is in bootloader mode, the LED is will show heartbeat by default.
		*/
		this.ipcon.sendRequest(this, BrickletSolidStateRelayV2.FUNCTION_SET_STATUS_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getStatusLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Status LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletSolidStateRelayV2.FUNCTION_GET_STATUS_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getChipTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature as measured inside the microcontroller. The
		value returned is not the ambient temperature!
		
		The temperature is only proportional to the real temperature and it has bad
		accuracy. Practically it is only useful as an indicator for
		temperature changes.
		*/
		this.ipcon.sendRequest(this, BrickletSolidStateRelayV2.FUNCTION_GET_CHIP_TEMPERATURE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.reset = function(returnCallback, errorCallback) {
		/*
		Calling this function will reset the Bricklet. All configurations
		will be lost.
		
		After a reset you have to create new device objects,
		calling functions on the existing ones will result in
		undefined behavior!
		*/
		this.ipcon.sendRequest(this, BrickletSolidStateRelayV2.FUNCTION_RESET, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeUID = function(uid, returnCallback, errorCallback) {
		/*
		Writes a new UID into flash. If you want to set a new UID
		you have to decode the Base58 encoded UID string into an
		integer first.
		
		We recommend that you use Brick Viewer to change the UID.
		*/
		this.ipcon.sendRequest(this, BrickletSolidStateRelayV2.FUNCTION_WRITE_UID, [uid], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.readUID = function(returnCallback, errorCallback) {
		/*
		Returns the current UID as an integer. Encode as
		Base58 to get the usual string version.
		*/
		this.ipcon.sendRequest(this, BrickletSolidStateRelayV2.FUNCTION_READ_UID, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletSolidStateRelayV2.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletSolidStateRelayV2;

},{"./Device":279,"./IPConnection":280}],262:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletSoundIntensity.DEVICE_IDENTIFIER = 238;
BrickletSoundIntensity.DEVICE_DISPLAY_NAME = 'Sound Intensity Bricklet';
BrickletSoundIntensity.CALLBACK_INTENSITY = 8;
BrickletSoundIntensity.CALLBACK_INTENSITY_REACHED = 9;
BrickletSoundIntensity.FUNCTION_GET_INTENSITY = 1;
BrickletSoundIntensity.FUNCTION_SET_INTENSITY_CALLBACK_PERIOD = 2;
BrickletSoundIntensity.FUNCTION_GET_INTENSITY_CALLBACK_PERIOD = 3;
BrickletSoundIntensity.FUNCTION_SET_INTENSITY_CALLBACK_THRESHOLD = 4;
BrickletSoundIntensity.FUNCTION_GET_INTENSITY_CALLBACK_THRESHOLD = 5;
BrickletSoundIntensity.FUNCTION_SET_DEBOUNCE_PERIOD = 6;
BrickletSoundIntensity.FUNCTION_GET_DEBOUNCE_PERIOD = 7;
BrickletSoundIntensity.FUNCTION_GET_IDENTITY = 255;
BrickletSoundIntensity.THRESHOLD_OPTION_OFF = 'x';
BrickletSoundIntensity.THRESHOLD_OPTION_OUTSIDE = 'o';
BrickletSoundIntensity.THRESHOLD_OPTION_INSIDE = 'i';
BrickletSoundIntensity.THRESHOLD_OPTION_SMALLER = '<';
BrickletSoundIntensity.THRESHOLD_OPTION_GREATER = '>';

function BrickletSoundIntensity(uid, ipcon) {
	//Measures sound intensity

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletSoundIntensity.DEVICE_IDENTIFIER, BrickletSoundIntensity.DEVICE_DISPLAY_NAME);
	BrickletSoundIntensity.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickletSoundIntensity.FUNCTION_GET_INTENSITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletSoundIntensity.FUNCTION_SET_INTENSITY_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletSoundIntensity.FUNCTION_GET_INTENSITY_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletSoundIntensity.FUNCTION_SET_INTENSITY_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletSoundIntensity.FUNCTION_GET_INTENSITY_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletSoundIntensity.FUNCTION_SET_DEBOUNCE_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletSoundIntensity.FUNCTION_GET_DEBOUNCE_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletSoundIntensity.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletSoundIntensity.CALLBACK_INTENSITY] = [10, 'H'];
	this.callbackFormats[BrickletSoundIntensity.CALLBACK_INTENSITY_REACHED] = [10, 'H'];



	this.getIntensity = function(returnCallback, errorCallback) {
		/*
		Returns the current sound intensity.
		
		The value corresponds to the
		`upper envelop <https://en.wikipedia.org/wiki/Envelope_(waves)>`__
		of the signal of the microphone capsule.
		
		If you want to get the intensity periodically, it is recommended to use the
		:cb:`Intensity` callback and set the period with
		:func:`Set Intensity Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletSoundIntensity.FUNCTION_GET_INTENSITY, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.setIntensityCallbackPeriod = function(period, returnCallback, errorCallback) {
		/*
		Sets the period with which the :cb:`Intensity` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		The :cb:`Intensity` callback is only triggered if the intensity has changed
		since the last triggering.
		*/
		this.ipcon.sendRequest(this, BrickletSoundIntensity.FUNCTION_SET_INTENSITY_CALLBACK_PERIOD, [period], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getIntensityCallbackPeriod = function(returnCallback, errorCallback) {
		/*
		Returns the period as set by :func:`Set Intensity Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletSoundIntensity.FUNCTION_GET_INTENSITY_CALLBACK_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setIntensityCallbackThreshold = function(option, min, max, returnCallback, errorCallback) {
		/*
		Sets the thresholds for the :cb:`Intensity Reached` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Callback is turned off"
		 "'o'",    "Callback is triggered when the intensity is *outside* the min and max values"
		 "'i'",    "Callback is triggered when the intensity is *inside* the min and max values"
		 "'<'",    "Callback is triggered when the intensity is smaller than the min value (max is ignored)"
		 "'>'",    "Callback is triggered when the intensity is greater than the min value (max is ignored)"
		*/
		this.ipcon.sendRequest(this, BrickletSoundIntensity.FUNCTION_SET_INTENSITY_CALLBACK_THRESHOLD, [option, min, max], 'c H H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getIntensityCallbackThreshold = function(returnCallback, errorCallback) {
		/*
		Returns the threshold as set by :func:`Set Intensity Callback Threshold`.
		*/
		this.ipcon.sendRequest(this, BrickletSoundIntensity.FUNCTION_GET_INTENSITY_CALLBACK_THRESHOLD, [], '', 13, 'c H H', returnCallback, errorCallback, false, true);
	};
	this.setDebouncePeriod = function(debounce, returnCallback, errorCallback) {
		/*
		Sets the period with which the threshold callback
		
		* :cb:`Intensity Reached`
		
		is triggered, if the thresholds
		
		* :func:`Set Intensity Callback Threshold`
		
		keeps being reached.
		*/
		this.ipcon.sendRequest(this, BrickletSoundIntensity.FUNCTION_SET_DEBOUNCE_PERIOD, [debounce], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getDebouncePeriod = function(returnCallback, errorCallback) {
		/*
		Returns the debounce period as set by :func:`Set Debounce Period`.
		*/
		this.ipcon.sendRequest(this, BrickletSoundIntensity.FUNCTION_GET_DEBOUNCE_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletSoundIntensity.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletSoundIntensity;

},{"./Device":279,"./IPConnection":280}],263:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletSoundPressureLevel.DEVICE_IDENTIFIER = 290;
BrickletSoundPressureLevel.DEVICE_DISPLAY_NAME = 'Sound Pressure Level Bricklet';
BrickletSoundPressureLevel.CALLBACK_DECIBEL = 4;
BrickletSoundPressureLevel.CALLBACK_SPECTRUM_LOW_LEVEL = 8;
BrickletSoundPressureLevel.CALLBACK_SPECTRUM = -8;
BrickletSoundPressureLevel.FUNCTION_GET_DECIBEL = 1;
BrickletSoundPressureLevel.FUNCTION_SET_DECIBEL_CALLBACK_CONFIGURATION = 2;
BrickletSoundPressureLevel.FUNCTION_GET_DECIBEL_CALLBACK_CONFIGURATION = 3;
BrickletSoundPressureLevel.FUNCTION_GET_SPECTRUM_LOW_LEVEL = 5;
BrickletSoundPressureLevel.FUNCTION_SET_SPECTRUM_CALLBACK_CONFIGURATION = 6;
BrickletSoundPressureLevel.FUNCTION_GET_SPECTRUM_CALLBACK_CONFIGURATION = 7;
BrickletSoundPressureLevel.FUNCTION_SET_CONFIGURATION = 9;
BrickletSoundPressureLevel.FUNCTION_GET_CONFIGURATION = 10;
BrickletSoundPressureLevel.FUNCTION_GET_SPITFP_ERROR_COUNT = 234;
BrickletSoundPressureLevel.FUNCTION_SET_BOOTLOADER_MODE = 235;
BrickletSoundPressureLevel.FUNCTION_GET_BOOTLOADER_MODE = 236;
BrickletSoundPressureLevel.FUNCTION_SET_WRITE_FIRMWARE_POINTER = 237;
BrickletSoundPressureLevel.FUNCTION_WRITE_FIRMWARE = 238;
BrickletSoundPressureLevel.FUNCTION_SET_STATUS_LED_CONFIG = 239;
BrickletSoundPressureLevel.FUNCTION_GET_STATUS_LED_CONFIG = 240;
BrickletSoundPressureLevel.FUNCTION_GET_CHIP_TEMPERATURE = 242;
BrickletSoundPressureLevel.FUNCTION_RESET = 243;
BrickletSoundPressureLevel.FUNCTION_WRITE_UID = 248;
BrickletSoundPressureLevel.FUNCTION_READ_UID = 249;
BrickletSoundPressureLevel.FUNCTION_GET_IDENTITY = 255;
BrickletSoundPressureLevel.THRESHOLD_OPTION_OFF = 'x';
BrickletSoundPressureLevel.THRESHOLD_OPTION_OUTSIDE = 'o';
BrickletSoundPressureLevel.THRESHOLD_OPTION_INSIDE = 'i';
BrickletSoundPressureLevel.THRESHOLD_OPTION_SMALLER = '<';
BrickletSoundPressureLevel.THRESHOLD_OPTION_GREATER = '>';
BrickletSoundPressureLevel.FFT_SIZE_128 = 0;
BrickletSoundPressureLevel.FFT_SIZE_256 = 1;
BrickletSoundPressureLevel.FFT_SIZE_512 = 2;
BrickletSoundPressureLevel.FFT_SIZE_1024 = 3;
BrickletSoundPressureLevel.WEIGHTING_A = 0;
BrickletSoundPressureLevel.WEIGHTING_B = 1;
BrickletSoundPressureLevel.WEIGHTING_C = 2;
BrickletSoundPressureLevel.WEIGHTING_D = 3;
BrickletSoundPressureLevel.WEIGHTING_Z = 4;
BrickletSoundPressureLevel.WEIGHTING_ITU_R_468 = 5;
BrickletSoundPressureLevel.BOOTLOADER_MODE_BOOTLOADER = 0;
BrickletSoundPressureLevel.BOOTLOADER_MODE_FIRMWARE = 1;
BrickletSoundPressureLevel.BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT = 2;
BrickletSoundPressureLevel.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT = 3;
BrickletSoundPressureLevel.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT = 4;
BrickletSoundPressureLevel.BOOTLOADER_STATUS_OK = 0;
BrickletSoundPressureLevel.BOOTLOADER_STATUS_INVALID_MODE = 1;
BrickletSoundPressureLevel.BOOTLOADER_STATUS_NO_CHANGE = 2;
BrickletSoundPressureLevel.BOOTLOADER_STATUS_ENTRY_FUNCTION_NOT_PRESENT = 3;
BrickletSoundPressureLevel.BOOTLOADER_STATUS_DEVICE_IDENTIFIER_INCORRECT = 4;
BrickletSoundPressureLevel.BOOTLOADER_STATUS_CRC_MISMATCH = 5;
BrickletSoundPressureLevel.STATUS_LED_CONFIG_OFF = 0;
BrickletSoundPressureLevel.STATUS_LED_CONFIG_ON = 1;
BrickletSoundPressureLevel.STATUS_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletSoundPressureLevel.STATUS_LED_CONFIG_SHOW_STATUS = 3;

function BrickletSoundPressureLevel(uid, ipcon) {
	//Measures Sound Pressure Level in dB(A/B/C/D/Z)

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletSoundPressureLevel.DEVICE_IDENTIFIER, BrickletSoundPressureLevel.DEVICE_DISPLAY_NAME);
	BrickletSoundPressureLevel.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickletSoundPressureLevel.FUNCTION_GET_DECIBEL] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletSoundPressureLevel.FUNCTION_SET_DECIBEL_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletSoundPressureLevel.FUNCTION_GET_DECIBEL_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletSoundPressureLevel.FUNCTION_GET_SPECTRUM_LOW_LEVEL] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletSoundPressureLevel.FUNCTION_SET_SPECTRUM_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletSoundPressureLevel.FUNCTION_GET_SPECTRUM_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletSoundPressureLevel.FUNCTION_SET_CONFIGURATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletSoundPressureLevel.FUNCTION_GET_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletSoundPressureLevel.FUNCTION_GET_SPITFP_ERROR_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletSoundPressureLevel.FUNCTION_SET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletSoundPressureLevel.FUNCTION_GET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletSoundPressureLevel.FUNCTION_SET_WRITE_FIRMWARE_POINTER] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletSoundPressureLevel.FUNCTION_WRITE_FIRMWARE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletSoundPressureLevel.FUNCTION_SET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletSoundPressureLevel.FUNCTION_GET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletSoundPressureLevel.FUNCTION_GET_CHIP_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletSoundPressureLevel.FUNCTION_RESET] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletSoundPressureLevel.FUNCTION_WRITE_UID] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletSoundPressureLevel.FUNCTION_READ_UID] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletSoundPressureLevel.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletSoundPressureLevel.CALLBACK_DECIBEL] = [10, 'H'];
	this.callbackFormats[BrickletSoundPressureLevel.CALLBACK_SPECTRUM_LOW_LEVEL] = [72, 'H H H30'];

	this.highLevelCallbacks[BrickletSoundPressureLevel.CALLBACK_SPECTRUM] = [['streamLength', 'streamChunkOffset', 'streamChunkData'], {'fixedLength': null, 'singleChunk': false}, null];

	this.streamStateObjects[BrickletSoundPressureLevel.FUNCTION_GET_SPECTRUM_LOW_LEVEL] = {
		'dataMapping': ['streamLength', 'streamChunkOffset', 'streamChunkData'],
		'dataMappingStreamIn': [],
		'streamProperties': {
			'fixedLength': null,
			'singleChunk': false,
			'shortWrite': false
		},
		'responseProperties': {
			'running': false,
			'runningSubcall': false,
			'runningSubcallOOS': false,
			'waitingFirstChunk': true,
			'timeout': null,
			'data': [],
			'streamInChunkOffset': 0,
			'streamInChunkLength': 0,
			'streamInResponseEmpty': true,
			'streamInWritten': 0,
			'streamInLLParams': null,
			'responseHandler': null,
			'packFormatString': '',
			'unpackFormatString': 'H H H30',
			'returnCB': null,
			'errorCB': null,
			'callQueue': []
		}
	};

	this.getDecibel = function(returnCallback, errorCallback) {
		/*
		Returns the measured sound pressure in decibels.
		
		The Bricklet supports the weighting standards dB(A), dB(B), dB(C), dB(D),
		dB(Z) and ITU-R 468. You can configure the weighting with :func:`Set Configuration`.
		
		By default dB(A) will be used.
		
		
		If you want to get the value periodically, it is recommended to use the
		:cb:`Decibel` callback. You can set the callback configuration
		with :func:`Set Decibel Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletSoundPressureLevel.FUNCTION_GET_DECIBEL, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.setDecibelCallbackConfiguration = function(period, valueHasToChange, option, min, max, returnCallback, errorCallback) {
		/*
		The period is the period with which the :cb:`Decibel` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		If the `value has to change`-parameter is set to true, the callback is only
		triggered after the value has changed. If the value didn't change
		within the period, the callback is triggered immediately on change.
		
		If it is set to false, the callback is continuously triggered with the period,
		independent of the value.
		
		It is furthermore possible to constrain the callback with thresholds.
		
		The `option`-parameter together with min/max sets a threshold for the :cb:`Decibel` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Threshold is turned off"
		 "'o'",    "Threshold is triggered when the value is *outside* the min and max values"
		 "'i'",    "Threshold is triggered when the value is *inside* or equal to the min and max values"
		 "'<'",    "Threshold is triggered when the value is smaller than the min value (max is ignored)"
		 "'>'",    "Threshold is triggered when the value is greater than the min value (max is ignored)"
		
		If the option is set to 'x' (threshold turned off) the callback is triggered with the fixed period.
		*/
		this.ipcon.sendRequest(this, BrickletSoundPressureLevel.FUNCTION_SET_DECIBEL_CALLBACK_CONFIGURATION, [period, valueHasToChange, option, min, max], 'I ? c H H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getDecibelCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the callback configuration as set by :func:`Set Decibel Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletSoundPressureLevel.FUNCTION_GET_DECIBEL_CALLBACK_CONFIGURATION, [], '', 18, 'I ? c H H', returnCallback, errorCallback, false, true);
	};
	this.getSpectrumLowLevel = function(returnCallback, errorCallback) {
		/*
		Returns the frequency spectrum. The length of the spectrum is between
		512 (FFT size 1024) and 64 (FFT size 128). See :func:`Set Configuration`.
		
		Each array element is one bin of the FFT. The first bin is always the
		DC offset and the other bins have a size between 40Hz (FFT size 1024) and
		320Hz (FFT size 128).
		
		In sum the frequency of the spectrum always has a range from 0 to
		20480Hz (the FFT is applied to samples with a frequency of 40960Hz).
		
		The returned data is already equalized, which means that the microphone
		frequency response is compensated and the weighting function is applied
		(see :func:`Set Configuration` for the available weighting standards). Use
		dB(Z) if you need the unaltered spectrum.
		
		The values are not in dB form yet. If you want a proper dB scale of the
		spectrum you have to apply the formula f(x) = 20*log10(max(1, x/sqrt(2)))
		on each value.
		*/
		this.ipcon.sendRequest(this, BrickletSoundPressureLevel.FUNCTION_GET_SPECTRUM_LOW_LEVEL, [], '', 72, 'H H H30', returnCallback, errorCallback, false, true);
	};
	this.setSpectrumCallbackConfiguration = function(period, returnCallback, errorCallback) {
		/*
		The period is the period with which the :cb:`Spectrum` callback is
		triggered periodically. A value of 0 turns the callback off.
		
		Every new measured spectrum will be send at most once. Set the period to 1 to
		make sure that you get every spectrum.
		*/
		this.ipcon.sendRequest(this, BrickletSoundPressureLevel.FUNCTION_SET_SPECTRUM_CALLBACK_CONFIGURATION, [period], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getSpectrumCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the callback configuration as set by
		:func:`Get Spectrum Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletSoundPressureLevel.FUNCTION_GET_SPECTRUM_CALLBACK_CONFIGURATION, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setConfiguration = function(fftSize, weighting, returnCallback, errorCallback) {
		/*
		Sets the Sound Pressure Level Bricklet configuration.
		
		With different FFT sizes the Bricklet has a different
		amount of samples per second and the size of the FFT bins
		changes. The higher the FFT size the more precise is the result
		of the dB(X) calculation.
		
		Available FFT sizes are:
		
		* 1024: 512 bins, 10 samples per second, each bin has size 40Hz
		* 512: 256 bins, 20 samples per second, each bin has size 80Hz
		* 256: 128 bins, 40 samples per second, each bin has size 160Hz
		* 128: 64 bins, 80 samples per second, each bin has size 320Hz
		
		The Bricklet supports different weighting functions. You can choose
		between dB(A), dB(B), dB(C), dB(D), dB(Z) and ITU-R 468.
		
		dB(A/B/C/D) are the standard dB weighting curves. dB(A) is
		often used to measure volumes at concerts etc. dB(Z) has a
		flat response, no weighting is applied. ITU-R 468 is an ITU
		weighting standard mostly used in the UK and Europe.
		*/
		this.ipcon.sendRequest(this, BrickletSoundPressureLevel.FUNCTION_SET_CONFIGURATION, [fftSize, weighting], 'B B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletSoundPressureLevel.FUNCTION_GET_CONFIGURATION, [], '', 10, 'B B', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPErrorCount = function(returnCallback, errorCallback) {
		/*
		Returns the error count for the communication between Brick and Bricklet.
		
		The errors are divided into
		
		* ACK checksum errors,
		* message checksum errors,
		* framing errors and
		* overflow errors.
		
		The errors counts are for errors that occur on the Bricklet side. All
		Bricks have a similar function that returns the errors on the Brick side.
		*/
		this.ipcon.sendRequest(this, BrickletSoundPressureLevel.FUNCTION_GET_SPITFP_ERROR_COUNT, [], '', 24, 'I I I I', returnCallback, errorCallback, false, true);
	};
	this.setBootloaderMode = function(mode, returnCallback, errorCallback) {
		/*
		Sets the bootloader mode and returns the status after the requested
		mode change was instigated.
		
		You can change from bootloader mode to firmware mode and vice versa. A change
		from bootloader mode to firmware mode will only take place if the entry function,
		device identifier and CRC are present and correct.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletSoundPressureLevel.FUNCTION_SET_BOOTLOADER_MODE, [mode], 'B', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getBootloaderMode = function(returnCallback, errorCallback) {
		/*
		Returns the current bootloader mode, see :func:`Set Bootloader Mode`.
		*/
		this.ipcon.sendRequest(this, BrickletSoundPressureLevel.FUNCTION_GET_BOOTLOADER_MODE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setWriteFirmwarePointer = function(pointer, returnCallback, errorCallback) {
		/*
		Sets the firmware pointer for :func:`Write Firmware`. The pointer has
		to be increased by chunks of size 64. The data is written to flash
		every 4 chunks (which equals to one page of size 256).
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletSoundPressureLevel.FUNCTION_SET_WRITE_FIRMWARE_POINTER, [pointer], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeFirmware = function(data, returnCallback, errorCallback) {
		/*
		Writes 64 Bytes of firmware at the position as written by
		:func:`Set Write Firmware Pointer` before. The firmware is written
		to flash every 4 chunks.
		
		You can only write firmware in bootloader mode.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletSoundPressureLevel.FUNCTION_WRITE_FIRMWARE, [data], 'B64', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setStatusLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Sets the status LED configuration. By default the LED shows
		communication traffic between Brick and Bricklet, it flickers once
		for every 10 received data packets.
		
		You can also turn the LED permanently on/off or show a heartbeat.
		
		If the Bricklet is in bootloader mode, the LED is will show heartbeat by default.
		*/
		this.ipcon.sendRequest(this, BrickletSoundPressureLevel.FUNCTION_SET_STATUS_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getStatusLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Status LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletSoundPressureLevel.FUNCTION_GET_STATUS_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getChipTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature as measured inside the microcontroller. The
		value returned is not the ambient temperature!
		
		The temperature is only proportional to the real temperature and it has bad
		accuracy. Practically it is only useful as an indicator for
		temperature changes.
		*/
		this.ipcon.sendRequest(this, BrickletSoundPressureLevel.FUNCTION_GET_CHIP_TEMPERATURE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.reset = function(returnCallback, errorCallback) {
		/*
		Calling this function will reset the Bricklet. All configurations
		will be lost.
		
		After a reset you have to create new device objects,
		calling functions on the existing ones will result in
		undefined behavior!
		*/
		this.ipcon.sendRequest(this, BrickletSoundPressureLevel.FUNCTION_RESET, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeUID = function(uid, returnCallback, errorCallback) {
		/*
		Writes a new UID into flash. If you want to set a new UID
		you have to decode the Base58 encoded UID string into an
		integer first.
		
		We recommend that you use Brick Viewer to change the UID.
		*/
		this.ipcon.sendRequest(this, BrickletSoundPressureLevel.FUNCTION_WRITE_UID, [uid], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.readUID = function(returnCallback, errorCallback) {
		/*
		Returns the current UID as an integer. Encode as
		Base58 to get the usual string version.
		*/
		this.ipcon.sendRequest(this, BrickletSoundPressureLevel.FUNCTION_READ_UID, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletSoundPressureLevel.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.getSpectrum = function(returnCallback, errorCallback) {
		/*
		Returns the frequency spectrum. The length of the spectrum is between
		512 (FFT size 1024) and 64 (FFT size 128). See :func:`Set Configuration`.
		
		Each array element is one bin of the FFT. The first bin is always the
		DC offset and the other bins have a size between 40Hz (FFT size 1024) and
		320Hz (FFT size 128).
		
		In sum the frequency of the spectrum always has a range from 0 to
		20480Hz (the FFT is applied to samples with a frequency of 40960Hz).
		
		The returned data is already equalized, which means that the microphone
		frequency response is compensated and the weighting function is applied
		(see :func:`Set Configuration` for the available weighting standards). Use
		dB(Z) if you need the unaltered spectrum.
		
		The values are not in dB form yet. If you want a proper dB scale of the
		spectrum you have to apply the formula f(x) = 20*log10(max(1, x/sqrt(2)))
		on each value.
		*/
		var responseHandler = null;
		var functionToQueue = null;
		var streamStateObject = this.streamStateObjects[5];
		if (streamStateObject['responseProperties']['responseHandler'] === null) {
			responseHandler = 
				function (device, fid, packetResponse) {
					var result = [];
					var llvalues = null;
					var packetErrorFlag = 0;
					var rolesMappedData = [];
					var spectrumLength = null;
					var spectrumChunkData = null;
					var spectrumOutOfSync = false;
					var streamStateObject = device.streamStateObjects[fid];
					var spectrumChunkOffset = null;
					var payload = device.ipcon.getPayloadFromPacket(packetResponse);

					packetErrorFlag = device.ipcon.getEFromPacket(packetResponse);

					if (packetErrorFlag !== 0) {
						if (streamStateObject['responseProperties']['errorCB'] !== undefined) {
							if (packetErrorFlag === 1) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_INVALID_PARAMETER);
							}
							else if (packetErrorFlag === 2) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_FUNCTION_NOT_SUPPORTED);
							}
							else {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_UNKNOWN_ERROR);
							}
						}

						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}

						return;
					}

					if (payload.length === 0) {
						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}

						return;
					}

					llvalues = device.ipcon.unpack(payload,
					                               streamStateObject['responseProperties']['unpackFormatString']);

					for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
						if (streamStateObject['dataMapping'][i] === 'streamChunkData') {
							spectrumChunkData = llvalues[i];
						}
						else if (streamStateObject['dataMapping'][i] === 'streamChunkOffset') {
							spectrumChunkOffset = llvalues[i];
						}
					}

					for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
						if (streamStateObject['dataMapping'][i] === 'streamLength') {
							spectrumLength = llvalues[i];
							break;
						}
					}

					function handleOOS() {
						if ((spectrumChunkOffset + 30) < spectrumLength) {
							streamStateObject['responseProperties']['runningSubcallOOS'] = true;
							device.ipcon.sendRequest(device, BrickletSoundPressureLevel.FUNCTION_GET_SPECTRUM_LOW_LEVEL, [], '', 72, 'H H H30', streamStateObject['responseProperties']['returnCB'], streamStateObject['responseProperties']['errorCB'], true, true);

							return;
						}

						if (streamStateObject['responseProperties']['errorCB']) {
							streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_STREAM_OUT_OF_SYNC);
						}

						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}
					}

					if (streamStateObject['responseProperties']['waitingFirstChunk']) {
						streamStateObject['responseProperties']['waitingFirstChunk'] = false;
						spectrumOutOfSync = (spectrumChunkOffset !== 0);
						streamStateObject['responseProperties']['data'] = spectrumChunkData;
					}

					if (!streamStateObject['responseProperties']['runningSubcallOOS']) {
						if (!streamStateObject['responseProperties']['runningSubcall']) {
							if (!spectrumOutOfSync &&
							    (streamStateObject['responseProperties']['data'].length < spectrumLength)) {
							        streamStateObject['responseProperties']['runningSubcall'] = true;
							        device.ipcon.sendRequest(device, BrickletSoundPressureLevel.FUNCTION_GET_SPECTRUM_LOW_LEVEL, [], '', 72, 'H H H30', streamStateObject['responseProperties']['returnCB'], streamStateObject['responseProperties']['errorCB'], true, true);

							        return;
							}
						}
						else {
							spectrumOutOfSync =
								(spectrumChunkOffset !== streamStateObject['responseProperties']['data'].length);

							if (!spectrumOutOfSync &&
								(streamStateObject['responseProperties']['data'].length < spectrumLength)) {
									streamStateObject['responseProperties']['data'] =
										streamStateObject['responseProperties']['data'].concat(spectrumChunkData);

									if (streamStateObject['responseProperties']['data'].length >= spectrumLength) {
										streamStateObject['responseProperties']['data'] =
											streamStateObject['responseProperties']['data'].splice(0, spectrumLength);
									}
									else {
										device.ipcon.sendRequest(device, BrickletSoundPressureLevel.FUNCTION_GET_SPECTRUM_LOW_LEVEL, [], '', 72, 'H H H30', streamStateObject['responseProperties']['returnCB'], streamStateObject['responseProperties']['errorCB'], true, true);

										return;
									}
							}
						}
					}
					else{
						handleOOS();

						return;
					}

					if (spectrumOutOfSync) { // Discard remaining stream to bring it back in-sync
						handleOOS();

						return;
					}

					if (streamStateObject['responseProperties']['returnCB']) {
						for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
							rolesMappedData.push({'role': streamStateObject['dataMapping'][i], 'llvalue': llvalues[i]});
						}

						for (var i = 0; i < rolesMappedData.length; i++) {
							if (rolesMappedData[i]['role'] === 'streamChunkData') {
								result.push(streamStateObject['responseProperties']['data'].splice(0, spectrumLength));
							}
							else if (rolesMappedData[i]['role'] === null) {
								result.push(rolesMappedData[i]['llvalue']);
							}
						}

						streamStateObject['responseProperties']['returnCB'].apply(device, result);
					}

					device.resetStreamStateObject(streamStateObject);

					if (streamStateObject['responseProperties']['callQueue'].length > 0) {
						streamStateObject['responseProperties']['callQueue'].shift()(device);
					}
					
				};

			streamStateObject['responseProperties']['responseHandler'] = responseHandler;
		}
		if (!streamStateObject['responseProperties']['running']) {
			streamStateObject['responseProperties']['running'] = true;
			streamStateObject['responseProperties']['returnCB'] = returnCallback;
			streamStateObject['responseProperties']['errorCB'] = errorCallback;
			this.ipcon.sendRequest(this,
			                       BrickletSoundPressureLevel.FUNCTION_GET_SPECTRUM_LOW_LEVEL,
			                       [],
			                       '',
			                       72,
			                       'H H H30',
			                       returnCallback,
			                       errorCallback,
			                       true,
			                       true);
		}
		else {
			functionToQueue = function (device) {
				device.getSpectrum.call(device, returnCallback, errorCallback);
			}
			streamStateObject['responseProperties']['callQueue'].push(functionToQueue);
		}
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletSoundPressureLevel;

},{"./Device":279,"./IPConnection":280}],264:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletTemperature.DEVICE_IDENTIFIER = 216;
BrickletTemperature.DEVICE_DISPLAY_NAME = 'Temperature Bricklet';
BrickletTemperature.CALLBACK_TEMPERATURE = 8;
BrickletTemperature.CALLBACK_TEMPERATURE_REACHED = 9;
BrickletTemperature.FUNCTION_GET_TEMPERATURE = 1;
BrickletTemperature.FUNCTION_SET_TEMPERATURE_CALLBACK_PERIOD = 2;
BrickletTemperature.FUNCTION_GET_TEMPERATURE_CALLBACK_PERIOD = 3;
BrickletTemperature.FUNCTION_SET_TEMPERATURE_CALLBACK_THRESHOLD = 4;
BrickletTemperature.FUNCTION_GET_TEMPERATURE_CALLBACK_THRESHOLD = 5;
BrickletTemperature.FUNCTION_SET_DEBOUNCE_PERIOD = 6;
BrickletTemperature.FUNCTION_GET_DEBOUNCE_PERIOD = 7;
BrickletTemperature.FUNCTION_SET_I2C_MODE = 10;
BrickletTemperature.FUNCTION_GET_I2C_MODE = 11;
BrickletTemperature.FUNCTION_GET_IDENTITY = 255;
BrickletTemperature.THRESHOLD_OPTION_OFF = 'x';
BrickletTemperature.THRESHOLD_OPTION_OUTSIDE = 'o';
BrickletTemperature.THRESHOLD_OPTION_INSIDE = 'i';
BrickletTemperature.THRESHOLD_OPTION_SMALLER = '<';
BrickletTemperature.THRESHOLD_OPTION_GREATER = '>';
BrickletTemperature.I2C_MODE_FAST = 0;
BrickletTemperature.I2C_MODE_SLOW = 1;

function BrickletTemperature(uid, ipcon) {
	//Measures ambient temperature with 0.5°C accuracy

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletTemperature.DEVICE_IDENTIFIER, BrickletTemperature.DEVICE_DISPLAY_NAME);
	BrickletTemperature.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 1];
	this.responseExpected[BrickletTemperature.FUNCTION_GET_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletTemperature.FUNCTION_SET_TEMPERATURE_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletTemperature.FUNCTION_GET_TEMPERATURE_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletTemperature.FUNCTION_SET_TEMPERATURE_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletTemperature.FUNCTION_GET_TEMPERATURE_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletTemperature.FUNCTION_SET_DEBOUNCE_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletTemperature.FUNCTION_GET_DEBOUNCE_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletTemperature.FUNCTION_SET_I2C_MODE] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletTemperature.FUNCTION_GET_I2C_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletTemperature.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletTemperature.CALLBACK_TEMPERATURE] = [10, 'h'];
	this.callbackFormats[BrickletTemperature.CALLBACK_TEMPERATURE_REACHED] = [10, 'h'];



	this.getTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature of the sensor.
		
		If you want to get the temperature periodically, it is recommended
		to use the :cb:`Temperature` callback and set the period with
		:func:`Set Temperature Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletTemperature.FUNCTION_GET_TEMPERATURE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.setTemperatureCallbackPeriod = function(period, returnCallback, errorCallback) {
		/*
		Sets the period with which the :cb:`Temperature` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		The :cb:`Temperature` callback is only triggered if the temperature has changed
		since the last triggering.
		*/
		this.ipcon.sendRequest(this, BrickletTemperature.FUNCTION_SET_TEMPERATURE_CALLBACK_PERIOD, [period], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getTemperatureCallbackPeriod = function(returnCallback, errorCallback) {
		/*
		Returns the period as set by :func:`Set Temperature Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletTemperature.FUNCTION_GET_TEMPERATURE_CALLBACK_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setTemperatureCallbackThreshold = function(option, min, max, returnCallback, errorCallback) {
		/*
		Sets the thresholds for the :cb:`Temperature Reached` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Callback is turned off"
		 "'o'",    "Callback is triggered when the temperature is *outside* the min and max values"
		 "'i'",    "Callback is triggered when the temperature is *inside* the min and max values"
		 "'<'",    "Callback is triggered when the temperature is smaller than the min value (max is ignored)"
		 "'>'",    "Callback is triggered when the temperature is greater than the min value (max is ignored)"
		*/
		this.ipcon.sendRequest(this, BrickletTemperature.FUNCTION_SET_TEMPERATURE_CALLBACK_THRESHOLD, [option, min, max], 'c h h', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getTemperatureCallbackThreshold = function(returnCallback, errorCallback) {
		/*
		Returns the threshold as set by :func:`Set Temperature Callback Threshold`.
		*/
		this.ipcon.sendRequest(this, BrickletTemperature.FUNCTION_GET_TEMPERATURE_CALLBACK_THRESHOLD, [], '', 13, 'c h h', returnCallback, errorCallback, false, true);
	};
	this.setDebouncePeriod = function(debounce, returnCallback, errorCallback) {
		/*
		Sets the period with which the threshold callback
		
		* :cb:`Temperature Reached`
		
		is triggered, if the threshold
		
		* :func:`Set Temperature Callback Threshold`
		
		keeps being reached.
		*/
		this.ipcon.sendRequest(this, BrickletTemperature.FUNCTION_SET_DEBOUNCE_PERIOD, [debounce], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getDebouncePeriod = function(returnCallback, errorCallback) {
		/*
		Returns the debounce period as set by :func:`Set Debounce Period`.
		*/
		this.ipcon.sendRequest(this, BrickletTemperature.FUNCTION_GET_DEBOUNCE_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setI2CMode = function(mode, returnCallback, errorCallback) {
		/*
		Sets the I2C mode. Possible modes are:
		
		* 0: Fast (400kHz)
		* 1: Slow (100kHz)
		
		If you have problems with obvious outliers in the
		Temperature Bricklet measurements, they may be caused by EMI issues.
		In this case it may be helpful to lower the I2C speed.
		
		It is however not recommended to lower the I2C speed in applications where
		a high throughput needs to be achieved.
		
		.. versionadded:: 2.0.1$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletTemperature.FUNCTION_SET_I2C_MODE, [mode], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getI2CMode = function(returnCallback, errorCallback) {
		/*
		Returns the I2C mode as set by :func:`Set I2C Mode`.
		
		.. versionadded:: 2.0.1$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletTemperature.FUNCTION_GET_I2C_MODE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletTemperature.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletTemperature;

},{"./Device":279,"./IPConnection":280}],265:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletTemperatureIR.DEVICE_IDENTIFIER = 217;
BrickletTemperatureIR.DEVICE_DISPLAY_NAME = 'Temperature IR Bricklet';
BrickletTemperatureIR.CALLBACK_AMBIENT_TEMPERATURE = 15;
BrickletTemperatureIR.CALLBACK_OBJECT_TEMPERATURE = 16;
BrickletTemperatureIR.CALLBACK_AMBIENT_TEMPERATURE_REACHED = 17;
BrickletTemperatureIR.CALLBACK_OBJECT_TEMPERATURE_REACHED = 18;
BrickletTemperatureIR.FUNCTION_GET_AMBIENT_TEMPERATURE = 1;
BrickletTemperatureIR.FUNCTION_GET_OBJECT_TEMPERATURE = 2;
BrickletTemperatureIR.FUNCTION_SET_EMISSIVITY = 3;
BrickletTemperatureIR.FUNCTION_GET_EMISSIVITY = 4;
BrickletTemperatureIR.FUNCTION_SET_AMBIENT_TEMPERATURE_CALLBACK_PERIOD = 5;
BrickletTemperatureIR.FUNCTION_GET_AMBIENT_TEMPERATURE_CALLBACK_PERIOD = 6;
BrickletTemperatureIR.FUNCTION_SET_OBJECT_TEMPERATURE_CALLBACK_PERIOD = 7;
BrickletTemperatureIR.FUNCTION_GET_OBJECT_TEMPERATURE_CALLBACK_PERIOD = 8;
BrickletTemperatureIR.FUNCTION_SET_AMBIENT_TEMPERATURE_CALLBACK_THRESHOLD = 9;
BrickletTemperatureIR.FUNCTION_GET_AMBIENT_TEMPERATURE_CALLBACK_THRESHOLD = 10;
BrickletTemperatureIR.FUNCTION_SET_OBJECT_TEMPERATURE_CALLBACK_THRESHOLD = 11;
BrickletTemperatureIR.FUNCTION_GET_OBJECT_TEMPERATURE_CALLBACK_THRESHOLD = 12;
BrickletTemperatureIR.FUNCTION_SET_DEBOUNCE_PERIOD = 13;
BrickletTemperatureIR.FUNCTION_GET_DEBOUNCE_PERIOD = 14;
BrickletTemperatureIR.FUNCTION_GET_IDENTITY = 255;
BrickletTemperatureIR.THRESHOLD_OPTION_OFF = 'x';
BrickletTemperatureIR.THRESHOLD_OPTION_OUTSIDE = 'o';
BrickletTemperatureIR.THRESHOLD_OPTION_INSIDE = 'i';
BrickletTemperatureIR.THRESHOLD_OPTION_SMALLER = '<';
BrickletTemperatureIR.THRESHOLD_OPTION_GREATER = '>';

function BrickletTemperatureIR(uid, ipcon) {
	//Measures contactless object temperature between -70°C and +380°C

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletTemperatureIR.DEVICE_IDENTIFIER, BrickletTemperatureIR.DEVICE_DISPLAY_NAME);
	BrickletTemperatureIR.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickletTemperatureIR.FUNCTION_GET_AMBIENT_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletTemperatureIR.FUNCTION_GET_OBJECT_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletTemperatureIR.FUNCTION_SET_EMISSIVITY] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletTemperatureIR.FUNCTION_GET_EMISSIVITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletTemperatureIR.FUNCTION_SET_AMBIENT_TEMPERATURE_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletTemperatureIR.FUNCTION_GET_AMBIENT_TEMPERATURE_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletTemperatureIR.FUNCTION_SET_OBJECT_TEMPERATURE_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletTemperatureIR.FUNCTION_GET_OBJECT_TEMPERATURE_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletTemperatureIR.FUNCTION_SET_AMBIENT_TEMPERATURE_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletTemperatureIR.FUNCTION_GET_AMBIENT_TEMPERATURE_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletTemperatureIR.FUNCTION_SET_OBJECT_TEMPERATURE_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletTemperatureIR.FUNCTION_GET_OBJECT_TEMPERATURE_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletTemperatureIR.FUNCTION_SET_DEBOUNCE_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletTemperatureIR.FUNCTION_GET_DEBOUNCE_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletTemperatureIR.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletTemperatureIR.CALLBACK_AMBIENT_TEMPERATURE] = [10, 'h'];
	this.callbackFormats[BrickletTemperatureIR.CALLBACK_OBJECT_TEMPERATURE] = [10, 'h'];
	this.callbackFormats[BrickletTemperatureIR.CALLBACK_AMBIENT_TEMPERATURE_REACHED] = [10, 'h'];
	this.callbackFormats[BrickletTemperatureIR.CALLBACK_OBJECT_TEMPERATURE_REACHED] = [10, 'h'];



	this.getAmbientTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the ambient temperature of the sensor.
		
		If you want to get the ambient temperature periodically, it is recommended
		to use the :cb:`Ambient Temperature` callback and set the period with
		:func:`Set Ambient Temperature Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletTemperatureIR.FUNCTION_GET_AMBIENT_TEMPERATURE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.getObjectTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the object temperature of the sensor, i.e. the temperature
		of the surface of the object the sensor is aimed at.
		
		The temperature of different materials is dependent on their `emissivity
		<https://en.wikipedia.org/wiki/Emissivity>`__. The emissivity of the material
		can be set with :func:`Set Emissivity`.
		
		If you want to get the object temperature periodically, it is recommended
		to use the :cb:`Object Temperature` callback and set the period with
		:func:`Set Object Temperature Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletTemperatureIR.FUNCTION_GET_OBJECT_TEMPERATURE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.setEmissivity = function(emissivity, returnCallback, errorCallback) {
		/*
		Sets the `emissivity <https://en.wikipedia.org/wiki/Emissivity>`__ that is
		used to calculate the surface temperature as returned by
		:func:`Get Object Temperature`.
		
		The emissivity is usually given as a value between 0.0 and 1.0. A list of
		emissivities of different materials can be found
		`here <https://www.infrared-thermography.com/material.htm>`__.
		
		The parameter of :func:`Set Emissivity` has to be given with a factor of
		65535 (16-bit). For example: An emissivity of 0.1 can be set with the
		value 6553, an emissivity of 0.5 with the value 32767 and so on.
		
		.. note::
		 If you need a precise measurement for the object temperature, it is
		 absolutely crucial that you also provide a precise emissivity.
		
		The emissivity is stored in non-volatile memory and will still be used after a restart or power cycle of the Bricklet.
		*/
		this.ipcon.sendRequest(this, BrickletTemperatureIR.FUNCTION_SET_EMISSIVITY, [emissivity], 'H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getEmissivity = function(returnCallback, errorCallback) {
		/*
		Returns the emissivity as set by :func:`Set Emissivity`.
		*/
		this.ipcon.sendRequest(this, BrickletTemperatureIR.FUNCTION_GET_EMISSIVITY, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.setAmbientTemperatureCallbackPeriod = function(period, returnCallback, errorCallback) {
		/*
		Sets the period with which the :cb:`Ambient Temperature` callback is
		triggered periodically. A value of 0 turns the callback off.
		
		The :cb:`Ambient Temperature` callback is only triggered if the temperature has
		changed since the last triggering.
		*/
		this.ipcon.sendRequest(this, BrickletTemperatureIR.FUNCTION_SET_AMBIENT_TEMPERATURE_CALLBACK_PERIOD, [period], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getAmbientTemperatureCallbackPeriod = function(returnCallback, errorCallback) {
		/*
		Returns the period as set by :func:`Set Ambient Temperature Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletTemperatureIR.FUNCTION_GET_AMBIENT_TEMPERATURE_CALLBACK_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setObjectTemperatureCallbackPeriod = function(period, returnCallback, errorCallback) {
		/*
		Sets the period with which the :cb:`Object Temperature` callback is
		triggered periodically. A value of 0 turns the callback off.
		
		The :cb:`Object Temperature` callback is only triggered if the temperature
		has changed since the last triggering.
		*/
		this.ipcon.sendRequest(this, BrickletTemperatureIR.FUNCTION_SET_OBJECT_TEMPERATURE_CALLBACK_PERIOD, [period], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getObjectTemperatureCallbackPeriod = function(returnCallback, errorCallback) {
		/*
		Returns the period as set by :func:`Set Object Temperature Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletTemperatureIR.FUNCTION_GET_OBJECT_TEMPERATURE_CALLBACK_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setAmbientTemperatureCallbackThreshold = function(option, min, max, returnCallback, errorCallback) {
		/*
		Sets the thresholds for the :cb:`Ambient Temperature Reached` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Callback is turned off"
		 "'o'",    "Callback is triggered when the ambient temperature is *outside* the min and max values"
		 "'i'",    "Callback is triggered when the ambient temperature is *inside* the min and max values"
		 "'<'",    "Callback is triggered when the ambient temperature is smaller than the min value (max is ignored)"
		 "'>'",    "Callback is triggered when the ambient temperature is greater than the min value (max is ignored)"
		*/
		this.ipcon.sendRequest(this, BrickletTemperatureIR.FUNCTION_SET_AMBIENT_TEMPERATURE_CALLBACK_THRESHOLD, [option, min, max], 'c h h', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getAmbientTemperatureCallbackThreshold = function(returnCallback, errorCallback) {
		/*
		Returns the threshold as set by :func:`Set Ambient Temperature Callback Threshold`.
		*/
		this.ipcon.sendRequest(this, BrickletTemperatureIR.FUNCTION_GET_AMBIENT_TEMPERATURE_CALLBACK_THRESHOLD, [], '', 13, 'c h h', returnCallback, errorCallback, false, true);
	};
	this.setObjectTemperatureCallbackThreshold = function(option, min, max, returnCallback, errorCallback) {
		/*
		Sets the thresholds for the :cb:`Object Temperature Reached` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Callback is turned off"
		 "'o'",    "Callback is triggered when the object temperature is *outside* the min and max values"
		 "'i'",    "Callback is triggered when the object temperature is *inside* the min and max values"
		 "'<'",    "Callback is triggered when the object temperature is smaller than the min value (max is ignored)"
		 "'>'",    "Callback is triggered when the object temperature is greater than the min value (max is ignored)"
		*/
		this.ipcon.sendRequest(this, BrickletTemperatureIR.FUNCTION_SET_OBJECT_TEMPERATURE_CALLBACK_THRESHOLD, [option, min, max], 'c h h', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getObjectTemperatureCallbackThreshold = function(returnCallback, errorCallback) {
		/*
		Returns the threshold as set by :func:`Set Object Temperature Callback Threshold`.
		*/
		this.ipcon.sendRequest(this, BrickletTemperatureIR.FUNCTION_GET_OBJECT_TEMPERATURE_CALLBACK_THRESHOLD, [], '', 13, 'c h h', returnCallback, errorCallback, false, true);
	};
	this.setDebouncePeriod = function(debounce, returnCallback, errorCallback) {
		/*
		Sets the period with which the threshold callbacks
		
		* :cb:`Ambient Temperature Reached`,
		* :cb:`Object Temperature Reached`
		
		are triggered, if the thresholds
		
		* :func:`Set Ambient Temperature Callback Threshold`,
		* :func:`Set Object Temperature Callback Threshold`
		
		keep being reached.
		*/
		this.ipcon.sendRequest(this, BrickletTemperatureIR.FUNCTION_SET_DEBOUNCE_PERIOD, [debounce], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getDebouncePeriod = function(returnCallback, errorCallback) {
		/*
		Returns the debounce period as set by :func:`Set Debounce Period`.
		*/
		this.ipcon.sendRequest(this, BrickletTemperatureIR.FUNCTION_GET_DEBOUNCE_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletTemperatureIR.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletTemperatureIR;

},{"./Device":279,"./IPConnection":280}],266:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletTemperatureIRV2.DEVICE_IDENTIFIER = 291;
BrickletTemperatureIRV2.DEVICE_DISPLAY_NAME = 'Temperature IR Bricklet 2.0';
BrickletTemperatureIRV2.CALLBACK_AMBIENT_TEMPERATURE = 4;
BrickletTemperatureIRV2.CALLBACK_OBJECT_TEMPERATURE = 8;
BrickletTemperatureIRV2.FUNCTION_GET_AMBIENT_TEMPERATURE = 1;
BrickletTemperatureIRV2.FUNCTION_SET_AMBIENT_TEMPERATURE_CALLBACK_CONFIGURATION = 2;
BrickletTemperatureIRV2.FUNCTION_GET_AMBIENT_TEMPERATURE_CALLBACK_CONFIGURATION = 3;
BrickletTemperatureIRV2.FUNCTION_GET_OBJECT_TEMPERATURE = 5;
BrickletTemperatureIRV2.FUNCTION_SET_OBJECT_TEMPERATURE_CALLBACK_CONFIGURATION = 6;
BrickletTemperatureIRV2.FUNCTION_GET_OBJECT_TEMPERATURE_CALLBACK_CONFIGURATION = 7;
BrickletTemperatureIRV2.FUNCTION_SET_EMISSIVITY = 9;
BrickletTemperatureIRV2.FUNCTION_GET_EMISSIVITY = 10;
BrickletTemperatureIRV2.FUNCTION_GET_SPITFP_ERROR_COUNT = 234;
BrickletTemperatureIRV2.FUNCTION_SET_BOOTLOADER_MODE = 235;
BrickletTemperatureIRV2.FUNCTION_GET_BOOTLOADER_MODE = 236;
BrickletTemperatureIRV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER = 237;
BrickletTemperatureIRV2.FUNCTION_WRITE_FIRMWARE = 238;
BrickletTemperatureIRV2.FUNCTION_SET_STATUS_LED_CONFIG = 239;
BrickletTemperatureIRV2.FUNCTION_GET_STATUS_LED_CONFIG = 240;
BrickletTemperatureIRV2.FUNCTION_GET_CHIP_TEMPERATURE = 242;
BrickletTemperatureIRV2.FUNCTION_RESET = 243;
BrickletTemperatureIRV2.FUNCTION_WRITE_UID = 248;
BrickletTemperatureIRV2.FUNCTION_READ_UID = 249;
BrickletTemperatureIRV2.FUNCTION_GET_IDENTITY = 255;
BrickletTemperatureIRV2.THRESHOLD_OPTION_OFF = 'x';
BrickletTemperatureIRV2.THRESHOLD_OPTION_OUTSIDE = 'o';
BrickletTemperatureIRV2.THRESHOLD_OPTION_INSIDE = 'i';
BrickletTemperatureIRV2.THRESHOLD_OPTION_SMALLER = '<';
BrickletTemperatureIRV2.THRESHOLD_OPTION_GREATER = '>';
BrickletTemperatureIRV2.BOOTLOADER_MODE_BOOTLOADER = 0;
BrickletTemperatureIRV2.BOOTLOADER_MODE_FIRMWARE = 1;
BrickletTemperatureIRV2.BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT = 2;
BrickletTemperatureIRV2.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT = 3;
BrickletTemperatureIRV2.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT = 4;
BrickletTemperatureIRV2.BOOTLOADER_STATUS_OK = 0;
BrickletTemperatureIRV2.BOOTLOADER_STATUS_INVALID_MODE = 1;
BrickletTemperatureIRV2.BOOTLOADER_STATUS_NO_CHANGE = 2;
BrickletTemperatureIRV2.BOOTLOADER_STATUS_ENTRY_FUNCTION_NOT_PRESENT = 3;
BrickletTemperatureIRV2.BOOTLOADER_STATUS_DEVICE_IDENTIFIER_INCORRECT = 4;
BrickletTemperatureIRV2.BOOTLOADER_STATUS_CRC_MISMATCH = 5;
BrickletTemperatureIRV2.STATUS_LED_CONFIG_OFF = 0;
BrickletTemperatureIRV2.STATUS_LED_CONFIG_ON = 1;
BrickletTemperatureIRV2.STATUS_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletTemperatureIRV2.STATUS_LED_CONFIG_SHOW_STATUS = 3;

function BrickletTemperatureIRV2(uid, ipcon) {
	//Measures contactless object temperature between -70°C and +380°C

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletTemperatureIRV2.DEVICE_IDENTIFIER, BrickletTemperatureIRV2.DEVICE_DISPLAY_NAME);
	BrickletTemperatureIRV2.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 1];
	this.responseExpected[BrickletTemperatureIRV2.FUNCTION_GET_AMBIENT_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletTemperatureIRV2.FUNCTION_SET_AMBIENT_TEMPERATURE_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletTemperatureIRV2.FUNCTION_GET_AMBIENT_TEMPERATURE_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletTemperatureIRV2.FUNCTION_GET_OBJECT_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletTemperatureIRV2.FUNCTION_SET_OBJECT_TEMPERATURE_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletTemperatureIRV2.FUNCTION_GET_OBJECT_TEMPERATURE_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletTemperatureIRV2.FUNCTION_SET_EMISSIVITY] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletTemperatureIRV2.FUNCTION_GET_EMISSIVITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletTemperatureIRV2.FUNCTION_GET_SPITFP_ERROR_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletTemperatureIRV2.FUNCTION_SET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletTemperatureIRV2.FUNCTION_GET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletTemperatureIRV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletTemperatureIRV2.FUNCTION_WRITE_FIRMWARE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletTemperatureIRV2.FUNCTION_SET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletTemperatureIRV2.FUNCTION_GET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletTemperatureIRV2.FUNCTION_GET_CHIP_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletTemperatureIRV2.FUNCTION_RESET] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletTemperatureIRV2.FUNCTION_WRITE_UID] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletTemperatureIRV2.FUNCTION_READ_UID] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletTemperatureIRV2.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletTemperatureIRV2.CALLBACK_AMBIENT_TEMPERATURE] = [10, 'h'];
	this.callbackFormats[BrickletTemperatureIRV2.CALLBACK_OBJECT_TEMPERATURE] = [10, 'h'];



	this.getAmbientTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the ambient temperature of the sensor.
		
		
		If you want to get the value periodically, it is recommended to use the
		:cb:`Ambient Temperature` callback. You can set the callback configuration
		with :func:`Set Ambient Temperature Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletTemperatureIRV2.FUNCTION_GET_AMBIENT_TEMPERATURE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.setAmbientTemperatureCallbackConfiguration = function(period, valueHasToChange, option, min, max, returnCallback, errorCallback) {
		/*
		The period is the period with which the :cb:`Ambient Temperature` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		If the `value has to change`-parameter is set to true, the callback is only
		triggered after the value has changed. If the value didn't change
		within the period, the callback is triggered immediately on change.
		
		If it is set to false, the callback is continuously triggered with the period,
		independent of the value.
		
		It is furthermore possible to constrain the callback with thresholds.
		
		The `option`-parameter together with min/max sets a threshold for the :cb:`Ambient Temperature` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Threshold is turned off"
		 "'o'",    "Threshold is triggered when the value is *outside* the min and max values"
		 "'i'",    "Threshold is triggered when the value is *inside* or equal to the min and max values"
		 "'<'",    "Threshold is triggered when the value is smaller than the min value (max is ignored)"
		 "'>'",    "Threshold is triggered when the value is greater than the min value (max is ignored)"
		
		If the option is set to 'x' (threshold turned off) the callback is triggered with the fixed period.
		*/
		this.ipcon.sendRequest(this, BrickletTemperatureIRV2.FUNCTION_SET_AMBIENT_TEMPERATURE_CALLBACK_CONFIGURATION, [period, valueHasToChange, option, min, max], 'I ? c h h', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getAmbientTemperatureCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the callback configuration as set by :func:`Set Ambient Temperature Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletTemperatureIRV2.FUNCTION_GET_AMBIENT_TEMPERATURE_CALLBACK_CONFIGURATION, [], '', 18, 'I ? c h h', returnCallback, errorCallback, false, true);
	};
	this.getObjectTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the object temperature of the sensor, i.e. the temperature
		of the surface of the object the sensor is aimed at.
		
		The temperature of different materials is dependent on their `emissivity
		<https://en.wikipedia.org/wiki/Emissivity>`__. The emissivity of the material
		can be set with :func:`Set Emissivity`.
		
		
		If you want to get the value periodically, it is recommended to use the
		:cb:`Object Temperature` callback. You can set the callback configuration
		with :func:`Set Object Temperature Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletTemperatureIRV2.FUNCTION_GET_OBJECT_TEMPERATURE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.setObjectTemperatureCallbackConfiguration = function(period, valueHasToChange, option, min, max, returnCallback, errorCallback) {
		/*
		The period is the period with which the :cb:`Object Temperature` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		If the `value has to change`-parameter is set to true, the callback is only
		triggered after the value has changed. If the value didn't change
		within the period, the callback is triggered immediately on change.
		
		If it is set to false, the callback is continuously triggered with the period,
		independent of the value.
		
		It is furthermore possible to constrain the callback with thresholds.
		
		The `option`-parameter together with min/max sets a threshold for the :cb:`Object Temperature` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Threshold is turned off"
		 "'o'",    "Threshold is triggered when the value is *outside* the min and max values"
		 "'i'",    "Threshold is triggered when the value is *inside* or equal to the min and max values"
		 "'<'",    "Threshold is triggered when the value is smaller than the min value (max is ignored)"
		 "'>'",    "Threshold is triggered when the value is greater than the min value (max is ignored)"
		
		If the option is set to 'x' (threshold turned off) the callback is triggered with the fixed period.
		*/
		this.ipcon.sendRequest(this, BrickletTemperatureIRV2.FUNCTION_SET_OBJECT_TEMPERATURE_CALLBACK_CONFIGURATION, [period, valueHasToChange, option, min, max], 'I ? c h h', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getObjectTemperatureCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the callback configuration as set by :func:`Set Object Temperature Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletTemperatureIRV2.FUNCTION_GET_OBJECT_TEMPERATURE_CALLBACK_CONFIGURATION, [], '', 18, 'I ? c h h', returnCallback, errorCallback, false, true);
	};
	this.setEmissivity = function(emissivity, returnCallback, errorCallback) {
		/*
		Sets the `emissivity <https://en.wikipedia.org/wiki/Emissivity>`__ that is
		used to calculate the surface temperature as returned by
		:func:`Get Object Temperature`.
		
		The emissivity is usually given as a value between 0.0 and 1.0. A list of
		emissivities of different materials can be found
		`here <https://www.infrared-thermography.com/material.htm>`__.
		
		The parameter of :func:`Set Emissivity` has to be given with a factor of
		65535 (16-bit). For example: An emissivity of 0.1 can be set with the
		value 6553, an emissivity of 0.5 with the value 32767 and so on.
		
		.. note::
		 If you need a precise measurement for the object temperature, it is
		 absolutely crucial that you also provide a precise emissivity.
		
		The emissivity is stored in non-volatile memory and will still be
		used after a restart or power cycle of the Bricklet.
		*/
		this.ipcon.sendRequest(this, BrickletTemperatureIRV2.FUNCTION_SET_EMISSIVITY, [emissivity], 'H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getEmissivity = function(returnCallback, errorCallback) {
		/*
		Returns the emissivity as set by :func:`Set Emissivity`.
		*/
		this.ipcon.sendRequest(this, BrickletTemperatureIRV2.FUNCTION_GET_EMISSIVITY, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPErrorCount = function(returnCallback, errorCallback) {
		/*
		Returns the error count for the communication between Brick and Bricklet.
		
		The errors are divided into
		
		* ACK checksum errors,
		* message checksum errors,
		* framing errors and
		* overflow errors.
		
		The errors counts are for errors that occur on the Bricklet side. All
		Bricks have a similar function that returns the errors on the Brick side.
		*/
		this.ipcon.sendRequest(this, BrickletTemperatureIRV2.FUNCTION_GET_SPITFP_ERROR_COUNT, [], '', 24, 'I I I I', returnCallback, errorCallback, false, true);
	};
	this.setBootloaderMode = function(mode, returnCallback, errorCallback) {
		/*
		Sets the bootloader mode and returns the status after the requested
		mode change was instigated.
		
		You can change from bootloader mode to firmware mode and vice versa. A change
		from bootloader mode to firmware mode will only take place if the entry function,
		device identifier and CRC are present and correct.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletTemperatureIRV2.FUNCTION_SET_BOOTLOADER_MODE, [mode], 'B', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getBootloaderMode = function(returnCallback, errorCallback) {
		/*
		Returns the current bootloader mode, see :func:`Set Bootloader Mode`.
		*/
		this.ipcon.sendRequest(this, BrickletTemperatureIRV2.FUNCTION_GET_BOOTLOADER_MODE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setWriteFirmwarePointer = function(pointer, returnCallback, errorCallback) {
		/*
		Sets the firmware pointer for :func:`Write Firmware`. The pointer has
		to be increased by chunks of size 64. The data is written to flash
		every 4 chunks (which equals to one page of size 256).
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletTemperatureIRV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER, [pointer], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeFirmware = function(data, returnCallback, errorCallback) {
		/*
		Writes 64 Bytes of firmware at the position as written by
		:func:`Set Write Firmware Pointer` before. The firmware is written
		to flash every 4 chunks.
		
		You can only write firmware in bootloader mode.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletTemperatureIRV2.FUNCTION_WRITE_FIRMWARE, [data], 'B64', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setStatusLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Sets the status LED configuration. By default the LED shows
		communication traffic between Brick and Bricklet, it flickers once
		for every 10 received data packets.
		
		You can also turn the LED permanently on/off or show a heartbeat.
		
		If the Bricklet is in bootloader mode, the LED is will show heartbeat by default.
		*/
		this.ipcon.sendRequest(this, BrickletTemperatureIRV2.FUNCTION_SET_STATUS_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getStatusLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Status LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletTemperatureIRV2.FUNCTION_GET_STATUS_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getChipTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature as measured inside the microcontroller. The
		value returned is not the ambient temperature!
		
		The temperature is only proportional to the real temperature and it has bad
		accuracy. Practically it is only useful as an indicator for
		temperature changes.
		*/
		this.ipcon.sendRequest(this, BrickletTemperatureIRV2.FUNCTION_GET_CHIP_TEMPERATURE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.reset = function(returnCallback, errorCallback) {
		/*
		Calling this function will reset the Bricklet. All configurations
		will be lost.
		
		After a reset you have to create new device objects,
		calling functions on the existing ones will result in
		undefined behavior!
		*/
		this.ipcon.sendRequest(this, BrickletTemperatureIRV2.FUNCTION_RESET, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeUID = function(uid, returnCallback, errorCallback) {
		/*
		Writes a new UID into flash. If you want to set a new UID
		you have to decode the Base58 encoded UID string into an
		integer first.
		
		We recommend that you use Brick Viewer to change the UID.
		*/
		this.ipcon.sendRequest(this, BrickletTemperatureIRV2.FUNCTION_WRITE_UID, [uid], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.readUID = function(returnCallback, errorCallback) {
		/*
		Returns the current UID as an integer. Encode as
		Base58 to get the usual string version.
		*/
		this.ipcon.sendRequest(this, BrickletTemperatureIRV2.FUNCTION_READ_UID, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletTemperatureIRV2.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletTemperatureIRV2;

},{"./Device":279,"./IPConnection":280}],267:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletTemperatureV2.DEVICE_IDENTIFIER = 2113;
BrickletTemperatureV2.DEVICE_DISPLAY_NAME = 'Temperature Bricklet 2.0';
BrickletTemperatureV2.CALLBACK_TEMPERATURE = 4;
BrickletTemperatureV2.FUNCTION_GET_TEMPERATURE = 1;
BrickletTemperatureV2.FUNCTION_SET_TEMPERATURE_CALLBACK_CONFIGURATION = 2;
BrickletTemperatureV2.FUNCTION_GET_TEMPERATURE_CALLBACK_CONFIGURATION = 3;
BrickletTemperatureV2.FUNCTION_SET_HEATER_CONFIGURATION = 5;
BrickletTemperatureV2.FUNCTION_GET_HEATER_CONFIGURATION = 6;
BrickletTemperatureV2.FUNCTION_GET_SPITFP_ERROR_COUNT = 234;
BrickletTemperatureV2.FUNCTION_SET_BOOTLOADER_MODE = 235;
BrickletTemperatureV2.FUNCTION_GET_BOOTLOADER_MODE = 236;
BrickletTemperatureV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER = 237;
BrickletTemperatureV2.FUNCTION_WRITE_FIRMWARE = 238;
BrickletTemperatureV2.FUNCTION_SET_STATUS_LED_CONFIG = 239;
BrickletTemperatureV2.FUNCTION_GET_STATUS_LED_CONFIG = 240;
BrickletTemperatureV2.FUNCTION_GET_CHIP_TEMPERATURE = 242;
BrickletTemperatureV2.FUNCTION_RESET = 243;
BrickletTemperatureV2.FUNCTION_WRITE_UID = 248;
BrickletTemperatureV2.FUNCTION_READ_UID = 249;
BrickletTemperatureV2.FUNCTION_GET_IDENTITY = 255;
BrickletTemperatureV2.THRESHOLD_OPTION_OFF = 'x';
BrickletTemperatureV2.THRESHOLD_OPTION_OUTSIDE = 'o';
BrickletTemperatureV2.THRESHOLD_OPTION_INSIDE = 'i';
BrickletTemperatureV2.THRESHOLD_OPTION_SMALLER = '<';
BrickletTemperatureV2.THRESHOLD_OPTION_GREATER = '>';
BrickletTemperatureV2.HEATER_CONFIG_DISABLED = 0;
BrickletTemperatureV2.HEATER_CONFIG_ENABLED = 1;
BrickletTemperatureV2.BOOTLOADER_MODE_BOOTLOADER = 0;
BrickletTemperatureV2.BOOTLOADER_MODE_FIRMWARE = 1;
BrickletTemperatureV2.BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT = 2;
BrickletTemperatureV2.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT = 3;
BrickletTemperatureV2.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT = 4;
BrickletTemperatureV2.BOOTLOADER_STATUS_OK = 0;
BrickletTemperatureV2.BOOTLOADER_STATUS_INVALID_MODE = 1;
BrickletTemperatureV2.BOOTLOADER_STATUS_NO_CHANGE = 2;
BrickletTemperatureV2.BOOTLOADER_STATUS_ENTRY_FUNCTION_NOT_PRESENT = 3;
BrickletTemperatureV2.BOOTLOADER_STATUS_DEVICE_IDENTIFIER_INCORRECT = 4;
BrickletTemperatureV2.BOOTLOADER_STATUS_CRC_MISMATCH = 5;
BrickletTemperatureV2.STATUS_LED_CONFIG_OFF = 0;
BrickletTemperatureV2.STATUS_LED_CONFIG_ON = 1;
BrickletTemperatureV2.STATUS_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletTemperatureV2.STATUS_LED_CONFIG_SHOW_STATUS = 3;

function BrickletTemperatureV2(uid, ipcon) {
	//Measures ambient temperature with 0.2°C accuracy

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletTemperatureV2.DEVICE_IDENTIFIER, BrickletTemperatureV2.DEVICE_DISPLAY_NAME);
	BrickletTemperatureV2.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickletTemperatureV2.FUNCTION_GET_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletTemperatureV2.FUNCTION_SET_TEMPERATURE_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletTemperatureV2.FUNCTION_GET_TEMPERATURE_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletTemperatureV2.FUNCTION_SET_HEATER_CONFIGURATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletTemperatureV2.FUNCTION_GET_HEATER_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletTemperatureV2.FUNCTION_GET_SPITFP_ERROR_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletTemperatureV2.FUNCTION_SET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletTemperatureV2.FUNCTION_GET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletTemperatureV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletTemperatureV2.FUNCTION_WRITE_FIRMWARE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletTemperatureV2.FUNCTION_SET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletTemperatureV2.FUNCTION_GET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletTemperatureV2.FUNCTION_GET_CHIP_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletTemperatureV2.FUNCTION_RESET] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletTemperatureV2.FUNCTION_WRITE_UID] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletTemperatureV2.FUNCTION_READ_UID] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletTemperatureV2.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletTemperatureV2.CALLBACK_TEMPERATURE] = [10, 'h'];



	this.getTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature measured by the sensor.
		
		
		If you want to get the value periodically, it is recommended to use the
		:cb:`Temperature` callback. You can set the callback configuration
		with :func:`Set Temperature Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletTemperatureV2.FUNCTION_GET_TEMPERATURE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.setTemperatureCallbackConfiguration = function(period, valueHasToChange, option, min, max, returnCallback, errorCallback) {
		/*
		The period is the period with which the :cb:`Temperature` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		If the `value has to change`-parameter is set to true, the callback is only
		triggered after the value has changed. If the value didn't change
		within the period, the callback is triggered immediately on change.
		
		If it is set to false, the callback is continuously triggered with the period,
		independent of the value.
		
		It is furthermore possible to constrain the callback with thresholds.
		
		The `option`-parameter together with min/max sets a threshold for the :cb:`Temperature` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Threshold is turned off"
		 "'o'",    "Threshold is triggered when the value is *outside* the min and max values"
		 "'i'",    "Threshold is triggered when the value is *inside* or equal to the min and max values"
		 "'<'",    "Threshold is triggered when the value is smaller than the min value (max is ignored)"
		 "'>'",    "Threshold is triggered when the value is greater than the min value (max is ignored)"
		
		If the option is set to 'x' (threshold turned off) the callback is triggered with the fixed period.
		*/
		this.ipcon.sendRequest(this, BrickletTemperatureV2.FUNCTION_SET_TEMPERATURE_CALLBACK_CONFIGURATION, [period, valueHasToChange, option, min, max], 'I ? c h h', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getTemperatureCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the callback configuration as set by :func:`Set Temperature Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletTemperatureV2.FUNCTION_GET_TEMPERATURE_CALLBACK_CONFIGURATION, [], '', 18, 'I ? c h h', returnCallback, errorCallback, false, true);
	};
	this.setHeaterConfiguration = function(heaterConfig, returnCallback, errorCallback) {
		/*
		Enables/disables the heater. The heater can be used to test the sensor.
		*/
		this.ipcon.sendRequest(this, BrickletTemperatureV2.FUNCTION_SET_HEATER_CONFIGURATION, [heaterConfig], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getHeaterConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the heater configuration as set by :func:`Set Heater Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletTemperatureV2.FUNCTION_GET_HEATER_CONFIGURATION, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPErrorCount = function(returnCallback, errorCallback) {
		/*
		Returns the error count for the communication between Brick and Bricklet.
		
		The errors are divided into
		
		* ACK checksum errors,
		* message checksum errors,
		* framing errors and
		* overflow errors.
		
		The errors counts are for errors that occur on the Bricklet side. All
		Bricks have a similar function that returns the errors on the Brick side.
		*/
		this.ipcon.sendRequest(this, BrickletTemperatureV2.FUNCTION_GET_SPITFP_ERROR_COUNT, [], '', 24, 'I I I I', returnCallback, errorCallback, false, true);
	};
	this.setBootloaderMode = function(mode, returnCallback, errorCallback) {
		/*
		Sets the bootloader mode and returns the status after the requested
		mode change was instigated.
		
		You can change from bootloader mode to firmware mode and vice versa. A change
		from bootloader mode to firmware mode will only take place if the entry function,
		device identifier and CRC are present and correct.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletTemperatureV2.FUNCTION_SET_BOOTLOADER_MODE, [mode], 'B', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getBootloaderMode = function(returnCallback, errorCallback) {
		/*
		Returns the current bootloader mode, see :func:`Set Bootloader Mode`.
		*/
		this.ipcon.sendRequest(this, BrickletTemperatureV2.FUNCTION_GET_BOOTLOADER_MODE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setWriteFirmwarePointer = function(pointer, returnCallback, errorCallback) {
		/*
		Sets the firmware pointer for :func:`Write Firmware`. The pointer has
		to be increased by chunks of size 64. The data is written to flash
		every 4 chunks (which equals to one page of size 256).
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletTemperatureV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER, [pointer], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeFirmware = function(data, returnCallback, errorCallback) {
		/*
		Writes 64 Bytes of firmware at the position as written by
		:func:`Set Write Firmware Pointer` before. The firmware is written
		to flash every 4 chunks.
		
		You can only write firmware in bootloader mode.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletTemperatureV2.FUNCTION_WRITE_FIRMWARE, [data], 'B64', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setStatusLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Sets the status LED configuration. By default the LED shows
		communication traffic between Brick and Bricklet, it flickers once
		for every 10 received data packets.
		
		You can also turn the LED permanently on/off or show a heartbeat.
		
		If the Bricklet is in bootloader mode, the LED is will show heartbeat by default.
		*/
		this.ipcon.sendRequest(this, BrickletTemperatureV2.FUNCTION_SET_STATUS_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getStatusLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Status LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletTemperatureV2.FUNCTION_GET_STATUS_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getChipTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature as measured inside the microcontroller. The
		value returned is not the ambient temperature!
		
		The temperature is only proportional to the real temperature and it has bad
		accuracy. Practically it is only useful as an indicator for
		temperature changes.
		*/
		this.ipcon.sendRequest(this, BrickletTemperatureV2.FUNCTION_GET_CHIP_TEMPERATURE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.reset = function(returnCallback, errorCallback) {
		/*
		Calling this function will reset the Bricklet. All configurations
		will be lost.
		
		After a reset you have to create new device objects,
		calling functions on the existing ones will result in
		undefined behavior!
		*/
		this.ipcon.sendRequest(this, BrickletTemperatureV2.FUNCTION_RESET, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeUID = function(uid, returnCallback, errorCallback) {
		/*
		Writes a new UID into flash. If you want to set a new UID
		you have to decode the Base58 encoded UID string into an
		integer first.
		
		We recommend that you use Brick Viewer to change the UID.
		*/
		this.ipcon.sendRequest(this, BrickletTemperatureV2.FUNCTION_WRITE_UID, [uid], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.readUID = function(returnCallback, errorCallback) {
		/*
		Returns the current UID as an integer. Encode as
		Base58 to get the usual string version.
		*/
		this.ipcon.sendRequest(this, BrickletTemperatureV2.FUNCTION_READ_UID, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletTemperatureV2.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletTemperatureV2;

},{"./Device":279,"./IPConnection":280}],268:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletThermalImaging.DEVICE_IDENTIFIER = 278;
BrickletThermalImaging.DEVICE_DISPLAY_NAME = 'Thermal Imaging Bricklet';
BrickletThermalImaging.CALLBACK_HIGH_CONTRAST_IMAGE_LOW_LEVEL = 12;
BrickletThermalImaging.CALLBACK_TEMPERATURE_IMAGE_LOW_LEVEL = 13;
BrickletThermalImaging.CALLBACK_HIGH_CONTRAST_IMAGE = -12;
BrickletThermalImaging.CALLBACK_TEMPERATURE_IMAGE = -13;
BrickletThermalImaging.FUNCTION_GET_HIGH_CONTRAST_IMAGE_LOW_LEVEL = 1;
BrickletThermalImaging.FUNCTION_GET_TEMPERATURE_IMAGE_LOW_LEVEL = 2;
BrickletThermalImaging.FUNCTION_GET_STATISTICS = 3;
BrickletThermalImaging.FUNCTION_SET_RESOLUTION = 4;
BrickletThermalImaging.FUNCTION_GET_RESOLUTION = 5;
BrickletThermalImaging.FUNCTION_SET_SPOTMETER_CONFIG = 6;
BrickletThermalImaging.FUNCTION_GET_SPOTMETER_CONFIG = 7;
BrickletThermalImaging.FUNCTION_SET_HIGH_CONTRAST_CONFIG = 8;
BrickletThermalImaging.FUNCTION_GET_HIGH_CONTRAST_CONFIG = 9;
BrickletThermalImaging.FUNCTION_SET_IMAGE_TRANSFER_CONFIG = 10;
BrickletThermalImaging.FUNCTION_GET_IMAGE_TRANSFER_CONFIG = 11;
BrickletThermalImaging.FUNCTION_SET_FLUX_LINEAR_PARAMETERS = 14;
BrickletThermalImaging.FUNCTION_GET_FLUX_LINEAR_PARAMETERS = 15;
BrickletThermalImaging.FUNCTION_GET_SPITFP_ERROR_COUNT = 234;
BrickletThermalImaging.FUNCTION_SET_BOOTLOADER_MODE = 235;
BrickletThermalImaging.FUNCTION_GET_BOOTLOADER_MODE = 236;
BrickletThermalImaging.FUNCTION_SET_WRITE_FIRMWARE_POINTER = 237;
BrickletThermalImaging.FUNCTION_WRITE_FIRMWARE = 238;
BrickletThermalImaging.FUNCTION_SET_STATUS_LED_CONFIG = 239;
BrickletThermalImaging.FUNCTION_GET_STATUS_LED_CONFIG = 240;
BrickletThermalImaging.FUNCTION_GET_CHIP_TEMPERATURE = 242;
BrickletThermalImaging.FUNCTION_RESET = 243;
BrickletThermalImaging.FUNCTION_WRITE_UID = 248;
BrickletThermalImaging.FUNCTION_READ_UID = 249;
BrickletThermalImaging.FUNCTION_GET_IDENTITY = 255;
BrickletThermalImaging.RESOLUTION_0_TO_6553_KELVIN = 0;
BrickletThermalImaging.RESOLUTION_0_TO_655_KELVIN = 1;
BrickletThermalImaging.FFC_STATUS_NEVER_COMMANDED = 0;
BrickletThermalImaging.FFC_STATUS_IMMINENT = 1;
BrickletThermalImaging.FFC_STATUS_IN_PROGRESS = 2;
BrickletThermalImaging.FFC_STATUS_COMPLETE = 3;
BrickletThermalImaging.IMAGE_TRANSFER_MANUAL_HIGH_CONTRAST_IMAGE = 0;
BrickletThermalImaging.IMAGE_TRANSFER_MANUAL_TEMPERATURE_IMAGE = 1;
BrickletThermalImaging.IMAGE_TRANSFER_CALLBACK_HIGH_CONTRAST_IMAGE = 2;
BrickletThermalImaging.IMAGE_TRANSFER_CALLBACK_TEMPERATURE_IMAGE = 3;
BrickletThermalImaging.BOOTLOADER_MODE_BOOTLOADER = 0;
BrickletThermalImaging.BOOTLOADER_MODE_FIRMWARE = 1;
BrickletThermalImaging.BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT = 2;
BrickletThermalImaging.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT = 3;
BrickletThermalImaging.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT = 4;
BrickletThermalImaging.BOOTLOADER_STATUS_OK = 0;
BrickletThermalImaging.BOOTLOADER_STATUS_INVALID_MODE = 1;
BrickletThermalImaging.BOOTLOADER_STATUS_NO_CHANGE = 2;
BrickletThermalImaging.BOOTLOADER_STATUS_ENTRY_FUNCTION_NOT_PRESENT = 3;
BrickletThermalImaging.BOOTLOADER_STATUS_DEVICE_IDENTIFIER_INCORRECT = 4;
BrickletThermalImaging.BOOTLOADER_STATUS_CRC_MISMATCH = 5;
BrickletThermalImaging.STATUS_LED_CONFIG_OFF = 0;
BrickletThermalImaging.STATUS_LED_CONFIG_ON = 1;
BrickletThermalImaging.STATUS_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletThermalImaging.STATUS_LED_CONFIG_SHOW_STATUS = 3;

function BrickletThermalImaging(uid, ipcon) {
	//80x60 pixel thermal imaging camera

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletThermalImaging.DEVICE_IDENTIFIER, BrickletThermalImaging.DEVICE_DISPLAY_NAME);
	BrickletThermalImaging.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 1];
	this.responseExpected[BrickletThermalImaging.FUNCTION_GET_HIGH_CONTRAST_IMAGE_LOW_LEVEL] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletThermalImaging.FUNCTION_GET_TEMPERATURE_IMAGE_LOW_LEVEL] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletThermalImaging.FUNCTION_GET_STATISTICS] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletThermalImaging.FUNCTION_SET_RESOLUTION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletThermalImaging.FUNCTION_GET_RESOLUTION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletThermalImaging.FUNCTION_SET_SPOTMETER_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletThermalImaging.FUNCTION_GET_SPOTMETER_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletThermalImaging.FUNCTION_SET_HIGH_CONTRAST_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletThermalImaging.FUNCTION_GET_HIGH_CONTRAST_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletThermalImaging.FUNCTION_SET_IMAGE_TRANSFER_CONFIG] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletThermalImaging.FUNCTION_GET_IMAGE_TRANSFER_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletThermalImaging.FUNCTION_SET_FLUX_LINEAR_PARAMETERS] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletThermalImaging.FUNCTION_GET_FLUX_LINEAR_PARAMETERS] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletThermalImaging.FUNCTION_GET_SPITFP_ERROR_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletThermalImaging.FUNCTION_SET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletThermalImaging.FUNCTION_GET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletThermalImaging.FUNCTION_SET_WRITE_FIRMWARE_POINTER] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletThermalImaging.FUNCTION_WRITE_FIRMWARE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletThermalImaging.FUNCTION_SET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletThermalImaging.FUNCTION_GET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletThermalImaging.FUNCTION_GET_CHIP_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletThermalImaging.FUNCTION_RESET] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletThermalImaging.FUNCTION_WRITE_UID] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletThermalImaging.FUNCTION_READ_UID] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletThermalImaging.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletThermalImaging.CALLBACK_HIGH_CONTRAST_IMAGE_LOW_LEVEL] = [72, 'H B62'];
	this.callbackFormats[BrickletThermalImaging.CALLBACK_TEMPERATURE_IMAGE_LOW_LEVEL] = [72, 'H H31'];

	this.highLevelCallbacks[BrickletThermalImaging.CALLBACK_HIGH_CONTRAST_IMAGE] = [['streamChunkOffset', 'streamChunkData'], {'fixedLength': 4800, 'singleChunk': false}, null];
	this.highLevelCallbacks[BrickletThermalImaging.CALLBACK_TEMPERATURE_IMAGE] = [['streamChunkOffset', 'streamChunkData'], {'fixedLength': 4800, 'singleChunk': false}, null];

	this.streamStateObjects[BrickletThermalImaging.FUNCTION_GET_HIGH_CONTRAST_IMAGE_LOW_LEVEL] = {
		'dataMapping': ['streamChunkOffset', 'streamChunkData'],
		'dataMappingStreamIn': [],
		'streamProperties': {
			'fixedLength': 4800,
			'singleChunk': false,
			'shortWrite': false
		},
		'responseProperties': {
			'running': false,
			'runningSubcall': false,
			'runningSubcallOOS': false,
			'waitingFirstChunk': true,
			'timeout': null,
			'data': [],
			'streamInChunkOffset': 0,
			'streamInChunkLength': 0,
			'streamInResponseEmpty': true,
			'streamInWritten': 0,
			'streamInLLParams': null,
			'responseHandler': null,
			'packFormatString': '',
			'unpackFormatString': 'H B62',
			'returnCB': null,
			'errorCB': null,
			'callQueue': []
		}
	};
	this.streamStateObjects[BrickletThermalImaging.FUNCTION_GET_TEMPERATURE_IMAGE_LOW_LEVEL] = {
		'dataMapping': ['streamChunkOffset', 'streamChunkData'],
		'dataMappingStreamIn': [],
		'streamProperties': {
			'fixedLength': 4800,
			'singleChunk': false,
			'shortWrite': false
		},
		'responseProperties': {
			'running': false,
			'runningSubcall': false,
			'runningSubcallOOS': false,
			'waitingFirstChunk': true,
			'timeout': null,
			'data': [],
			'streamInChunkOffset': 0,
			'streamInChunkLength': 0,
			'streamInResponseEmpty': true,
			'streamInWritten': 0,
			'streamInLLParams': null,
			'responseHandler': null,
			'packFormatString': '',
			'unpackFormatString': 'H H31',
			'returnCB': null,
			'errorCB': null,
			'callQueue': []
		}
	};

	this.getHighContrastImageLowLevel = function(returnCallback, errorCallback) {
		/*
		Returns the current high contrast image. See `here <https://www.tinkerforge.com/en/doc/Hardware/Bricklets/Thermal_Imaging.html#high-contrast-image-vs-temperature-image>`__
		for the difference between
		High Contrast and Temperature Image. If you don't know what to use
		the High Contrast Image is probably right for you.
		
		The data is organized as a 8-bit value 80x60 pixel matrix linearized in
		a one-dimensional array. The data is arranged line by line from top left to
		bottom right.
		
		Each 8-bit value represents one gray-scale image pixel that can directly be
		shown to a user on a display.
		
		Before you can use this function you have to enable it with
		:func:`Set Image Transfer Config`.
		*/
		this.ipcon.sendRequest(this, BrickletThermalImaging.FUNCTION_GET_HIGH_CONTRAST_IMAGE_LOW_LEVEL, [], '', 72, 'H B62', returnCallback, errorCallback, false, true);
	};
	this.getTemperatureImageLowLevel = function(returnCallback, errorCallback) {
		/*
		Returns the current temperature image. See `here <https://www.tinkerforge.com/en/doc/Hardware/Bricklets/Thermal_Imaging.html#high-contrast-image-vs-temperature-image>`__
		for the difference between High Contrast and Temperature Image.
		If you don't know what to use the High Contrast Image is probably right for you.
		
		The data is organized as a 16-bit value 80x60 pixel matrix linearized in
		a one-dimensional array. The data is arranged line by line from top left to
		bottom right.
		
		Each 16-bit value represents one temperature measurement in either
		Kelvin/10 or Kelvin/100 (depending on the resolution set with :func:`Set Resolution`).
		
		Before you can use this function you have to enable it with
		:func:`Set Image Transfer Config`.
		*/
		this.ipcon.sendRequest(this, BrickletThermalImaging.FUNCTION_GET_TEMPERATURE_IMAGE_LOW_LEVEL, [], '', 72, 'H H31', returnCallback, errorCallback, false, true);
	};
	this.getStatistics = function(returnCallback, errorCallback) {
		/*
		Returns the spotmeter statistics, various temperatures, current resolution and status bits.
		
		The spotmeter statistics are:
		
		* Index 0: Mean Temperature.
		* Index 1: Maximum Temperature.
		* Index 2: Minimum Temperature.
		* Index 3: Pixel Count of spotmeter region of interest.
		
		The temperatures are:
		
		* Index 0: Focal Plain Array temperature.
		* Index 1: Focal Plain Array temperature at last FFC (Flat Field Correction).
		* Index 2: Housing temperature.
		* Index 3: Housing temperature at last FFC.
		
		The resolution is either `0 to 6553 Kelvin` or `0 to 655 Kelvin`. If the resolution is the former,
		the temperatures are in Kelvin/10, if it is the latter the temperatures are in Kelvin/100.
		
		FFC (Flat Field Correction) Status:
		
		* FFC Never Commanded: Only seen on startup before first FFC.
		* FFC Imminent: This state is entered 2 seconds prior to initiating FFC.
		* FFC In Progress: Flat field correction is started (shutter moves in front of lens and back). Takes about 1 second.
		* FFC Complete: Shutter is in waiting position again, FFC done.
		
		Temperature warning bits:
		
		* Index 0: Shutter lockout (if true shutter is locked out because temperature is outside -10°C to +65°C)
		* Index 1: Overtemperature shut down imminent (goes true 10 seconds before shutdown)
		*/
		this.ipcon.sendRequest(this, BrickletThermalImaging.FUNCTION_GET_STATISTICS, [], '', 27, 'H4 H4 B B ?2', returnCallback, errorCallback, false, true);
	};
	this.setResolution = function(resolution, returnCallback, errorCallback) {
		/*
		Sets the resolution. The Thermal Imaging Bricklet can either measure
		
		* from 0 to 6553 Kelvin (-273.15°C to +6279.85°C) with 0.1°C resolution or
		* from 0 to 655 Kelvin (-273.15°C to +381.85°C) with 0.01°C resolution.
		
		The accuracy is specified for -10°C to 450°C in the
		first range and -10°C and 140°C in the second range.
		*/
		this.ipcon.sendRequest(this, BrickletThermalImaging.FUNCTION_SET_RESOLUTION, [resolution], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getResolution = function(returnCallback, errorCallback) {
		/*
		Returns the resolution as set by :func:`Set Resolution`.
		*/
		this.ipcon.sendRequest(this, BrickletThermalImaging.FUNCTION_GET_RESOLUTION, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setSpotmeterConfig = function(regionOfInterest, returnCallback, errorCallback) {
		/*
		Sets the spotmeter region of interest. The 4 values are
		
		* Index 0: Column start (has to be smaller then Column end).
		* Index 1: Row start (has to be smaller then Row end).
		* Index 2: Column end (has to be smaller then 80).
		* Index 3: Row end (has to be smaller then 60).
		
		The spotmeter statistics can be read out with :func:`Get Statistics`.
		*/
		this.ipcon.sendRequest(this, BrickletThermalImaging.FUNCTION_SET_SPOTMETER_CONFIG, [regionOfInterest], 'B4', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getSpotmeterConfig = function(returnCallback, errorCallback) {
		/*
		Returns the spotmeter config as set by :func:`Set Spotmeter Config`.
		*/
		this.ipcon.sendRequest(this, BrickletThermalImaging.FUNCTION_GET_SPOTMETER_CONFIG, [], '', 12, 'B4', returnCallback, errorCallback, false, true);
	};
	this.setHighContrastConfig = function(regionOfInterest, dampeningFactor, clipLimit, emptyCounts, returnCallback, errorCallback) {
		/*
		Sets the high contrast region of interest, dampening factor, clip limit and empty counts.
		This config is only used in high contrast mode (see :func:`Set Image Transfer Config`).
		
		The high contrast region of interest consists of four values:
		
		* Index 0: Column start (has to be smaller or equal then Column end).
		* Index 1: Row start (has to be smaller then Row end).
		* Index 2: Column end (has to be smaller then 80).
		* Index 3: Row end (has to be smaller then 60).
		
		The algorithm to generate the high contrast image is applied to this region.
		
		Dampening Factor: This parameter is the amount of temporal dampening applied to the HEQ
		(history equalization) transformation function. An IIR filter of the form::
		
		 (N / 256) * previous + ((256 - N) / 256) * current
		
		is applied, and the HEQ dampening factor
		represents the value N in the equation, i.e., a value that applies to the amount of
		influence the previous HEQ transformation function has on the current function. The
		lower the value of N the higher the influence of the current video frame whereas
		the higher the value of N the more influence the previous damped transfer function has.
		
		Clip Limit Index 0 (AGC HEQ Clip Limit High): This parameter defines the maximum number of pixels allowed
		to accumulate in any given histogram bin. Any additional pixels in a given bin are clipped.
		The effect of this parameter is to limit the influence of highly-populated bins on the
		resulting HEQ transformation function.
		
		Clip Limit Index 1 (AGC HEQ Clip Limit Low): This parameter defines an artificial population that is added to
		every non-empty histogram bin. In other words, if the Clip Limit Low is set to L, a bin
		with an actual population of X will have an effective population of L + X. Any empty bin
		that is nearby a populated bin will be given an artificial population of L. The effect of
		higher values is to provide a more linear transfer function; lower values provide a more
		non-linear (equalized) transfer function.
		
		Empty Counts: This parameter specifies the maximum number of pixels in a bin that will be
		interpreted as an empty bin. Histogram bins with this number of pixels or less will be
		processed as an empty bin.
		*/
		this.ipcon.sendRequest(this, BrickletThermalImaging.FUNCTION_SET_HIGH_CONTRAST_CONFIG, [regionOfInterest, dampeningFactor, clipLimit, emptyCounts], 'B4 H H2 H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getHighContrastConfig = function(returnCallback, errorCallback) {
		/*
		Returns the high contrast config as set by :func:`Set High Contrast Config`.
		*/
		this.ipcon.sendRequest(this, BrickletThermalImaging.FUNCTION_GET_HIGH_CONTRAST_CONFIG, [], '', 20, 'B4 H H2 H', returnCallback, errorCallback, false, true);
	};
	this.setImageTransferConfig = function(config, returnCallback, errorCallback) {
		/*
		The necessary bandwidth of this Bricklet is too high to use getter/callback or
		high contrast/temperature image at the same time. You have to configure the one
		you want to use, the Bricklet will optimize the internal configuration accordingly.
		
		Corresponding functions:
		
		* Manual High Contrast Image: :func:`Get High Contrast Image`.
		* Manual Temperature Image: :func:`Get Temperature Image`.
		* Callback High Contrast Image: :cb:`High Contrast Image` callback.
		* Callback Temperature Image: :cb:`Temperature Image` callback.
		*/
		this.ipcon.sendRequest(this, BrickletThermalImaging.FUNCTION_SET_IMAGE_TRANSFER_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getImageTransferConfig = function(returnCallback, errorCallback) {
		/*
		Returns the image transfer config, as set by :func:`Set Image Transfer Config`.
		*/
		this.ipcon.sendRequest(this, BrickletThermalImaging.FUNCTION_GET_IMAGE_TRANSFER_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setFluxLinearParameters = function(sceneEmissivity, temperatureBackground, tauWindow, temperaturWindow, tauAtmosphere, temperatureAtmosphere, reflectionWindow, temperatureReflection, returnCallback, errorCallback) {
		/*
		Sets the flux linear parameters that can be used for radiometry calibration.
		
		See FLIR document 102-PS245-100-01 for more details.
		
		.. versionadded:: 2.0.5$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletThermalImaging.FUNCTION_SET_FLUX_LINEAR_PARAMETERS, [sceneEmissivity, temperatureBackground, tauWindow, temperaturWindow, tauAtmosphere, temperatureAtmosphere, reflectionWindow, temperatureReflection], 'H H H H H H H H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getFluxLinearParameters = function(returnCallback, errorCallback) {
		/*
		Returns the flux linear parameters, as set by :func:`Set Flux Linear Parameters`.
		
		.. versionadded:: 2.0.5$nbsp;(Plugin)
		*/
		this.ipcon.sendRequest(this, BrickletThermalImaging.FUNCTION_GET_FLUX_LINEAR_PARAMETERS, [], '', 24, 'H H H H H H H H', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPErrorCount = function(returnCallback, errorCallback) {
		/*
		Returns the error count for the communication between Brick and Bricklet.
		
		The errors are divided into
		
		* ACK checksum errors,
		* message checksum errors,
		* framing errors and
		* overflow errors.
		
		The errors counts are for errors that occur on the Bricklet side. All
		Bricks have a similar function that returns the errors on the Brick side.
		*/
		this.ipcon.sendRequest(this, BrickletThermalImaging.FUNCTION_GET_SPITFP_ERROR_COUNT, [], '', 24, 'I I I I', returnCallback, errorCallback, false, true);
	};
	this.setBootloaderMode = function(mode, returnCallback, errorCallback) {
		/*
		Sets the bootloader mode and returns the status after the requested
		mode change was instigated.
		
		You can change from bootloader mode to firmware mode and vice versa. A change
		from bootloader mode to firmware mode will only take place if the entry function,
		device identifier and CRC are present and correct.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletThermalImaging.FUNCTION_SET_BOOTLOADER_MODE, [mode], 'B', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getBootloaderMode = function(returnCallback, errorCallback) {
		/*
		Returns the current bootloader mode, see :func:`Set Bootloader Mode`.
		*/
		this.ipcon.sendRequest(this, BrickletThermalImaging.FUNCTION_GET_BOOTLOADER_MODE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setWriteFirmwarePointer = function(pointer, returnCallback, errorCallback) {
		/*
		Sets the firmware pointer for :func:`Write Firmware`. The pointer has
		to be increased by chunks of size 64. The data is written to flash
		every 4 chunks (which equals to one page of size 256).
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletThermalImaging.FUNCTION_SET_WRITE_FIRMWARE_POINTER, [pointer], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeFirmware = function(data, returnCallback, errorCallback) {
		/*
		Writes 64 Bytes of firmware at the position as written by
		:func:`Set Write Firmware Pointer` before. The firmware is written
		to flash every 4 chunks.
		
		You can only write firmware in bootloader mode.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletThermalImaging.FUNCTION_WRITE_FIRMWARE, [data], 'B64', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setStatusLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Sets the status LED configuration. By default the LED shows
		communication traffic between Brick and Bricklet, it flickers once
		for every 10 received data packets.
		
		You can also turn the LED permanently on/off or show a heartbeat.
		
		If the Bricklet is in bootloader mode, the LED is will show heartbeat by default.
		*/
		this.ipcon.sendRequest(this, BrickletThermalImaging.FUNCTION_SET_STATUS_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getStatusLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Status LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletThermalImaging.FUNCTION_GET_STATUS_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getChipTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature as measured inside the microcontroller. The
		value returned is not the ambient temperature!
		
		The temperature is only proportional to the real temperature and it has bad
		accuracy. Practically it is only useful as an indicator for
		temperature changes.
		*/
		this.ipcon.sendRequest(this, BrickletThermalImaging.FUNCTION_GET_CHIP_TEMPERATURE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.reset = function(returnCallback, errorCallback) {
		/*
		Calling this function will reset the Bricklet. All configurations
		will be lost.
		
		After a reset you have to create new device objects,
		calling functions on the existing ones will result in
		undefined behavior!
		*/
		this.ipcon.sendRequest(this, BrickletThermalImaging.FUNCTION_RESET, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeUID = function(uid, returnCallback, errorCallback) {
		/*
		Writes a new UID into flash. If you want to set a new UID
		you have to decode the Base58 encoded UID string into an
		integer first.
		
		We recommend that you use Brick Viewer to change the UID.
		*/
		this.ipcon.sendRequest(this, BrickletThermalImaging.FUNCTION_WRITE_UID, [uid], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.readUID = function(returnCallback, errorCallback) {
		/*
		Returns the current UID as an integer. Encode as
		Base58 to get the usual string version.
		*/
		this.ipcon.sendRequest(this, BrickletThermalImaging.FUNCTION_READ_UID, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletThermalImaging.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.getHighContrastImage = function(returnCallback, errorCallback) {
		/*
		Returns the current high contrast image. See `here <https://www.tinkerforge.com/en/doc/Hardware/Bricklets/Thermal_Imaging.html#high-contrast-image-vs-temperature-image>`__
		for the difference between
		High Contrast and Temperature Image. If you don't know what to use
		the High Contrast Image is probably right for you.
		
		The data is organized as a 8-bit value 80x60 pixel matrix linearized in
		a one-dimensional array. The data is arranged line by line from top left to
		bottom right.
		
		Each 8-bit value represents one gray-scale image pixel that can directly be
		shown to a user on a display.
		
		Before you can use this function you have to enable it with
		:func:`Set Image Transfer Config`.
		*/
		var responseHandler = null;
		var functionToQueue = null;
		var streamStateObject = this.streamStateObjects[1];
		if (streamStateObject['responseProperties']['responseHandler'] === null) {
			responseHandler = 
				function (device, fid, packetResponse) {
					var result = [];
					var llvalues = null;
					var packetErrorFlag = 0;
					var rolesMappedData = [];
					var imageLength = null;
					var imageChunkData = null;
					var imageOutOfSync = false;
					var streamStateObject = device.streamStateObjects[fid];
					var imageChunkOffset = null;
					var payload = device.ipcon.getPayloadFromPacket(packetResponse);

					packetErrorFlag = device.ipcon.getEFromPacket(packetResponse);

					if (packetErrorFlag !== 0) {
						if (streamStateObject['responseProperties']['errorCB'] !== undefined) {
							if (packetErrorFlag === 1) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_INVALID_PARAMETER);
							}
							else if (packetErrorFlag === 2) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_FUNCTION_NOT_SUPPORTED);
							}
							else {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_UNKNOWN_ERROR);
							}
						}

						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}

						return;
					}

					if (payload.length === 0) {
						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}

						return;
					}

					llvalues = device.ipcon.unpack(payload,
					                               streamStateObject['responseProperties']['unpackFormatString']);

					for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
						if (streamStateObject['dataMapping'][i] === 'streamChunkData') {
							imageChunkData = llvalues[i];
						}
						else if (streamStateObject['dataMapping'][i] === 'streamChunkOffset') {
							imageChunkOffset = llvalues[i];
						}
					}

					imageLength = streamStateObject['streamProperties']['fixedLength'];

					function handleOOS() {
						if ((imageChunkOffset + 62) < imageLength) {
							streamStateObject['responseProperties']['runningSubcallOOS'] = true;
							device.ipcon.sendRequest(device, BrickletThermalImaging.FUNCTION_GET_HIGH_CONTRAST_IMAGE_LOW_LEVEL, [], '', 72, 'H B62', streamStateObject['responseProperties']['returnCB'], streamStateObject['responseProperties']['errorCB'], true, true);

							return;
						}

						if (streamStateObject['responseProperties']['errorCB']) {
							streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_STREAM_OUT_OF_SYNC);
						}

						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}
					}

					if (streamStateObject['responseProperties']['waitingFirstChunk']) {
						streamStateObject['responseProperties']['waitingFirstChunk'] = false;

						if (imageChunkOffset === ((1 << 16) - 1)) { // maximum chunk offset -> stream has no data
							imageLength = 0;
							imageOutOfSync = false;
							streamStateObject['responseProperties']['data'].length = 0;
						}
						else {
								imageOutOfSync = (imageChunkOffset !== 0);
								streamStateObject['responseProperties']['data'] = imageChunkData;
						}
					}

					if (!streamStateObject['responseProperties']['runningSubcallOOS']) {
						if (!streamStateObject['responseProperties']['runningSubcall']) {
							if (!imageOutOfSync &&
								(streamStateObject['responseProperties']['data'].length < imageLength)) {
									streamStateObject['responseProperties']['runningSubcall'] = true;
									device.ipcon.sendRequest(device, BrickletThermalImaging.FUNCTION_GET_HIGH_CONTRAST_IMAGE_LOW_LEVEL, [], '', 72, 'H B62', streamStateObject['responseProperties']['returnCB'], streamStateObject['responseProperties']['errorCB'], true, true);

									return;
							}
						}
						else {
							imageOutOfSync =
								(imageChunkOffset !== streamStateObject['responseProperties']['data'].length);

							if (!imageOutOfSync &&
								(streamStateObject['responseProperties']['data'].length < imageLength)) {
									streamStateObject['responseProperties']['data'] =
										streamStateObject['responseProperties']['data'].concat(imageChunkData);
									if (streamStateObject['responseProperties']['data'].length >= imageLength) {
										streamStateObject['responseProperties']['data'] =
											streamStateObject['responseProperties']['data'].splice(0, imageLength);
									}
									else {
										device.ipcon.sendRequest(device, BrickletThermalImaging.FUNCTION_GET_HIGH_CONTRAST_IMAGE_LOW_LEVEL, [], '', 72, 'H B62', streamStateObject['responseProperties']['returnCB'], streamStateObject['responseProperties']['errorCB'], true, true);

										return;
									}
							}
						}
					}
					else {
						handleOOS();

						return;
					}

					if (imageOutOfSync) { // Discard remaining stream to bring it back in-sync
						handleOOS();

						return;
					}

					if (streamStateObject['responseProperties']['returnCB']) {
						for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
							rolesMappedData.push({'role': streamStateObject['dataMapping'][i], 'llvalue': llvalues[i]});
						}

						for (var i = 0; i < rolesMappedData.length; i++) {
							if (rolesMappedData[i]['role'] === 'streamChunkData') {
								result.push(streamStateObject['responseProperties']['data'].splice(0, imageLength));
							}
							else if (rolesMappedData[i]['role'] === null) {
								result.push(rolesMappedData[i]['llvalue']);
							}
						}

						streamStateObject['responseProperties']['returnCB'].apply(device, result);
					}

					device.resetStreamStateObject(streamStateObject);

					if (streamStateObject['responseProperties']['callQueue'].length > 0) {
						streamStateObject['responseProperties']['callQueue'].shift()(device);
					}
				};

			streamStateObject['responseProperties']['responseHandler'] = responseHandler;
		}
		if (!streamStateObject['responseProperties']['running']) {
			streamStateObject['responseProperties']['running'] = true;
			streamStateObject['responseProperties']['returnCB'] = returnCallback;
			streamStateObject['responseProperties']['errorCB'] = errorCallback;
			this.ipcon.sendRequest(this,
			                       BrickletThermalImaging.FUNCTION_GET_HIGH_CONTRAST_IMAGE_LOW_LEVEL,
			                       [],
			                       '',
			                       72,
			                       'H B62',
			                       returnCallback,
			                       errorCallback,
			                       true,
			                       true);
		}
		else {
			functionToQueue = function (device) {
				device.getHighContrastImage.call(device, returnCallback, errorCallback);
			}
			streamStateObject['responseProperties']['callQueue'].push(functionToQueue);
		}
	};

	this.getTemperatureImage = function(returnCallback, errorCallback) {
		/*
		Returns the current temperature image. See `here <https://www.tinkerforge.com/en/doc/Hardware/Bricklets/Thermal_Imaging.html#high-contrast-image-vs-temperature-image>`__
		for the difference between High Contrast and Temperature Image.
		If you don't know what to use the High Contrast Image is probably right for you.
		
		The data is organized as a 16-bit value 80x60 pixel matrix linearized in
		a one-dimensional array. The data is arranged line by line from top left to
		bottom right.
		
		Each 16-bit value represents one temperature measurement in either
		Kelvin/10 or Kelvin/100 (depending on the resolution set with :func:`Set Resolution`).
		
		Before you can use this function you have to enable it with
		:func:`Set Image Transfer Config`.
		*/
		var responseHandler = null;
		var functionToQueue = null;
		var streamStateObject = this.streamStateObjects[2];
		if (streamStateObject['responseProperties']['responseHandler'] === null) {
			responseHandler = 
				function (device, fid, packetResponse) {
					var result = [];
					var llvalues = null;
					var packetErrorFlag = 0;
					var rolesMappedData = [];
					var imageLength = null;
					var imageChunkData = null;
					var imageOutOfSync = false;
					var streamStateObject = device.streamStateObjects[fid];
					var imageChunkOffset = null;
					var payload = device.ipcon.getPayloadFromPacket(packetResponse);

					packetErrorFlag = device.ipcon.getEFromPacket(packetResponse);

					if (packetErrorFlag !== 0) {
						if (streamStateObject['responseProperties']['errorCB'] !== undefined) {
							if (packetErrorFlag === 1) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_INVALID_PARAMETER);
							}
							else if (packetErrorFlag === 2) {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_FUNCTION_NOT_SUPPORTED);
							}
							else {
								streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_UNKNOWN_ERROR);
							}
						}

						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}

						return;
					}

					if (payload.length === 0) {
						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}

						return;
					}

					llvalues = device.ipcon.unpack(payload,
					                               streamStateObject['responseProperties']['unpackFormatString']);

					for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
						if (streamStateObject['dataMapping'][i] === 'streamChunkData') {
							imageChunkData = llvalues[i];
						}
						else if (streamStateObject['dataMapping'][i] === 'streamChunkOffset') {
							imageChunkOffset = llvalues[i];
						}
					}

					imageLength = streamStateObject['streamProperties']['fixedLength'];

					function handleOOS() {
						if ((imageChunkOffset + 31) < imageLength) {
							streamStateObject['responseProperties']['runningSubcallOOS'] = true;
							device.ipcon.sendRequest(device, BrickletThermalImaging.FUNCTION_GET_TEMPERATURE_IMAGE_LOW_LEVEL, [], '', 72, 'H H31', streamStateObject['responseProperties']['returnCB'], streamStateObject['responseProperties']['errorCB'], true, true);

							return;
						}

						if (streamStateObject['responseProperties']['errorCB']) {
							streamStateObject['responseProperties']['errorCB'].call(device, IPConnection.ERROR_STREAM_OUT_OF_SYNC);
						}

						device.resetStreamStateObject(streamStateObject);

						if (streamStateObject['responseProperties']['callQueue'].length > 0) {
							streamStateObject['responseProperties']['callQueue'].shift()(device);
						}
					}

					if (streamStateObject['responseProperties']['waitingFirstChunk']) {
						streamStateObject['responseProperties']['waitingFirstChunk'] = false;

						if (imageChunkOffset === ((1 << 16) - 1)) { // maximum chunk offset -> stream has no data
							imageLength = 0;
							imageOutOfSync = false;
							streamStateObject['responseProperties']['data'].length = 0;
						}
						else {
								imageOutOfSync = (imageChunkOffset !== 0);
								streamStateObject['responseProperties']['data'] = imageChunkData;
						}
					}

					if (!streamStateObject['responseProperties']['runningSubcallOOS']) {
						if (!streamStateObject['responseProperties']['runningSubcall']) {
							if (!imageOutOfSync &&
								(streamStateObject['responseProperties']['data'].length < imageLength)) {
									streamStateObject['responseProperties']['runningSubcall'] = true;
									device.ipcon.sendRequest(device, BrickletThermalImaging.FUNCTION_GET_TEMPERATURE_IMAGE_LOW_LEVEL, [], '', 72, 'H H31', streamStateObject['responseProperties']['returnCB'], streamStateObject['responseProperties']['errorCB'], true, true);

									return;
							}
						}
						else {
							imageOutOfSync =
								(imageChunkOffset !== streamStateObject['responseProperties']['data'].length);

							if (!imageOutOfSync &&
								(streamStateObject['responseProperties']['data'].length < imageLength)) {
									streamStateObject['responseProperties']['data'] =
										streamStateObject['responseProperties']['data'].concat(imageChunkData);
									if (streamStateObject['responseProperties']['data'].length >= imageLength) {
										streamStateObject['responseProperties']['data'] =
											streamStateObject['responseProperties']['data'].splice(0, imageLength);
									}
									else {
										device.ipcon.sendRequest(device, BrickletThermalImaging.FUNCTION_GET_TEMPERATURE_IMAGE_LOW_LEVEL, [], '', 72, 'H H31', streamStateObject['responseProperties']['returnCB'], streamStateObject['responseProperties']['errorCB'], true, true);

										return;
									}
							}
						}
					}
					else {
						handleOOS();

						return;
					}

					if (imageOutOfSync) { // Discard remaining stream to bring it back in-sync
						handleOOS();

						return;
					}

					if (streamStateObject['responseProperties']['returnCB']) {
						for (var i = 0; i < streamStateObject['dataMapping'].length; i++) {
							rolesMappedData.push({'role': streamStateObject['dataMapping'][i], 'llvalue': llvalues[i]});
						}

						for (var i = 0; i < rolesMappedData.length; i++) {
							if (rolesMappedData[i]['role'] === 'streamChunkData') {
								result.push(streamStateObject['responseProperties']['data'].splice(0, imageLength));
							}
							else if (rolesMappedData[i]['role'] === null) {
								result.push(rolesMappedData[i]['llvalue']);
							}
						}

						streamStateObject['responseProperties']['returnCB'].apply(device, result);
					}

					device.resetStreamStateObject(streamStateObject);

					if (streamStateObject['responseProperties']['callQueue'].length > 0) {
						streamStateObject['responseProperties']['callQueue'].shift()(device);
					}
				};

			streamStateObject['responseProperties']['responseHandler'] = responseHandler;
		}
		if (!streamStateObject['responseProperties']['running']) {
			streamStateObject['responseProperties']['running'] = true;
			streamStateObject['responseProperties']['returnCB'] = returnCallback;
			streamStateObject['responseProperties']['errorCB'] = errorCallback;
			this.ipcon.sendRequest(this,
			                       BrickletThermalImaging.FUNCTION_GET_TEMPERATURE_IMAGE_LOW_LEVEL,
			                       [],
			                       '',
			                       72,
			                       'H H31',
			                       returnCallback,
			                       errorCallback,
			                       true,
			                       true);
		}
		else {
			functionToQueue = function (device) {
				device.getTemperatureImage.call(device, returnCallback, errorCallback);
			}
			streamStateObject['responseProperties']['callQueue'].push(functionToQueue);
		}
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletThermalImaging;

},{"./Device":279,"./IPConnection":280}],269:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletThermocouple.DEVICE_IDENTIFIER = 266;
BrickletThermocouple.DEVICE_DISPLAY_NAME = 'Thermocouple Bricklet';
BrickletThermocouple.CALLBACK_TEMPERATURE = 8;
BrickletThermocouple.CALLBACK_TEMPERATURE_REACHED = 9;
BrickletThermocouple.CALLBACK_ERROR_STATE = 13;
BrickletThermocouple.FUNCTION_GET_TEMPERATURE = 1;
BrickletThermocouple.FUNCTION_SET_TEMPERATURE_CALLBACK_PERIOD = 2;
BrickletThermocouple.FUNCTION_GET_TEMPERATURE_CALLBACK_PERIOD = 3;
BrickletThermocouple.FUNCTION_SET_TEMPERATURE_CALLBACK_THRESHOLD = 4;
BrickletThermocouple.FUNCTION_GET_TEMPERATURE_CALLBACK_THRESHOLD = 5;
BrickletThermocouple.FUNCTION_SET_DEBOUNCE_PERIOD = 6;
BrickletThermocouple.FUNCTION_GET_DEBOUNCE_PERIOD = 7;
BrickletThermocouple.FUNCTION_SET_CONFIGURATION = 10;
BrickletThermocouple.FUNCTION_GET_CONFIGURATION = 11;
BrickletThermocouple.FUNCTION_GET_ERROR_STATE = 12;
BrickletThermocouple.FUNCTION_GET_IDENTITY = 255;
BrickletThermocouple.THRESHOLD_OPTION_OFF = 'x';
BrickletThermocouple.THRESHOLD_OPTION_OUTSIDE = 'o';
BrickletThermocouple.THRESHOLD_OPTION_INSIDE = 'i';
BrickletThermocouple.THRESHOLD_OPTION_SMALLER = '<';
BrickletThermocouple.THRESHOLD_OPTION_GREATER = '>';
BrickletThermocouple.AVERAGING_1 = 1;
BrickletThermocouple.AVERAGING_2 = 2;
BrickletThermocouple.AVERAGING_4 = 4;
BrickletThermocouple.AVERAGING_8 = 8;
BrickletThermocouple.AVERAGING_16 = 16;
BrickletThermocouple.TYPE_B = 0;
BrickletThermocouple.TYPE_E = 1;
BrickletThermocouple.TYPE_J = 2;
BrickletThermocouple.TYPE_K = 3;
BrickletThermocouple.TYPE_N = 4;
BrickletThermocouple.TYPE_R = 5;
BrickletThermocouple.TYPE_S = 6;
BrickletThermocouple.TYPE_T = 7;
BrickletThermocouple.TYPE_G8 = 8;
BrickletThermocouple.TYPE_G32 = 9;
BrickletThermocouple.FILTER_OPTION_50HZ = 0;
BrickletThermocouple.FILTER_OPTION_60HZ = 1;

function BrickletThermocouple(uid, ipcon) {
	//Measures temperature with thermocouples

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletThermocouple.DEVICE_IDENTIFIER, BrickletThermocouple.DEVICE_DISPLAY_NAME);
	BrickletThermocouple.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickletThermocouple.FUNCTION_GET_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletThermocouple.FUNCTION_SET_TEMPERATURE_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletThermocouple.FUNCTION_GET_TEMPERATURE_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletThermocouple.FUNCTION_SET_TEMPERATURE_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletThermocouple.FUNCTION_GET_TEMPERATURE_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletThermocouple.FUNCTION_SET_DEBOUNCE_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletThermocouple.FUNCTION_GET_DEBOUNCE_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletThermocouple.FUNCTION_SET_CONFIGURATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletThermocouple.FUNCTION_GET_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletThermocouple.FUNCTION_GET_ERROR_STATE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletThermocouple.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletThermocouple.CALLBACK_TEMPERATURE] = [12, 'i'];
	this.callbackFormats[BrickletThermocouple.CALLBACK_TEMPERATURE_REACHED] = [12, 'i'];
	this.callbackFormats[BrickletThermocouple.CALLBACK_ERROR_STATE] = [10, '? ?'];



	this.getTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature of the thermocouple.
		
		If you want to get the temperature periodically, it is recommended
		to use the :cb:`Temperature` callback and set the period with
		:func:`Set Temperature Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletThermocouple.FUNCTION_GET_TEMPERATURE, [], '', 12, 'i', returnCallback, errorCallback, false, true);
	};
	this.setTemperatureCallbackPeriod = function(period, returnCallback, errorCallback) {
		/*
		Sets the period with which the :cb:`Temperature` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		The :cb:`Temperature` callback is only triggered if the temperature has changed
		since the last triggering.
		*/
		this.ipcon.sendRequest(this, BrickletThermocouple.FUNCTION_SET_TEMPERATURE_CALLBACK_PERIOD, [period], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getTemperatureCallbackPeriod = function(returnCallback, errorCallback) {
		/*
		Returns the period as set by :func:`Set Temperature Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletThermocouple.FUNCTION_GET_TEMPERATURE_CALLBACK_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setTemperatureCallbackThreshold = function(option, min, max, returnCallback, errorCallback) {
		/*
		Sets the thresholds for the :cb:`Temperature Reached` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Callback is turned off"
		 "'o'",    "Callback is triggered when the temperature is *outside* the min and max values"
		 "'i'",    "Callback is triggered when the temperature is *inside* the min and max values"
		 "'<'",    "Callback is triggered when the temperature is smaller than the min value (max is ignored)"
		 "'>'",    "Callback is triggered when the temperature is greater than the min value (max is ignored)"
		*/
		this.ipcon.sendRequest(this, BrickletThermocouple.FUNCTION_SET_TEMPERATURE_CALLBACK_THRESHOLD, [option, min, max], 'c i i', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getTemperatureCallbackThreshold = function(returnCallback, errorCallback) {
		/*
		Returns the threshold as set by :func:`Set Temperature Callback Threshold`.
		*/
		this.ipcon.sendRequest(this, BrickletThermocouple.FUNCTION_GET_TEMPERATURE_CALLBACK_THRESHOLD, [], '', 17, 'c i i', returnCallback, errorCallback, false, true);
	};
	this.setDebouncePeriod = function(debounce, returnCallback, errorCallback) {
		/*
		Sets the period with which the threshold callback
		
		* :cb:`Temperature Reached`
		
		is triggered, if the threshold
		
		* :func:`Set Temperature Callback Threshold`
		
		keeps being reached.
		*/
		this.ipcon.sendRequest(this, BrickletThermocouple.FUNCTION_SET_DEBOUNCE_PERIOD, [debounce], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getDebouncePeriod = function(returnCallback, errorCallback) {
		/*
		Returns the debounce period as set by :func:`Set Debounce Period`.
		*/
		this.ipcon.sendRequest(this, BrickletThermocouple.FUNCTION_GET_DEBOUNCE_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setConfiguration = function(averaging, thermocoupleType, filter, returnCallback, errorCallback) {
		/*
		You can configure averaging size, thermocouple type and frequency
		filtering.
		
		Available averaging sizes are 1, 2, 4, 8 and 16 samples.
		
		As thermocouple type you can use B, E, J, K, N, R, S and T. If you have a
		different thermocouple or a custom thermocouple you can also use
		G8 and G32. With these types the returned value will not be in °C/100,
		it will be calculated by the following formulas:
		
		* G8: ``value = 8 * 1.6 * 2^17 * Vin``
		* G32: ``value = 32 * 1.6 * 2^17 * Vin``
		
		where Vin is the thermocouple input voltage.
		
		The frequency filter can be either configured to 50Hz or to 60Hz. You should
		configure it according to your utility frequency.
		
		The conversion time depends on the averaging and filter configuration, it can
		be calculated as follows:
		
		* 60Hz: ``time = 82 + (samples - 1) * 16.67``
		* 50Hz: ``time = 98 + (samples - 1) * 20``
		*/
		this.ipcon.sendRequest(this, BrickletThermocouple.FUNCTION_SET_CONFIGURATION, [averaging, thermocoupleType, filter], 'B B B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletThermocouple.FUNCTION_GET_CONFIGURATION, [], '', 11, 'B B B', returnCallback, errorCallback, false, true);
	};
	this.getErrorState = function(returnCallback, errorCallback) {
		/*
		Returns the current error state. There are two possible errors:
		
		* Over/Under Voltage and
		* Open Circuit.
		
		Over/Under Voltage happens for voltages below 0V or above 3.3V. In this case
		it is very likely that your thermocouple is defective. An Open Circuit error
		indicates that there is no thermocouple connected.
		
		You can use the :cb:`Error State` callback to automatically get triggered
		when the error state changes.
		*/
		this.ipcon.sendRequest(this, BrickletThermocouple.FUNCTION_GET_ERROR_STATE, [], '', 10, '? ?', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletThermocouple.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletThermocouple;

},{"./Device":279,"./IPConnection":280}],270:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletThermocoupleV2.DEVICE_IDENTIFIER = 2109;
BrickletThermocoupleV2.DEVICE_DISPLAY_NAME = 'Thermocouple Bricklet 2.0';
BrickletThermocoupleV2.CALLBACK_TEMPERATURE = 4;
BrickletThermocoupleV2.CALLBACK_ERROR_STATE = 8;
BrickletThermocoupleV2.FUNCTION_GET_TEMPERATURE = 1;
BrickletThermocoupleV2.FUNCTION_SET_TEMPERATURE_CALLBACK_CONFIGURATION = 2;
BrickletThermocoupleV2.FUNCTION_GET_TEMPERATURE_CALLBACK_CONFIGURATION = 3;
BrickletThermocoupleV2.FUNCTION_SET_CONFIGURATION = 5;
BrickletThermocoupleV2.FUNCTION_GET_CONFIGURATION = 6;
BrickletThermocoupleV2.FUNCTION_GET_ERROR_STATE = 7;
BrickletThermocoupleV2.FUNCTION_GET_SPITFP_ERROR_COUNT = 234;
BrickletThermocoupleV2.FUNCTION_SET_BOOTLOADER_MODE = 235;
BrickletThermocoupleV2.FUNCTION_GET_BOOTLOADER_MODE = 236;
BrickletThermocoupleV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER = 237;
BrickletThermocoupleV2.FUNCTION_WRITE_FIRMWARE = 238;
BrickletThermocoupleV2.FUNCTION_SET_STATUS_LED_CONFIG = 239;
BrickletThermocoupleV2.FUNCTION_GET_STATUS_LED_CONFIG = 240;
BrickletThermocoupleV2.FUNCTION_GET_CHIP_TEMPERATURE = 242;
BrickletThermocoupleV2.FUNCTION_RESET = 243;
BrickletThermocoupleV2.FUNCTION_WRITE_UID = 248;
BrickletThermocoupleV2.FUNCTION_READ_UID = 249;
BrickletThermocoupleV2.FUNCTION_GET_IDENTITY = 255;
BrickletThermocoupleV2.THRESHOLD_OPTION_OFF = 'x';
BrickletThermocoupleV2.THRESHOLD_OPTION_OUTSIDE = 'o';
BrickletThermocoupleV2.THRESHOLD_OPTION_INSIDE = 'i';
BrickletThermocoupleV2.THRESHOLD_OPTION_SMALLER = '<';
BrickletThermocoupleV2.THRESHOLD_OPTION_GREATER = '>';
BrickletThermocoupleV2.AVERAGING_1 = 1;
BrickletThermocoupleV2.AVERAGING_2 = 2;
BrickletThermocoupleV2.AVERAGING_4 = 4;
BrickletThermocoupleV2.AVERAGING_8 = 8;
BrickletThermocoupleV2.AVERAGING_16 = 16;
BrickletThermocoupleV2.TYPE_B = 0;
BrickletThermocoupleV2.TYPE_E = 1;
BrickletThermocoupleV2.TYPE_J = 2;
BrickletThermocoupleV2.TYPE_K = 3;
BrickletThermocoupleV2.TYPE_N = 4;
BrickletThermocoupleV2.TYPE_R = 5;
BrickletThermocoupleV2.TYPE_S = 6;
BrickletThermocoupleV2.TYPE_T = 7;
BrickletThermocoupleV2.TYPE_G8 = 8;
BrickletThermocoupleV2.TYPE_G32 = 9;
BrickletThermocoupleV2.FILTER_OPTION_50HZ = 0;
BrickletThermocoupleV2.FILTER_OPTION_60HZ = 1;
BrickletThermocoupleV2.BOOTLOADER_MODE_BOOTLOADER = 0;
BrickletThermocoupleV2.BOOTLOADER_MODE_FIRMWARE = 1;
BrickletThermocoupleV2.BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT = 2;
BrickletThermocoupleV2.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT = 3;
BrickletThermocoupleV2.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT = 4;
BrickletThermocoupleV2.BOOTLOADER_STATUS_OK = 0;
BrickletThermocoupleV2.BOOTLOADER_STATUS_INVALID_MODE = 1;
BrickletThermocoupleV2.BOOTLOADER_STATUS_NO_CHANGE = 2;
BrickletThermocoupleV2.BOOTLOADER_STATUS_ENTRY_FUNCTION_NOT_PRESENT = 3;
BrickletThermocoupleV2.BOOTLOADER_STATUS_DEVICE_IDENTIFIER_INCORRECT = 4;
BrickletThermocoupleV2.BOOTLOADER_STATUS_CRC_MISMATCH = 5;
BrickletThermocoupleV2.STATUS_LED_CONFIG_OFF = 0;
BrickletThermocoupleV2.STATUS_LED_CONFIG_ON = 1;
BrickletThermocoupleV2.STATUS_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletThermocoupleV2.STATUS_LED_CONFIG_SHOW_STATUS = 3;

function BrickletThermocoupleV2(uid, ipcon) {
	//Measures temperature with thermocouples

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletThermocoupleV2.DEVICE_IDENTIFIER, BrickletThermocoupleV2.DEVICE_DISPLAY_NAME);
	BrickletThermocoupleV2.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickletThermocoupleV2.FUNCTION_GET_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletThermocoupleV2.FUNCTION_SET_TEMPERATURE_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletThermocoupleV2.FUNCTION_GET_TEMPERATURE_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletThermocoupleV2.FUNCTION_SET_CONFIGURATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletThermocoupleV2.FUNCTION_GET_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletThermocoupleV2.FUNCTION_GET_ERROR_STATE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletThermocoupleV2.FUNCTION_GET_SPITFP_ERROR_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletThermocoupleV2.FUNCTION_SET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletThermocoupleV2.FUNCTION_GET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletThermocoupleV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletThermocoupleV2.FUNCTION_WRITE_FIRMWARE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletThermocoupleV2.FUNCTION_SET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletThermocoupleV2.FUNCTION_GET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletThermocoupleV2.FUNCTION_GET_CHIP_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletThermocoupleV2.FUNCTION_RESET] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletThermocoupleV2.FUNCTION_WRITE_UID] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletThermocoupleV2.FUNCTION_READ_UID] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletThermocoupleV2.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletThermocoupleV2.CALLBACK_TEMPERATURE] = [12, 'i'];
	this.callbackFormats[BrickletThermocoupleV2.CALLBACK_ERROR_STATE] = [10, '? ?'];



	this.getTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature of the thermocouple. The value is given in °C/100,
		e.g. a value of 4223 means that a temperature of 42.23 °C is measured.
		
		If you want to get the temperature periodically, it is recommended
		to use the :cb:`Temperature` callback and set the period with
		:func:`Set Temperature Callback Configuration`.
		
		
		If you want to get the value periodically, it is recommended to use the
		:cb:`Temperature` callback. You can set the callback configuration
		with :func:`Set Temperature Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletThermocoupleV2.FUNCTION_GET_TEMPERATURE, [], '', 12, 'i', returnCallback, errorCallback, false, true);
	};
	this.setTemperatureCallbackConfiguration = function(period, valueHasToChange, option, min, max, returnCallback, errorCallback) {
		/*
		The period is the period with which the :cb:`Temperature` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		If the `value has to change`-parameter is set to true, the callback is only
		triggered after the value has changed. If the value didn't change
		within the period, the callback is triggered immediately on change.
		
		If it is set to false, the callback is continuously triggered with the period,
		independent of the value.
		
		It is furthermore possible to constrain the callback with thresholds.
		
		The `option`-parameter together with min/max sets a threshold for the :cb:`Temperature` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Threshold is turned off"
		 "'o'",    "Threshold is triggered when the value is *outside* the min and max values"
		 "'i'",    "Threshold is triggered when the value is *inside* or equal to the min and max values"
		 "'<'",    "Threshold is triggered when the value is smaller than the min value (max is ignored)"
		 "'>'",    "Threshold is triggered when the value is greater than the min value (max is ignored)"
		
		If the option is set to 'x' (threshold turned off) the callback is triggered with the fixed period.
		*/
		this.ipcon.sendRequest(this, BrickletThermocoupleV2.FUNCTION_SET_TEMPERATURE_CALLBACK_CONFIGURATION, [period, valueHasToChange, option, min, max], 'I ? c i i', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getTemperatureCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the callback configuration as set by :func:`Set Temperature Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletThermocoupleV2.FUNCTION_GET_TEMPERATURE_CALLBACK_CONFIGURATION, [], '', 22, 'I ? c i i', returnCallback, errorCallback, false, true);
	};
	this.setConfiguration = function(averaging, thermocoupleType, filter, returnCallback, errorCallback) {
		/*
		You can configure averaging size, thermocouple type and frequency
		filtering.
		
		Available averaging sizes are 1, 2, 4, 8 and 16 samples.
		
		As thermocouple type you can use B, E, J, K, N, R, S and T. If you have a
		different thermocouple or a custom thermocouple you can also use
		G8 and G32. With these types the returned value will not be in °C/100,
		it will be calculated by the following formulas:
		
		* G8: ``value = 8 * 1.6 * 2^17 * Vin``
		* G32: ``value = 32 * 1.6 * 2^17 * Vin``
		
		where Vin is the thermocouple input voltage.
		
		The frequency filter can be either configured to 50Hz or to 60Hz. You should
		configure it according to your utility frequency.
		
		The conversion time depends on the averaging and filter configuration, it can
		be calculated as follows:
		
		* 60Hz: ``time = 82 + (samples - 1) * 16.67``
		* 50Hz: ``time = 98 + (samples - 1) * 20``
		*/
		this.ipcon.sendRequest(this, BrickletThermocoupleV2.FUNCTION_SET_CONFIGURATION, [averaging, thermocoupleType, filter], 'B B B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletThermocoupleV2.FUNCTION_GET_CONFIGURATION, [], '', 11, 'B B B', returnCallback, errorCallback, false, true);
	};
	this.getErrorState = function(returnCallback, errorCallback) {
		/*
		Returns the current error state. There are two possible errors:
		
		* Over/Under Voltage and
		* Open Circuit.
		
		Over/Under Voltage happens for voltages below 0V or above 3.3V. In this case
		it is very likely that your thermocouple is defective. An Open Circuit error
		indicates that there is no thermocouple connected.
		
		You can use the :cb:`Error State` callback to automatically get triggered
		when the error state changes.
		*/
		this.ipcon.sendRequest(this, BrickletThermocoupleV2.FUNCTION_GET_ERROR_STATE, [], '', 10, '? ?', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPErrorCount = function(returnCallback, errorCallback) {
		/*
		Returns the error count for the communication between Brick and Bricklet.
		
		The errors are divided into
		
		* ACK checksum errors,
		* message checksum errors,
		* framing errors and
		* overflow errors.
		
		The errors counts are for errors that occur on the Bricklet side. All
		Bricks have a similar function that returns the errors on the Brick side.
		*/
		this.ipcon.sendRequest(this, BrickletThermocoupleV2.FUNCTION_GET_SPITFP_ERROR_COUNT, [], '', 24, 'I I I I', returnCallback, errorCallback, false, true);
	};
	this.setBootloaderMode = function(mode, returnCallback, errorCallback) {
		/*
		Sets the bootloader mode and returns the status after the requested
		mode change was instigated.
		
		You can change from bootloader mode to firmware mode and vice versa. A change
		from bootloader mode to firmware mode will only take place if the entry function,
		device identifier and CRC are present and correct.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletThermocoupleV2.FUNCTION_SET_BOOTLOADER_MODE, [mode], 'B', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getBootloaderMode = function(returnCallback, errorCallback) {
		/*
		Returns the current bootloader mode, see :func:`Set Bootloader Mode`.
		*/
		this.ipcon.sendRequest(this, BrickletThermocoupleV2.FUNCTION_GET_BOOTLOADER_MODE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setWriteFirmwarePointer = function(pointer, returnCallback, errorCallback) {
		/*
		Sets the firmware pointer for :func:`Write Firmware`. The pointer has
		to be increased by chunks of size 64. The data is written to flash
		every 4 chunks (which equals to one page of size 256).
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletThermocoupleV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER, [pointer], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeFirmware = function(data, returnCallback, errorCallback) {
		/*
		Writes 64 Bytes of firmware at the position as written by
		:func:`Set Write Firmware Pointer` before. The firmware is written
		to flash every 4 chunks.
		
		You can only write firmware in bootloader mode.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletThermocoupleV2.FUNCTION_WRITE_FIRMWARE, [data], 'B64', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setStatusLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Sets the status LED configuration. By default the LED shows
		communication traffic between Brick and Bricklet, it flickers once
		for every 10 received data packets.
		
		You can also turn the LED permanently on/off or show a heartbeat.
		
		If the Bricklet is in bootloader mode, the LED is will show heartbeat by default.
		*/
		this.ipcon.sendRequest(this, BrickletThermocoupleV2.FUNCTION_SET_STATUS_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getStatusLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Status LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletThermocoupleV2.FUNCTION_GET_STATUS_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getChipTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature as measured inside the microcontroller. The
		value returned is not the ambient temperature!
		
		The temperature is only proportional to the real temperature and it has bad
		accuracy. Practically it is only useful as an indicator for
		temperature changes.
		*/
		this.ipcon.sendRequest(this, BrickletThermocoupleV2.FUNCTION_GET_CHIP_TEMPERATURE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.reset = function(returnCallback, errorCallback) {
		/*
		Calling this function will reset the Bricklet. All configurations
		will be lost.
		
		After a reset you have to create new device objects,
		calling functions on the existing ones will result in
		undefined behavior!
		*/
		this.ipcon.sendRequest(this, BrickletThermocoupleV2.FUNCTION_RESET, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeUID = function(uid, returnCallback, errorCallback) {
		/*
		Writes a new UID into flash. If you want to set a new UID
		you have to decode the Base58 encoded UID string into an
		integer first.
		
		We recommend that you use Brick Viewer to change the UID.
		*/
		this.ipcon.sendRequest(this, BrickletThermocoupleV2.FUNCTION_WRITE_UID, [uid], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.readUID = function(returnCallback, errorCallback) {
		/*
		Returns the current UID as an integer. Encode as
		Base58 to get the usual string version.
		*/
		this.ipcon.sendRequest(this, BrickletThermocoupleV2.FUNCTION_READ_UID, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletThermocoupleV2.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletThermocoupleV2;

},{"./Device":279,"./IPConnection":280}],271:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletTilt.DEVICE_IDENTIFIER = 239;
BrickletTilt.DEVICE_DISPLAY_NAME = 'Tilt Bricklet';
BrickletTilt.CALLBACK_TILT_STATE = 5;
BrickletTilt.FUNCTION_GET_TILT_STATE = 1;
BrickletTilt.FUNCTION_ENABLE_TILT_STATE_CALLBACK = 2;
BrickletTilt.FUNCTION_DISABLE_TILT_STATE_CALLBACK = 3;
BrickletTilt.FUNCTION_IS_TILT_STATE_CALLBACK_ENABLED = 4;
BrickletTilt.FUNCTION_GET_IDENTITY = 255;
BrickletTilt.TILT_STATE_CLOSED = 0;
BrickletTilt.TILT_STATE_OPEN = 1;
BrickletTilt.TILT_STATE_CLOSED_VIBRATING = 2;

function BrickletTilt(uid, ipcon) {
	//Detects inclination of Bricklet (tilt switch open/closed)

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletTilt.DEVICE_IDENTIFIER, BrickletTilt.DEVICE_DISPLAY_NAME);
	BrickletTilt.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickletTilt.FUNCTION_GET_TILT_STATE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletTilt.FUNCTION_ENABLE_TILT_STATE_CALLBACK] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletTilt.FUNCTION_DISABLE_TILT_STATE_CALLBACK] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletTilt.FUNCTION_IS_TILT_STATE_CALLBACK_ENABLED] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletTilt.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletTilt.CALLBACK_TILT_STATE] = [9, 'B'];



	this.getTiltState = function(returnCallback, errorCallback) {
		/*
		Returns the current tilt state. The state can either be
		
		* 0 = Closed: The ball in the tilt switch closes the circuit.
		* 1 = Open: The ball in the tilt switch does not close the circuit.
		* 2 = Closed Vibrating: The tilt switch is in motion (rapid change between open and close).
		
		.. image:: /Images/Bricklets/bricklet_tilt_mechanics.jpg
		   :scale: 100 %
		   :alt: Tilt states
		   :align: center
		   :target: ../../_images/Bricklets/bricklet_tilt_mechanics.jpg
		*/
		this.ipcon.sendRequest(this, BrickletTilt.FUNCTION_GET_TILT_STATE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.enableTiltStateCallback = function(returnCallback, errorCallback) {
		/*
		Enables the :cb:`Tilt State` callback.
		*/
		this.ipcon.sendRequest(this, BrickletTilt.FUNCTION_ENABLE_TILT_STATE_CALLBACK, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.disableTiltStateCallback = function(returnCallback, errorCallback) {
		/*
		Disables the :cb:`Tilt State` callback.
		*/
		this.ipcon.sendRequest(this, BrickletTilt.FUNCTION_DISABLE_TILT_STATE_CALLBACK, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.isTiltStateCallbackEnabled = function(returnCallback, errorCallback) {
		/*
		Returns *true* if the :cb:`Tilt State` callback is enabled.
		*/
		this.ipcon.sendRequest(this, BrickletTilt.FUNCTION_IS_TILT_STATE_CALLBACK_ENABLED, [], '', 9, '?', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletTilt.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletTilt;

},{"./Device":279,"./IPConnection":280}],272:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletUVLight.DEVICE_IDENTIFIER = 265;
BrickletUVLight.DEVICE_DISPLAY_NAME = 'UV Light Bricklet';
BrickletUVLight.CALLBACK_UV_LIGHT = 8;
BrickletUVLight.CALLBACK_UV_LIGHT_REACHED = 9;
BrickletUVLight.FUNCTION_GET_UV_LIGHT = 1;
BrickletUVLight.FUNCTION_SET_UV_LIGHT_CALLBACK_PERIOD = 2;
BrickletUVLight.FUNCTION_GET_UV_LIGHT_CALLBACK_PERIOD = 3;
BrickletUVLight.FUNCTION_SET_UV_LIGHT_CALLBACK_THRESHOLD = 4;
BrickletUVLight.FUNCTION_GET_UV_LIGHT_CALLBACK_THRESHOLD = 5;
BrickletUVLight.FUNCTION_SET_DEBOUNCE_PERIOD = 6;
BrickletUVLight.FUNCTION_GET_DEBOUNCE_PERIOD = 7;
BrickletUVLight.FUNCTION_GET_IDENTITY = 255;
BrickletUVLight.THRESHOLD_OPTION_OFF = 'x';
BrickletUVLight.THRESHOLD_OPTION_OUTSIDE = 'o';
BrickletUVLight.THRESHOLD_OPTION_INSIDE = 'i';
BrickletUVLight.THRESHOLD_OPTION_SMALLER = '<';
BrickletUVLight.THRESHOLD_OPTION_GREATER = '>';

function BrickletUVLight(uid, ipcon) {
	//Measures UV light

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletUVLight.DEVICE_IDENTIFIER, BrickletUVLight.DEVICE_DISPLAY_NAME);
	BrickletUVLight.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickletUVLight.FUNCTION_GET_UV_LIGHT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletUVLight.FUNCTION_SET_UV_LIGHT_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletUVLight.FUNCTION_GET_UV_LIGHT_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletUVLight.FUNCTION_SET_UV_LIGHT_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletUVLight.FUNCTION_GET_UV_LIGHT_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletUVLight.FUNCTION_SET_DEBOUNCE_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletUVLight.FUNCTION_GET_DEBOUNCE_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletUVLight.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletUVLight.CALLBACK_UV_LIGHT] = [12, 'I'];
	this.callbackFormats[BrickletUVLight.CALLBACK_UV_LIGHT_REACHED] = [12, 'I'];



	this.getUVLight = function(returnCallback, errorCallback) {
		/*
		Returns the UV light intensity of the sensor.
		The sensor has already weighted the intensity with the erythemal
		action spectrum to get the skin-affecting irradiation.
		
		To get UV index you just have to divide the value by 250. For example, a UV
		light intensity of 500 is equivalent to an UV index of 2.
		
		If you want to get the intensity periodically, it is recommended to use the
		:cb:`UV Light` callback and set the period with
		:func:`Set UV Light Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletUVLight.FUNCTION_GET_UV_LIGHT, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setUVLightCallbackPeriod = function(period, returnCallback, errorCallback) {
		/*
		Sets the period with which the :cb:`UV Light` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		The :cb:`UV Light` callback is only triggered if the intensity has changed since
		the last triggering.
		*/
		this.ipcon.sendRequest(this, BrickletUVLight.FUNCTION_SET_UV_LIGHT_CALLBACK_PERIOD, [period], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getUVLightCallbackPeriod = function(returnCallback, errorCallback) {
		/*
		Returns the period as set by :func:`Set UV Light Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletUVLight.FUNCTION_GET_UV_LIGHT_CALLBACK_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setUVLightCallbackThreshold = function(option, min, max, returnCallback, errorCallback) {
		/*
		Sets the thresholds for the :cb:`UV Light Reached` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Callback is turned off"
		 "'o'",    "Callback is triggered when the intensity is *outside* the min and max values"
		 "'i'",    "Callback is triggered when the intensity is *inside* the min and max values"
		 "'<'",    "Callback is triggered when the intensity is smaller than the min value (max is ignored)"
		 "'>'",    "Callback is triggered when the intensity is greater than the min value (max is ignored)"
		*/
		this.ipcon.sendRequest(this, BrickletUVLight.FUNCTION_SET_UV_LIGHT_CALLBACK_THRESHOLD, [option, min, max], 'c I I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getUVLightCallbackThreshold = function(returnCallback, errorCallback) {
		/*
		Returns the threshold as set by :func:`Set UV Light Callback Threshold`.
		*/
		this.ipcon.sendRequest(this, BrickletUVLight.FUNCTION_GET_UV_LIGHT_CALLBACK_THRESHOLD, [], '', 17, 'c I I', returnCallback, errorCallback, false, true);
	};
	this.setDebouncePeriod = function(debounce, returnCallback, errorCallback) {
		/*
		Sets the period with which the threshold callbacks
		
		* :cb:`UV Light Reached`,
		
		are triggered, if the thresholds
		
		* :func:`Set UV Light Callback Threshold`,
		
		keep being reached.
		*/
		this.ipcon.sendRequest(this, BrickletUVLight.FUNCTION_SET_DEBOUNCE_PERIOD, [debounce], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getDebouncePeriod = function(returnCallback, errorCallback) {
		/*
		Returns the debounce period as set by :func:`Set Debounce Period`.
		*/
		this.ipcon.sendRequest(this, BrickletUVLight.FUNCTION_GET_DEBOUNCE_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletUVLight.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletUVLight;

},{"./Device":279,"./IPConnection":280}],273:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletUVLightV2.DEVICE_IDENTIFIER = 2118;
BrickletUVLightV2.DEVICE_DISPLAY_NAME = 'UV Light Bricklet 2.0';
BrickletUVLightV2.CALLBACK_UVA = 4;
BrickletUVLightV2.CALLBACK_UVB = 8;
BrickletUVLightV2.CALLBACK_UVI = 12;
BrickletUVLightV2.FUNCTION_GET_UVA = 1;
BrickletUVLightV2.FUNCTION_SET_UVA_CALLBACK_CONFIGURATION = 2;
BrickletUVLightV2.FUNCTION_GET_UVA_CALLBACK_CONFIGURATION = 3;
BrickletUVLightV2.FUNCTION_GET_UVB = 5;
BrickletUVLightV2.FUNCTION_SET_UVB_CALLBACK_CONFIGURATION = 6;
BrickletUVLightV2.FUNCTION_GET_UVB_CALLBACK_CONFIGURATION = 7;
BrickletUVLightV2.FUNCTION_GET_UVI = 9;
BrickletUVLightV2.FUNCTION_SET_UVI_CALLBACK_CONFIGURATION = 10;
BrickletUVLightV2.FUNCTION_GET_UVI_CALLBACK_CONFIGURATION = 11;
BrickletUVLightV2.FUNCTION_SET_CONFIGURATION = 13;
BrickletUVLightV2.FUNCTION_GET_CONFIGURATION = 14;
BrickletUVLightV2.FUNCTION_GET_SPITFP_ERROR_COUNT = 234;
BrickletUVLightV2.FUNCTION_SET_BOOTLOADER_MODE = 235;
BrickletUVLightV2.FUNCTION_GET_BOOTLOADER_MODE = 236;
BrickletUVLightV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER = 237;
BrickletUVLightV2.FUNCTION_WRITE_FIRMWARE = 238;
BrickletUVLightV2.FUNCTION_SET_STATUS_LED_CONFIG = 239;
BrickletUVLightV2.FUNCTION_GET_STATUS_LED_CONFIG = 240;
BrickletUVLightV2.FUNCTION_GET_CHIP_TEMPERATURE = 242;
BrickletUVLightV2.FUNCTION_RESET = 243;
BrickletUVLightV2.FUNCTION_WRITE_UID = 248;
BrickletUVLightV2.FUNCTION_READ_UID = 249;
BrickletUVLightV2.FUNCTION_GET_IDENTITY = 255;
BrickletUVLightV2.THRESHOLD_OPTION_OFF = 'x';
BrickletUVLightV2.THRESHOLD_OPTION_OUTSIDE = 'o';
BrickletUVLightV2.THRESHOLD_OPTION_INSIDE = 'i';
BrickletUVLightV2.THRESHOLD_OPTION_SMALLER = '<';
BrickletUVLightV2.THRESHOLD_OPTION_GREATER = '>';
BrickletUVLightV2.INTEGRATION_TIME_50MS = 0;
BrickletUVLightV2.INTEGRATION_TIME_100MS = 1;
BrickletUVLightV2.INTEGRATION_TIME_200MS = 2;
BrickletUVLightV2.INTEGRATION_TIME_400MS = 3;
BrickletUVLightV2.INTEGRATION_TIME_800MS = 4;
BrickletUVLightV2.BOOTLOADER_MODE_BOOTLOADER = 0;
BrickletUVLightV2.BOOTLOADER_MODE_FIRMWARE = 1;
BrickletUVLightV2.BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT = 2;
BrickletUVLightV2.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT = 3;
BrickletUVLightV2.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT = 4;
BrickletUVLightV2.BOOTLOADER_STATUS_OK = 0;
BrickletUVLightV2.BOOTLOADER_STATUS_INVALID_MODE = 1;
BrickletUVLightV2.BOOTLOADER_STATUS_NO_CHANGE = 2;
BrickletUVLightV2.BOOTLOADER_STATUS_ENTRY_FUNCTION_NOT_PRESENT = 3;
BrickletUVLightV2.BOOTLOADER_STATUS_DEVICE_IDENTIFIER_INCORRECT = 4;
BrickletUVLightV2.BOOTLOADER_STATUS_CRC_MISMATCH = 5;
BrickletUVLightV2.STATUS_LED_CONFIG_OFF = 0;
BrickletUVLightV2.STATUS_LED_CONFIG_ON = 1;
BrickletUVLightV2.STATUS_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletUVLightV2.STATUS_LED_CONFIG_SHOW_STATUS = 3;

function BrickletUVLightV2(uid, ipcon) {
	//Measures UV-A, UV-B and UV index

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletUVLightV2.DEVICE_IDENTIFIER, BrickletUVLightV2.DEVICE_DISPLAY_NAME);
	BrickletUVLightV2.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickletUVLightV2.FUNCTION_GET_UVA] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletUVLightV2.FUNCTION_SET_UVA_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletUVLightV2.FUNCTION_GET_UVA_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletUVLightV2.FUNCTION_GET_UVB] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletUVLightV2.FUNCTION_SET_UVB_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletUVLightV2.FUNCTION_GET_UVB_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletUVLightV2.FUNCTION_GET_UVI] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletUVLightV2.FUNCTION_SET_UVI_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletUVLightV2.FUNCTION_GET_UVI_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletUVLightV2.FUNCTION_SET_CONFIGURATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletUVLightV2.FUNCTION_GET_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletUVLightV2.FUNCTION_GET_SPITFP_ERROR_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletUVLightV2.FUNCTION_SET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletUVLightV2.FUNCTION_GET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletUVLightV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletUVLightV2.FUNCTION_WRITE_FIRMWARE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletUVLightV2.FUNCTION_SET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletUVLightV2.FUNCTION_GET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletUVLightV2.FUNCTION_GET_CHIP_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletUVLightV2.FUNCTION_RESET] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletUVLightV2.FUNCTION_WRITE_UID] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletUVLightV2.FUNCTION_READ_UID] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletUVLightV2.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletUVLightV2.CALLBACK_UVA] = [12, 'i'];
	this.callbackFormats[BrickletUVLightV2.CALLBACK_UVB] = [12, 'i'];
	this.callbackFormats[BrickletUVLightV2.CALLBACK_UVI] = [12, 'i'];



	this.getUVA = function(returnCallback, errorCallback) {
		/*
		Returns the UVA intensity of the sensor.
		The sensor has not weighted the intensity with the erythemal
		action spectrum to get the skin-affecting irradiation. Therefore, you cannot
		just divide the value by 250 to get the UVA index. To get the UV index use
		:func:`Get UVI`.
		
		If the sensor is saturated, then -1 is returned, see :func:`Set Configuration`.
		
		If you want to get the intensity periodically, it is recommended to use the
		:cb:`UVA` callback and set the period with
		:func:`Set UVA Callback Configuration`.
		
		
		If you want to get the value periodically, it is recommended to use the
		:cb:`UVA` callback. You can set the callback configuration
		with :func:`Set UVA Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletUVLightV2.FUNCTION_GET_UVA, [], '', 12, 'i', returnCallback, errorCallback, false, true);
	};
	this.setUVACallbackConfiguration = function(period, valueHasToChange, option, min, max, returnCallback, errorCallback) {
		/*
		The period is the period with which the :cb:`UVA` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		If the `value has to change`-parameter is set to true, the callback is only
		triggered after the value has changed. If the value didn't change
		within the period, the callback is triggered immediately on change.
		
		If it is set to false, the callback is continuously triggered with the period,
		independent of the value.
		
		It is furthermore possible to constrain the callback with thresholds.
		
		The `option`-parameter together with min/max sets a threshold for the :cb:`UVA` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Threshold is turned off"
		 "'o'",    "Threshold is triggered when the value is *outside* the min and max values"
		 "'i'",    "Threshold is triggered when the value is *inside* or equal to the min and max values"
		 "'<'",    "Threshold is triggered when the value is smaller than the min value (max is ignored)"
		 "'>'",    "Threshold is triggered when the value is greater than the min value (max is ignored)"
		
		If the option is set to 'x' (threshold turned off) the callback is triggered with the fixed period.
		*/
		this.ipcon.sendRequest(this, BrickletUVLightV2.FUNCTION_SET_UVA_CALLBACK_CONFIGURATION, [period, valueHasToChange, option, min, max], 'I ? c i i', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getUVACallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the callback configuration as set by :func:`Set UVA Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletUVLightV2.FUNCTION_GET_UVA_CALLBACK_CONFIGURATION, [], '', 22, 'I ? c i i', returnCallback, errorCallback, false, true);
	};
	this.getUVB = function(returnCallback, errorCallback) {
		/*
		Returns the UVB intensity of the sensor.
		The sensor has not weighted the intensity with the erythemal
		action spectrum to get the skin-affecting irradiation. Therefore, you cannot
		just divide the value by 250 to get the UVB index. To get the UV index use
		:func:`Get UVI`.
		
		If the sensor is saturated, then -1 is returned, see :func:`Set Configuration`.
		
		If you want to get the intensity periodically, it is recommended to use the
		:cb:`UVB` callback and set the period with
		:func:`Set UVB Callback Configuration`.
		
		
		If you want to get the value periodically, it is recommended to use the
		:cb:`UVB` callback. You can set the callback configuration
		with :func:`Set UVB Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletUVLightV2.FUNCTION_GET_UVB, [], '', 12, 'i', returnCallback, errorCallback, false, true);
	};
	this.setUVBCallbackConfiguration = function(period, valueHasToChange, option, min, max, returnCallback, errorCallback) {
		/*
		The period is the period with which the :cb:`UVB` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		If the `value has to change`-parameter is set to true, the callback is only
		triggered after the value has changed. If the value didn't change
		within the period, the callback is triggered immediately on change.
		
		If it is set to false, the callback is continuously triggered with the period,
		independent of the value.
		
		It is furthermore possible to constrain the callback with thresholds.
		
		The `option`-parameter together with min/max sets a threshold for the :cb:`UVB` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Threshold is turned off"
		 "'o'",    "Threshold is triggered when the value is *outside* the min and max values"
		 "'i'",    "Threshold is triggered when the value is *inside* or equal to the min and max values"
		 "'<'",    "Threshold is triggered when the value is smaller than the min value (max is ignored)"
		 "'>'",    "Threshold is triggered when the value is greater than the min value (max is ignored)"
		
		If the option is set to 'x' (threshold turned off) the callback is triggered with the fixed period.
		*/
		this.ipcon.sendRequest(this, BrickletUVLightV2.FUNCTION_SET_UVB_CALLBACK_CONFIGURATION, [period, valueHasToChange, option, min, max], 'I ? c i i', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getUVBCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the callback configuration as set by :func:`Set UVB Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletUVLightV2.FUNCTION_GET_UVB_CALLBACK_CONFIGURATION, [], '', 22, 'I ? c i i', returnCallback, errorCallback, false, true);
	};
	this.getUVI = function(returnCallback, errorCallback) {
		/*
		Returns the UV index of the sensor, the index is given in 1/10.
		
		If the sensor is saturated, then -1 is returned, see :func:`Set Configuration`.
		
		If you want to get the intensity periodically, it is recommended to use the
		:cb:`UVI` callback and set the period with
		:func:`Set UVI Callback Configuration`.
		
		
		If you want to get the value periodically, it is recommended to use the
		:cb:`UVI` callback. You can set the callback configuration
		with :func:`Set UVI Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletUVLightV2.FUNCTION_GET_UVI, [], '', 12, 'i', returnCallback, errorCallback, false, true);
	};
	this.setUVICallbackConfiguration = function(period, valueHasToChange, option, min, max, returnCallback, errorCallback) {
		/*
		The period is the period with which the :cb:`UVI` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		If the `value has to change`-parameter is set to true, the callback is only
		triggered after the value has changed. If the value didn't change
		within the period, the callback is triggered immediately on change.
		
		If it is set to false, the callback is continuously triggered with the period,
		independent of the value.
		
		It is furthermore possible to constrain the callback with thresholds.
		
		The `option`-parameter together with min/max sets a threshold for the :cb:`UVI` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Threshold is turned off"
		 "'o'",    "Threshold is triggered when the value is *outside* the min and max values"
		 "'i'",    "Threshold is triggered when the value is *inside* or equal to the min and max values"
		 "'<'",    "Threshold is triggered when the value is smaller than the min value (max is ignored)"
		 "'>'",    "Threshold is triggered when the value is greater than the min value (max is ignored)"
		
		If the option is set to 'x' (threshold turned off) the callback is triggered with the fixed period.
		*/
		this.ipcon.sendRequest(this, BrickletUVLightV2.FUNCTION_SET_UVI_CALLBACK_CONFIGURATION, [period, valueHasToChange, option, min, max], 'I ? c i i', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getUVICallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the callback configuration as set by :func:`Set UVI Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletUVLightV2.FUNCTION_GET_UVI_CALLBACK_CONFIGURATION, [], '', 22, 'I ? c i i', returnCallback, errorCallback, false, true);
	};
	this.setConfiguration = function(integrationTime, returnCallback, errorCallback) {
		/*
		Sets the configuration of the sensor. The integration time can be configured
		between 50 and 800 ms. With a shorter integration time the sensor reading updates
		more often but contains more noise. With a longer integration the sensor reading
		contains less noise but updates less often.
		
		With a longer integration time (especially 800 ms) and a higher UV intensity the
		sensor can be saturated. If this happens the UVA/UVB/UVI readings are all -1.
		In this case you need to choose a shorter integration time.
		*/
		this.ipcon.sendRequest(this, BrickletUVLightV2.FUNCTION_SET_CONFIGURATION, [integrationTime], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletUVLightV2.FUNCTION_GET_CONFIGURATION, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPErrorCount = function(returnCallback, errorCallback) {
		/*
		Returns the error count for the communication between Brick and Bricklet.
		
		The errors are divided into
		
		* ACK checksum errors,
		* message checksum errors,
		* framing errors and
		* overflow errors.
		
		The errors counts are for errors that occur on the Bricklet side. All
		Bricks have a similar function that returns the errors on the Brick side.
		*/
		this.ipcon.sendRequest(this, BrickletUVLightV2.FUNCTION_GET_SPITFP_ERROR_COUNT, [], '', 24, 'I I I I', returnCallback, errorCallback, false, true);
	};
	this.setBootloaderMode = function(mode, returnCallback, errorCallback) {
		/*
		Sets the bootloader mode and returns the status after the requested
		mode change was instigated.
		
		You can change from bootloader mode to firmware mode and vice versa. A change
		from bootloader mode to firmware mode will only take place if the entry function,
		device identifier and CRC are present and correct.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletUVLightV2.FUNCTION_SET_BOOTLOADER_MODE, [mode], 'B', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getBootloaderMode = function(returnCallback, errorCallback) {
		/*
		Returns the current bootloader mode, see :func:`Set Bootloader Mode`.
		*/
		this.ipcon.sendRequest(this, BrickletUVLightV2.FUNCTION_GET_BOOTLOADER_MODE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setWriteFirmwarePointer = function(pointer, returnCallback, errorCallback) {
		/*
		Sets the firmware pointer for :func:`Write Firmware`. The pointer has
		to be increased by chunks of size 64. The data is written to flash
		every 4 chunks (which equals to one page of size 256).
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletUVLightV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER, [pointer], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeFirmware = function(data, returnCallback, errorCallback) {
		/*
		Writes 64 Bytes of firmware at the position as written by
		:func:`Set Write Firmware Pointer` before. The firmware is written
		to flash every 4 chunks.
		
		You can only write firmware in bootloader mode.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletUVLightV2.FUNCTION_WRITE_FIRMWARE, [data], 'B64', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setStatusLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Sets the status LED configuration. By default the LED shows
		communication traffic between Brick and Bricklet, it flickers once
		for every 10 received data packets.
		
		You can also turn the LED permanently on/off or show a heartbeat.
		
		If the Bricklet is in bootloader mode, the LED is will show heartbeat by default.
		*/
		this.ipcon.sendRequest(this, BrickletUVLightV2.FUNCTION_SET_STATUS_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getStatusLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Status LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletUVLightV2.FUNCTION_GET_STATUS_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getChipTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature as measured inside the microcontroller. The
		value returned is not the ambient temperature!
		
		The temperature is only proportional to the real temperature and it has bad
		accuracy. Practically it is only useful as an indicator for
		temperature changes.
		*/
		this.ipcon.sendRequest(this, BrickletUVLightV2.FUNCTION_GET_CHIP_TEMPERATURE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.reset = function(returnCallback, errorCallback) {
		/*
		Calling this function will reset the Bricklet. All configurations
		will be lost.
		
		After a reset you have to create new device objects,
		calling functions on the existing ones will result in
		undefined behavior!
		*/
		this.ipcon.sendRequest(this, BrickletUVLightV2.FUNCTION_RESET, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeUID = function(uid, returnCallback, errorCallback) {
		/*
		Writes a new UID into flash. If you want to set a new UID
		you have to decode the Base58 encoded UID string into an
		integer first.
		
		We recommend that you use Brick Viewer to change the UID.
		*/
		this.ipcon.sendRequest(this, BrickletUVLightV2.FUNCTION_WRITE_UID, [uid], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.readUID = function(returnCallback, errorCallback) {
		/*
		Returns the current UID as an integer. Encode as
		Base58 to get the usual string version.
		*/
		this.ipcon.sendRequest(this, BrickletUVLightV2.FUNCTION_READ_UID, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletUVLightV2.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletUVLightV2;

},{"./Device":279,"./IPConnection":280}],274:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletVoltage.DEVICE_IDENTIFIER = 218;
BrickletVoltage.DEVICE_DISPLAY_NAME = 'Voltage Bricklet';
BrickletVoltage.CALLBACK_VOLTAGE = 13;
BrickletVoltage.CALLBACK_ANALOG_VALUE = 14;
BrickletVoltage.CALLBACK_VOLTAGE_REACHED = 15;
BrickletVoltage.CALLBACK_ANALOG_VALUE_REACHED = 16;
BrickletVoltage.FUNCTION_GET_VOLTAGE = 1;
BrickletVoltage.FUNCTION_GET_ANALOG_VALUE = 2;
BrickletVoltage.FUNCTION_SET_VOLTAGE_CALLBACK_PERIOD = 3;
BrickletVoltage.FUNCTION_GET_VOLTAGE_CALLBACK_PERIOD = 4;
BrickletVoltage.FUNCTION_SET_ANALOG_VALUE_CALLBACK_PERIOD = 5;
BrickletVoltage.FUNCTION_GET_ANALOG_VALUE_CALLBACK_PERIOD = 6;
BrickletVoltage.FUNCTION_SET_VOLTAGE_CALLBACK_THRESHOLD = 7;
BrickletVoltage.FUNCTION_GET_VOLTAGE_CALLBACK_THRESHOLD = 8;
BrickletVoltage.FUNCTION_SET_ANALOG_VALUE_CALLBACK_THRESHOLD = 9;
BrickletVoltage.FUNCTION_GET_ANALOG_VALUE_CALLBACK_THRESHOLD = 10;
BrickletVoltage.FUNCTION_SET_DEBOUNCE_PERIOD = 11;
BrickletVoltage.FUNCTION_GET_DEBOUNCE_PERIOD = 12;
BrickletVoltage.FUNCTION_GET_IDENTITY = 255;
BrickletVoltage.THRESHOLD_OPTION_OFF = 'x';
BrickletVoltage.THRESHOLD_OPTION_OUTSIDE = 'o';
BrickletVoltage.THRESHOLD_OPTION_INSIDE = 'i';
BrickletVoltage.THRESHOLD_OPTION_SMALLER = '<';
BrickletVoltage.THRESHOLD_OPTION_GREATER = '>';

function BrickletVoltage(uid, ipcon) {
	//Measures DC voltage between 0V and 50V

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletVoltage.DEVICE_IDENTIFIER, BrickletVoltage.DEVICE_DISPLAY_NAME);
	BrickletVoltage.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 1];
	this.responseExpected[BrickletVoltage.FUNCTION_GET_VOLTAGE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletVoltage.FUNCTION_GET_ANALOG_VALUE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletVoltage.FUNCTION_SET_VOLTAGE_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletVoltage.FUNCTION_GET_VOLTAGE_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletVoltage.FUNCTION_SET_ANALOG_VALUE_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletVoltage.FUNCTION_GET_ANALOG_VALUE_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletVoltage.FUNCTION_SET_VOLTAGE_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletVoltage.FUNCTION_GET_VOLTAGE_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletVoltage.FUNCTION_SET_ANALOG_VALUE_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletVoltage.FUNCTION_GET_ANALOG_VALUE_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletVoltage.FUNCTION_SET_DEBOUNCE_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletVoltage.FUNCTION_GET_DEBOUNCE_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletVoltage.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletVoltage.CALLBACK_VOLTAGE] = [10, 'H'];
	this.callbackFormats[BrickletVoltage.CALLBACK_ANALOG_VALUE] = [10, 'H'];
	this.callbackFormats[BrickletVoltage.CALLBACK_VOLTAGE_REACHED] = [10, 'H'];
	this.callbackFormats[BrickletVoltage.CALLBACK_ANALOG_VALUE_REACHED] = [10, 'H'];



	this.getVoltage = function(returnCallback, errorCallback) {
		/*
		Returns the voltage of the sensor.
		
		If you want to get the voltage periodically, it is recommended to use the
		:cb:`Voltage` callback and set the period with
		:func:`Set Voltage Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletVoltage.FUNCTION_GET_VOLTAGE, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.getAnalogValue = function(returnCallback, errorCallback) {
		/*
		Returns the value as read by a 12-bit analog-to-digital converter.
		
		.. note::
		 The value returned by :func:`Get Voltage` is averaged over several samples
		 to yield less noise, while :func:`Get Analog Value` gives back raw
		 unfiltered analog values. The only reason to use :func:`Get Analog Value` is,
		 if you need the full resolution of the analog-to-digital converter.
		
		If you want the analog value periodically, it is recommended to use the
		:cb:`Analog Value` callback and set the period with
		:func:`Set Analog Value Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletVoltage.FUNCTION_GET_ANALOG_VALUE, [], '', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.setVoltageCallbackPeriod = function(period, returnCallback, errorCallback) {
		/*
		Sets the period with which the :cb:`Voltage` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		The :cb:`Voltage` callback is only triggered if the voltage has changed since
		the last triggering.
		*/
		this.ipcon.sendRequest(this, BrickletVoltage.FUNCTION_SET_VOLTAGE_CALLBACK_PERIOD, [period], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getVoltageCallbackPeriod = function(returnCallback, errorCallback) {
		/*
		Returns the period as set by :func:`Set Voltage Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletVoltage.FUNCTION_GET_VOLTAGE_CALLBACK_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setAnalogValueCallbackPeriod = function(period, returnCallback, errorCallback) {
		/*
		Sets the period with which the :cb:`Analog Value` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		The :cb:`Analog Value` callback is only triggered if the analog value has
		changed since the last triggering.
		*/
		this.ipcon.sendRequest(this, BrickletVoltage.FUNCTION_SET_ANALOG_VALUE_CALLBACK_PERIOD, [period], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getAnalogValueCallbackPeriod = function(returnCallback, errorCallback) {
		/*
		Returns the period as set by :func:`Set Analog Value Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletVoltage.FUNCTION_GET_ANALOG_VALUE_CALLBACK_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setVoltageCallbackThreshold = function(option, min, max, returnCallback, errorCallback) {
		/*
		Sets the thresholds for the :cb:`Voltage Reached` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Callback is turned off"
		 "'o'",    "Callback is triggered when the voltage is *outside* the min and max values"
		 "'i'",    "Callback is triggered when the voltage is *inside* the min and max values"
		 "'<'",    "Callback is triggered when the voltage is smaller than the min value (max is ignored)"
		 "'>'",    "Callback is triggered when the voltage is greater than the min value (max is ignored)"
		*/
		this.ipcon.sendRequest(this, BrickletVoltage.FUNCTION_SET_VOLTAGE_CALLBACK_THRESHOLD, [option, min, max], 'c H H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getVoltageCallbackThreshold = function(returnCallback, errorCallback) {
		/*
		Returns the threshold as set by :func:`Set Voltage Callback Threshold`.
		*/
		this.ipcon.sendRequest(this, BrickletVoltage.FUNCTION_GET_VOLTAGE_CALLBACK_THRESHOLD, [], '', 13, 'c H H', returnCallback, errorCallback, false, true);
	};
	this.setAnalogValueCallbackThreshold = function(option, min, max, returnCallback, errorCallback) {
		/*
		Sets the thresholds for the :cb:`Analog Value Reached` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Callback is turned off"
		 "'o'",    "Callback is triggered when the analog value is *outside* the min and max values"
		 "'i'",    "Callback is triggered when the analog value is *inside* the min and max values"
		 "'<'",    "Callback is triggered when the analog value is smaller than the min value (max is ignored)"
		 "'>'",    "Callback is triggered when the analog value is greater than the min value (max is ignored)"
		*/
		this.ipcon.sendRequest(this, BrickletVoltage.FUNCTION_SET_ANALOG_VALUE_CALLBACK_THRESHOLD, [option, min, max], 'c H H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getAnalogValueCallbackThreshold = function(returnCallback, errorCallback) {
		/*
		Returns the threshold as set by :func:`Set Analog Value Callback Threshold`.
		*/
		this.ipcon.sendRequest(this, BrickletVoltage.FUNCTION_GET_ANALOG_VALUE_CALLBACK_THRESHOLD, [], '', 13, 'c H H', returnCallback, errorCallback, false, true);
	};
	this.setDebouncePeriod = function(debounce, returnCallback, errorCallback) {
		/*
		Sets the period with which the threshold callbacks
		
		* :cb:`Voltage Reached`,
		* :cb:`Analog Value Reached`
		
		are triggered, if the thresholds
		
		* :func:`Set Voltage Callback Threshold`,
		* :func:`Set Analog Value Callback Threshold`
		
		keep being reached.
		*/
		this.ipcon.sendRequest(this, BrickletVoltage.FUNCTION_SET_DEBOUNCE_PERIOD, [debounce], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getDebouncePeriod = function(returnCallback, errorCallback) {
		/*
		Returns the debounce period as set by :func:`Set Debounce Period`.
		*/
		this.ipcon.sendRequest(this, BrickletVoltage.FUNCTION_GET_DEBOUNCE_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletVoltage.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletVoltage;

},{"./Device":279,"./IPConnection":280}],275:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletVoltageCurrent.DEVICE_IDENTIFIER = 227;
BrickletVoltageCurrent.DEVICE_DISPLAY_NAME = 'Voltage/Current Bricklet';
BrickletVoltageCurrent.CALLBACK_CURRENT = 22;
BrickletVoltageCurrent.CALLBACK_VOLTAGE = 23;
BrickletVoltageCurrent.CALLBACK_POWER = 24;
BrickletVoltageCurrent.CALLBACK_CURRENT_REACHED = 25;
BrickletVoltageCurrent.CALLBACK_VOLTAGE_REACHED = 26;
BrickletVoltageCurrent.CALLBACK_POWER_REACHED = 27;
BrickletVoltageCurrent.FUNCTION_GET_CURRENT = 1;
BrickletVoltageCurrent.FUNCTION_GET_VOLTAGE = 2;
BrickletVoltageCurrent.FUNCTION_GET_POWER = 3;
BrickletVoltageCurrent.FUNCTION_SET_CONFIGURATION = 4;
BrickletVoltageCurrent.FUNCTION_GET_CONFIGURATION = 5;
BrickletVoltageCurrent.FUNCTION_SET_CALIBRATION = 6;
BrickletVoltageCurrent.FUNCTION_GET_CALIBRATION = 7;
BrickletVoltageCurrent.FUNCTION_SET_CURRENT_CALLBACK_PERIOD = 8;
BrickletVoltageCurrent.FUNCTION_GET_CURRENT_CALLBACK_PERIOD = 9;
BrickletVoltageCurrent.FUNCTION_SET_VOLTAGE_CALLBACK_PERIOD = 10;
BrickletVoltageCurrent.FUNCTION_GET_VOLTAGE_CALLBACK_PERIOD = 11;
BrickletVoltageCurrent.FUNCTION_SET_POWER_CALLBACK_PERIOD = 12;
BrickletVoltageCurrent.FUNCTION_GET_POWER_CALLBACK_PERIOD = 13;
BrickletVoltageCurrent.FUNCTION_SET_CURRENT_CALLBACK_THRESHOLD = 14;
BrickletVoltageCurrent.FUNCTION_GET_CURRENT_CALLBACK_THRESHOLD = 15;
BrickletVoltageCurrent.FUNCTION_SET_VOLTAGE_CALLBACK_THRESHOLD = 16;
BrickletVoltageCurrent.FUNCTION_GET_VOLTAGE_CALLBACK_THRESHOLD = 17;
BrickletVoltageCurrent.FUNCTION_SET_POWER_CALLBACK_THRESHOLD = 18;
BrickletVoltageCurrent.FUNCTION_GET_POWER_CALLBACK_THRESHOLD = 19;
BrickletVoltageCurrent.FUNCTION_SET_DEBOUNCE_PERIOD = 20;
BrickletVoltageCurrent.FUNCTION_GET_DEBOUNCE_PERIOD = 21;
BrickletVoltageCurrent.FUNCTION_GET_IDENTITY = 255;
BrickletVoltageCurrent.AVERAGING_1 = 0;
BrickletVoltageCurrent.AVERAGING_4 = 1;
BrickletVoltageCurrent.AVERAGING_16 = 2;
BrickletVoltageCurrent.AVERAGING_64 = 3;
BrickletVoltageCurrent.AVERAGING_128 = 4;
BrickletVoltageCurrent.AVERAGING_256 = 5;
BrickletVoltageCurrent.AVERAGING_512 = 6;
BrickletVoltageCurrent.AVERAGING_1024 = 7;
BrickletVoltageCurrent.THRESHOLD_OPTION_OFF = 'x';
BrickletVoltageCurrent.THRESHOLD_OPTION_OUTSIDE = 'o';
BrickletVoltageCurrent.THRESHOLD_OPTION_INSIDE = 'i';
BrickletVoltageCurrent.THRESHOLD_OPTION_SMALLER = '<';
BrickletVoltageCurrent.THRESHOLD_OPTION_GREATER = '>';
BrickletVoltageCurrent.CONVERSION_TIME_140US = 0;
BrickletVoltageCurrent.CONVERSION_TIME_204US = 1;
BrickletVoltageCurrent.CONVERSION_TIME_332US = 2;
BrickletVoltageCurrent.CONVERSION_TIME_588US = 3;
BrickletVoltageCurrent.CONVERSION_TIME_1_1MS = 4;
BrickletVoltageCurrent.CONVERSION_TIME_2_116MS = 5;
BrickletVoltageCurrent.CONVERSION_TIME_4_156MS = 6;
BrickletVoltageCurrent.CONVERSION_TIME_8_244MS = 7;

function BrickletVoltageCurrent(uid, ipcon) {
	//Measures power, DC voltage and DC current up to 720W/36V/20A

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletVoltageCurrent.DEVICE_IDENTIFIER, BrickletVoltageCurrent.DEVICE_DISPLAY_NAME);
	BrickletVoltageCurrent.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickletVoltageCurrent.FUNCTION_GET_CURRENT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletVoltageCurrent.FUNCTION_GET_VOLTAGE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletVoltageCurrent.FUNCTION_GET_POWER] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletVoltageCurrent.FUNCTION_SET_CONFIGURATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletVoltageCurrent.FUNCTION_GET_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletVoltageCurrent.FUNCTION_SET_CALIBRATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletVoltageCurrent.FUNCTION_GET_CALIBRATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletVoltageCurrent.FUNCTION_SET_CURRENT_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletVoltageCurrent.FUNCTION_GET_CURRENT_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletVoltageCurrent.FUNCTION_SET_VOLTAGE_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletVoltageCurrent.FUNCTION_GET_VOLTAGE_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletVoltageCurrent.FUNCTION_SET_POWER_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletVoltageCurrent.FUNCTION_GET_POWER_CALLBACK_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletVoltageCurrent.FUNCTION_SET_CURRENT_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletVoltageCurrent.FUNCTION_GET_CURRENT_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletVoltageCurrent.FUNCTION_SET_VOLTAGE_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletVoltageCurrent.FUNCTION_GET_VOLTAGE_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletVoltageCurrent.FUNCTION_SET_POWER_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletVoltageCurrent.FUNCTION_GET_POWER_CALLBACK_THRESHOLD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletVoltageCurrent.FUNCTION_SET_DEBOUNCE_PERIOD] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletVoltageCurrent.FUNCTION_GET_DEBOUNCE_PERIOD] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletVoltageCurrent.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletVoltageCurrent.CALLBACK_CURRENT] = [12, 'i'];
	this.callbackFormats[BrickletVoltageCurrent.CALLBACK_VOLTAGE] = [12, 'i'];
	this.callbackFormats[BrickletVoltageCurrent.CALLBACK_POWER] = [12, 'i'];
	this.callbackFormats[BrickletVoltageCurrent.CALLBACK_CURRENT_REACHED] = [12, 'i'];
	this.callbackFormats[BrickletVoltageCurrent.CALLBACK_VOLTAGE_REACHED] = [12, 'i'];
	this.callbackFormats[BrickletVoltageCurrent.CALLBACK_POWER_REACHED] = [12, 'i'];



	this.getCurrent = function(returnCallback, errorCallback) {
		/*
		Returns the current.
		
		If you want to get the current periodically, it is recommended to use the
		:cb:`Current` callback and set the period with
		:func:`Set Current Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletVoltageCurrent.FUNCTION_GET_CURRENT, [], '', 12, 'i', returnCallback, errorCallback, false, true);
	};
	this.getVoltage = function(returnCallback, errorCallback) {
		/*
		Returns the voltage.
		
		If you want to get the voltage periodically, it is recommended to use the
		:cb:`Voltage` callback and set the period with
		:func:`Set Voltage Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletVoltageCurrent.FUNCTION_GET_VOLTAGE, [], '', 12, 'i', returnCallback, errorCallback, false, true);
	};
	this.getPower = function(returnCallback, errorCallback) {
		/*
		Returns the power.
		
		If you want to get the power periodically, it is recommended to use the
		:cb:`Power` callback and set the period with
		:func:`Set Power Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletVoltageCurrent.FUNCTION_GET_POWER, [], '', 12, 'i', returnCallback, errorCallback, false, true);
	};
	this.setConfiguration = function(averaging, voltageConversionTime, currentConversionTime, returnCallback, errorCallback) {
		/*
		Sets the configuration of the Voltage/Current Bricklet. It is
		possible to configure number of averages as well as
		voltage and current conversion time.
		*/
		this.ipcon.sendRequest(this, BrickletVoltageCurrent.FUNCTION_SET_CONFIGURATION, [averaging, voltageConversionTime, currentConversionTime], 'B B B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletVoltageCurrent.FUNCTION_GET_CONFIGURATION, [], '', 11, 'B B B', returnCallback, errorCallback, false, true);
	};
	this.setCalibration = function(gainMultiplier, gainDivisor, returnCallback, errorCallback) {
		/*
		Since the shunt resistor that is used to measure the current is not
		perfectly precise, it needs to be calibrated by a multiplier and
		divisor if a very precise reading is needed.
		
		For example, if you are expecting a measurement of 1000mA and you
		are measuring 1023mA, you can calibrate the Voltage/Current Bricklet
		by setting the multiplier to 1000 and the divisor to 1023.
		*/
		this.ipcon.sendRequest(this, BrickletVoltageCurrent.FUNCTION_SET_CALIBRATION, [gainMultiplier, gainDivisor], 'H H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getCalibration = function(returnCallback, errorCallback) {
		/*
		Returns the calibration as set by :func:`Set Calibration`.
		*/
		this.ipcon.sendRequest(this, BrickletVoltageCurrent.FUNCTION_GET_CALIBRATION, [], '', 12, 'H H', returnCallback, errorCallback, false, true);
	};
	this.setCurrentCallbackPeriod = function(period, returnCallback, errorCallback) {
		/*
		Sets the period with which the :cb:`Current` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		The :cb:`Current` callback is only triggered if the current has changed since
		the last triggering.
		*/
		this.ipcon.sendRequest(this, BrickletVoltageCurrent.FUNCTION_SET_CURRENT_CALLBACK_PERIOD, [period], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getCurrentCallbackPeriod = function(returnCallback, errorCallback) {
		/*
		Returns the period as set by :func:`Set Current Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletVoltageCurrent.FUNCTION_GET_CURRENT_CALLBACK_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setVoltageCallbackPeriod = function(period, returnCallback, errorCallback) {
		/*
		Sets the period with which the :cb:`Voltage` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		The :cb:`Voltage` callback is only triggered if the voltage has changed since
		the last triggering.
		*/
		this.ipcon.sendRequest(this, BrickletVoltageCurrent.FUNCTION_SET_VOLTAGE_CALLBACK_PERIOD, [period], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getVoltageCallbackPeriod = function(returnCallback, errorCallback) {
		/*
		Returns the period as set by :func:`Set Voltage Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletVoltageCurrent.FUNCTION_GET_VOLTAGE_CALLBACK_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setPowerCallbackPeriod = function(period, returnCallback, errorCallback) {
		/*
		Sets the period with which the :cb:`Power` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		The :cb:`Power` callback is only triggered if the power has changed since the
		last triggering.
		*/
		this.ipcon.sendRequest(this, BrickletVoltageCurrent.FUNCTION_SET_POWER_CALLBACK_PERIOD, [period], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getPowerCallbackPeriod = function(returnCallback, errorCallback) {
		/*
		Returns the period as set by :func:`Get Power Callback Period`.
		*/
		this.ipcon.sendRequest(this, BrickletVoltageCurrent.FUNCTION_GET_POWER_CALLBACK_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setCurrentCallbackThreshold = function(option, min, max, returnCallback, errorCallback) {
		/*
		Sets the thresholds for the :cb:`Current Reached` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Callback is turned off"
		 "'o'",    "Callback is triggered when the current is *outside* the min and max values"
		 "'i'",    "Callback is triggered when the current is *inside* the min and max values"
		 "'<'",    "Callback is triggered when the current is smaller than the min value (max is ignored)"
		 "'>'",    "Callback is triggered when the current is greater than the min value (max is ignored)"
		*/
		this.ipcon.sendRequest(this, BrickletVoltageCurrent.FUNCTION_SET_CURRENT_CALLBACK_THRESHOLD, [option, min, max], 'c i i', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getCurrentCallbackThreshold = function(returnCallback, errorCallback) {
		/*
		Returns the threshold as set by :func:`Set Current Callback Threshold`.
		*/
		this.ipcon.sendRequest(this, BrickletVoltageCurrent.FUNCTION_GET_CURRENT_CALLBACK_THRESHOLD, [], '', 17, 'c i i', returnCallback, errorCallback, false, true);
	};
	this.setVoltageCallbackThreshold = function(option, min, max, returnCallback, errorCallback) {
		/*
		Sets the thresholds for the :cb:`Voltage Reached` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Callback is turned off"
		 "'o'",    "Callback is triggered when the voltage is *outside* the min and max values"
		 "'i'",    "Callback is triggered when the voltage is *inside* the min and max values"
		 "'<'",    "Callback is triggered when the voltage is smaller than the min value (max is ignored)"
		 "'>'",    "Callback is triggered when the voltage is greater than the min value (max is ignored)"
		*/
		this.ipcon.sendRequest(this, BrickletVoltageCurrent.FUNCTION_SET_VOLTAGE_CALLBACK_THRESHOLD, [option, min, max], 'c i i', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getVoltageCallbackThreshold = function(returnCallback, errorCallback) {
		/*
		Returns the threshold as set by :func:`Set Voltage Callback Threshold`.
		*/
		this.ipcon.sendRequest(this, BrickletVoltageCurrent.FUNCTION_GET_VOLTAGE_CALLBACK_THRESHOLD, [], '', 17, 'c i i', returnCallback, errorCallback, false, true);
	};
	this.setPowerCallbackThreshold = function(option, min, max, returnCallback, errorCallback) {
		/*
		Sets the thresholds for the :cb:`Power Reached` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Callback is turned off"
		 "'o'",    "Callback is triggered when the power is *outside* the min and max values"
		 "'i'",    "Callback is triggered when the power is *inside* the min and max values"
		 "'<'",    "Callback is triggered when the power is smaller than the min value (max is ignored)"
		 "'>'",    "Callback is triggered when the power is greater than the min value (max is ignored)"
		*/
		this.ipcon.sendRequest(this, BrickletVoltageCurrent.FUNCTION_SET_POWER_CALLBACK_THRESHOLD, [option, min, max], 'c i i', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getPowerCallbackThreshold = function(returnCallback, errorCallback) {
		/*
		Returns the threshold as set by :func:`Set Power Callback Threshold`.
		*/
		this.ipcon.sendRequest(this, BrickletVoltageCurrent.FUNCTION_GET_POWER_CALLBACK_THRESHOLD, [], '', 17, 'c i i', returnCallback, errorCallback, false, true);
	};
	this.setDebouncePeriod = function(debounce, returnCallback, errorCallback) {
		/*
		Sets the period with which the threshold callbacks
		
		* :cb:`Current Reached`,
		* :cb:`Voltage Reached`,
		* :cb:`Power Reached`
		
		are triggered, if the thresholds
		
		* :func:`Set Current Callback Threshold`,
		* :func:`Set Voltage Callback Threshold`,
		* :func:`Set Power Callback Threshold`
		
		keep being reached.
		*/
		this.ipcon.sendRequest(this, BrickletVoltageCurrent.FUNCTION_SET_DEBOUNCE_PERIOD, [debounce], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getDebouncePeriod = function(returnCallback, errorCallback) {
		/*
		Returns the debounce period as set by :func:`Set Debounce Period`.
		*/
		this.ipcon.sendRequest(this, BrickletVoltageCurrent.FUNCTION_GET_DEBOUNCE_PERIOD, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletVoltageCurrent.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletVoltageCurrent;

},{"./Device":279,"./IPConnection":280}],276:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletVoltageCurrentV2.DEVICE_IDENTIFIER = 2105;
BrickletVoltageCurrentV2.DEVICE_DISPLAY_NAME = 'Voltage/Current Bricklet 2.0';
BrickletVoltageCurrentV2.CALLBACK_CURRENT = 4;
BrickletVoltageCurrentV2.CALLBACK_VOLTAGE = 8;
BrickletVoltageCurrentV2.CALLBACK_POWER = 12;
BrickletVoltageCurrentV2.FUNCTION_GET_CURRENT = 1;
BrickletVoltageCurrentV2.FUNCTION_SET_CURRENT_CALLBACK_CONFIGURATION = 2;
BrickletVoltageCurrentV2.FUNCTION_GET_CURRENT_CALLBACK_CONFIGURATION = 3;
BrickletVoltageCurrentV2.FUNCTION_GET_VOLTAGE = 5;
BrickletVoltageCurrentV2.FUNCTION_SET_VOLTAGE_CALLBACK_CONFIGURATION = 6;
BrickletVoltageCurrentV2.FUNCTION_GET_VOLTAGE_CALLBACK_CONFIGURATION = 7;
BrickletVoltageCurrentV2.FUNCTION_GET_POWER = 9;
BrickletVoltageCurrentV2.FUNCTION_SET_POWER_CALLBACK_CONFIGURATION = 10;
BrickletVoltageCurrentV2.FUNCTION_GET_POWER_CALLBACK_CONFIGURATION = 11;
BrickletVoltageCurrentV2.FUNCTION_SET_CONFIGURATION = 13;
BrickletVoltageCurrentV2.FUNCTION_GET_CONFIGURATION = 14;
BrickletVoltageCurrentV2.FUNCTION_SET_CALIBRATION = 15;
BrickletVoltageCurrentV2.FUNCTION_GET_CALIBRATION = 16;
BrickletVoltageCurrentV2.FUNCTION_GET_SPITFP_ERROR_COUNT = 234;
BrickletVoltageCurrentV2.FUNCTION_SET_BOOTLOADER_MODE = 235;
BrickletVoltageCurrentV2.FUNCTION_GET_BOOTLOADER_MODE = 236;
BrickletVoltageCurrentV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER = 237;
BrickletVoltageCurrentV2.FUNCTION_WRITE_FIRMWARE = 238;
BrickletVoltageCurrentV2.FUNCTION_SET_STATUS_LED_CONFIG = 239;
BrickletVoltageCurrentV2.FUNCTION_GET_STATUS_LED_CONFIG = 240;
BrickletVoltageCurrentV2.FUNCTION_GET_CHIP_TEMPERATURE = 242;
BrickletVoltageCurrentV2.FUNCTION_RESET = 243;
BrickletVoltageCurrentV2.FUNCTION_WRITE_UID = 248;
BrickletVoltageCurrentV2.FUNCTION_READ_UID = 249;
BrickletVoltageCurrentV2.FUNCTION_GET_IDENTITY = 255;
BrickletVoltageCurrentV2.THRESHOLD_OPTION_OFF = 'x';
BrickletVoltageCurrentV2.THRESHOLD_OPTION_OUTSIDE = 'o';
BrickletVoltageCurrentV2.THRESHOLD_OPTION_INSIDE = 'i';
BrickletVoltageCurrentV2.THRESHOLD_OPTION_SMALLER = '<';
BrickletVoltageCurrentV2.THRESHOLD_OPTION_GREATER = '>';
BrickletVoltageCurrentV2.AVERAGING_1 = 0;
BrickletVoltageCurrentV2.AVERAGING_4 = 1;
BrickletVoltageCurrentV2.AVERAGING_16 = 2;
BrickletVoltageCurrentV2.AVERAGING_64 = 3;
BrickletVoltageCurrentV2.AVERAGING_128 = 4;
BrickletVoltageCurrentV2.AVERAGING_256 = 5;
BrickletVoltageCurrentV2.AVERAGING_512 = 6;
BrickletVoltageCurrentV2.AVERAGING_1024 = 7;
BrickletVoltageCurrentV2.CONVERSION_TIME_140US = 0;
BrickletVoltageCurrentV2.CONVERSION_TIME_204US = 1;
BrickletVoltageCurrentV2.CONVERSION_TIME_332US = 2;
BrickletVoltageCurrentV2.CONVERSION_TIME_588US = 3;
BrickletVoltageCurrentV2.CONVERSION_TIME_1_1MS = 4;
BrickletVoltageCurrentV2.CONVERSION_TIME_2_116MS = 5;
BrickletVoltageCurrentV2.CONVERSION_TIME_4_156MS = 6;
BrickletVoltageCurrentV2.CONVERSION_TIME_8_244MS = 7;
BrickletVoltageCurrentV2.BOOTLOADER_MODE_BOOTLOADER = 0;
BrickletVoltageCurrentV2.BOOTLOADER_MODE_FIRMWARE = 1;
BrickletVoltageCurrentV2.BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT = 2;
BrickletVoltageCurrentV2.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT = 3;
BrickletVoltageCurrentV2.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT = 4;
BrickletVoltageCurrentV2.BOOTLOADER_STATUS_OK = 0;
BrickletVoltageCurrentV2.BOOTLOADER_STATUS_INVALID_MODE = 1;
BrickletVoltageCurrentV2.BOOTLOADER_STATUS_NO_CHANGE = 2;
BrickletVoltageCurrentV2.BOOTLOADER_STATUS_ENTRY_FUNCTION_NOT_PRESENT = 3;
BrickletVoltageCurrentV2.BOOTLOADER_STATUS_DEVICE_IDENTIFIER_INCORRECT = 4;
BrickletVoltageCurrentV2.BOOTLOADER_STATUS_CRC_MISMATCH = 5;
BrickletVoltageCurrentV2.STATUS_LED_CONFIG_OFF = 0;
BrickletVoltageCurrentV2.STATUS_LED_CONFIG_ON = 1;
BrickletVoltageCurrentV2.STATUS_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletVoltageCurrentV2.STATUS_LED_CONFIG_SHOW_STATUS = 3;

function BrickletVoltageCurrentV2(uid, ipcon) {
	//Measures power, DC voltage and DC current up to 720W/36V/20A

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletVoltageCurrentV2.DEVICE_IDENTIFIER, BrickletVoltageCurrentV2.DEVICE_DISPLAY_NAME);
	BrickletVoltageCurrentV2.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickletVoltageCurrentV2.FUNCTION_GET_CURRENT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletVoltageCurrentV2.FUNCTION_SET_CURRENT_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletVoltageCurrentV2.FUNCTION_GET_CURRENT_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletVoltageCurrentV2.FUNCTION_GET_VOLTAGE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletVoltageCurrentV2.FUNCTION_SET_VOLTAGE_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletVoltageCurrentV2.FUNCTION_GET_VOLTAGE_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletVoltageCurrentV2.FUNCTION_GET_POWER] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletVoltageCurrentV2.FUNCTION_SET_POWER_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletVoltageCurrentV2.FUNCTION_GET_POWER_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletVoltageCurrentV2.FUNCTION_SET_CONFIGURATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletVoltageCurrentV2.FUNCTION_GET_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletVoltageCurrentV2.FUNCTION_SET_CALIBRATION] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletVoltageCurrentV2.FUNCTION_GET_CALIBRATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletVoltageCurrentV2.FUNCTION_GET_SPITFP_ERROR_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletVoltageCurrentV2.FUNCTION_SET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletVoltageCurrentV2.FUNCTION_GET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletVoltageCurrentV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletVoltageCurrentV2.FUNCTION_WRITE_FIRMWARE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletVoltageCurrentV2.FUNCTION_SET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletVoltageCurrentV2.FUNCTION_GET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletVoltageCurrentV2.FUNCTION_GET_CHIP_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletVoltageCurrentV2.FUNCTION_RESET] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletVoltageCurrentV2.FUNCTION_WRITE_UID] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletVoltageCurrentV2.FUNCTION_READ_UID] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletVoltageCurrentV2.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletVoltageCurrentV2.CALLBACK_CURRENT] = [12, 'i'];
	this.callbackFormats[BrickletVoltageCurrentV2.CALLBACK_VOLTAGE] = [12, 'i'];
	this.callbackFormats[BrickletVoltageCurrentV2.CALLBACK_POWER] = [12, 'i'];



	this.getCurrent = function(returnCallback, errorCallback) {
		/*
		Returns the current.
		
		
		If you want to get the value periodically, it is recommended to use the
		:cb:`Current` callback. You can set the callback configuration
		with :func:`Set Current Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletVoltageCurrentV2.FUNCTION_GET_CURRENT, [], '', 12, 'i', returnCallback, errorCallback, false, true);
	};
	this.setCurrentCallbackConfiguration = function(period, valueHasToChange, option, min, max, returnCallback, errorCallback) {
		/*
		The period is the period with which the :cb:`Current` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		If the `value has to change`-parameter is set to true, the callback is only
		triggered after the value has changed. If the value didn't change
		within the period, the callback is triggered immediately on change.
		
		If it is set to false, the callback is continuously triggered with the period,
		independent of the value.
		
		It is furthermore possible to constrain the callback with thresholds.
		
		The `option`-parameter together with min/max sets a threshold for the :cb:`Current` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Threshold is turned off"
		 "'o'",    "Threshold is triggered when the value is *outside* the min and max values"
		 "'i'",    "Threshold is triggered when the value is *inside* or equal to the min and max values"
		 "'<'",    "Threshold is triggered when the value is smaller than the min value (max is ignored)"
		 "'>'",    "Threshold is triggered when the value is greater than the min value (max is ignored)"
		
		If the option is set to 'x' (threshold turned off) the callback is triggered with the fixed period.
		*/
		this.ipcon.sendRequest(this, BrickletVoltageCurrentV2.FUNCTION_SET_CURRENT_CALLBACK_CONFIGURATION, [period, valueHasToChange, option, min, max], 'I ? c i i', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getCurrentCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the callback configuration as set by :func:`Set Current Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletVoltageCurrentV2.FUNCTION_GET_CURRENT_CALLBACK_CONFIGURATION, [], '', 22, 'I ? c i i', returnCallback, errorCallback, false, true);
	};
	this.getVoltage = function(returnCallback, errorCallback) {
		/*
		Returns the voltage.
		
		
		If you want to get the value periodically, it is recommended to use the
		:cb:`Voltage` callback. You can set the callback configuration
		with :func:`Set Voltage Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletVoltageCurrentV2.FUNCTION_GET_VOLTAGE, [], '', 12, 'i', returnCallback, errorCallback, false, true);
	};
	this.setVoltageCallbackConfiguration = function(period, valueHasToChange, option, min, max, returnCallback, errorCallback) {
		/*
		The period is the period with which the :cb:`Voltage` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		If the `value has to change`-parameter is set to true, the callback is only
		triggered after the value has changed. If the value didn't change
		within the period, the callback is triggered immediately on change.
		
		If it is set to false, the callback is continuously triggered with the period,
		independent of the value.
		
		It is furthermore possible to constrain the callback with thresholds.
		
		The `option`-parameter together with min/max sets a threshold for the :cb:`Voltage` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Threshold is turned off"
		 "'o'",    "Threshold is triggered when the value is *outside* the min and max values"
		 "'i'",    "Threshold is triggered when the value is *inside* or equal to the min and max values"
		 "'<'",    "Threshold is triggered when the value is smaller than the min value (max is ignored)"
		 "'>'",    "Threshold is triggered when the value is greater than the min value (max is ignored)"
		
		If the option is set to 'x' (threshold turned off) the callback is triggered with the fixed period.
		*/
		this.ipcon.sendRequest(this, BrickletVoltageCurrentV2.FUNCTION_SET_VOLTAGE_CALLBACK_CONFIGURATION, [period, valueHasToChange, option, min, max], 'I ? c i i', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getVoltageCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the callback configuration as set by :func:`Set Voltage Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletVoltageCurrentV2.FUNCTION_GET_VOLTAGE_CALLBACK_CONFIGURATION, [], '', 22, 'I ? c i i', returnCallback, errorCallback, false, true);
	};
	this.getPower = function(returnCallback, errorCallback) {
		/*
		Returns the power.
		
		
		If you want to get the value periodically, it is recommended to use the
		:cb:`Power` callback. You can set the callback configuration
		with :func:`Set Power Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletVoltageCurrentV2.FUNCTION_GET_POWER, [], '', 12, 'i', returnCallback, errorCallback, false, true);
	};
	this.setPowerCallbackConfiguration = function(period, valueHasToChange, option, min, max, returnCallback, errorCallback) {
		/*
		The period is the period with which the :cb:`Power` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		If the `value has to change`-parameter is set to true, the callback is only
		triggered after the value has changed. If the value didn't change
		within the period, the callback is triggered immediately on change.
		
		If it is set to false, the callback is continuously triggered with the period,
		independent of the value.
		
		It is furthermore possible to constrain the callback with thresholds.
		
		The `option`-parameter together with min/max sets a threshold for the :cb:`Power` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Threshold is turned off"
		 "'o'",    "Threshold is triggered when the value is *outside* the min and max values"
		 "'i'",    "Threshold is triggered when the value is *inside* or equal to the min and max values"
		 "'<'",    "Threshold is triggered when the value is smaller than the min value (max is ignored)"
		 "'>'",    "Threshold is triggered when the value is greater than the min value (max is ignored)"
		
		If the option is set to 'x' (threshold turned off) the callback is triggered with the fixed period.
		*/
		this.ipcon.sendRequest(this, BrickletVoltageCurrentV2.FUNCTION_SET_POWER_CALLBACK_CONFIGURATION, [period, valueHasToChange, option, min, max], 'I ? c i i', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getPowerCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the callback configuration as set by :func:`Set Power Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletVoltageCurrentV2.FUNCTION_GET_POWER_CALLBACK_CONFIGURATION, [], '', 22, 'I ? c i i', returnCallback, errorCallback, false, true);
	};
	this.setConfiguration = function(averaging, voltageConversionTime, currentConversionTime, returnCallback, errorCallback) {
		/*
		Sets the configuration of the Voltage/Current Bricklet 2.0. It is
		possible to configure number of averages as well as
		voltage and current conversion time.
		*/
		this.ipcon.sendRequest(this, BrickletVoltageCurrentV2.FUNCTION_SET_CONFIGURATION, [averaging, voltageConversionTime, currentConversionTime], 'B B B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletVoltageCurrentV2.FUNCTION_GET_CONFIGURATION, [], '', 11, 'B B B', returnCallback, errorCallback, false, true);
	};
	this.setCalibration = function(voltageMultiplier, voltageDivisor, currentMultiplier, currentDivisor, returnCallback, errorCallback) {
		/*
		Since the ADC and the shunt resistor used for the measurements
		are not perfect they need to be calibrated by a multiplier and
		a divisor if a very precise reading is needed.
		
		For example, if you are expecting a current of 1000mA and you
		are measuring 1023mA, you can calibrate the Voltage/Current Bricklet
		by setting the current multiplier to 1000 and the divisor to 1023.
		The same applies for the voltage.
		
		The calibration will be saved on the EEPROM of the Voltage/Current
		Bricklet and only needs to be done once.
		*/
		this.ipcon.sendRequest(this, BrickletVoltageCurrentV2.FUNCTION_SET_CALIBRATION, [voltageMultiplier, voltageDivisor, currentMultiplier, currentDivisor], 'H H H H', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getCalibration = function(returnCallback, errorCallback) {
		/*
		Returns the calibration as set by :func:`Set Calibration`.
		*/
		this.ipcon.sendRequest(this, BrickletVoltageCurrentV2.FUNCTION_GET_CALIBRATION, [], '', 16, 'H H H H', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPErrorCount = function(returnCallback, errorCallback) {
		/*
		Returns the error count for the communication between Brick and Bricklet.
		
		The errors are divided into
		
		* ACK checksum errors,
		* message checksum errors,
		* framing errors and
		* overflow errors.
		
		The errors counts are for errors that occur on the Bricklet side. All
		Bricks have a similar function that returns the errors on the Brick side.
		*/
		this.ipcon.sendRequest(this, BrickletVoltageCurrentV2.FUNCTION_GET_SPITFP_ERROR_COUNT, [], '', 24, 'I I I I', returnCallback, errorCallback, false, true);
	};
	this.setBootloaderMode = function(mode, returnCallback, errorCallback) {
		/*
		Sets the bootloader mode and returns the status after the requested
		mode change was instigated.
		
		You can change from bootloader mode to firmware mode and vice versa. A change
		from bootloader mode to firmware mode will only take place if the entry function,
		device identifier and CRC are present and correct.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletVoltageCurrentV2.FUNCTION_SET_BOOTLOADER_MODE, [mode], 'B', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getBootloaderMode = function(returnCallback, errorCallback) {
		/*
		Returns the current bootloader mode, see :func:`Set Bootloader Mode`.
		*/
		this.ipcon.sendRequest(this, BrickletVoltageCurrentV2.FUNCTION_GET_BOOTLOADER_MODE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setWriteFirmwarePointer = function(pointer, returnCallback, errorCallback) {
		/*
		Sets the firmware pointer for :func:`Write Firmware`. The pointer has
		to be increased by chunks of size 64. The data is written to flash
		every 4 chunks (which equals to one page of size 256).
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletVoltageCurrentV2.FUNCTION_SET_WRITE_FIRMWARE_POINTER, [pointer], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeFirmware = function(data, returnCallback, errorCallback) {
		/*
		Writes 64 Bytes of firmware at the position as written by
		:func:`Set Write Firmware Pointer` before. The firmware is written
		to flash every 4 chunks.
		
		You can only write firmware in bootloader mode.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletVoltageCurrentV2.FUNCTION_WRITE_FIRMWARE, [data], 'B64', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setStatusLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Sets the status LED configuration. By default the LED shows
		communication traffic between Brick and Bricklet, it flickers once
		for every 10 received data packets.
		
		You can also turn the LED permanently on/off or show a heartbeat.
		
		If the Bricklet is in bootloader mode, the LED is will show heartbeat by default.
		*/
		this.ipcon.sendRequest(this, BrickletVoltageCurrentV2.FUNCTION_SET_STATUS_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getStatusLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Status LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletVoltageCurrentV2.FUNCTION_GET_STATUS_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getChipTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature as measured inside the microcontroller. The
		value returned is not the ambient temperature!
		
		The temperature is only proportional to the real temperature and it has bad
		accuracy. Practically it is only useful as an indicator for
		temperature changes.
		*/
		this.ipcon.sendRequest(this, BrickletVoltageCurrentV2.FUNCTION_GET_CHIP_TEMPERATURE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.reset = function(returnCallback, errorCallback) {
		/*
		Calling this function will reset the Bricklet. All configurations
		will be lost.
		
		After a reset you have to create new device objects,
		calling functions on the existing ones will result in
		undefined behavior!
		*/
		this.ipcon.sendRequest(this, BrickletVoltageCurrentV2.FUNCTION_RESET, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeUID = function(uid, returnCallback, errorCallback) {
		/*
		Writes a new UID into flash. If you want to set a new UID
		you have to decode the Base58 encoded UID string into an
		integer first.
		
		We recommend that you use Brick Viewer to change the UID.
		*/
		this.ipcon.sendRequest(this, BrickletVoltageCurrentV2.FUNCTION_WRITE_UID, [uid], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.readUID = function(returnCallback, errorCallback) {
		/*
		Returns the current UID as an integer. Encode as
		Base58 to get the usual string version.
		*/
		this.ipcon.sendRequest(this, BrickletVoltageCurrentV2.FUNCTION_READ_UID, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletVoltageCurrentV2.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletVoltageCurrentV2;

},{"./Device":279,"./IPConnection":280}],277:[function(require,module,exports){
/* ***********************************************************
 * This file was automatically generated on 2021-03-02.      *
 *                                                           *
 * JavaScript Bindings Version 2.1.33                        *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

var Device = require('./Device');
var IPConnection = require('./IPConnection');

BrickletXMC1400Breakout.DEVICE_IDENTIFIER = 279;
BrickletXMC1400Breakout.DEVICE_DISPLAY_NAME = 'XMC1400 Breakout Bricklet';
BrickletXMC1400Breakout.CALLBACK_ADC_VALUES = 9;
BrickletXMC1400Breakout.CALLBACK_COUNT = 13;
BrickletXMC1400Breakout.FUNCTION_SET_GPIO_CONFIG = 1;
BrickletXMC1400Breakout.FUNCTION_GET_GPIO_INPUT = 2;
BrickletXMC1400Breakout.FUNCTION_SET_ADC_CHANNEL_CONFIG = 3;
BrickletXMC1400Breakout.FUNCTION_GET_ADC_CHANNEL_CONFIG = 4;
BrickletXMC1400Breakout.FUNCTION_GET_ADC_CHANNEL_VALUE = 5;
BrickletXMC1400Breakout.FUNCTION_GET_ADC_VALUES = 6;
BrickletXMC1400Breakout.FUNCTION_SET_ADC_VALUES_CALLBACK_CONFIGURATION = 7;
BrickletXMC1400Breakout.FUNCTION_GET_ADC_VALUES_CALLBACK_CONFIGURATION = 8;
BrickletXMC1400Breakout.FUNCTION_GET_COUNT = 10;
BrickletXMC1400Breakout.FUNCTION_SET_COUNT_CALLBACK_CONFIGURATION = 11;
BrickletXMC1400Breakout.FUNCTION_GET_COUNT_CALLBACK_CONFIGURATION = 12;
BrickletXMC1400Breakout.FUNCTION_GET_SPITFP_ERROR_COUNT = 234;
BrickletXMC1400Breakout.FUNCTION_SET_BOOTLOADER_MODE = 235;
BrickletXMC1400Breakout.FUNCTION_GET_BOOTLOADER_MODE = 236;
BrickletXMC1400Breakout.FUNCTION_SET_WRITE_FIRMWARE_POINTER = 237;
BrickletXMC1400Breakout.FUNCTION_WRITE_FIRMWARE = 238;
BrickletXMC1400Breakout.FUNCTION_SET_STATUS_LED_CONFIG = 239;
BrickletXMC1400Breakout.FUNCTION_GET_STATUS_LED_CONFIG = 240;
BrickletXMC1400Breakout.FUNCTION_GET_CHIP_TEMPERATURE = 242;
BrickletXMC1400Breakout.FUNCTION_RESET = 243;
BrickletXMC1400Breakout.FUNCTION_WRITE_UID = 248;
BrickletXMC1400Breakout.FUNCTION_READ_UID = 249;
BrickletXMC1400Breakout.FUNCTION_GET_IDENTITY = 255;
BrickletXMC1400Breakout.THRESHOLD_OPTION_OFF = 'x';
BrickletXMC1400Breakout.THRESHOLD_OPTION_OUTSIDE = 'o';
BrickletXMC1400Breakout.THRESHOLD_OPTION_INSIDE = 'i';
BrickletXMC1400Breakout.THRESHOLD_OPTION_SMALLER = '<';
BrickletXMC1400Breakout.THRESHOLD_OPTION_GREATER = '>';
BrickletXMC1400Breakout.GPIO_MODE_INPUT_TRISTATE = 0;
BrickletXMC1400Breakout.GPIO_MODE_INPUT_PULL_DOWN = 1;
BrickletXMC1400Breakout.GPIO_MODE_INPUT_PULL_UP = 2;
BrickletXMC1400Breakout.GPIO_MODE_INPUT_SAMPLING = 3;
BrickletXMC1400Breakout.GPIO_MODE_INPUT_INVERTED_TRISTATE = 4;
BrickletXMC1400Breakout.GPIO_MODE_INPUT_INVERTED_PULL_DOWN = 5;
BrickletXMC1400Breakout.GPIO_MODE_INPUT_INVERTED_PULL_UP = 6;
BrickletXMC1400Breakout.GPIO_MODE_INPUT_INVERTED_SAMPLING = 7;
BrickletXMC1400Breakout.GPIO_MODE_OUTPUT_PUSH_PULL = 8;
BrickletXMC1400Breakout.GPIO_MODE_OUTPUT_OPEN_DRAIN = 9;
BrickletXMC1400Breakout.GPIO_INPUT_HYSTERESIS_STANDARD = 0;
BrickletXMC1400Breakout.GPIO_INPUT_HYSTERESIS_LARGE = 4;
BrickletXMC1400Breakout.BOOTLOADER_MODE_BOOTLOADER = 0;
BrickletXMC1400Breakout.BOOTLOADER_MODE_FIRMWARE = 1;
BrickletXMC1400Breakout.BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT = 2;
BrickletXMC1400Breakout.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT = 3;
BrickletXMC1400Breakout.BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT = 4;
BrickletXMC1400Breakout.BOOTLOADER_STATUS_OK = 0;
BrickletXMC1400Breakout.BOOTLOADER_STATUS_INVALID_MODE = 1;
BrickletXMC1400Breakout.BOOTLOADER_STATUS_NO_CHANGE = 2;
BrickletXMC1400Breakout.BOOTLOADER_STATUS_ENTRY_FUNCTION_NOT_PRESENT = 3;
BrickletXMC1400Breakout.BOOTLOADER_STATUS_DEVICE_IDENTIFIER_INCORRECT = 4;
BrickletXMC1400Breakout.BOOTLOADER_STATUS_CRC_MISMATCH = 5;
BrickletXMC1400Breakout.STATUS_LED_CONFIG_OFF = 0;
BrickletXMC1400Breakout.STATUS_LED_CONFIG_ON = 1;
BrickletXMC1400Breakout.STATUS_LED_CONFIG_SHOW_HEARTBEAT = 2;
BrickletXMC1400Breakout.STATUS_LED_CONFIG_SHOW_STATUS = 3;

function BrickletXMC1400Breakout(uid, ipcon) {
	//Breakout for Infineon XMC1400 microcontroller

	/*
	Creates an object with the unique device ID *uid* and adds it to
	the IP Connection *ipcon*.
	*/
	Device.call(this, this, uid, ipcon, BrickletXMC1400Breakout.DEVICE_IDENTIFIER, BrickletXMC1400Breakout.DEVICE_DISPLAY_NAME);
	BrickletXMC1400Breakout.prototype = Object.create(Device);
	this.APIVersion = [2, 0, 0];
	this.responseExpected[BrickletXMC1400Breakout.FUNCTION_SET_GPIO_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletXMC1400Breakout.FUNCTION_GET_GPIO_INPUT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletXMC1400Breakout.FUNCTION_SET_ADC_CHANNEL_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletXMC1400Breakout.FUNCTION_GET_ADC_CHANNEL_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletXMC1400Breakout.FUNCTION_GET_ADC_CHANNEL_VALUE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletXMC1400Breakout.FUNCTION_GET_ADC_VALUES] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletXMC1400Breakout.FUNCTION_SET_ADC_VALUES_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletXMC1400Breakout.FUNCTION_GET_ADC_VALUES_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletXMC1400Breakout.FUNCTION_GET_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletXMC1400Breakout.FUNCTION_SET_COUNT_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_TRUE;
	this.responseExpected[BrickletXMC1400Breakout.FUNCTION_GET_COUNT_CALLBACK_CONFIGURATION] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletXMC1400Breakout.FUNCTION_GET_SPITFP_ERROR_COUNT] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletXMC1400Breakout.FUNCTION_SET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletXMC1400Breakout.FUNCTION_GET_BOOTLOADER_MODE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletXMC1400Breakout.FUNCTION_SET_WRITE_FIRMWARE_POINTER] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletXMC1400Breakout.FUNCTION_WRITE_FIRMWARE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletXMC1400Breakout.FUNCTION_SET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletXMC1400Breakout.FUNCTION_GET_STATUS_LED_CONFIG] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletXMC1400Breakout.FUNCTION_GET_CHIP_TEMPERATURE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletXMC1400Breakout.FUNCTION_RESET] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletXMC1400Breakout.FUNCTION_WRITE_UID] = Device.RESPONSE_EXPECTED_FALSE;
	this.responseExpected[BrickletXMC1400Breakout.FUNCTION_READ_UID] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.responseExpected[BrickletXMC1400Breakout.FUNCTION_GET_IDENTITY] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
	this.callbackFormats[BrickletXMC1400Breakout.CALLBACK_ADC_VALUES] = [24, 'H8'];
	this.callbackFormats[BrickletXMC1400Breakout.CALLBACK_COUNT] = [12, 'I'];



	this.setGPIOConfig = function(port, pin, mode, inputHysteresis, outputLevel, returnCallback, errorCallback) {
		/*
		Example for a setter function. The values are the values that can be given to
		the XMC_GPIO_Init function. See communication.c in the firmware.
		*/
		this.ipcon.sendRequest(this, BrickletXMC1400Breakout.FUNCTION_SET_GPIO_CONFIG, [port, pin, mode, inputHysteresis, outputLevel], 'B B B B ?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getGPIOInput = function(port, pin, returnCallback, errorCallback) {
		/*
		Example for a getter function. Returns the result of a
		XMC_GPIO_GetInput call for the given port/pin.
		*/
		this.ipcon.sendRequest(this, BrickletXMC1400Breakout.FUNCTION_GET_GPIO_INPUT, [port, pin], 'B B', 9, '?', returnCallback, errorCallback, false, true);
	};
	this.setADCChannelConfig = function(channel, enable, returnCallback, errorCallback) {
		/*
		Enables a ADC channel for the ADC driver example (adc.c/adc.h).
		
		There are 8 ADC channels and they correspond to the following pins:
		
		* Channel 0: P2_6
		* Channel 1: P2_8
		* Channel 2: P2_9
		* Channel 3: P2_10
		* Channel 4: P2_11
		* Channel 5: P2_0
		* Channel 6: P2_1
		* Channel 7: P2_2
		*/
		this.ipcon.sendRequest(this, BrickletXMC1400Breakout.FUNCTION_SET_ADC_CHANNEL_CONFIG, [channel, enable], 'B ?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getADCChannelConfig = function(channel, returnCallback, errorCallback) {
		/*
		Returns the config for the given channel as set by :func:`Set ADC Channel Config`.
		*/
		this.ipcon.sendRequest(this, BrickletXMC1400Breakout.FUNCTION_GET_ADC_CHANNEL_CONFIG, [channel], 'B', 9, '?', returnCallback, errorCallback, false, true);
	};
	this.getADCChannelValue = function(channel, returnCallback, errorCallback) {
		/*
		Returns the 12-bit value of the given ADC channel of the ADC driver example.
		*/
		this.ipcon.sendRequest(this, BrickletXMC1400Breakout.FUNCTION_GET_ADC_CHANNEL_VALUE, [channel], 'B', 10, 'H', returnCallback, errorCallback, false, true);
	};
	this.getADCValues = function(returnCallback, errorCallback) {
		/*
		Returns the values for all 8 ADC channels of the adc driver example.
		
		This example function also has a corresponding callback.
		
		See :func:`Set ADC Values Callback Configuration` and :cb:`ADC Values` callback.
		*/
		this.ipcon.sendRequest(this, BrickletXMC1400Breakout.FUNCTION_GET_ADC_VALUES, [], '', 24, 'H8', returnCallback, errorCallback, false, true);
	};
	this.setADCValuesCallbackConfiguration = function(period, valueHasToChange, returnCallback, errorCallback) {
		/*
		The period is the period with which the :cb:`ADC Values`
		callback is triggered periodically. A value of 0 turns the callback off.
		
		If the `value has to change`-parameter is set to true, the callback is only
		triggered after the value has changed. If the value didn't change within the
		period, the callback is triggered immediately on change.
		
		If it is set to false, the callback is continuously triggered with the period,
		independent of the value.
		*/
		this.ipcon.sendRequest(this, BrickletXMC1400Breakout.FUNCTION_SET_ADC_VALUES_CALLBACK_CONFIGURATION, [period, valueHasToChange], 'I ?', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getADCValuesCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the callback configuration as set by
		:func:`Set ADC Values Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletXMC1400Breakout.FUNCTION_GET_ADC_VALUES_CALLBACK_CONFIGURATION, [], '', 13, 'I ?', returnCallback, errorCallback, false, true);
	};
	this.getCount = function(returnCallback, errorCallback) {
		/*
		Returns the value of the example count (see example.c).
		
		This example function uses the "add_callback_value_function"-helper in the
		generator. The getter as well as the callback and callback configuration
		functions are auto-generated for the API as well as the firmware.
		
		
		If you want to get the value periodically, it is recommended to use the
		:cb:`Count` callback. You can set the callback configuration
		with :func:`Set Count Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletXMC1400Breakout.FUNCTION_GET_COUNT, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.setCountCallbackConfiguration = function(period, valueHasToChange, option, min, max, returnCallback, errorCallback) {
		/*
		The period is the period with which the :cb:`Count` callback is triggered
		periodically. A value of 0 turns the callback off.
		
		If the `value has to change`-parameter is set to true, the callback is only
		triggered after the value has changed. If the value didn't change
		within the period, the callback is triggered immediately on change.
		
		If it is set to false, the callback is continuously triggered with the period,
		independent of the value.
		
		It is furthermore possible to constrain the callback with thresholds.
		
		The `option`-parameter together with min/max sets a threshold for the :cb:`Count` callback.
		
		The following options are possible:
		
		.. csv-table::
		 :header: "Option", "Description"
		 :widths: 10, 100
		
		 "'x'",    "Threshold is turned off"
		 "'o'",    "Threshold is triggered when the value is *outside* the min and max values"
		 "'i'",    "Threshold is triggered when the value is *inside* or equal to the min and max values"
		 "'<'",    "Threshold is triggered when the value is smaller than the min value (max is ignored)"
		 "'>'",    "Threshold is triggered when the value is greater than the min value (max is ignored)"
		
		If the option is set to 'x' (threshold turned off) the callback is triggered with the fixed period.
		*/
		this.ipcon.sendRequest(this, BrickletXMC1400Breakout.FUNCTION_SET_COUNT_CALLBACK_CONFIGURATION, [period, valueHasToChange, option, min, max], 'I ? c I I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getCountCallbackConfiguration = function(returnCallback, errorCallback) {
		/*
		Returns the callback configuration as set by :func:`Set Count Callback Configuration`.
		*/
		this.ipcon.sendRequest(this, BrickletXMC1400Breakout.FUNCTION_GET_COUNT_CALLBACK_CONFIGURATION, [], '', 22, 'I ? c I I', returnCallback, errorCallback, false, true);
	};
	this.getSPITFPErrorCount = function(returnCallback, errorCallback) {
		/*
		Returns the error count for the communication between Brick and Bricklet.
		
		The errors are divided into
		
		* ACK checksum errors,
		* message checksum errors,
		* framing errors and
		* overflow errors.
		
		The errors counts are for errors that occur on the Bricklet side. All
		Bricks have a similar function that returns the errors on the Brick side.
		*/
		this.ipcon.sendRequest(this, BrickletXMC1400Breakout.FUNCTION_GET_SPITFP_ERROR_COUNT, [], '', 24, 'I I I I', returnCallback, errorCallback, false, true);
	};
	this.setBootloaderMode = function(mode, returnCallback, errorCallback) {
		/*
		Sets the bootloader mode and returns the status after the requested
		mode change was instigated.
		
		You can change from bootloader mode to firmware mode and vice versa. A change
		from bootloader mode to firmware mode will only take place if the entry function,
		device identifier and CRC are present and correct.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletXMC1400Breakout.FUNCTION_SET_BOOTLOADER_MODE, [mode], 'B', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getBootloaderMode = function(returnCallback, errorCallback) {
		/*
		Returns the current bootloader mode, see :func:`Set Bootloader Mode`.
		*/
		this.ipcon.sendRequest(this, BrickletXMC1400Breakout.FUNCTION_GET_BOOTLOADER_MODE, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setWriteFirmwarePointer = function(pointer, returnCallback, errorCallback) {
		/*
		Sets the firmware pointer for :func:`Write Firmware`. The pointer has
		to be increased by chunks of size 64. The data is written to flash
		every 4 chunks (which equals to one page of size 256).
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletXMC1400Breakout.FUNCTION_SET_WRITE_FIRMWARE_POINTER, [pointer], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeFirmware = function(data, returnCallback, errorCallback) {
		/*
		Writes 64 Bytes of firmware at the position as written by
		:func:`Set Write Firmware Pointer` before. The firmware is written
		to flash every 4 chunks.
		
		You can only write firmware in bootloader mode.
		
		This function is used by Brick Viewer during flashing. It should not be
		necessary to call it in a normal user program.
		*/
		this.ipcon.sendRequest(this, BrickletXMC1400Breakout.FUNCTION_WRITE_FIRMWARE, [data], 'B64', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.setStatusLEDConfig = function(config, returnCallback, errorCallback) {
		/*
		Sets the status LED configuration. By default the LED shows
		communication traffic between Brick and Bricklet, it flickers once
		for every 10 received data packets.
		
		You can also turn the LED permanently on/off or show a heartbeat.
		
		If the Bricklet is in bootloader mode, the LED is will show heartbeat by default.
		*/
		this.ipcon.sendRequest(this, BrickletXMC1400Breakout.FUNCTION_SET_STATUS_LED_CONFIG, [config], 'B', 0, '', returnCallback, errorCallback, false, true);
	};
	this.getStatusLEDConfig = function(returnCallback, errorCallback) {
		/*
		Returns the configuration as set by :func:`Set Status LED Config`
		*/
		this.ipcon.sendRequest(this, BrickletXMC1400Breakout.FUNCTION_GET_STATUS_LED_CONFIG, [], '', 9, 'B', returnCallback, errorCallback, false, true);
	};
	this.getChipTemperature = function(returnCallback, errorCallback) {
		/*
		Returns the temperature as measured inside the microcontroller. The
		value returned is not the ambient temperature!
		
		The temperature is only proportional to the real temperature and it has bad
		accuracy. Practically it is only useful as an indicator for
		temperature changes.
		*/
		this.ipcon.sendRequest(this, BrickletXMC1400Breakout.FUNCTION_GET_CHIP_TEMPERATURE, [], '', 10, 'h', returnCallback, errorCallback, false, true);
	};
	this.reset = function(returnCallback, errorCallback) {
		/*
		Calling this function will reset the Bricklet. All configurations
		will be lost.
		
		After a reset you have to create new device objects,
		calling functions on the existing ones will result in
		undefined behavior!
		*/
		this.ipcon.sendRequest(this, BrickletXMC1400Breakout.FUNCTION_RESET, [], '', 0, '', returnCallback, errorCallback, false, true);
	};
	this.writeUID = function(uid, returnCallback, errorCallback) {
		/*
		Writes a new UID into flash. If you want to set a new UID
		you have to decode the Base58 encoded UID string into an
		integer first.
		
		We recommend that you use Brick Viewer to change the UID.
		*/
		this.ipcon.sendRequest(this, BrickletXMC1400Breakout.FUNCTION_WRITE_UID, [uid], 'I', 0, '', returnCallback, errorCallback, false, true);
	};
	this.readUID = function(returnCallback, errorCallback) {
		/*
		Returns the current UID as an integer. Encode as
		Base58 to get the usual string version.
		*/
		this.ipcon.sendRequest(this, BrickletXMC1400Breakout.FUNCTION_READ_UID, [], '', 12, 'I', returnCallback, errorCallback, false, true);
	};
	this.getIdentity = function(returnCallback, errorCallback) {
		/*
		Returns the UID, the UID where the Bricklet is connected to,
		the position, the hardware and firmware version as well as the
		device identifier.
		
		The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
		A Bricklet connected to an :ref:`Isolator Bricklet <isolator_bricklet>` is always at
		position 'z'.
		
		The device identifier numbers can be found :ref:`here <device_identifier>`.
		|device_identifier_constant|
		*/
		this.ipcon.sendRequest(this, BrickletXMC1400Breakout.FUNCTION_GET_IDENTITY, [], '', 33, 's8 s8 c B3 B3 H', returnCallback, errorCallback, false, false);
	};

	this.ipcon.addDevice(this);
}

module.exports = BrickletXMC1400Breakout;

},{"./Device":279,"./IPConnection":280}],278:[function(require,module,exports){
(function (global){
function Tinkerforge() {
	this.IPConnection = require('./IPConnection');
	this.BrickDC = require('./BrickDC');
	this.BrickHAT = require('./BrickHAT');
	this.BrickHATZero = require('./BrickHATZero');
	this.BrickIMU = require('./BrickIMU');
	this.BrickIMUV2 = require('./BrickIMUV2');
	this.BrickMaster = require('./BrickMaster');
	this.BrickRED = require('./BrickRED');
	this.BrickServo = require('./BrickServo');
	this.BrickSilentStepper = require('./BrickSilentStepper');
	this.BrickStepper = require('./BrickStepper');
	this.BrickletAccelerometer = require('./BrickletAccelerometer');
	this.BrickletAccelerometerV2 = require('./BrickletAccelerometerV2');
	this.BrickletAirQuality = require('./BrickletAirQuality');
	this.BrickletAmbientLight = require('./BrickletAmbientLight');
	this.BrickletAmbientLightV2 = require('./BrickletAmbientLightV2');
	this.BrickletAmbientLightV3 = require('./BrickletAmbientLightV3');
	this.BrickletAnalogIn = require('./BrickletAnalogIn');
	this.BrickletAnalogInV2 = require('./BrickletAnalogInV2');
	this.BrickletAnalogInV3 = require('./BrickletAnalogInV3');
	this.BrickletAnalogOut = require('./BrickletAnalogOut');
	this.BrickletAnalogOutV2 = require('./BrickletAnalogOutV2');
	this.BrickletAnalogOutV3 = require('./BrickletAnalogOutV3');
	this.BrickletBarometer = require('./BrickletBarometer');
	this.BrickletBarometerV2 = require('./BrickletBarometerV2');
	this.BrickletCAN = require('./BrickletCAN');
	this.BrickletCANV2 = require('./BrickletCANV2');
	this.BrickletCO2 = require('./BrickletCO2');
	this.BrickletCO2V2 = require('./BrickletCO2V2');
	this.BrickletColor = require('./BrickletColor');
	this.BrickletColorV2 = require('./BrickletColorV2');
	this.BrickletCompass = require('./BrickletCompass');
	this.BrickletCurrent12 = require('./BrickletCurrent12');
	this.BrickletCurrent25 = require('./BrickletCurrent25');
	this.BrickletDistanceIR = require('./BrickletDistanceIR');
	this.BrickletDistanceIRV2 = require('./BrickletDistanceIRV2');
	this.BrickletDistanceUS = require('./BrickletDistanceUS');
	this.BrickletDistanceUSV2 = require('./BrickletDistanceUSV2');
	this.BrickletDMX = require('./BrickletDMX');
	this.BrickletDualButton = require('./BrickletDualButton');
	this.BrickletDualButtonV2 = require('./BrickletDualButtonV2');
	this.BrickletDualRelay = require('./BrickletDualRelay');
	this.BrickletDustDetector = require('./BrickletDustDetector');
	this.BrickletEPaper296x128 = require('./BrickletEPaper296x128');
	this.BrickletEnergyMonitor = require('./BrickletEnergyMonitor');
	this.BrickletGPS = require('./BrickletGPS');
	this.BrickletGPSV2 = require('./BrickletGPSV2');
	this.BrickletHallEffect = require('./BrickletHallEffect');
	this.BrickletHallEffectV2 = require('./BrickletHallEffectV2');
	this.BrickletHumidity = require('./BrickletHumidity');
	this.BrickletHumidityV2 = require('./BrickletHumidityV2');
	this.BrickletIMUV3 = require('./BrickletIMUV3');
	this.BrickletIndustrialAnalogOut = require('./BrickletIndustrialAnalogOut');
	this.BrickletIndustrialAnalogOutV2 = require('./BrickletIndustrialAnalogOutV2');
	this.BrickletIndustrialCounter = require('./BrickletIndustrialCounter');
	this.BrickletIndustrialDigitalIn4 = require('./BrickletIndustrialDigitalIn4');
	this.BrickletIndustrialDigitalIn4V2 = require('./BrickletIndustrialDigitalIn4V2');
	this.BrickletIndustrialDigitalOut4 = require('./BrickletIndustrialDigitalOut4');
	this.BrickletIndustrialDigitalOut4V2 = require('./BrickletIndustrialDigitalOut4V2');
	this.BrickletIndustrialDual020mA = require('./BrickletIndustrialDual020mA');
	this.BrickletIndustrialDual020mAV2 = require('./BrickletIndustrialDual020mAV2');
	this.BrickletIndustrialDualACRelay = require('./BrickletIndustrialDualACRelay');
	this.BrickletIndustrialDualAnalogIn = require('./BrickletIndustrialDualAnalogIn');
	this.BrickletIndustrialDualAnalogInV2 = require('./BrickletIndustrialDualAnalogInV2');
	this.BrickletIndustrialDualRelay = require('./BrickletIndustrialDualRelay');
	this.BrickletIndustrialQuadRelay = require('./BrickletIndustrialQuadRelay');
	this.BrickletIndustrialQuadRelayV2 = require('./BrickletIndustrialQuadRelayV2');
	this.BrickletIO16 = require('./BrickletIO16');
	this.BrickletIO16V2 = require('./BrickletIO16V2');
	this.BrickletIO4 = require('./BrickletIO4');
	this.BrickletIO4V2 = require('./BrickletIO4V2');
	this.BrickletIsolator = require('./BrickletIsolator');
	this.BrickletJoystick = require('./BrickletJoystick');
	this.BrickletJoystickV2 = require('./BrickletJoystickV2');
	this.BrickletLaserRangeFinder = require('./BrickletLaserRangeFinder');
	this.BrickletLaserRangeFinderV2 = require('./BrickletLaserRangeFinderV2');
	this.BrickletLCD128x64 = require('./BrickletLCD128x64');
	this.BrickletLCD16x2 = require('./BrickletLCD16x2');
	this.BrickletLCD20x4 = require('./BrickletLCD20x4');
	this.BrickletLEDStrip = require('./BrickletLEDStrip');
	this.BrickletLEDStripV2 = require('./BrickletLEDStripV2');
	this.BrickletLine = require('./BrickletLine');
	this.BrickletLinearPoti = require('./BrickletLinearPoti');
	this.BrickletLinearPotiV2 = require('./BrickletLinearPotiV2');
	this.BrickletLoadCell = require('./BrickletLoadCell');
	this.BrickletLoadCellV2 = require('./BrickletLoadCellV2');
	this.BrickletMoisture = require('./BrickletMoisture');
	this.BrickletMotionDetector = require('./BrickletMotionDetector');
	this.BrickletMotionDetectorV2 = require('./BrickletMotionDetectorV2');
	this.BrickletMotorizedLinearPoti = require('./BrickletMotorizedLinearPoti');
	this.BrickletMultiTouch = require('./BrickletMultiTouch');
	this.BrickletMultiTouchV2 = require('./BrickletMultiTouchV2');
	this.BrickletNFC = require('./BrickletNFC');
	this.BrickletNFCRFID = require('./BrickletNFCRFID');
	this.BrickletOLED128x64 = require('./BrickletOLED128x64');
	this.BrickletOLED128x64V2 = require('./BrickletOLED128x64V2');
	this.BrickletOLED64x48 = require('./BrickletOLED64x48');
	this.BrickletOneWire = require('./BrickletOneWire');
	this.BrickletOutdoorWeather = require('./BrickletOutdoorWeather');
	this.BrickletParticulateMatter = require('./BrickletParticulateMatter');
	this.BrickletPerformanceDC = require('./BrickletPerformanceDC');
	this.BrickletPiezoBuzzer = require('./BrickletPiezoBuzzer');
	this.BrickletPiezoSpeaker = require('./BrickletPiezoSpeaker');
	this.BrickletPiezoSpeakerV2 = require('./BrickletPiezoSpeakerV2');
	this.BrickletPTC = require('./BrickletPTC');
	this.BrickletPTCV2 = require('./BrickletPTCV2');
	this.BrickletRealTimeClock = require('./BrickletRealTimeClock');
	this.BrickletRealTimeClockV2 = require('./BrickletRealTimeClockV2');
	this.BrickletRemoteSwitch = require('./BrickletRemoteSwitch');
	this.BrickletRemoteSwitchV2 = require('./BrickletRemoteSwitchV2');
	this.BrickletRGBLEDButton = require('./BrickletRGBLEDButton');
	this.BrickletRGBLED = require('./BrickletRGBLED');
	this.BrickletRGBLEDMatrix = require('./BrickletRGBLEDMatrix');
	this.BrickletRGBLEDV2 = require('./BrickletRGBLEDV2');
	this.BrickletRotaryEncoder = require('./BrickletRotaryEncoder');
	this.BrickletRotaryEncoderV2 = require('./BrickletRotaryEncoderV2');
	this.BrickletRotaryPoti = require('./BrickletRotaryPoti');
	this.BrickletRotaryPotiV2 = require('./BrickletRotaryPotiV2');
	this.BrickletRS232 = require('./BrickletRS232');
	this.BrickletRS232V2 = require('./BrickletRS232V2');
	this.BrickletRS485 = require('./BrickletRS485');
	this.BrickletSegmentDisplay4x7 = require('./BrickletSegmentDisplay4x7');
	this.BrickletSegmentDisplay4x7V2 = require('./BrickletSegmentDisplay4x7V2');
	this.BrickletServoV2 = require('./BrickletServoV2');
	this.BrickletSolidStateRelay = require('./BrickletSolidStateRelay');
	this.BrickletSolidStateRelayV2 = require('./BrickletSolidStateRelayV2');
	this.BrickletSoundIntensity = require('./BrickletSoundIntensity');
	this.BrickletSoundPressureLevel = require('./BrickletSoundPressureLevel');
	this.BrickletTemperature = require('./BrickletTemperature');
	this.BrickletTemperatureIR = require('./BrickletTemperatureIR');
	this.BrickletTemperatureIRV2 = require('./BrickletTemperatureIRV2');
	this.BrickletTemperatureV2 = require('./BrickletTemperatureV2');
	this.BrickletThermalImaging = require('./BrickletThermalImaging');
	this.BrickletThermocouple = require('./BrickletThermocouple');
	this.BrickletThermocoupleV2 = require('./BrickletThermocoupleV2');
	this.BrickletTilt = require('./BrickletTilt');
	this.BrickletUVLight = require('./BrickletUVLight');
	this.BrickletUVLightV2 = require('./BrickletUVLightV2');
	this.BrickletVoltage = require('./BrickletVoltage');
	this.BrickletVoltageCurrent = require('./BrickletVoltageCurrent');
	this.BrickletVoltageCurrentV2 = require('./BrickletVoltageCurrentV2');
	this.BrickletXMC1400Breakout = require('./BrickletXMC1400Breakout');
}

global.Tinkerforge = new Tinkerforge();
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{"./BrickDC":137,"./BrickHAT":138,"./BrickHATZero":139,"./BrickIMU":140,"./BrickIMUV2":141,"./BrickMaster":142,"./BrickRED":143,"./BrickServo":144,"./BrickSilentStepper":145,"./BrickStepper":146,"./BrickletAccelerometer":147,"./BrickletAccelerometerV2":148,"./BrickletAirQuality":149,"./BrickletAmbientLight":150,"./BrickletAmbientLightV2":151,"./BrickletAmbientLightV3":152,"./BrickletAnalogIn":153,"./BrickletAnalogInV2":154,"./BrickletAnalogInV3":155,"./BrickletAnalogOut":156,"./BrickletAnalogOutV2":157,"./BrickletAnalogOutV3":158,"./BrickletBarometer":159,"./BrickletBarometerV2":160,"./BrickletCAN":161,"./BrickletCANV2":162,"./BrickletCO2":163,"./BrickletCO2V2":164,"./BrickletColor":165,"./BrickletColorV2":166,"./BrickletCompass":167,"./BrickletCurrent12":168,"./BrickletCurrent25":169,"./BrickletDMX":170,"./BrickletDistanceIR":171,"./BrickletDistanceIRV2":172,"./BrickletDistanceUS":173,"./BrickletDistanceUSV2":174,"./BrickletDualButton":175,"./BrickletDualButtonV2":176,"./BrickletDualRelay":177,"./BrickletDustDetector":178,"./BrickletEPaper296x128":179,"./BrickletEnergyMonitor":180,"./BrickletGPS":181,"./BrickletGPSV2":182,"./BrickletHallEffect":183,"./BrickletHallEffectV2":184,"./BrickletHumidity":185,"./BrickletHumidityV2":186,"./BrickletIMUV3":187,"./BrickletIO16":188,"./BrickletIO16V2":189,"./BrickletIO4":190,"./BrickletIO4V2":191,"./BrickletIndustrialAnalogOut":192,"./BrickletIndustrialAnalogOutV2":193,"./BrickletIndustrialCounter":194,"./BrickletIndustrialDigitalIn4":195,"./BrickletIndustrialDigitalIn4V2":196,"./BrickletIndustrialDigitalOut4":197,"./BrickletIndustrialDigitalOut4V2":198,"./BrickletIndustrialDual020mA":199,"./BrickletIndustrialDual020mAV2":200,"./BrickletIndustrialDualACRelay":201,"./BrickletIndustrialDualAnalogIn":202,"./BrickletIndustrialDualAnalogInV2":203,"./BrickletIndustrialDualRelay":204,"./BrickletIndustrialQuadRelay":205,"./BrickletIndustrialQuadRelayV2":206,"./BrickletIsolator":207,"./BrickletJoystick":208,"./BrickletJoystickV2":209,"./BrickletLCD128x64":210,"./BrickletLCD16x2":211,"./BrickletLCD20x4":212,"./BrickletLEDStrip":213,"./BrickletLEDStripV2":214,"./BrickletLaserRangeFinder":215,"./BrickletLaserRangeFinderV2":216,"./BrickletLine":217,"./BrickletLinearPoti":218,"./BrickletLinearPotiV2":219,"./BrickletLoadCell":220,"./BrickletLoadCellV2":221,"./BrickletMoisture":222,"./BrickletMotionDetector":223,"./BrickletMotionDetectorV2":224,"./BrickletMotorizedLinearPoti":225,"./BrickletMultiTouch":226,"./BrickletMultiTouchV2":227,"./BrickletNFC":228,"./BrickletNFCRFID":229,"./BrickletOLED128x64":230,"./BrickletOLED128x64V2":231,"./BrickletOLED64x48":232,"./BrickletOneWire":233,"./BrickletOutdoorWeather":234,"./BrickletPTC":235,"./BrickletPTCV2":236,"./BrickletParticulateMatter":237,"./BrickletPerformanceDC":238,"./BrickletPiezoBuzzer":239,"./BrickletPiezoSpeaker":240,"./BrickletPiezoSpeakerV2":241,"./BrickletRGBLED":242,"./BrickletRGBLEDButton":243,"./BrickletRGBLEDMatrix":244,"./BrickletRGBLEDV2":245,"./BrickletRS232":246,"./BrickletRS232V2":247,"./BrickletRS485":248,"./BrickletRealTimeClock":249,"./BrickletRealTimeClockV2":250,"./BrickletRemoteSwitch":251,"./BrickletRemoteSwitchV2":252,"./BrickletRotaryEncoder":253,"./BrickletRotaryEncoderV2":254,"./BrickletRotaryPoti":255,"./BrickletRotaryPotiV2":256,"./BrickletSegmentDisplay4x7":257,"./BrickletSegmentDisplay4x7V2":258,"./BrickletServoV2":259,"./BrickletSolidStateRelay":260,"./BrickletSolidStateRelayV2":261,"./BrickletSoundIntensity":262,"./BrickletSoundPressureLevel":263,"./BrickletTemperature":264,"./BrickletTemperatureIR":265,"./BrickletTemperatureIRV2":266,"./BrickletTemperatureV2":267,"./BrickletThermalImaging":268,"./BrickletThermocouple":269,"./BrickletThermocoupleV2":270,"./BrickletTilt":271,"./BrickletUVLight":272,"./BrickletUVLightV2":273,"./BrickletVoltage":274,"./BrickletVoltageCurrent":275,"./BrickletVoltageCurrentV2":276,"./BrickletXMC1400Breakout":277,"./IPConnection":280}],279:[function(require,module,exports){
/*
Copyright (C) 2014 Ishraq Ibne Ashraf <ishraq@tinkerforge.com>
Copyright (C) 2020 Matthias Bolte <matthias@tinkerforge.com>

Redistribution and use in source and binary forms of this file,
with or without modification, are permitted. See the Creative
Commons Zero (CC0 1.0) License for more details.
*/

Device.RESPONSE_EXPECTED_ALWAYS_TRUE = 1; // getter
Device.RESPONSE_EXPECTED_TRUE = 2; // setter
Device.RESPONSE_EXPECTED_FALSE = 3; // setter, default

Device.ERROR_INVALID_FUNCTION_ID = 21; // keep in sync with IPConnection.ERROR_INVALID_FUNCTION_ID
Device.ERROR_WRONG_DEVICE_TYPE = 81; // keep in sync with IPConnection.ERROR_WRONG_DEVICE_TYPE
Device.ERROR_DEVICE_REPLACED = 82; // keep in sync with IPConnection.ERROR_DEVICE_REPLACED

Device.DEVICE_IDENTIFIER_CHECK_PENDING = 0;
Device.DEVICE_IDENTIFIER_CHECK_MATCH = 1;
Device.DEVICE_IDENTIFIER_CHECK_MISMATCH = 2;

function base58Decode(str) {
    var alphabet = "123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ";
    var base = alphabet.length;
    var char, char_index, index, num, i, len, ref;

    num = 0;
    ref = str.split(/(?:)/).reverse();

    for (index = i = 0, len = ref.length; i < len; index = ++i) {
        char = ref[index];

        if ((char_index = alphabet.indexOf(char)) === -1) {
            throw new Error('UID "' + str + '" contains invalid character');
        }

        num += char_index * Math.pow(base, index);

        if (!Number.isSafeInteger(num) || num > 0xFFFFFFFF) {
            throw new Error('UID "' + str + '" is too big');
        }
    }

    return num;
}

function Device(that, uid, ipcon, deviceIdentifier, deviceDisplayName) {
    if (uid !== undefined && ipcon !== undefined && deviceIdentifier !== undefined && deviceDisplayName !== undefined) {
        this.replaced = false;
        this.uid = base58Decode(uid);

        if (this.uid === 0) {
            throw new Error('UID "' + uid + '" is empty or maps to zero');
        }

        this.deviceIdentifier = deviceIdentifier;
        this.deviceDisplayName = deviceDisplayName;
        this.deviceIdentifierCheck = Device.DEVICE_IDENTIFIER_CHECK_PENDING;
        this.responseExpected = {};
        this.callbackFormats = {};
        this.highLevelCallbacks = {};
        this.streamStateObjects = {};
        this.registeredCallbacks = {};
        this.ipcon = ipcon;
        this.deviceOID = 0;
        this.APIVersion = [0, 0, 0];
        this.expectedResponses = []; // Has following structured objects as elements of the array,
                                    /*
                                    {
                                        DeviceOID:,
                                        FID:,
                                        SEQ:,
                                        unpackFormat:,
                                        timeout:,
                                        returnCB:,
                                        errorCB:
                                    }
                                    */

        this.getDeviceOID = function () {
            return this.deviceOID++;
        };

        this.getAPIVersion = function () {
            return this.APIVersion;
        };

        this.on = function (callbackID, function_, errorCallback) {
            // Support for 64 bit integers exists only in node 10.4 or higher
            if ((typeof BigInt == 'undefined')
                && ((this.callbackFormats[callbackID].indexOf('q') > -1)
                    || (this.callbackFormats[callbackID].indexOf('Q') > -1))) {
                if (errorCallback !== undefined) {
                    errorCallback(IPConnection.ERROR_INT64_NOT_SUPPORTED);
                }

                return;
            }
            this.registeredCallbacks[callbackID] = function_;
        };

        this.getResponseExpected = function (functionID, errorCallback) {
            if (this.responseExpected[functionID] === undefined) {
                if (errorCallback !== undefined) {
                    errorCallback(Device.ERROR_INVALID_FUNCTION_ID);
                }
                return;
            }

            if (this.responseExpected[functionID] === Device.RESPONSE_EXPECTED_TRUE ||
                this.responseExpected[functionID] === Device.RESPONSE_EXPECTED_ALWAYS_TRUE) {
                return true;
            } else {
                return false;
            }
        };

        this.setResponseExpected = function (functionID, responseBoolean, errorCallback) {
            if (this.responseExpected[functionID] === undefined) {
                if (errorCallback !== undefined) {
                    errorCallback(Device.ERROR_INVALID_FUNCTION_ID);
                }

                return;
            }

            if (this.responseExpected[functionID] === Device.RESPONSE_EXPECTED_TRUE ||
                this.responseExpected[functionID] === Device.RESPONSE_EXPECTED_FALSE) {
                if (responseBoolean) {
                    this.responseExpected[functionID] = Device.RESPONSE_EXPECTED_TRUE;
                } else {
                    this.responseExpected[functionID] = Device.RESPONSE_EXPECTED_FALSE;
                }

                return;
            }

            if (errorCallback !== undefined) {
                errorCallback(Device.ERROR_INVALID_FUNCTION_ID);
            }
        };

        this.setResponseExpectedAll = function (responseBoolean) {
            if (responseBoolean === true || responseBoolean === false) {
                for (var fid in this.responseExpected) {
                    if (this.responseExpected[fid] === Device.RESPONSE_EXPECTED_TRUE ||
                        this.responseExpected[fid] === Device.RESPONSE_EXPECTED_FALSE) {
                        if (responseBoolean) {
                            this.responseExpected[fid] = Device.RESPONSE_EXPECTED_TRUE;
                        } else {
                            this.responseExpected[fid] = Device.RESPONSE_EXPECTED_FALSE;
                        }
                    }
                }
            }
        };

        this.resetStreamStateObject = function (streamStateObject) {
            streamStateObject['responseProperties']['running'] = false;
            streamStateObject['responseProperties']['runningSubcall'] = false;
            streamStateObject['responseProperties']['runningSubcallOOS'] = false;
            streamStateObject['responseProperties']['waitingFirstChunk'] = true;

            if (streamStateObject['responseProperties']['timeout'] !== null) {
                clearTimeout(streamStateObject['responseProperties']['timeout']);
                streamStateObject['responseProperties']['timeout'] = null;
            }

            streamStateObject['responseProperties']['data'].length = 0;
            streamStateObject['responseProperties']['streamInChunkOffset'] = 0;
            streamStateObject['responseProperties']['streamInChunkLength'] = 0;
            streamStateObject['responseProperties']['streamInWritten'] = 0;
            streamStateObject['responseProperties']['streamInLLParams'] = null;
            streamStateObject['responseProperties']['returnCB'] = null;
            streamStateObject['responseProperties']['errorCB'] = null;
        };

        this.checkValidity = function (returnCallback, errorCallback) {
            if (this.replaced) {
                if (errorCallback !== undefined) {
                    errorCallback(Device.ERROR_DEVICE_REPLACED);
                }
            } else if (this.deviceIdentifierCheck === Device.DEVICE_IDENTIFIER_CHECK_MATCH) {
                if (returnCallback !== undefined) {
                    returnCallback();
                }
            } else if (this.deviceIdentifierCheck === Device.DEVICE_IDENTIFIER_CHECK_MISMATCH) {
                if (errorCallback !== undefined) {
                    errorCallback(Device.ERROR_WRONG_DEVICE_TYPE);
                }
            } else { // Device.DEVICE_IDENTIFIER_CHECK_PENDING
                this.ipcon.sendRequest(this, 255, [], '', 33, 's8 s8 c B3 B3 H', // getIdentity
                    function (uid, connectedUid, position, hardwareVersion, firmwareVersion, deviceIdentifier) {
                        if (deviceIdentifier == this.deviceIdentifier) {
                            this.deviceIdentifierCheck = Device.DEVICE_IDENTIFIER_CHECK_MATCH;

                            if (returnCallback !== undefined) {
                                returnCallback();
                            }
                        } else {
                            this.deviceIdentifierCheck = Device.DEVICE_IDENTIFIER_CHECK_MISMATCH;

                            if (errorCallback !== undefined) {
                                errorCallback(Device.ERROR_WRONG_DEVICE_TYPE);
                            }
                        }
                    }.bind(this),
                    errorCallback,
                    false,
                    false
                );
            }
        }
    }
}

module.exports = Device;

},{}],280:[function(require,module,exports){
(function (process,Buffer){
/*
Copyright (C) 2014 Ishraq Ibne Ashraf <ishraq@tinkerforge.com>
Copyright (C) 2014, 2020 Matthias Bolte <matthias@tinkerforge.com>
Copyright (C) 2014 Olaf Lüke <olaf@tinkerforge.com>

Redistribution and use in source and binary forms of this file,
with or without modification, are permitted. See the Creative
Commons Zero (CC0 1.0) License for more details.
*/

var Device = require('./Device');

IPConnection.FUNCTION_ENUMERATE = 254;
IPConnection.FUNCTION_DISCONNECT_PROBE = 128;
IPConnection.CALLBACK_ENUMERATE = 253;
IPConnection.CALLBACK_CONNECTED = 0;
IPConnection.CALLBACK_DISCONNECTED = 1;
IPConnection.BROADCAST_UID = 0;

// Enumeration type parameter to the enumerate callback
IPConnection.ENUMERATION_TYPE_AVAILABLE = 0;
IPConnection.ENUMERATION_TYPE_CONNECTED = 1;
IPConnection.ENUMERATION_TYPE_DISCONNECTED = 2;

// Connect reason parameter to the connected callback
IPConnection.CONNECT_REASON_REQUEST = 0;
IPConnection.CONNECT_REASON_AUTO_RECONNECT = 1;

// Disconnect reason parameter to the disconnected callback
IPConnection.DISCONNECT_REASON_REQUEST = 0;
IPConnection.DISCONNECT_REASON_ERROR = 1;
IPConnection.DISCONNECT_REASON_SHUTDOWN = 2;

// Returned by getConnectionState()
IPConnection.CONNECTION_STATE_DISCONNECTED = 0;
IPConnection.CONNECTION_STATE_CONNECTED = 1;
IPConnection.CONNECTION_STATE_PENDING = 2; // auto-reconnect in process
IPConnection.DISCONNECT_PROBE_INTERVAL = 5000;
IPConnection.RETRY_CONNECTION_INTERVAL = 2000;

// Error codes
IPConnection.ERROR_ALREADY_CONNECTED = 11;
IPConnection.ERROR_NOT_CONNECTED = 12;
IPConnection.ERROR_CONNECT_FAILED = 13;
IPConnection.ERROR_INVALID_FUNCTION_ID = 21; // keep in sync with Device.ERROR_INVALID_FUNCTION_ID
IPConnection.ERROR_TIMEOUT = 31;
IPConnection.ERROR_INVALID_PARAMETER = 41;
IPConnection.ERROR_FUNCTION_NOT_SUPPORTED = 42;
IPConnection.ERROR_UNKNOWN_ERROR = 43;
IPConnection.ERROR_STREAM_OUT_OF_SYNC = 51;
IPConnection.ERROR_NON_ASCII_CHAR_IN_SECRET = 71;
IPConnection.ERROR_WRONG_DEVICE_TYPE = 81; // keep in sync with Device.ERROR_WRONG_DEVICE_TYPE
IPConnection.ERROR_DEVICE_REPLACED = 82; // keep in sync with Device.ERROR_DEVICE_REPLACED
IPConnection.ERROR_WRONG_RESPONSE_LENGTH = 83;
IPConnection.ERROR_INT64_NOT_SUPPORTED = 91;

IPConnection.TASK_KIND_CONNECT = 0;
IPConnection.TASK_KIND_DISCONNECT = 1;
IPConnection.TASK_KIND_AUTO_RECONNECT = 2;
IPConnection.TASK_KIND_AUTHENTICATE = 3;

// Socket implementation for Node.js and Websocket.
// The API resembles the Node.js API.
function TFSocket(PORT, HOST, ipcon) {
    this.port = PORT;
    this.host = HOST;
    this.socket = null;

    if (process.browser) {
        var webSocketURL = "ws://" + this.host + ":" + this.port + "/";

        if (typeof MozWebSocket != "undefined") {
            this.socket = new MozWebSocket(webSocketURL, "tfp");
        } else {
            this.socket = new WebSocket(webSocketURL, "tfp");
        }

        this.socket.binaryType = 'arraybuffer';
    } else {
        var net = require('net');

        this.socket = new net.Socket();
    }

    this.on = function (str, func) {
        if (process.browser) {
            switch (str) {
            case "connect":
                this.socket.onopen = func;
                break;
            case "data":
                // Websockets in browsers return a MessageEvent. We just
                // expose the data from the event as a Buffer as in Node.js.
                this.socket.onmessage = function (messageEvent) {
                    if (Buffer.from && Buffer.from !== Uint8Array.from) {
                        var data = Buffer.from(new Uint8Array(messageEvent.data));
                    } else {
                        var data = new Buffer(new Uint8Array(messageEvent.data));
                    }
                    func(data);
                };
                break;
            case "error":
                // There is no easy way to get errno for error in browser websockets.
                // We assume error['errno'] === 'ECONNRESET'
                this.socket.onerror = function () {
                    var error = {"errno": "ECONNRESET"};
                    func(error);
                };
                break;
            case "close":
                this.socket.onclose = func;
                break;
            }
        } else {
            this.socket.on(str, func);
        }
    };

    this.connect = function () {
        if (process.browser) {
            // In the browser we already connected by creating a WebSocket object
        } else {
            this.socket.connect(this.port, this.host, null);
        }
    };

    this.setNoDelay = function (value) {
        if (process.browser) {
            // Currently no API available in browsers
            // But Nagle algorithm seems te be turned off in most browsers by default anyway
        } else {
            this.socket.setNoDelay(value);
        }
    };

    this.write = function (data, reset_disconnect_probe) {
        if (process.browser) {
            // Some browers can't send a nodejs Buffer through a websocket,
            // we copy it into an ArrayBuffer
            var arrayBuffer = new Uint8Array(data).buffer;

            this.socket.send(arrayBuffer);

            if (reset_disconnect_probe) {
                ipcon.resetDisconnectProbe();
            }
        } else {
            if (reset_disconnect_probe) {
                this.socket.write(data, ipcon.resetDisconnectProbe);
            } else {
                this.socket.write(data);
            }
        }
    };

    this.end = function () {
        if (process.browser) {
            this.socket.close();
        } else {
            this.socket.end();
        }
    };

    this.destroy = function () {
        if (process.browser) {
            // There is no end/destroy in browser socket, so we close in end
            // and do nothing in destroy
        } else {
            this.socket.destroy();
        }
    };
}

BrickDaemon.FUNCTION_GET_AUTHENTICATION_NONCE = 1;
BrickDaemon.FUNCTION_AUTHENTICATE = 2;

function BrickDaemon(uid, ipcon) {
    Device.call(this, this, uid, ipcon, 0, 'Brick Daemon');
    BrickDaemon.prototype = Object.create(Device);
    this.responseExpected = {};
    this.callbackFormats = {};
    this.APIVersion = [2, 0, 0];
    this.responseExpected[BrickDaemon.FUNCTION_GET_AUTHENTICATION_NONCE] = Device.RESPONSE_EXPECTED_ALWAYS_TRUE;
    this.responseExpected[BrickDaemon.FUNCTION_AUTHENTICATE] = Device.RESPONSE_EXPECTED_TRUE;

    this.getAuthenticationNonce = function(returnCallback, errorCallback) {
        this.ipcon.sendRequest(this, BrickDaemon.FUNCTION_GET_AUTHENTICATION_NONCE, [], '', 12, 'B4', returnCallback, errorCallback, false, false);
    };

    this.authenticate = function(clientNonce, digest, returnCallback, errorCallback) {
        this.ipcon.sendRequest(this, BrickDaemon.FUNCTION_AUTHENTICATE, [clientNonce, digest], 'B4 B20', 0, '', returnCallback, errorCallback, false, false);
    };

    this.ipcon.addDevice(this);
}

// the IPConnection class and constructor
function IPConnection() {
    // Creates an IP Connection object that can be used to enumerate the available
    // devices. It is also required for the constructor of Bricks and Bricklets.
    this.host = undefined;
    this.port = undefined;
    this.timeout = 2500;
    this.autoReconnect = true;
    this.nextSequenceNumber = 0;
    this.nextAuthenticationNonce = 0;
    this.devices = {};
    this.registeredCallbacks = {};
    this.socket = undefined;
    this.disconnectProbeIID = undefined;
    this.taskQueue = [];
    this.isConnected = false;
    this.connectErrorCallback = undefined;
    this.mergeBuffer = Buffer.concat([]); //See https://nodejs.org/en/docs/guides/buffer-constructor-deprecation/#buffer-0

    this.addDevice = function (device) {
        var replacedDevice = this.devices[device.uid];

        if (replacedDevice !== undefined) {
            replacedDevice.replaced = true;
        }

        this.devices[device.uid] = device;
    };

    this.brickd = new BrickDaemon('2', this);

    this.disconnectProbe = function () {
        if (this.socket !== undefined) {
            try {
                this.socket.write(this.createPacketHeader(undefined, 8, IPConnection.FUNCTION_DISCONNECT_PROBE), false);
            }
            catch(e) {
                // Initiating a normal disconnect will ensure autoreconnect decision and connection management
                this.disconnect(undefined);
            }
        }
    };

    this.pushTask = function (handler, kind) {
        this.taskQueue.push({"handler": handler, "kind": kind});

        if (this.taskQueue.length === 1) {
            this.executeTask();
        }
    };

    this.executeTask = function () {
        var task = this.taskQueue[0];

        if (task !== undefined) {
            task.handler();
        }
    };

    this.popTask = function () {
        this.taskQueue.splice(0, 1);
        this.executeTask();
    };

    this.removeNextTask = function () {
        this.taskQueue.splice(1, 1);
    };

    this.getCurrentTaskKind = function () {
        var task = this.taskQueue[0];

        if (task !== undefined) {
            return task.kind;
        }

        return undefined;
    };

    this.getNextTaskKind = function () {
        var task = this.taskQueue[1];

        if (task !== undefined) {
            return task.kind;
        }

        return undefined;
    };

    this.disconnect = function (errorCallback) {
        this.pushTask(this.disconnectInternal.bind(this, errorCallback), IPConnection.TASK_KIND_DISCONNECT);
    };

    this.disconnectInternal = function (errorCallback) {
        var autoReconnectAborted = false;

        if (this.getNextTaskKind() === IPConnection.TASK_KIND_AUTO_RECONNECT) {
            // Remove auto-reconnect task, to break recursion
            this.removeNextTask();
            autoReconnectAborted = true;
        }

        if (!this.isConnected) {
            if (!autoReconnectAborted && errorCallback !== undefined) {
                // Not using `this.` for the error callback function because
                // we want to call what user provided not the saved one
                errorCallback(IPConnection.ERROR_NOT_CONNECTED);
            }

            this.popTask();
            return;
        }

        this.socket.end();
        this.socket.destroy();
        // no popTask() here, will be done in handleConnectionClose()
        return;
    };

    this.connect = function (host, port, errorCallback) {
        this.pushTask(this.connectInternal.bind(this, host, port, errorCallback), IPConnection.TASK_KIND_CONNECT);
    };

    this.connectInternal = function (host, port, errorCallback) {
        if (this.isConnected) {
            if (errorCallback !== undefined) {
                // Not using `this.` for the error callback function because
                // we want to call what user provided not the saved one
                errorCallback(IPConnection.ERROR_ALREADY_CONNECTED);
            }

            this.popTask();
            return;
        }

        // Saving the user provided error callback function for future use
        this.connectErrorCallback = errorCallback;
        clearInterval(this.disconnectProbeIID);
        this.disconnectProbeIID = undefined;
        this.host = host;
        this.port = port;
        this.socket = new TFSocket(this.port, this.host, this);
        this.socket.setNoDelay(true);
        this.socket.on('connect', this.handleConnect.bind(this));
        this.socket.on('data', this.handleIncomingData.bind(this));
        this.socket.on('error', this.handleConnectionError.bind(this));
        this.socket.on('close', this.handleConnectionClose.bind(this));
        this.socket.connect();
    };

    this.handleConnect = function () {
        var connectReason = IPConnection.CONNECT_REASON_REQUEST;

        if (this.getCurrentTaskKind() === IPConnection.TASK_KIND_AUTO_RECONNECT) {
            connectReason = IPConnection.CONNECT_REASON_AUTO_RECONNECT;
        }

        clearInterval(this.disconnectProbeIID);
        this.disconnectProbeIID = undefined;
        this.isConnected = true;

        // Check and call functions if registered for callback connected
        if (this.registeredCallbacks[IPConnection.CALLBACK_CONNECTED] !== undefined) {
            this.registeredCallbacks[IPConnection.CALLBACK_CONNECTED](connectReason);
        }

        this.disconnectProbeIID = setInterval(this.disconnectProbe.bind(this),
                                              IPConnection.DISCONNECT_PROBE_INTERVAL);

        this.popTask();
    };

    this.handleIncomingData = function (data) {
        this.resetDisconnectProbe();

        if (data.length === 0) {
            return;
        }

        this.mergeBuffer = bufferConcat([this.mergeBuffer, data]);

        while (this.mergeBuffer.length > 0) {
            if (this.mergeBuffer.length < 8) {
                return; // wait for complete header
            }

            var length = this.mergeBuffer.readUInt8(4);

            if (this.mergeBuffer.length < length) {
                return; // wait for complete packet
            }

            var newPacket = buffer_wrapper(length);
            this.mergeBuffer.copy(newPacket, 0, 0, length);
            this.handlePacket(newPacket);
            this.mergeBuffer = this.mergeBuffer.slice(length);
        }
    };

    this.handleConnectionError = function (error) {
        if (error.errno === 'ECONNRESET') {
            // Check and call functions if registered for callback disconnected
            if (this.registeredCallbacks[IPConnection.CALLBACK_DISCONNECTED] !== undefined) {
                this.registeredCallbacks[IPConnection.CALLBACK_DISCONNECTED](IPConnection.DISCONNECT_REASON_SHUTDOWN);
            }
        }
    };

    this.handleAutoReconnectError = function (error) {
        if (!this.isConnected && this.autoReconnect && error !== IPConnection.ERROR_ALREADY_CONNECTED) {
            // FIXME: add a small sleep here to avoid a tight loop that could consume 100% CPU power
            this.pushTask(this.connectInternal.bind(this, this.host, this.port, this.handleAutoReconnectError), IPConnection.TASK_KIND_AUTO_RECONNECT);
        }
    };

    this.handleConnectionClose = function () {
        if (this.getCurrentTaskKind() === IPConnection.TASK_KIND_DISCONNECT) {
            // This disconnect was requested
            var uid;

            for (uid in this.devices) {
                for (var i=0;i<this.devices[uid].expectedResponses.length;i++) {
                    clearTimeout(this.devices[uid].expectedResponses[i].timeout);

                    if (this.devices[uid].expectedResponses[i].errorCB !== undefined) {
                        this.devices[uid].expectedResponses[i].errorCB(IPConnection.ERROR_TIMEOUT);
                    }
                }

                this.devices[uid].expectedResponses = [];
            }

            this.isConnected = false;
            clearInterval(this.disconnectProbeIID);
            this.disconnectProbeIID = undefined;

            if (this.socket !== undefined) {
                this.socket.end();
                this.socket.destroy();
                this.socket = undefined;
            }

            // Check and call functions if registered for callback disconnected
            if (this.registeredCallbacks[IPConnection.CALLBACK_DISCONNECTED] !== undefined) {
                this.registeredCallbacks[IPConnection.CALLBACK_DISCONNECTED](IPConnection.DISCONNECT_REASON_REQUEST);
            }

            this.popTask();
            return;
        }
        // Was connected, disconnected because of error and auto reconnect is enabled
        if (this.isConnected) {
            this.isConnected = false;
            clearInterval(this.disconnectProbeIID);
            this.disconnectProbeIID = undefined;

            if (this.socket !== undefined) {
                this.socket.end();
                this.socket.destroy();
                this.socket = undefined;
            }

            // Check and call functions if registered for callback disconnected
            if (this.registeredCallbacks[IPConnection.CALLBACK_DISCONNECTED] !== undefined) {
                this.registeredCallbacks[IPConnection.CALLBACK_DISCONNECTED](IPConnection.DISCONNECT_REASON_ERROR);
            }

            if (this.autoReconnect) {
                this.pushTask(this.connectInternal.bind(this, this.host, this.port, this.handleAutoReconnectError), IPConnection.TASK_KIND_AUTO_RECONNECT);
            }

            return;
        }

        // Were not connected. failed at new connection attempt
        if (this.getCurrentTaskKind() === IPConnection.TASK_KIND_CONNECT || this.getCurrentTaskKind() === IPConnection.TASK_KIND_AUTO_RECONNECT) {
            if (this.connectErrorCallback !== undefined) {
                this.connectErrorCallback(IPConnection.ERROR_CONNECT_FAILED);
            }

            this.popTask();
            return;
        }
    };

    this.resetDisconnectProbe = function() {
        if(this.disconnectProbeIID === undefined) {
            return;
        }

        clearInterval(this.disconnectProbeIID);
        this.disconnectProbeIID = undefined;
        this.disconnectProbeIID = setInterval(this.disconnectProbe.bind(this),
                                              IPConnection.DISCONNECT_PROBE_INTERVAL);
    };

    this.getUIDFromPacket = function (packetUID){
        return packetUID.readUInt32LE(0);
    };

    this.getLengthFromPacket = function (packetLen) {
        return packetLen.readUInt8(4);
    };

    this.getFunctionIDFromPacket = function (packetFID) {
        return packetFID.readUInt8(5);
    };

    this.getSequenceNumberFromPacket = function (packetSeq) {
        return (packetSeq.readUInt8(6) >>> 4) & 0x0F;
    };

    this.getRFromPacket = function (packetR) {
        return (packetR.readUInt8(6) >>> 3) & 0x01;
    };

    this.getEFromPacket = function (packetE) {
        // Getting Error bits(E, 2bits)
        return (packetE.readUInt8(7) >>> 6) & 0x03;
    };

    this.getPayloadFromPacket = function (packetPayload) {
        var payloadReturn = buffer_wrapper(packetPayload.length - 8);
        packetPayload.copy(payloadReturn, 0, 8, packetPayload.length);
        return buffer_wrapper(payloadReturn);
    };

    function mapsToFalse(value) {
        return value === 0 || value === false || value === undefined || value === null || isNaN(value);
    }

    this.pack = function (data, format) {
        var formatArray = format.split(' ');

        if (formatArray.length <= 0) {
            return buffer_wrapper(0);
        }

        var packedBuffer = buffer_wrapper(0);

        for (var i=0; i<formatArray.length; i++){
            if (formatArray[i].split('').length === 1) {
                if (formatArray[i] === 's') {
                    var tmpPackedBuffer = buffer_wrapper(1);
                    tmpPackedBuffer.writeUInt8(data[i].charCodeAt(0), 0);
                    packedBuffer = bufferConcat([packedBuffer,tmpPackedBuffer]);
                    continue;
                }

                switch (formatArray[i]) {
                    case 'c':
                        var tmpPackedBuffer = buffer_wrapper(1);
                        tmpPackedBuffer.writeUInt8(data[i].charCodeAt(0), 0);
                        packedBuffer = bufferConcat([packedBuffer,tmpPackedBuffer]);
                        continue;
                    case 'b':
                        var tmpPackedBuffer = buffer_wrapper(1);
                        tmpPackedBuffer.writeInt8(data[i], 0);
                        packedBuffer = bufferConcat([packedBuffer,tmpPackedBuffer]);
                        continue;
                    case 'B':
                        var tmpPackedBuffer = buffer_wrapper(1);
                        tmpPackedBuffer.writeUInt8(data[i], 0);
                        packedBuffer = bufferConcat([packedBuffer,tmpPackedBuffer]);
                        continue;
                    case 'h':
                        var tmpPackedBuffer = buffer_wrapper(2);
                        tmpPackedBuffer.writeInt16LE(data[i], 0);
                        packedBuffer = bufferConcat([packedBuffer,tmpPackedBuffer]);
                        continue;
                    case 'H':
                        var tmpPackedBuffer = buffer_wrapper(2);
                        tmpPackedBuffer.writeUInt16LE(data[i], 0);
                        packedBuffer = bufferConcat([packedBuffer,tmpPackedBuffer]);
                        continue;
                    case 'i':
                        var tmpPackedBuffer = buffer_wrapper(4);
                        tmpPackedBuffer.writeInt32LE(data[i], 0);
                        packedBuffer = bufferConcat([packedBuffer,tmpPackedBuffer]);
                        continue;
                    case 'I':
                        var tmpPackedBuffer = buffer_wrapper(4);
                        tmpPackedBuffer.writeUInt32LE(data[i], 0);
                        packedBuffer = bufferConcat([packedBuffer,tmpPackedBuffer]);
                        continue;
                    case 'q':
                        var tmpPackedBuffer = buffer_wrapper(8);
                        tmpPackedBuffer.writeBigInt64LE(data[i], 0);
                        packedBuffer = bufferConcat([packedBuffer,tmpPackedBuffer]);
                        continue;
                    case 'Q':
                        var tmpPackedBuffer = buffer_wrapper(8);
                        tmpPackedBuffer.writeBigUInt64LE(data[i], 0);
                        packedBuffer = bufferConcat([packedBuffer,tmpPackedBuffer]);
                        continue;
                    case 'f':
                        var tmpPackedBuffer = buffer_wrapper(4);
                        tmpPackedBuffer.writeFloatLE(data[i], 0);
                        packedBuffer = bufferConcat([packedBuffer,tmpPackedBuffer]);
                        continue;
                    case 'd':
                        var tmpPackedBuffer = buffer_wrapper(8);
                        tmpPackedBuffer.writeDoubleLE(data[i], 0);
                        packedBuffer = bufferConcat([packedBuffer,tmpPackedBuffer]);
                        continue;
                    case '?':
                        var tmpPackedBuffer = buffer_wrapper(1);

                        if (mapsToFalse(data[i])) {
                            tmpPackedBuffer.writeUInt8(0x00, 0);
                        } else {
                            tmpPackedBuffer.writeUInt8(0x01, 0);
                        }

                        packedBuffer = bufferConcat([packedBuffer,tmpPackedBuffer]);
                        continue;
                }
            }

            if (formatArray[i].split('').length > 1) {
                var singleFormatArray = formatArray[i].split('');

                // Boolean type with cardinality greater than 1
                if (singleFormatArray[0] === '?') {
                    var buffer_value = 0;
                    var count = parseInt(singleFormatArray.slice(1, singleFormatArray.length).join(''));
                    var count_bits = Math.ceil(count / 8);
                    var tmpPackedBuffer = buffer_wrapper(count_bits);

                    for(var _i = 0; _i < count; _i++) {
                        if (mapsToFalse(data[i][_i])) {
                            continue;
                        } else {
                            buffer_value = tmpPackedBuffer.readUInt8(Math.floor(_i / 8));
                            buffer_value |= 1 << (_i % 8);
                            tmpPackedBuffer.writeUInt8(buffer_value, Math.floor(_i / 8));
                        }
                    }

                    packedBuffer = bufferConcat([packedBuffer,tmpPackedBuffer]);
                    continue;
                }

                for (var j = 0; j < parseInt(formatArray[i].match(/\d/g).join('')); j++) {
                    if (singleFormatArray[0] === 's') {
                        if (!isNaN(data[i].charCodeAt(j))) {
                            var tmpPackedBuffer = buffer_wrapper(1);
                            tmpPackedBuffer.writeUInt8(data[i].charCodeAt(j), 0);
                            packedBuffer = bufferConcat([packedBuffer,tmpPackedBuffer]);
                        } else {
                            var tmpPackedBuffer = buffer_wrapper(1);
                            tmpPackedBuffer.writeUInt8(0x00, 0);
                            packedBuffer = bufferConcat([packedBuffer,tmpPackedBuffer]);
                        }

                        continue;
                    }

                    switch (singleFormatArray[0]) {
                        case 'c':
                            var tmpPackedBuffer = buffer_wrapper(1);
                            tmpPackedBuffer.writeUInt8(data[i][j].charCodeAt(0), 0);
                            packedBuffer = bufferConcat([packedBuffer,tmpPackedBuffer]);
                            continue;
                        case 'b':
                            var tmpPackedBuffer = buffer_wrapper(1);
                            tmpPackedBuffer.writeInt8(data[i][j], 0);
                            packedBuffer = bufferConcat([packedBuffer,tmpPackedBuffer]);
                            continue;
                        case 'B':
                            var tmpPackedBuffer = buffer_wrapper(1);
                            tmpPackedBuffer.writeUInt8(data[i][j], 0);
                            packedBuffer = bufferConcat([packedBuffer,tmpPackedBuffer]);
                            continue;
                        case 'h':
                            var tmpPackedBuffer = buffer_wrapper(2);
                            tmpPackedBuffer.writeInt16LE(data[i][j], 0);
                            packedBuffer = bufferConcat([packedBuffer,tmpPackedBuffer]);
                            continue;
                        case 'H':
                            var tmpPackedBuffer = buffer_wrapper(2);
                            tmpPackedBuffer.writeUInt16LE(data[i][j], 0);
                            packedBuffer = bufferConcat([packedBuffer,tmpPackedBuffer]);
                            continue;
                        case 'i':
                            var tmpPackedBuffer = buffer_wrapper(4);
                            tmpPackedBuffer.writeInt32LE(data[i][j], 0);
                            packedBuffer = bufferConcat([packedBuffer,tmpPackedBuffer]);
                            continue;
                        case 'I':
                            var tmpPackedBuffer = buffer_wrapper(4);
                            tmpPackedBuffer.writeUInt32LE(data[i][j], 0);
                            packedBuffer = bufferConcat([packedBuffer,tmpPackedBuffer]);
                            continue;
                        case 'q':
                            var tmpPackedBuffer = buffer_wrapper(8);
                            tmpPackedBuffer.writeBigInt64LE(data[i][j], 0);
                            packedBuffer = bufferConcat([packedBuffer,tmpPackedBuffer]);
                            continue;
                        case 'Q':
                            var tmpPackedBuffer = buffer_wrapper(8);
                            tmpPackedBuffer.writeBigUInt64LE(data[i][j], 0);
                            packedBuffer = bufferConcat([packedBuffer,tmpPackedBuffer]);
                            continue;
                        case 'f':
                            var tmpPackedBuffer = buffer_wrapper(4);
                            tmpPackedBuffer.writeFloatLE(data[i][j], 0);
                            packedBuffer = bufferConcat([packedBuffer,tmpPackedBuffer]);
                            continue;
                        case 'd':
                            var tmpPackedBuffer = buffer_wrapper(8);
                            tmpPackedBuffer.writeDoubleLE(data[i][j], 0);
                            packedBuffer = bufferConcat([packedBuffer,tmpPackedBuffer]);
                            continue;
                        case '?':
                            var tmpPackedBuffer = buffer_wrapper(1);

                            if (mapsToFalse(data[i][j])) {
                                tmpPackedBuffer.writeUInt8(0x00, 0);
                            } else {
                                tmpPackedBuffer.writeUInt8(0x01, 0);
                            }

                            packedBuffer = bufferConcat([packedBuffer,tmpPackedBuffer]);
                            continue;
                    }
                }
            }
        }

        return packedBuffer;
    }

    this.unpack = function (unpackPayload, format) {
        var formatArray = format.split(' ');
        var returnArguments = [];
        var returnSubArray = [];
        var constructedString = '';
        var payloadReadOffset = 0;

        if (formatArray.length <= 0) {
            return returnArguments;
        }

        for (var i = 0; i < formatArray.length; i++) {
            if (formatArray[i].split('').length === 1) {
                if (formatArray[i] === 's') {
                    constructedString += String.fromCharCode(unpackPayload.readUInt8(payloadReadOffset));
                    payloadReadOffset++;
                    returnArguments.push(constructedString);
                    constructedString = '';
                    continue;
                }

                switch (formatArray[i]) {
                    case 'c':
                        returnArguments.push(String.fromCharCode(unpackPayload.readUInt8(payloadReadOffset)));
                        payloadReadOffset += 1;
                        continue;
                    case 'b':
                        returnArguments.push(unpackPayload.readInt8(payloadReadOffset));
                        payloadReadOffset += 1;
                        continue;
                    case 'B':
                        returnArguments.push(unpackPayload.readUInt8(payloadReadOffset));
                        payloadReadOffset += 1;
                        continue;
                    case 'h':
                        returnArguments.push(unpackPayload.readInt16LE(payloadReadOffset));
                        payloadReadOffset += 2;
                        continue;
                    case 'H':
                        returnArguments.push(unpackPayload.readUInt16LE(payloadReadOffset));
                        payloadReadOffset += 2;
                        continue;
                    case 'i':
                        returnArguments.push(unpackPayload.readInt32LE(payloadReadOffset));
                        payloadReadOffset += 4;
                        continue;
                    case 'I':
                        returnArguments.push(unpackPayload.readUInt32LE(payloadReadOffset));
                        payloadReadOffset += 4;
                        continue;
                    case 'q':
                        returnArguments.push(unpackPayload.readBigInt64LE(payloadReadOffset));
                        payloadReadOffset += 8;
                        continue;
                    case 'Q':
                        returnArguments.push(unpackPayload.readBigUInt64LE(payloadReadOffset));
                        payloadReadOffset += 8;
                        continue;
                    case 'f':
                        returnArguments.push(unpackPayload.readFloatLE(payloadReadOffset));
                        payloadReadOffset += 4;
                        continue;
                    case 'd':
                        returnArguments.push(unpackPayload.readDoubleLE(payloadReadOffset));
                        payloadReadOffset += 8;
                        continue;
                    case '?':
                        returnArguments.push(unpackPayload.readUInt8(payloadReadOffset) !== 0);
                        payloadReadOffset += 1;
                        continue;
                }
            }

            if (formatArray[i].split('').length > 1) {
                var singleFormatArray = formatArray[i].split('');

                // Boolean type with cardinality greater than 1
                if (singleFormatArray[0] === '?') {
                    var count = parseInt(formatArray[i].match(/\d/g).join(''));
                    var payloadBoolArray = new Array(count);
                    var extractedBoolArray = new Array(count);

                    payloadBoolArray.fill(0x00);
                    extractedBoolArray.fill(false);

                    for (var j = 0; j < Math.ceil(count / 8); j++) {
                        payloadBoolArray[j] = unpackPayload.readUInt8(payloadReadOffset);
                        payloadReadOffset++;
                    }

                    for (var j = 0; j < count; j++) {
                        extractedBoolArray[j] = ((payloadBoolArray[Math.floor(j / 8)] & (1 << (j % 8))) != 0);
                    }

                    returnArguments.push(extractedBoolArray);

                    continue;
                }

                if (singleFormatArray[0] === 's') {
                    constructedString = '';
                    skip = false;

                    for (var j = 0; j < parseInt(formatArray[i].match(/\d/g).join('')); j++) {
                        c = String.fromCharCode(unpackPayload.readUInt8(payloadReadOffset));

                        if (c === '\0' || skip) {
                            skip = true;
                        } else {
                            constructedString += c;
                        }

                        payloadReadOffset++;
                    }

                    skip = false;
                    returnArguments.push(constructedString);
                    constructedString = '';
                    continue;
                }

                returnSubArray = [];

                for (var k = 0; k < parseInt(formatArray[i].match(/\d/g).join('')); k++) {
                    switch (singleFormatArray[0]) {
                        case 'c':
                            returnSubArray.push(String.fromCharCode(unpackPayload.readUInt8(payloadReadOffset)));
                            payloadReadOffset += 1;
                            continue;
                        case 'b':
                            returnSubArray.push(unpackPayload.readInt8(payloadReadOffset));
                            payloadReadOffset += 1;
                            continue;
                        case 'B':
                            returnSubArray.push(unpackPayload.readUInt8(payloadReadOffset));
                            payloadReadOffset += 1;
                            continue;
                        case 'h':
                            returnSubArray.push(unpackPayload.readInt16LE(payloadReadOffset));
                            payloadReadOffset += 2;
                            continue;
                        case 'H':
                            returnSubArray.push(unpackPayload.readUInt16LE(payloadReadOffset));
                            payloadReadOffset += 2;
                            continue;
                        case 'i':
                            returnSubArray.push(unpackPayload.readInt32LE(payloadReadOffset));
                            payloadReadOffset += 4;
                            continue;
                        case 'I':
                            returnSubArray.push(unpackPayload.readUInt32LE(payloadReadOffset));
                            payloadReadOffset += 4;
                            continue;
                        case 'q':
                            returnSubArray.push(unpackPayload.readBigInt64LE(payloadReadOffset));
                            payloadReadOffset += 8;
                            continue;
                        case 'Q':
                            returnSubArray.push(unpackPayload.readBigUInt64LE(payloadReadOffset));
                            payloadReadOffset += 8;
                            continue;
                        case 'f':
                            returnSubArray.push(unpackPayload.readFloatLE(payloadReadOffset));
                            payloadReadOffset += 4;
                            continue;
                        case 'd':
                            returnSubArray.push(unpackPayload.readDoubleLE(payloadReadOffset));
                            payloadReadOffset += 8;
                            continue;
                        case '?':
                            returnSubArray.push(unpackPayload.readUInt8(payloadReadOffset) !== 0);
                            payloadReadOffset += 1;
                            continue;
                    }
                }

                if (returnSubArray.length !== 0) {
                    returnArguments.push(returnSubArray);
                    returnSubArray = [];
                    continue;
                }
            }
        }

        return returnArguments;
    }

    this.sendRequest = function (sendRequestDevice,
                                 sendRequestFID,
                                 sendRequestData,
                                 sendRequestPackFormat,
                                 sendRequestExpectedResponseLength,
                                 sendRequestUnpackFormat,
                                 sendRequestReturnCB,
                                 sendRequestErrorCB,
                                 startStreamResponseTimer,
                                 checkValidity) {
        if (this.getConnectionState() !== IPConnection.CONNECTION_STATE_CONNECTED) {
            if (sendRequestErrorCB !== undefined) {
                sendRequestErrorCB(IPConnection.ERROR_NOT_CONNECTED);
            }

            return;
        }

        // Support for 64 bit integers exists only in node 10.2 or higher
        if ((typeof BigInt == 'undefined')
            && ((sendRequestPackFormat.indexOf('q') > -1)
            || (sendRequestPackFormat.indexOf('Q') > -1)
            || (sendRequestUnpackFormat.indexOf('q') > -1)
            || (sendRequestUnpackFormat.indexOf('Q') > -1))) {
            if (sendRequestErrorCB !== undefined) {
                sendRequestErrorCB(IPConnection.ERROR_INT64_NOT_SUPPORTED);
            }

            return;
        }

        if (checkValidity) {
            sendRequestDevice.checkValidity(function () {
                this.sendRequestInternal(sendRequestDevice,
                                         sendRequestFID,
                                         sendRequestData,
                                         sendRequestPackFormat,
                                         sendRequestExpectedResponseLength,
                                         sendRequestUnpackFormat,
                                         sendRequestReturnCB,
                                         sendRequestErrorCB,
                                         startStreamResponseTimer);
            }.bind(this),
            sendRequestErrorCB);
        } else {
            this.sendRequestInternal(sendRequestDevice,
                                     sendRequestFID,
                                     sendRequestData,
                                     sendRequestPackFormat,
                                     sendRequestExpectedResponseLength,
                                     sendRequestUnpackFormat,
                                     sendRequestReturnCB,
                                     sendRequestErrorCB,
                                     startStreamResponseTimer);
        }
    }

    this.sendRequestInternal = function (sendRequestDevice,
                                         sendRequestFID,
                                         sendRequestData,
                                         sendRequestPackFormat,
                                         sendRequestExpectedResponseLength,
                                         sendRequestUnpackFormat,
                                         sendRequestReturnCB,
                                         sendRequestErrorCB,
                                         startStreamResponseTimer) {
        // Packet creation
        var sendRequestPayload = this.pack(sendRequestData, sendRequestPackFormat);
        var sendRequestHeader = this.createPacketHeader(sendRequestDevice,
                                                        8+sendRequestPayload.length,
                                                        sendRequestFID,
                                                        sendRequestErrorCB);

        if (sendRequestHeader === undefined) {
            return;
        }

        var sendRequestPacket = bufferConcat([sendRequestHeader, sendRequestPayload]);
        var sendRequestSEQ = this.getSequenceNumberFromPacket(sendRequestHeader);
        var responseExpected = sendRequestDevice.getResponseExpected(sendRequestFID);

        // Sending the created packet
        if (responseExpected) {
            // Setting the requesting current device's current request
            var sendRequestDeviceOID = sendRequestDevice.getDeviceOID();

            if (!startStreamResponseTimer) {
                sendRequestDevice.expectedResponses.push({
                    DeviceOID:sendRequestDeviceOID,
                    FID:sendRequestFID,
                    SEQ:sendRequestSEQ,
                    unpackFormat:sendRequestUnpackFormat,
                    expectedResponseLength:sendRequestExpectedResponseLength,
                    timeout:setTimeout(this.sendRequestTimeout.bind(this,
                                                                    sendRequestDevice,
                                                                    sendRequestDeviceOID,
                                                                    sendRequestErrorCB),
                                       this.timeout),
                    returnCB:sendRequestReturnCB,
                    errorCB:sendRequestErrorCB
                });
            } else {
                // Setup streaming timer
                if (sendRequestFID in sendRequestDevice.streamStateObjects) {
                    if (sendRequestDevice.streamStateObjects[sendRequestFID]['responseProperties']['timeout'] !== null) {
                        clearTimeout(sendRequestDevice.streamStateObjects[sendRequestFID]['responseProperties']['timeout']);
                        sendRequestDevice.streamStateObjects[sendRequestFID]['responseProperties']['timeout'] = null;
                    }

                    sendRequestDevice.streamStateObjects[sendRequestFID]['responseProperties']['timeout'] =
                        setTimeout(this.sendRequestTimeoutStreamOut.bind(this,
                                                                         sendRequestDevice,
                                                                         sendRequestFID,
                                                                         sendRequestErrorCB),

                                   this.timeout);
                }
            }
        }

        this.socket.write(sendRequestPacket, true);

        if (!responseExpected && sendRequestReturnCB !== undefined) {
            eval('sendRequestReturnCB();');
        }
    };

    this.sendRequestTimeout = function (timeoutDevice, timeoutDeviceOID, timeoutErrorCB) {
        for (var i = 0; i < timeoutDevice.expectedResponses.length; ++i) {
            if (timeoutDevice.expectedResponses[i].DeviceOID === timeoutDeviceOID) {
                clearTimeout(timeoutDevice.expectedResponses[i].timeout);
                timeoutDevice.expectedResponses.splice(i, 1);

                if (timeoutErrorCB !== undefined){
                    timeoutErrorCB(IPConnection.ERROR_TIMEOUT);
                }

                return;
            }
        }
    };

    this.sendRequestTimeoutStreamOut = function (timeoutDevice, timeoutFID, timeoutErrorCB) {
        var streamOutObject = null;

        if (!(timeoutFID in timeoutDevice.streamStateObjects)) {
            return;
        }

        streamOutObject = timeoutDevice.streamStateObjects[timeoutFID];

        if (streamOutObject === null) {
            return;
        }

        // Clear timer
        clearTimeout(streamOutObject['responseProperties']['timeout']);

        // Call error callback (if any)
        if (streamOutObject['responseProperties']['errorCB'] !== undefined) {
            streamOutObject['responseProperties']['errorCB'](IPConnection.ERROR_TIMEOUT);
        }

        // Reset stream state object
        timeoutDevice.resetStreamStateObject(streamOutObject);

        // Call next function from call queue (if any)
        if (streamOutObject['responseProperties']['callQueue'].length > 0) {
            streamOutObject['responseProperties']['callQueue'].shift()(timeoutDevice);
        }
    };

    this.handleResponse = function (packetResponse) {
        var streamStateObject = null;
        var handleResponseDevice = null;
        var handleResponseFID = this.getFunctionIDFromPacket(packetResponse);
        var handleResponseSEQ = this.getSequenceNumberFromPacket(packetResponse);

        handleResponseDevice = this.devices[this.getUIDFromPacket(packetResponse)];

        if (handleResponseDevice === undefined) {
            return;
        }

        // Handle non-streamed response
        if (!(handleResponseFID in handleResponseDevice.streamStateObjects)) {
            for (var i = 0; i < handleResponseDevice.expectedResponses.length; i++) {
                var expectedResponse = handleResponseDevice.expectedResponses[i];

                if (expectedResponse.FID === handleResponseFID &&
                    expectedResponse.SEQ === handleResponseSEQ) {
                    clearTimeout(expectedResponse.timeout);

                    if (this.getEFromPacket(packetResponse) === 1) {
                        if (expectedResponse.errorCB !== undefined) {
                            eval('expectedResponse.errorCB(IPConnection.ERROR_INVALID_PARAMETER);');
                        }

                        handleResponseDevice.expectedResponses.splice(i, 1);
                        return;
                    }

                    if (this.getEFromPacket(packetResponse) === 2) {
                        if (expectedResponse.errorCB !== undefined) {
                            eval('expectedResponse.errorCB(IPConnection.ERROR_FUNCTION_NOT_SUPPORTED);');
                        }

                        handleResponseDevice.expectedResponses.splice(i, 1);
                        return;
                    }

                    if (this.getEFromPacket(packetResponse) !== 0) {
                        if (expectedResponse.errorCB !== undefined) {
                            eval('expectedResponse.errorCB(IPConnection.ERROR_UNKNOWN_ERROR);');
                        }

                        handleResponseDevice.expectedResponses.splice(i, 1);
                        return;
                    }

                    if (expectedResponse.expectedResponseLength === 0) {
                        // setter with response-expected enabled
                        expectedResponse.expectedResponseLength = 8;
                    }

                    if (packetResponse.length != expectedResponse.expectedResponseLength) {
                        if (expectedResponse.errorCB !== undefined) {
                            eval('expectedResponse.errorCB(IPConnection.ERROR_WRONG_RESPONSE_LENGTH);');
                        }

                        handleResponseDevice.expectedResponses.splice(i, 1);
                        return;
                    }

                    if (expectedResponse.returnCB !== undefined) {
                        var retArgs = this.unpack(this.getPayloadFromPacket(packetResponse),
                                                  expectedResponse.unpackFormat);
                        var evalStr = 'expectedResponse.returnCB(';

                        for (var j = 0; j < retArgs.length; j++) {
                            eval('var retSingleArg' + j + ' = retArgs[' + j + '];');

                            evalStr += 'retSingleArg' + j;

                            if (j != retArgs.length - 1) {
                                evalStr += ', ';
                            }
                        }

                        eval(evalStr + ');');
                    }

                    handleResponseDevice.expectedResponses.splice(i, 1);
                    return;
                }
            }
        }
        // Handle streamed response
        else {
            streamStateObject = handleResponseDevice.streamStateObjects[handleResponseFID];

            if (streamStateObject === null) {
                return;
            }

            if (!streamStateObject['responseProperties']['running']) {
                handleResponseDevice.resetStreamStateObject(streamStateObject);
                return;
            }

            if (streamStateObject['responseProperties']['responseHandler'] === null) {
                handleResponseDevice.resetStreamStateObject(streamStateObject);
                return;
            }

            streamStateObject['responseProperties']['responseHandler'](handleResponseDevice,
                                                                       handleResponseFID,
                                                                       packetResponse);
        }
    };

    this.handleCallback = function (packetCallback) {
        var functionID = this.getFunctionIDFromPacket(packetCallback);

        if (functionID === IPConnection.CALLBACK_ENUMERATE) {
            var registeredCallback = this.registeredCallbacks[IPConnection.CALLBACK_ENUMERATE];

            if (registeredCallback !== undefined) {
                if (packetCallback.length != 34) {
                    return; // silently ignoring callback with wrong length
                }

                var args = this.unpack(this.getPayloadFromPacket(packetCallback), 's8 s8 c B3 B3 H B');
                var evalCBString = 'registeredCallback(';

                for (var i = 0; i < args.length; i++) {
                    eval('var cbArg' + i + ' = args[' + i + '];');

                    evalCBString += 'cbArg' + i;

                    if (i != args.length - 1) {
                        evalCBString += ', ';
                    }
                }

                eval(evalCBString + ');');
            }

            return;
        }

        var device = this.devices[this.getUIDFromPacket(packetCallback)];

        if (device === undefined) {
            return;
        }

        if ((device.registeredCallbacks[functionID] === undefined &&
             device.registeredCallbacks[-functionID] === undefined) ||
             device.callbackFormats[functionID] === undefined) {
            return;
        }

        var cbFunction = undefined;
        var cbUnpack = undefined;

        if (device.registeredCallbacks[functionID] !== undefined) {
            cbFunction = device.registeredCallbacks[functionID];
            cbUnpack = device.callbackFormats[functionID];
        } else if (device.registeredCallbacks[-functionID] !== undefined) {
            cbFunction = device.registeredCallbacks[-functionID];
            cbUnpack = device.callbackFormats[functionID];
        }

        if (cbFunction === undefined || cbUnpack === undefined) {
            return;
        }

        if (packetCallback.length != cbUnpack[0]) {
            return; // silently ignoring callback with wrong length
        }

        // llvalues is an array with unpacked values
        var llvalues = this.unpack(this.getPayloadFromPacket(packetCallback), cbUnpack[1]);

        // Process high-level callback
        if (-functionID in device.registeredCallbacks) {
            var length = 0;
            var chunkOffset = 0;
            var chunkData = null;
            var hlcb = device.highLevelCallbacks[-functionID];
            // FIXME: currently assuming that cbUnpack is longer than 1
            var data = null;
            var hasData = false;

            if (hlcb[1]['fixedLength'] !== null) {
                length = hlcb[1]['fixedLength'];
            } else {
                length = llvalues[hlcb[0].indexOf('streamLength')];
            }

            if (!hlcb[1]['singleChunk']) {
                chunkOffset = llvalues[hlcb[0].indexOf('streamChunkOffset')];
            } else {
                chunkOffset = 0;
            }

            chunkData = llvalues[hlcb[0].indexOf('streamChunkData')];

            if (hlcb[2] === null) { // No stream in-progress
                if (chunkOffset === 0) { // Stream starts
                    hlcb[2] = chunkData;

                    if (hlcb[2].length >= length) { // Stream complete
                        hasData = true;
                        data = hlcb[2].splice(0, length);
                    }
                } else {
                    // Ignore tail of current stream, wait for next stream start
                }
            } else { // Stream in-progress
                if (chunkOffset !== hlcb[2].length) { // Stream out-of-sync
                    hasData = true;
                    data = null;
                } else { // Stream in-sync
                    hlcb[2] = hlcb[2].concat(chunkData);

                    if (hlcb[2].length >= length) { // Stream complete
                        hasData = true;
                        data = hlcb[2].splice(0, length);
                    }
                }
            }

            var registeredCallback = device.registeredCallbacks[-functionID];

            if (hasData && registeredCallback !== undefined) {
                var result = [];
                var rolesMappedData = [];
                var evalCBString = 'registeredCallback(';

                for (var i = 0; i < hlcb[0].length; i++) {
                    rolesMappedData.push({'role': hlcb[0][i], 'llvalue': llvalues[i]});
                }

                for (var i = 0; i < rolesMappedData.length; i++) {
                    if (rolesMappedData[i]['role'] === 'streamChunkData') {
                        result.push(data);
                    } else if (rolesMappedData[i]['role'] === null) {
                        result.push(rolesMappedData[i]['llvalue']);
                    }
                }

                for (var i = 0; i < result.length; i++) {
                    eval('var cbArg' + i + ' = result[' + i + '];');

                    evalCBString += 'cbArg' + i;

                    if (i != result.length - 1) {
                        evalCBString += ', ';
                    }
                }

                hlcb[2] = null;

                eval(evalCBString + ');');
            }
        }

        // Process normal or low-level callbacks
        var registeredCallback = device.registeredCallbacks[functionID];

        if (registeredCallback !== undefined) {
            var evalCBString = 'registeredCallback(';

            for (var i = 0; i < llvalues.length; i++) {
                eval('var cbArg' + i + ' = llvalues[' + i + '];');

                evalCBString += 'cbArg' + i;

                if (i != llvalues.length - 1) {
                    evalCBString += ', ';
                }
            }

            eval(evalCBString + ');');
        }
    };

    this.handlePacket = function (packet) {
        if (this.getSequenceNumberFromPacket(packet) === 0) {
            this.handleCallback(packet);
        }

        if (this.getSequenceNumberFromPacket(packet) > 0) {
            this.handleResponse(packet);
        }
    };

    this.getConnectionState = function () {
        if (this.isConnected) {
            return IPConnection.CONNECTION_STATE_CONNECTED;
        }

        if (this.getCurrentTaskKind() === IPConnection.TASK_KIND_AUTO_RECONNECT) {
            return IPConnection.CONNECTION_STATE_PENDING;
        }

        return IPConnection.CONNECTION_STATE_DISCONNECTED;
    };

    this.setAutoReconnect = function (autoReconnect) {
        this.autoReconnect = autoReconnect;
    };

    this.getAutoReconnect = function () {
        return this.autoReconnect;
    };

    this.setTimeout = function (timeout) {
        this.timeout = timeout;
    };

    this.getTimeout = function () {
        return this.timeout;
    };

    this.enumerate = function (errorCallback) {
        if (this.getConnectionState() !== IPConnection.CONNECTION_STATE_CONNECTED) {
            if (errorCallback !== undefined) {
                errorCallback(IPConnection.ERROR_NOT_CONNECTED);
            }

            return;
        }

        this.socket.write(this.createPacketHeader(undefined, 8, IPConnection.FUNCTION_ENUMERATE), true);
    };

    this.getRandomUInt32 = function (returnCallback) {
        if (process.browser) {
            if (typeof window !== 'undefined' && window.crypto && window.crypto.getRandomValues) {
                var r = new Uint32Array(1);
                window.crypto.getRandomValues(r);
                returnCallback(r[0]);
            } else if (typeof window !== 'undefined' && window.msCrypto && window.msCrypto.getRandomValues) {
                var r = new Uint32Array(1);
                window.msCrypto.getRandomValues(r);
                returnCallback(r[0]);
            } else {
                // fallback to non-crypto random numbers
                returnCallback(Math.ceil(Math.random() * 4294967295));
            }
        } else {
            var crypto = require('crypto');

            crypto.randomBytes(4, function(error, buffer) {
                if (error) {
                    crypto.pseudoRandomBytes(4, function(error, buffer) {
                        if (error) {
                            returnCallback(Math.ceil(Math.random() * 4294967295));
                        } else {
                            var data = buffer_wrapper(buffer);
                            returnCallback(data.readUInt32LE(0));
                        }
                    });
                } else {
                    var data = buffer_wrapper(buffer);
                    returnCallback(data.readUInt32LE(0));
                }
            });
        }
    };

    function isASCII(s) {
        for (var i = 0; i < s.length; ++i) {
            if (s.charCodeAt(i) > 0x7f) {
                return false;
            }
        }
        return true;
    }

    this.authenticateInternal = function (secret, returnCallback, errorCallback) {
        if (!isASCII(secret)) {
            errorCallback(IPConnection.ERROR_NON_ASCII_CHAR_IN_SECRET);
        }

        this.brickd.getAuthenticationNonce(function (serverNonce) {
            var clientNonceNumber = this.nextAuthenticationNonce++;
            var clientNonceBytes = this.pack([clientNonceNumber], 'I');
            var clientNonce = this.unpack(clientNonceBytes, 'B4')[0];
            var combinedNonceBytes = this.pack([serverNonce, clientNonce], 'B4 B4');
            var crypto = require('crypto');
            var hmac = crypto.createHmac('sha1', secret);

            hmac.update(combinedNonceBytes);

            var digestBytes = hmac.digest();
            var digest = this.unpack(digestBytes, 'B20')[0];

            this.brickd.authenticate(clientNonce, digest,
                function () {
                    if (returnCallback !== undefined) {
                        returnCallback();
                    }

                    this.popTask();
                }.bind(this),
                function (error) {
                    if (errorCallback !== undefined) {
                        errorCallback(error);
                    }

                    this.popTask();
                }.bind(this)
            );
        }.bind(this), function (error) {
            if (errorCallback !== undefined) {
                errorCallback(error);
            }

            this.popTask();
        }.bind(this));
    };

    this.authenticate = function (secret, returnCallback, errorCallback) {
        // need to do authenticate() as a task because two authenticate() calls
        // are not allowed to overlap, otherwise the correct order of operations
        // in the handshake process cannot be guaranteed
        this.pushTask(function () {
            if (this.nextAuthenticationNonce === 0) {
                this.getRandomUInt32(function (r) {
                    this.nextAuthenticationNonce = r;
                    this.authenticateInternal(secret, returnCallback, errorCallback);
                }.bind(this));
            } else {
                this.authenticateInternal(secret, returnCallback, errorCallback);
            }
        }.bind(this), IPConnection.TASK_KIND_AUTHENTICATE);
    };

    this.on = function (callbackID, function_) {
        this.registeredCallbacks[callbackID] = function_;
    };

    this.getNextSequenceNumber = function () {
        if (this.nextSequenceNumber >= 15) {
            this.nextSequenceNumber = 0;
        }

        return ++this.nextSequenceNumber;
    };

    this.createPacketHeader = function (headerDevice, headerLength, headerFunctionID, headerErrorCB) {
        var UID = IPConnection.BROADCAST_UID;
        var len = headerLength;
        var FID = headerFunctionID;
        var seq = this.getNextSequenceNumber();
        var responseBits = 0;
        var EFutureUse = 0;
        var returnOnError = false;

        if (headerDevice !== undefined) {
            var responseExpected = headerDevice.getResponseExpected(headerFunctionID,
                function (errorCode) {
                    returnOnError = true;

                    if (headerErrorCB !== undefined) {
                        headerErrorCB(errorCode);
                    }
                }
            );

            if (returnOnError) {
                returnOnError = false;
                return;
            }

            UID = headerDevice.uid;

            if (responseExpected) {
                responseBits = 1;
            }
        }

        var seqResponseOOBits = seq << 4;

        if (responseBits) {
            seqResponseOOBits |= (responseBits << 3);
        }

        var returnHeader = buffer_wrapper(8);
        returnHeader.writeUInt32LE(UID, 0);
        returnHeader.writeUInt8(len, 4);
        returnHeader.writeUInt8(FID, 5);
        returnHeader.writeUInt8(seqResponseOOBits, 6);
        returnHeader.writeUInt8(EFutureUse , 7);

        return returnHeader;
    };

    this.createChunkData = function(data, chunkOffset, chunkLength, chunkPadding) {
        var padding = null;
        var chunkData = data.slice(chunkOffset, chunkOffset + chunkLength);

        if (chunkData.length < chunkLength) {
            padding = new Array(chunkLength - chunkData.length);
            padding.fill(chunkPadding);
            chunkData = chunkData.concat(padding);
        }

        return chunkData;
    };

    function bufferConcat(arrayOfBuffers) {
        var newBufferSize = 0;
        var targetStart = 0;

        for (var i = 0; i < arrayOfBuffers.length; i++) {
            newBufferSize += arrayOfBuffers[i].length;
        }

        var returnBufferConcat = buffer_wrapper(newBufferSize);

        for (var j = 0; j < arrayOfBuffers.length; j++) {
            arrayOfBuffers[j].copy(returnBufferConcat, targetStart);
            targetStart += arrayOfBuffers[j].length;
        }

        return returnBufferConcat;
    }

    // new Buffer() is deprecated since nodejs v10.0.0. Use recommended replacements
    // as described here: https://nodejs.org/en/docs/guides/buffer-constructor-deprecation
    // Fallback to buffer constructor to be compatible to v0.10.x.
    function buffer_wrapper(size_or_array, encoding) {
        var result = null;
        if (typeof size_or_array === 'number') {
            if (Buffer.alloc) {
                result = Buffer.alloc(size_or_array);
            }
            else {
                var buf = new Buffer(size_or_array);
                buf.fill(0);
                result = buf;
            }
        } else {
            if (Buffer.from && Buffer.from !== Uint8Array.from) {
                result = Buffer.from(size_or_array, encoding);
            } else {
                result = new Buffer(size_or_array, encoding);
            }
        }

        result.writeBigInt64LE = function(value, offset) {
            for(var i = 0; i < 8; ++i) {
                this[offset + i] = Number(value & BigInt(0xFF));
                value >>= BigInt(8);
            }
        }

        result.writeBigUInt64LE = function(value, offset) {
            for(var i = 0; i < 8; ++i) {
                this[offset + i] = Number(value & BigInt(0xFF));
                value >>= BigInt(8);
            }
        }

        result.readBigInt64LE = function(offset) {
            var result = BigInt(0);
            for(var i = 0; i < 7; ++i) {
                result |= BigInt(this[offset + i]) << BigInt(i * 8);
            }
            return (BigInt(this[offset + 7] << 24) << BigInt(32)) + result;
        }

        result.readBigUInt64LE = function(offset) {
            var result = BigInt(0);
            for(var i = 0; i < 8; ++i) {
                result |= BigInt(this[offset + i]) << BigInt(i * 8);
            }
            return result;
        }

        return result;
    }
}

module.exports = IPConnection;

}).call(this,require('_process'),require("buffer").Buffer)
},{"./Device":279,"_process":105,"buffer":45,"crypto":56,"net":44}],281:[function(require,module,exports){
/*!
 * https://github.com/es-shims/es5-shim
 * @license es5-shim Copyright 2009-2020 by contributors, MIT License
 * see https://github.com/es-shims/es5-shim/blob/v4.5.14/LICENSE
 */
(function(e,t){"use strict";if(typeof define==="function"&&define.amd){define(t)}else if(typeof exports==="object"){module.exports=t()}else{e.returnExports=t()}})(this,function(){var e=Function.call;var t=Object.prototype;var r=e.bind(t.hasOwnProperty);var n=e.bind(t.propertyIsEnumerable);var o=e.bind(t.toString);var i;var c;var f;var a;var l=r(t,"__defineGetter__");if(l){i=e.bind(t.__defineGetter__);c=e.bind(t.__defineSetter__);f=e.bind(t.__lookupGetter__);a=e.bind(t.__lookupSetter__)}var u=function isPrimitive(e){return e==null||typeof e!=="object"&&typeof e!=="function"};if(!Object.getPrototypeOf){Object.getPrototypeOf=function getPrototypeOf(e){var r=e.__proto__;if(r||r===null){return r}else if(o(e.constructor)==="[object Function]"){return e.constructor.prototype}else if(e instanceof Object){return t}else{return null}}}if(Object.defineProperty){var s=function doesGetOwnPropertyDescriptorWork(e){try{e.sentinel=0;return Object.getOwnPropertyDescriptor(e,"sentinel").value===0}catch(t){return false}};var p=s({});var b=typeof document==="undefined"||s(document.createElement("div"));if(!b||!p){var O=Object.getOwnPropertyDescriptor}}if(!Object.getOwnPropertyDescriptor||O){var d="Object.getOwnPropertyDescriptor called on a non-object: ";Object.getOwnPropertyDescriptor=function getOwnPropertyDescriptor(e,o){if(u(e)){throw new TypeError(d+e)}if(O){try{return O.call(Object,e,o)}catch(i){}}var c;if(!r(e,o)){return c}c={enumerable:n(e,o),configurable:true};if(l){var s=e.__proto__;var p=e!==t;if(p){e.__proto__=t}var b=f(e,o);var y=a(e,o);if(p){e.__proto__=s}if(b||y){if(b){c.get=b}if(y){c.set=y}return c}}c.value=e[o];c.writable=true;return c}}if(!Object.getOwnPropertyNames){Object.getOwnPropertyNames=function getOwnPropertyNames(e){return Object.keys(e)}}if(!Object.create){var y;var j=!({__proto__:null}instanceof Object);var v=function shouldUseActiveX(){if(!document.domain){return false}try{return!!new ActiveXObject("htmlfile")}catch(e){return false}};var _=function getEmptyViaActiveX(){var e;var t;t=new ActiveXObject("htmlfile");var r="script";t.write("<"+r+"></"+r+">");t.close();e=t.parentWindow.Object.prototype;t=null;return e};var w=function getEmptyViaIFrame(){var e=document.createElement("iframe");var t=document.body||document.documentElement;var r;e.style.display="none";t.appendChild(e);e.src="javascript:";r=e.contentWindow.Object.prototype;t.removeChild(e);e=null;return r};if(j||typeof document==="undefined"){y=function(){return{__proto__:null}}}else{y=function(){var e=v()?_():w();delete e.constructor;delete e.hasOwnProperty;delete e.propertyIsEnumerable;delete e.isPrototypeOf;delete e.toLocaleString;delete e.toString;delete e.valueOf;var t=function Empty(){};t.prototype=e;y=function(){return new t};return new t}}Object.create=function create(e,t){var r;var n=function Type(){};if(e===null){r=y()}else if(u(e)){throw new TypeError("Object prototype may only be an Object or null")}else{n.prototype=e;r=new n;r.__proto__=e}if(t!==void 0){Object.defineProperties(r,t)}return r}}var m=function doesDefinePropertyWork(e){try{Object.defineProperty(e,"sentinel",{});return"sentinel"in e}catch(t){return false}};if(Object.defineProperty){var P=m({});var E=typeof document==="undefined"||m(document.createElement("div"));if(!P||!E){var h=Object.defineProperty,g=Object.defineProperties}}if(!Object.defineProperty||h){var z="Property description must be an object: ";var T="Object.defineProperty called on non-object: ";var x="getters & setters can not be defined on this javascript engine";Object.defineProperty=function defineProperty(e,r,n){if(u(e)){throw new TypeError(T+e)}if(u(n)){throw new TypeError(z+n)}if(h){try{return h.call(Object,e,r,n)}catch(o){}}if("value"in n){if(l&&(f(e,r)||a(e,r))){var s=e.__proto__;e.__proto__=t;delete e[r];e[r]=n.value;e.__proto__=s}else{e[r]=n.value}}else{var p="get"in n;var b="set"in n;if(!l&&(p||b)){throw new TypeError(x)}if(p){i(e,r,n.get)}if(b){c(e,r,n.set)}}return e}}if(!Object.defineProperties||g){Object.defineProperties=function defineProperties(e,t){if(g){try{return g.call(Object,e,t)}catch(r){}}Object.keys(t).forEach(function(r){if(r!=="__proto__"){Object.defineProperty(e,r,t[r])}});return e}}if(!Object.seal){Object.seal=function seal(e){if(Object(e)!==e){throw new TypeError("Object.seal can only be called on Objects.")}return e}}if(!Object.freeze){Object.freeze=function freeze(e){if(Object(e)!==e){throw new TypeError("Object.freeze can only be called on Objects.")}return e}}try{Object.freeze(function(){})}catch(S){Object.freeze=function(e){return function freeze(t){if(typeof t==="function"){return t}else{return e(t)}}}(Object.freeze)}if(!Object.preventExtensions){Object.preventExtensions=function preventExtensions(e){if(Object(e)!==e){throw new TypeError("Object.preventExtensions can only be called on Objects.")}return e}}if(!Object.isSealed){Object.isSealed=function isSealed(e){if(Object(e)!==e){throw new TypeError("Object.isSealed can only be called on Objects.")}return false}}if(!Object.isFrozen){Object.isFrozen=function isFrozen(e){if(Object(e)!==e){throw new TypeError("Object.isFrozen can only be called on Objects.")}return false}}if(!Object.isExtensible){Object.isExtensible=function isExtensible(e){if(Object(e)!==e){throw new TypeError("Object.isExtensible can only be called on Objects.")}var t="";while(r(e,t)){t+="?"}e[t]=true;var n=r(e,t);delete e[t];return n}}});


},{}],282:[function(require,module,exports){
/*!
 * https://github.com/es-shims/es5-shim
 * @license es5-shim Copyright 2009-2020 by contributors, MIT License
 * see https://github.com/es-shims/es5-shim/blob/v4.5.14/LICENSE
 */
(function(t,r){"use strict";if(typeof define==="function"&&define.amd){define(r)}else if(typeof exports==="object"){module.exports=r()}else{t.returnExports=r()}})(this,function(){var t=Array;var r=t.prototype;var e=Object;var n=e.prototype;var i=Function;var a=i.prototype;var o=String;var f=o.prototype;var u=Number;var l=u.prototype;var s=r.slice;var c=r.splice;var v=r.push;var h=r.unshift;var p=r.concat;var y=r.join;var d=a.call;var g=a.apply;var w=Math.max;var b=Math.min;var T=n.toString;var m=typeof Symbol==="function"&&typeof Symbol.toStringTag==="symbol";var D;var S=Function.prototype.toString,x=/^\s*class /,O=function isES6ClassFn(t){try{var r=S.call(t);var e=r.replace(/\/\/.*\n/g,"");var n=e.replace(/\/\*[.\s\S]*\*\//g,"");var i=n.replace(/\n/gm," ").replace(/ {2}/g," ");return x.test(i)}catch(a){return false}},E=function tryFunctionObject(t){try{if(O(t)){return false}S.call(t);return true}catch(r){return false}},j="[object Function]",I="[object GeneratorFunction]",D=function isCallable(t){if(!t){return false}if(typeof t!=="function"&&typeof t!=="object"){return false}if(m){return E(t)}if(O(t)){return false}var r=T.call(t);return r===j||r===I};var M;var U=RegExp.prototype.exec,$=function tryRegexExec(t){try{U.call(t);return true}catch(r){return false}},F="[object RegExp]";M=function isRegex(t){if(typeof t!=="object"){return false}return m?$(t):T.call(t)===F};var N;var C=String.prototype.valueOf,k=function tryStringObject(t){try{C.call(t);return true}catch(r){return false}},A="[object String]";N=function isString(t){if(typeof t==="string"){return true}if(typeof t!=="object"){return false}return m?k(t):T.call(t)===A};var R=e.defineProperty&&function(){try{var t={};e.defineProperty(t,"x",{enumerable:false,value:t});for(var r in t){return false}return t.x===t}catch(n){return false}}();var P=function(t){var r;if(R){r=function(t,r,n,i){if(!i&&r in t){return}e.defineProperty(t,r,{configurable:true,enumerable:false,writable:true,value:n})}}else{r=function(t,r,e,n){if(!n&&r in t){return}t[r]=e}}return function defineProperties(e,n,i){for(var a in n){if(t.call(n,a)){r(e,a,n[a],i)}}}}(n.hasOwnProperty);var J=function isPrimitive(t){var r=typeof t;return t===null||r!=="object"&&r!=="function"};var Y=u.isNaN||function isActualNaN(t){return t!==t};var z={ToInteger:function ToInteger(t){var r=+t;if(Y(r)){r=0}else if(r!==0&&r!==1/0&&r!==-(1/0)){r=(r>0||-1)*Math.floor(Math.abs(r))}return r},ToPrimitive:function ToPrimitive(t){var r,e,n;if(J(t)){return t}e=t.valueOf;if(D(e)){r=e.call(t);if(J(r)){return r}}n=t.toString;if(D(n)){r=n.call(t);if(J(r)){return r}}throw new TypeError},ToObject:function(t){if(t==null){throw new TypeError("can't convert "+t+" to object")}return e(t)},ToUint32:function ToUint32(t){return t>>>0}};var Z=function Empty(){};P(a,{bind:function bind(t){var r=this;if(!D(r)){throw new TypeError("Function.prototype.bind called on incompatible "+r)}var n=s.call(arguments,1);var a;var o=function(){if(this instanceof a){var i=g.call(r,this,p.call(n,s.call(arguments)));if(e(i)===i){return i}return this}else{return g.call(r,t,p.call(n,s.call(arguments)))}};var f=w(0,r.length-n.length);var u=[];for(var l=0;l<f;l++){v.call(u,"$"+l)}a=i("binder","return function ("+y.call(u,",")+"){ return binder.apply(this, arguments); }")(o);if(r.prototype){Z.prototype=r.prototype;a.prototype=new Z;Z.prototype=null}return a}});var G=d.bind(n.hasOwnProperty);var H=d.bind(n.toString);var W=d.bind(s);var B=g.bind(s);if(typeof document==="object"&&document&&document.documentElement){try{W(document.documentElement.childNodes)}catch(X){var L=W;var q=B;W=function arraySliceIE(t){var r=[];var e=t.length;while(e-- >0){r[e]=t[e]}return q(r,L(arguments,1))};B=function arraySliceApplyIE(t,r){return q(W(t),r)}}}var K=d.bind(f.slice);var Q=d.bind(f.split);var V=d.bind(f.indexOf);var _=d.bind(v);var tt=d.bind(n.propertyIsEnumerable);var rt=d.bind(r.sort);var et=t.isArray||function isArray(t){return H(t)==="[object Array]"};var nt=[].unshift(0)!==1;P(r,{unshift:function(){h.apply(this,arguments);return this.length}},nt);P(t,{isArray:et});var it=e("a");var at=it[0]!=="a"||!(0 in it);var ot=function properlyBoxed(t){var r=true;var e=true;var n=false;if(t){try{t.call("foo",function(t,e,n){if(typeof n!=="object"){r=false}});t.call([1],function(){"use strict";e=typeof this==="string"},"x")}catch(i){n=true}}return!!t&&!n&&r&&e};P(r,{forEach:function forEach(t){var r=z.ToObject(this);var e=at&&N(this)?Q(this,""):r;var n=-1;var i=z.ToUint32(e.length);var a;if(arguments.length>1){a=arguments[1]}if(!D(t)){throw new TypeError("Array.prototype.forEach callback must be a function")}while(++n<i){if(n in e){if(typeof a==="undefined"){t(e[n],n,r)}else{t.call(a,e[n],n,r)}}}}},!ot(r.forEach));P(r,{map:function map(r){var e=z.ToObject(this);var n=at&&N(this)?Q(this,""):e;var i=z.ToUint32(n.length);var a=t(i);var o;if(arguments.length>1){o=arguments[1]}if(!D(r)){throw new TypeError("Array.prototype.map callback must be a function")}for(var f=0;f<i;f++){if(f in n){if(typeof o==="undefined"){a[f]=r(n[f],f,e)}else{a[f]=r.call(o,n[f],f,e)}}}return a}},!ot(r.map));P(r,{filter:function filter(t){var r=z.ToObject(this);var e=at&&N(this)?Q(this,""):r;var n=z.ToUint32(e.length);var i=[];var a;var o;if(arguments.length>1){o=arguments[1]}if(!D(t)){throw new TypeError("Array.prototype.filter callback must be a function")}for(var f=0;f<n;f++){if(f in e){a=e[f];if(typeof o==="undefined"?t(a,f,r):t.call(o,a,f,r)){_(i,a)}}}return i}},!ot(r.filter));P(r,{every:function every(t){var r=z.ToObject(this);var e=at&&N(this)?Q(this,""):r;var n=z.ToUint32(e.length);var i;if(arguments.length>1){i=arguments[1]}if(!D(t)){throw new TypeError("Array.prototype.every callback must be a function")}for(var a=0;a<n;a++){if(a in e&&!(typeof i==="undefined"?t(e[a],a,r):t.call(i,e[a],a,r))){return false}}return true}},!ot(r.every));P(r,{some:function some(t){var r=z.ToObject(this);var e=at&&N(this)?Q(this,""):r;var n=z.ToUint32(e.length);var i;if(arguments.length>1){i=arguments[1]}if(!D(t)){throw new TypeError("Array.prototype.some callback must be a function")}for(var a=0;a<n;a++){if(a in e&&(typeof i==="undefined"?t(e[a],a,r):t.call(i,e[a],a,r))){return true}}return false}},!ot(r.some));var ft=false;if(r.reduce){ft=typeof r.reduce.call("es5",function(t,r,e,n){return n})==="object"}P(r,{reduce:function reduce(t){var r=z.ToObject(this);var e=at&&N(this)?Q(this,""):r;var n=z.ToUint32(e.length);if(!D(t)){throw new TypeError("Array.prototype.reduce callback must be a function")}if(n===0&&arguments.length===1){throw new TypeError("reduce of empty array with no initial value")}var i=0;var a;if(arguments.length>=2){a=arguments[1]}else{do{if(i in e){a=e[i++];break}if(++i>=n){throw new TypeError("reduce of empty array with no initial value")}}while(true)}for(;i<n;i++){if(i in e){a=t(a,e[i],i,r)}}return a}},!ft);var ut=false;if(r.reduceRight){ut=typeof r.reduceRight.call("es5",function(t,r,e,n){return n})==="object"}P(r,{reduceRight:function reduceRight(t){var r=z.ToObject(this);var e=at&&N(this)?Q(this,""):r;var n=z.ToUint32(e.length);if(!D(t)){throw new TypeError("Array.prototype.reduceRight callback must be a function")}if(n===0&&arguments.length===1){throw new TypeError("reduceRight of empty array with no initial value")}var i;var a=n-1;if(arguments.length>=2){i=arguments[1]}else{do{if(a in e){i=e[a--];break}if(--a<0){throw new TypeError("reduceRight of empty array with no initial value")}}while(true)}if(a<0){return i}do{if(a in e){i=t(i,e[a],a,r)}}while(a--);return i}},!ut);var lt=r.indexOf&&[0,1].indexOf(1,2)!==-1;P(r,{indexOf:function indexOf(t){var r=at&&N(this)?Q(this,""):z.ToObject(this);var e=z.ToUint32(r.length);if(e===0){return-1}var n=0;if(arguments.length>1){n=z.ToInteger(arguments[1])}n=n>=0?n:w(0,e+n);for(;n<e;n++){if(n in r&&r[n]===t){return n}}return-1}},lt);var st=r.lastIndexOf&&[0,1].lastIndexOf(0,-3)!==-1;P(r,{lastIndexOf:function lastIndexOf(t){var r=at&&N(this)?Q(this,""):z.ToObject(this);var e=z.ToUint32(r.length);if(e===0){return-1}var n=e-1;if(arguments.length>1){n=b(n,z.ToInteger(arguments[1]))}n=n>=0?n:e-Math.abs(n);for(;n>=0;n--){if(n in r&&t===r[n]){return n}}return-1}},st);var ct=function(){var t=[1,2];var r=t.splice();return t.length===2&&et(r)&&r.length===0}();P(r,{splice:function splice(t,r){if(arguments.length===0){return[]}else{return c.apply(this,arguments)}}},!ct);var vt=function(){var t={};r.splice.call(t,0,0,1);return t.length===1}();P(r,{splice:function splice(t,r){if(arguments.length===0){return[]}var e=arguments;this.length=w(z.ToInteger(this.length),0);if(arguments.length>0&&typeof r!=="number"){e=W(arguments);if(e.length<2){_(e,this.length-t)}else{e[1]=z.ToInteger(r)}}return c.apply(this,e)}},!vt);var ht=function(){var r=new t(1e5);r[8]="x";r.splice(1,1);return r.indexOf("x")===7}();var pt=function(){var t=256;var r=[];r[t]="a";r.splice(t+1,0,"b");return r[t]==="a"}();P(r,{splice:function splice(t,r){var e=z.ToObject(this);var n=[];var i=z.ToUint32(e.length);var a=z.ToInteger(t);var f=a<0?w(i+a,0):b(a,i);var u=arguments.length===0?0:arguments.length===1?i-f:b(w(z.ToInteger(r),0),i-f);var l=0;var s;while(l<u){s=o(f+l);if(G(e,s)){n[l]=e[s]}l+=1}var c=W(arguments,2);var v=c.length;var h;if(v<u){l=f;var p=i-u;while(l<p){s=o(l+u);h=o(l+v);if(G(e,s)){e[h]=e[s]}else{delete e[h]}l+=1}l=i;var y=i-u+v;while(l>y){delete e[l-1];l-=1}}else if(v>u){l=i-u;while(l>f){s=o(l+u-1);h=o(l+v-1);if(G(e,s)){e[h]=e[s]}else{delete e[h]}l-=1}}l=f;for(var d=0;d<c.length;++d){e[l]=c[d];l+=1}e.length=i-u+v;return n}},!ht||!pt);var yt=r.join;var dt;try{dt=Array.prototype.join.call("123",",")!=="1,2,3"}catch(X){dt=true}if(dt){P(r,{join:function join(t){var r=typeof t==="undefined"?",":t;return yt.call(N(this)?Q(this,""):this,r)}},dt)}var gt=[1,2].join(undefined)!=="1,2";if(gt){P(r,{join:function join(t){var r=typeof t==="undefined"?",":t;return yt.call(this,r)}},gt)}var wt=function push(t){var r=z.ToObject(this);var e=z.ToUint32(r.length);var n=0;while(n<arguments.length){r[e+n]=arguments[n];n+=1}r.length=e+n;return e+n};var bt=function(){var t={};var r=Array.prototype.push.call(t,undefined);return r!==1||t.length!==1||typeof t[0]!=="undefined"||!G(t,0)}();P(r,{push:function push(t){if(et(this)){return v.apply(this,arguments)}return wt.apply(this,arguments)}},bt);var Tt=function(){var t=[];var r=t.push(undefined);return r!==1||t.length!==1||typeof t[0]!=="undefined"||!G(t,0)}();P(r,{push:wt},Tt);P(r,{slice:function(t,r){var e=N(this)?Q(this,""):this;return B(e,arguments)}},at);var mt=function(){try{[1,2].sort(null)}catch(t){try{[1,2].sort({})}catch(r){return false}}return true}();var Dt=function(){try{[1,2].sort(/a/);return false}catch(t){}return true}();var St=function(){try{[1,2].sort(undefined);return true}catch(t){}return false}();P(r,{sort:function sort(t){if(typeof t==="undefined"){return rt(this)}if(!D(t)){throw new TypeError("Array.prototype.sort callback must be a function")}return rt(this,t)}},mt||!St||!Dt);var xt=!tt({toString:null},"toString");var Ot=tt(function(){},"prototype");var Et=!G("x","0");var jt=function(t){var r=t.constructor;return r&&r.prototype===t};var It={$applicationCache:true,$console:true,$external:true,$frame:true,$frameElement:true,$frames:true,$innerHeight:true,$innerWidth:true,$onmozfullscreenchange:true,$onmozfullscreenerror:true,$outerHeight:true,$outerWidth:true,$pageXOffset:true,$pageYOffset:true,$parent:true,$scrollLeft:true,$scrollTop:true,$scrollX:true,$scrollY:true,$self:true,$webkitIndexedDB:true,$webkitStorageInfo:true,$window:true,$width:true,$height:true,$top:true,$localStorage:true};var Mt=function(){if(typeof window==="undefined"){return false}for(var t in window){try{if(!It["$"+t]&&G(window,t)&&window[t]!==null&&typeof window[t]==="object"){jt(window[t])}}catch(r){return true}}return false}();var Ut=function(t){if(typeof window==="undefined"||!Mt){return jt(t)}try{return jt(t)}catch(r){return false}};var $t=["toString","toLocaleString","valueOf","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","constructor"];var Ft=$t.length;var Nt=function isArguments(t){return H(t)==="[object Arguments]"};var Ct=function isArguments(t){return t!==null&&typeof t==="object"&&typeof t.length==="number"&&t.length>=0&&!et(t)&&D(t.callee)};var kt=Nt(arguments)?Nt:Ct;P(e,{keys:function keys(t){var r=D(t);var e=kt(t);var n=t!==null&&typeof t==="object";var i=n&&N(t);if(!n&&!r&&!e){throw new TypeError("Object.keys called on a non-object")}var a=[];var f=Ot&&r;if(i&&Et||e){for(var u=0;u<t.length;++u){_(a,o(u))}}if(!e){for(var l in t){if(!(f&&l==="prototype")&&G(t,l)){_(a,o(l))}}}if(xt){var s=Ut(t);for(var c=0;c<Ft;c++){var v=$t[c];if(!(s&&v==="constructor")&&G(t,v)){_(a,v)}}}return a}});var At=e.keys&&function(){return e.keys(arguments).length===2}(1,2);var Rt=e.keys&&function(){var t=e.keys(arguments);return arguments.length!==1||t.length!==1||t[0]!==1}(1);var Pt=e.keys;P(e,{keys:function keys(t){if(kt(t)){return Pt(W(t))}else{return Pt(t)}}},!At||Rt);var Jt=new Date(-0xc782b5b342b24).getUTCMonth()!==0;var Yt=new Date(-0x55d318d56a724);var zt=new Date(14496624e5);var Zt=Yt.toUTCString()!=="Mon, 01 Jan -45875 11:59:59 GMT";var Gt;var Ht;var Wt=Yt.getTimezoneOffset();if(Wt<-720){Gt=Yt.toDateString()!=="Tue Jan 02 -45875";Ht=!/^Thu Dec 10 2015 \d\d:\d\d:\d\d GMT[-+]\d\d\d\d(?: |$)/.test(String(zt))}else{Gt=Yt.toDateString()!=="Mon Jan 01 -45875";Ht=!/^Wed Dec 09 2015 \d\d:\d\d:\d\d GMT[-+]\d\d\d\d(?: |$)/.test(String(zt))}var Bt=d.bind(Date.prototype.getFullYear);var Xt=d.bind(Date.prototype.getMonth);var Lt=d.bind(Date.prototype.getDate);var qt=d.bind(Date.prototype.getUTCFullYear);var Kt=d.bind(Date.prototype.getUTCMonth);var Qt=d.bind(Date.prototype.getUTCDate);var Vt=d.bind(Date.prototype.getUTCDay);var _t=d.bind(Date.prototype.getUTCHours);var tr=d.bind(Date.prototype.getUTCMinutes);var rr=d.bind(Date.prototype.getUTCSeconds);var er=d.bind(Date.prototype.getUTCMilliseconds);var nr=["Sun","Mon","Tue","Wed","Thu","Fri","Sat"];var ir=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];var ar=function daysInMonth(t,r){return Lt(new Date(r,t,0))};P(Date.prototype,{getFullYear:function getFullYear(){if(!this||!(this instanceof Date)){throw new TypeError("this is not a Date object.")}var t=Bt(this);if(t<0&&Xt(this)>11){return t+1}return t},getMonth:function getMonth(){if(!this||!(this instanceof Date)){throw new TypeError("this is not a Date object.")}var t=Bt(this);var r=Xt(this);if(t<0&&r>11){return 0}return r},getDate:function getDate(){if(!this||!(this instanceof Date)){throw new TypeError("this is not a Date object.")}var t=Bt(this);var r=Xt(this);var e=Lt(this);if(t<0&&r>11){if(r===12){return e}var n=ar(0,t+1);return n-e+1}return e},getUTCFullYear:function getUTCFullYear(){if(!this||!(this instanceof Date)){throw new TypeError("this is not a Date object.")}var t=qt(this);if(t<0&&Kt(this)>11){return t+1}return t},getUTCMonth:function getUTCMonth(){if(!this||!(this instanceof Date)){throw new TypeError("this is not a Date object.")}var t=qt(this);var r=Kt(this);if(t<0&&r>11){return 0}return r},getUTCDate:function getUTCDate(){if(!this||!(this instanceof Date)){throw new TypeError("this is not a Date object.")}var t=qt(this);var r=Kt(this);var e=Qt(this);if(t<0&&r>11){if(r===12){return e}var n=ar(0,t+1);return n-e+1}return e}},Jt);P(Date.prototype,{toUTCString:function toUTCString(){if(!this||!(this instanceof Date)){throw new TypeError("this is not a Date object.")}var t=Vt(this);var r=Qt(this);var e=Kt(this);var n=qt(this);var i=_t(this);var a=tr(this);var o=rr(this);return nr[t]+", "+(r<10?"0"+r:r)+" "+ir[e]+" "+n+" "+(i<10?"0"+i:i)+":"+(a<10?"0"+a:a)+":"+(o<10?"0"+o:o)+" GMT"}},Jt||Zt);P(Date.prototype,{toDateString:function toDateString(){if(!this||!(this instanceof Date)){throw new TypeError("this is not a Date object.")}var t=this.getDay();var r=this.getDate();var e=this.getMonth();var n=this.getFullYear();return nr[t]+" "+ir[e]+" "+(r<10?"0"+r:r)+" "+n}},Jt||Gt);if(Jt||Ht){Date.prototype.toString=function toString(){if(!this||!(this instanceof Date)){throw new TypeError("this is not a Date object.")}var t=this.getDay();var r=this.getDate();var e=this.getMonth();var n=this.getFullYear();var i=this.getHours();var a=this.getMinutes();var o=this.getSeconds();var f=this.getTimezoneOffset();var u=Math.floor(Math.abs(f)/60);var l=Math.floor(Math.abs(f)%60);return nr[t]+" "+ir[e]+" "+(r<10?"0"+r:r)+" "+n+" "+(i<10?"0"+i:i)+":"+(a<10?"0"+a:a)+":"+(o<10?"0"+o:o)+" GMT"+(f>0?"-":"+")+(u<10?"0"+u:u)+(l<10?"0"+l:l)};if(R){e.defineProperty(Date.prototype,"toString",{configurable:true,enumerable:false,writable:true})}}var or=-621987552e5;var fr="-000001";var ur=Date.prototype.toISOString&&new Date(or).toISOString().indexOf(fr)===-1;var lr=Date.prototype.toISOString&&new Date(-1).toISOString()!=="1969-12-31T23:59:59.999Z";var sr=d.bind(Date.prototype.getTime);P(Date.prototype,{toISOString:function toISOString(){if(!isFinite(this)||!isFinite(sr(this))){throw new RangeError("Date.prototype.toISOString called on non-finite value.")}var t=qt(this);var r=Kt(this);t+=Math.floor(r/12);r=(r%12+12)%12;var e=[r+1,Qt(this),_t(this),tr(this),rr(this)];t=(t<0?"-":t>9999?"+":"")+K("00000"+Math.abs(t),0<=t&&t<=9999?-4:-6);for(var n=0;n<e.length;++n){e[n]=K("00"+e[n],-2)}return t+"-"+W(e,0,2).join("-")+"T"+W(e,2).join(":")+"."+K("000"+er(this),-3)+"Z"}},ur||lr);var cr=function(){try{return Date.prototype.toJSON&&new Date(NaN).toJSON()===null&&new Date(or).toJSON().indexOf(fr)!==-1&&Date.prototype.toJSON.call({toISOString:function(){return true}})}catch(t){return false}}();if(!cr){Date.prototype.toJSON=function toJSON(t){var r=e(this);var n=z.ToPrimitive(r);if(typeof n==="number"&&!isFinite(n)){return null}var i=r.toISOString;if(!D(i)){throw new TypeError("toISOString property is not callable")}return i.call(r)}}var vr=Date.parse("+033658-09-27T01:46:40.000Z")===1e15;var hr=!isNaN(Date.parse("2012-04-04T24:00:00.500Z"))||!isNaN(Date.parse("2012-11-31T23:59:59.000Z"))||!isNaN(Date.parse("2012-12-31T23:59:60.000Z"));var pr=isNaN(Date.parse("2000-01-01T00:00:00.000Z"));if(pr||hr||!vr){var yr=Math.pow(2,31)-1;var dr=Y(new Date(1970,0,1,0,0,0,yr+1).getTime());Date=function(t){var r=function Date(e,n,i,a,f,u,l){var s=arguments.length;var c;if(this instanceof t){var v=u;var h=l;if(dr&&s>=7&&l>yr){var p=Math.floor(l/yr)*yr;var y=Math.floor(p/1e3);v+=y;h-=y*1e3}c=s===1&&o(e)===e?new t(r.parse(e)):s>=7?new t(e,n,i,a,f,v,h):s>=6?new t(e,n,i,a,f,v):s>=5?new t(e,n,i,a,f):s>=4?new t(e,n,i,a):s>=3?new t(e,n,i):s>=2?new t(e,n):s>=1?new t(e instanceof t?+e:e):new t}else{c=t.apply(this,arguments)}if(!J(c)){P(c,{constructor:r},true)}return c};var e=new RegExp("^"+"(\\d{4}|[+-]\\d{6})"+"(?:-(\\d{2})"+"(?:-(\\d{2})"+"(?:"+"T(\\d{2})"+":(\\d{2})"+"(?:"+":(\\d{2})"+"(?:(\\.\\d{1,}))?"+")?"+"("+"Z|"+"(?:"+"([-+])"+"(\\d{2})"+":(\\d{2})"+")"+")?)?)?)?"+"$");var n=[0,31,59,90,120,151,181,212,243,273,304,334,365];var i=function dayFromMonth(t,r){var e=r>1?1:0;return n[r]+Math.floor((t-1969+e)/4)-Math.floor((t-1901+e)/100)+Math.floor((t-1601+e)/400)+365*(t-1970)};var a=function toUTC(r){var e=0;var n=r;if(dr&&n>yr){var i=Math.floor(n/yr)*yr;var a=Math.floor(i/1e3);e+=a;n-=a*1e3}return u(new t(1970,0,1,0,0,e,n))};for(var f in t){if(G(t,f)){r[f]=t[f]}}P(r,{now:t.now,UTC:t.UTC},true);r.prototype=t.prototype;P(r.prototype,{constructor:r},true);var l=function parse(r){var n=e.exec(r);if(n){var o=u(n[1]),f=u(n[2]||1)-1,l=u(n[3]||1)-1,s=u(n[4]||0),c=u(n[5]||0),v=u(n[6]||0),h=Math.floor(u(n[7]||0)*1e3),p=Boolean(n[4]&&!n[8]),y=n[9]==="-"?1:-1,d=u(n[10]||0),g=u(n[11]||0),w;var b=c>0||v>0||h>0;if(s<(b?24:25)&&c<60&&v<60&&h<1e3&&f>-1&&f<12&&d<24&&g<60&&l>-1&&l<i(o,f+1)-i(o,f)){w=((i(o,f)+l)*24+s+d*y)*60;w=((w+c+g*y)*60+v)*1e3+h;if(p){w=a(w)}if(-864e13<=w&&w<=864e13){return w}}return NaN}return t.parse.apply(this,arguments)};P(r,{parse:l});return r}(Date)}if(!Date.now){Date.now=function now(){return(new Date).getTime()}}var gr=l.toFixed&&(8e-5.toFixed(3)!=="0.000"||.9.toFixed(0)!=="1"||1.255.toFixed(2)!=="1.25"||(1000000000000000128).toFixed(0)!=="1000000000000000128");var wr={base:1e7,size:6,data:[0,0,0,0,0,0],multiply:function multiply(t,r){var e=-1;var n=r;while(++e<wr.size){n+=t*wr.data[e];wr.data[e]=n%wr.base;n=Math.floor(n/wr.base)}},divide:function divide(t){var r=wr.size;var e=0;while(--r>=0){e+=wr.data[r];wr.data[r]=Math.floor(e/t);e=e%t*wr.base}},numToString:function numToString(){var t=wr.size;var r="";while(--t>=0){if(r!==""||t===0||wr.data[t]!==0){var e=o(wr.data[t]);if(r===""){r=e}else{r+=K("0000000",0,7-e.length)+e}}}return r},pow:function pow(t,r,e){return r===0?e:r%2===1?pow(t,r-1,e*t):pow(t*t,r/2,e)},log:function log(t){var r=0;var e=t;while(e>=4096){r+=12;e/=4096}while(e>=2){r+=1;e/=2}return r}};var br=function toFixed(t){var r,e,n,i,a,f,l,s;r=u(t);r=Y(r)?0:Math.floor(r);if(r<0||r>20){throw new RangeError("Number.toFixed called with invalid number of decimals")}e=u(this);if(Y(e)){return"NaN"}if(e<=-1e21||e>=1e21){return o(e)}n="";if(e<0){n="-";e=-e}i="0";if(e>1e-21){a=wr.log(e*wr.pow(2,69,1))-69;f=a<0?e*wr.pow(2,-a,1):e/wr.pow(2,a,1);f*=4503599627370496;a=52-a;if(a>0){wr.multiply(0,f);l=r;while(l>=7){wr.multiply(1e7,0);l-=7}wr.multiply(wr.pow(10,l,1),0);l=a-1;while(l>=23){wr.divide(1<<23);l-=23}wr.divide(1<<l);wr.multiply(1,1);wr.divide(2);i=wr.numToString()}else{wr.multiply(0,f);wr.multiply(1<<-a,0);i=wr.numToString()+K("0.00000000000000000000",2,2+r)}}if(r>0){s=i.length;if(s<=r){i=n+K("0.0000000000000000000",0,r-s+2)+i}else{i=n+K(i,0,s-r)+"."+K(i,s-r)}}else{i=n+i}return i};P(l,{toFixed:br},gr);var Tr=function(){try{return 1..toPrecision(undefined)==="1"}catch(t){return true}}();var mr=l.toPrecision;P(l,{toPrecision:function toPrecision(t){return typeof t==="undefined"?mr.call(this):mr.call(this,t)}},Tr);if("ab".split(/(?:ab)*/).length!==2||".".split(/(.?)(.?)/).length!==4||"tesst".split(/(s)*/)[1]==="t"||"test".split(/(?:)/,-1).length!==4||"".split(/.?/).length||".".split(/()()/).length>1){(function(){var t=typeof/()??/.exec("")[1]==="undefined";var r=Math.pow(2,32)-1;f.split=function(e,n){var i=String(this);if(typeof e==="undefined"&&n===0){return[]}if(!M(e)){return Q(this,e,n)}var a=[];var o=(e.ignoreCase?"i":"")+(e.multiline?"m":"")+(e.unicode?"u":"")+(e.sticky?"y":""),f=0,u,l,s,c;var h=new RegExp(e.source,o+"g");if(!t){u=new RegExp("^"+h.source+"$(?!\\s)",o)}var p=typeof n==="undefined"?r:z.ToUint32(n);l=h.exec(i);while(l){s=l.index+l[0].length;if(s>f){_(a,K(i,f,l.index));if(!t&&l.length>1){l[0].replace(u,function(){for(var t=1;t<arguments.length-2;t++){if(typeof arguments[t]==="undefined"){l[t]=void 0}}})}if(l.length>1&&l.index<i.length){v.apply(a,W(l,1))}c=l[0].length;f=s;if(a.length>=p){break}}if(h.lastIndex===l.index){h.lastIndex++}l=h.exec(i)}if(f===i.length){if(c||!h.test("")){_(a,"")}}else{_(a,K(i,f))}return a.length>p?W(a,0,p):a}})()}else if("0".split(void 0,0).length){f.split=function split(t,r){if(typeof t==="undefined"&&r===0){return[]}return Q(this,t,r)}}var Dr=f.replace;var Sr=function(){var t=[];"x".replace(/x(.)?/g,function(r,e){_(t,e)});return t.length===1&&typeof t[0]==="undefined"}();if(!Sr){f.replace=function replace(t,r){var e=D(r);var n=M(t)&&/\)[*?]/.test(t.source);if(!e||!n){return Dr.call(this,t,r)}else{var i=function(e){var n=arguments.length;var i=t.lastIndex;t.lastIndex=0;var a=t.exec(e)||[];t.lastIndex=i;_(a,arguments[n-2],arguments[n-1]);return r.apply(this,a)};return Dr.call(this,t,i)}}}var xr=f.substr;var Or="".substr&&"0b".substr(-1)!=="b";P(f,{substr:function substr(t,r){var e=t;if(t<0){e=w(this.length+t,0)}return xr.call(this,e,r)}},Or);var Er="\t\n\x0B\f\r \xa0\u1680\u180e\u2000\u2001\u2002\u2003"+"\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028"+"\u2029\ufeff";var jr="\u200b";var Ir="["+Er+"]";var Mr=new RegExp("^"+Ir+Ir+"*");var Ur=new RegExp(Ir+Ir+"*$");var $r=f.trim&&(Er.trim()||!jr.trim());P(f,{trim:function trim(){if(typeof this==="undefined"||this===null){throw new TypeError("can't convert "+this+" to object")}return o(this).replace(Mr,"").replace(Ur,"")}},$r);var Fr=d.bind(String.prototype.trim);var Nr=f.lastIndexOf&&"abc\u3042\u3044".lastIndexOf("\u3042\u3044",2)!==-1;P(f,{lastIndexOf:function lastIndexOf(t){if(typeof this==="undefined"||this===null){throw new TypeError("can't convert "+this+" to object")}var r=o(this);var e=o(t);var n=arguments.length>1?u(arguments[1]):NaN;var i=Y(n)?Infinity:z.ToInteger(n);var a=b(w(i,0),r.length);var f=e.length;var l=a+f;while(l>0){l=w(0,l-f);var s=V(K(r,l,a+f),e);if(s!==-1){return l+s}}return-1}},Nr);var Cr=f.lastIndexOf;P(f,{lastIndexOf:function lastIndexOf(t){return Cr.apply(this,arguments)}},f.lastIndexOf.length!==1);if(parseInt(Er+"08")!==8||parseInt(Er+"0x16")!==22){parseInt=function(t){var r=/^[-+]?0[xX]/;return function parseInt(e,n){if(typeof e==="symbol"){""+e}var i=Fr(String(e));var a=u(n)||(r.test(i)?16:10);return t(i,a)}}(parseInt)}if(1/parseFloat("-0")!==-Infinity){parseFloat=function(t){return function parseFloat(r){var e=Fr(String(r));var n=t(e);return n===0&&K(e,0,1)==="-"?-0:n}}(parseFloat)}if(String(new RangeError("test"))!=="RangeError: test"){var kr=function toString(){if(typeof this==="undefined"||this===null){throw new TypeError("can't convert "+this+" to object")}var t=this.name;if(typeof t==="undefined"){t="Error"}else if(typeof t!=="string"){t=o(t)}var r=this.message;if(typeof r==="undefined"){r=""}else if(typeof r!=="string"){r=o(r)}if(!t){return r}if(!r){return t}return t+": "+r};Error.prototype.toString=kr}if(R){var Ar=function(t,r){if(tt(t,r)){var e=Object.getOwnPropertyDescriptor(t,r);if(e.configurable){e.enumerable=false;Object.defineProperty(t,r,e)}}};Ar(Error.prototype,"message");if(Error.prototype.message!==""){Error.prototype.message=""}Ar(Error.prototype,"name")}if(String(/a/gim)!=="/a/gim"){var Rr=function toString(){var t="/"+this.source+"/";if(this.global){t+="g"}if(this.ignoreCase){t+="i"}if(this.multiline){t+="m"}return t};RegExp.prototype.toString=Rr}});


},{}]},{},[137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282]);
