Source: blinkupSDK.js

(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){
(function (global){
/**
 *  JavaScript BlinkUp
 *
 * @version <packageVersion>
 * @copyright Electric Imp Inc. 2016-18
 * @website https://electricimp.com
 * @license Closed
 */
module.exports = require('./lib/blinkup/blinkupSDK');

/**
 * Global accessor for blinkupSDK module if needed
 * @global
 */
global.BU = module.exports;

/**
 * Global accessor for a NetworkConfig class if not using modules
 * @deprecated Please use BU.NetworkConfig if not using modules
 * @global
 */
global.BUNetworkConfig = require('./lib/blinkup/NetworkConfig');

/**
 * Global accessor for a StaticAddressing class if not using modules
 * @deprecated Please use BU.StaticAddressing if not using modules
 * @global
 */
global.BUStaticAddressing = require('./lib/blinkup/StaticAddressing');

/**
 * Global accessor for a NetworkProxy class if not using modules
 * @deprecated Please use BU.NetworkProxy if not using modules
 * @global
 */
global.BUNetworkProxy = require('./lib/blinkup/NetworkProxy');

}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{"./lib/blinkup/NetworkConfig":10,"./lib/blinkup/NetworkProxy":11,"./lib/blinkup/StaticAddressing":12,"./lib/blinkup/blinkupSDK":13}],2:[function(require,module,exports){
var Base64 = {_keyStr:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",encode:function(e){var t="";var n,r,i,s,o,u,a;var f=0;e=Base64._utf8_encode(e);while(f<e.length){n=e.charCodeAt(f++);r=e.charCodeAt(f++);i=e.charCodeAt(f++);s=n>>2;o=(n&3)<<4|r>>4;u=(r&15)<<2|i>>6;a=i&63;if(isNaN(r)){u=a=64}else if(isNaN(i)){a=64}t=t+this._keyStr.charAt(s)+this._keyStr.charAt(o)+this._keyStr.charAt(u)+this._keyStr.charAt(a)}return t},decode:function(e){var t="";var n,r,i;var s,o,u,a;var f=0;e=e.replace(/[^A-Za-z0-9\+\/\=]/g,"");while(f<e.length){s=this._keyStr.indexOf(e.charAt(f++));o=this._keyStr.indexOf(e.charAt(f++));u=this._keyStr.indexOf(e.charAt(f++));a=this._keyStr.indexOf(e.charAt(f++));n=s<<2|o>>4;r=(o&15)<<4|u>>2;i=(u&3)<<6|a;t=t+String.fromCharCode(n);if(u!=64){t=t+String.fromCharCode(r)}if(a!=64){t=t+String.fromCharCode(i)}}t=Base64._utf8_decode(t);return t},_utf8_encode:function(e){e=e.replace(/\r\n/g,"\n");var t="";for(var n=0;n<e.length;n++){var r=e.charCodeAt(n);if(r<128){t+=String.fromCharCode(r)}else if(r>127&&r<2048){t+=String.fromCharCode(r>>6|192);t+=String.fromCharCode(r&63|128)}else{t+=String.fromCharCode(r>>12|224);t+=String.fromCharCode(r>>6&63|128);t+=String.fromCharCode(r&63|128)}}return t},_utf8_decode:function(e){var t="";var n=0;var r=c1=c2=0;while(n<e.length){r=e.charCodeAt(n);if(r<128){t+=String.fromCharCode(r);n++}else if(r>191&&r<224){c2=e.charCodeAt(n+1);t+=String.fromCharCode((r&31)<<6|c2&63);n+=2}else{c2=e.charCodeAt(n+1);c3=e.charCodeAt(n+2);t+=String.fromCharCode((r&15)<<12|(c2&63)<<6|c3&63);n+=3}}return t}}; // eslint-disable-line
module.exports = Base64;

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

module.exports = exports = {};

var ByteOperations = {
  utf8: function (s) {
    return unescape(encodeURIComponent(s));
  },
  hexStringToLEBytes: function (hexstring) {
    // Convert a hex string to a little-endian byte string
    var bytes = [];
    while (hexstring.length) {
      bytes = String.fromCharCode(parseInt(hexstring.slice(0, 2), 16)) + bytes;
      hexstring = hexstring.slice(2);
    }
    return bytes;
  },
  dottedQuadToLEBytes: function (quad) {
    // Convert a dotted quad string to a little-endian byte string
    var buf = '';
    quad.split('.').forEach(function (part) {
      // Make sure it's zero-padded to two digits
      buf += ('0' + parseInt(part, 10).toString(16)).slice(-2);
    });
    return this.hexStringToLEBytes(buf);
  },
  dottedQuadToBytes: function (quad) {
    // Convert a dotted quad string to a big-endian byte string
    var bytes = [];
    quad.split('.').forEach(function (part) {
      bytes += String.fromCharCode(parseInt(part, 10));
    });
    return bytes;
  }
};

exports.utf8 = ByteOperations.utf8;
exports.hexStringToLEBytes = ByteOperations.hexStringToLEBytes;
exports.dottedQuadToLEBytes = ByteOperations.dottedQuadToLEBytes;
exports.dottedQuadToBytes = ByteOperations.dottedQuadToBytes;

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

/**
 * Represents a ConfigId returned by the Electric Imp API corresponding to a BlinkUp attempt.
 * This object is created by the module:blinkupSDK.getConfigId method.
 * You should never have to create it yourself.
 * @class
 * @memberof module:blinkupSDK~
 * @param {object} params Initialization parameters
 * @example
 * var blinkup = require('blinkup/blinkupSDK');
 * blinkup.getConfigId('myElectricImpAPIKey', null, 'production', function (err, configId) {
 *   if (err) {
 *     // Handle error
 *   } else {
 *      // The configId has been retrieved.
 *      // Generally it should be passed to the startNetworkFlash function
 *      var theConfigId = configId;
 *   }
 * });
 */
function ConfigId (params) {
  /**
   * The ID of the token
   * @member {string} token
   * @memberof ConfigId
   */
  this.token = params.token;

  /**
   * @memberof module:blinkkupSDK~ConfigId
   * The plan ID if available
   */
  this.planId = params.planId;

  /**
   * @instance
   * Your API key from ElectricImp
   *
   */
  this.apiKey = params.apiKey;

    /**
    * Production environment for API calls
    * Ensure the correlating apiKey is used
    * Values: 'production'
    */
  this.environment = params.environment || 'production';
};

module.exports = ConfigId;

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

/**
 * Represents the results of a device poll event.
 * @class
 * @memberof module:blinkupSDK~
 * @param {object} params Initialization parameters
 * This object is created by the function module:blinkupSDK.pollForDeviceInfo as part of the polling process.
 * A device will only be returned if the flash was successful.
 * You should never have to create it yourself.
 * @example
 * var blinkup = require('blinkup/blinkupSDK');
 * blinkup.pollForDeviceInfo (configId, function(err, deviceInfo) {
 *   if (err) {
 *     // Handle error
 *     // (device rejected or server connection timed out)
 *   } else if (deviceInfo) {
 *     // Do something with deviceInfo data
 *   }
 * });
 */
function DeviceInfo (params) {
  /** The URL of the agent for the device that connected */
  this.agentURL = params.agentURL;
  /** The deviceId of the device that connected */
  this.deviceId = params.deviceId;
  /** The planId of the device that connected */
  this.planId = params.planId;
  /** The date when the device connected to the server */
  this.verificationDate = params.verificationDate;
};

module.exports = DeviceInfo;

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

var exports = {};

exports.isOnMobile = function (userAgent) {
  userAgent = userAgent || navigator.userAgent;
  return (/tablet|pad|mobile|phone|symbian|android|ipod|ios|blackberry|webos/i.test(userAgent));
};

exports.isOnIOS = function (userAgent) {
  userAgent = userAgent || navigator.userAgent;
  return (/(iPhone|iPod|iPod touch|iPad)/i.test(userAgent) && !exports.isOnIE(userAgent));
};

exports.iOSMajorVersion = function (global, userAgent) {
  if (exports.isOnIOS(userAgent)) {
    global = global || window;
    /* eslint-disable */
    if (!!global.indexedDB) { return 8; }
    if (!!global.SpeechSynthesisUtterance) { return 7; }
    if (!!global.webkitAudioContext) { return 6; }
    if (!!global.matchMedia) { return 5; }
    if (!!global.history && 'pushState' in global.history) { return 4; }
    /* eslint-enable */
    return 3;
  }
  return null;
};

exports.isOnChrome = function (userAgent) {
  userAgent = userAgent || navigator.userAgent;
  return (/chrome|crios/i.test(userAgent) && !exports.isOnIE(userAgent));
};

exports.isOnIE = function (userAgent) {
  userAgent = userAgent || navigator.userAgent;
  return (/msie|trident|edge/i.test(userAgent));
};

exports.isOnFirefox = function (userAgent) {
  userAgent = userAgent || navigator.userAgent;
  return (/firefox|seamonkey/i.test(userAgent));
};

module.exports = exports;

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

function FlashData (params) {
  params = params || {};
  this.byteArray = params.byteArray || [];
};

var translate = function (bytes) {
  // handle empty case
  if (bytes.length === 0) {
    return '';
  }

  var string = '';

  var holder = 0x00;
  var mask = 0x01;
  var shiftSize = -1;

  for (var i = 0, len = bytes.length; i < len; i++) {
    // Move old value in case it is needed (for 3 bits)
    // OR in new byte
    shiftSize += 8; // Add on 8 more bytes
    holder = (holder << 8) | bytes[i];

    // Process the lower 8 bits that we can
    while (shiftSize >= 0) {
      // Find the value
      var value = (holder >>> shiftSize) & mask;
      // Add 1 as 0 is clock
      value += 1;
      // Prepend clock and now we are in bitsPerFlash^2 + 1 radix system
      string += '0' + value.toString(17);

      // Shift less next time
      shiftSize -= 1;
    }
  }

  return string;
};

FlashData.prototype.preambleByteArray = function () {
  // sync header; this is just the 01 pattern (ie trilevel 0x00 gives
  // the pattern "0101010101010101". This should go on for ~1s to ensure
  // that the imp is listening.
  var preamble = [0x00, 0x00, 0x00];

  // Magic number (2a) header which signifies end of sync and start of packet
  preamble.push(0x2a);

  return preamble;
};

FlashData.prototype.asciiEncodePreamble = function () {
  var dataString = translate(this.preambleByteArray());
  return dataString;
};

FlashData.prototype.asciiEncode = function () {
  var dataString = translate(this.byteArray);
  return dataString;
};

module.exports = FlashData;

},{}],8:[function(require,module,exports){
'use strict';
var Bytes = require('./ByteOperations');
var FlashData = require('./FlashData');

var FlashPacket = {
  _mCRC: 0,
  flashData: null,
  PACKET_ID: {
    WIFI_SSID: 1,
    ENROLMENT: 5,
    DISCONNECT: 7,
    CLEAR_TEXT_PASSWORD: 6,
    NETWORK_STATIC_CONFIG: 11,
    HTTP_PROXY_SETTINGS: 13
  },
  init: function (configId, networkConfig, options) {
    // Constants
    var HEADER_LEN = 2;
    var TOKEN_PLAN_LEN = 16;
    var STATIC_IP_1_DNS_LEN = 16;
    var STATIC_IP_2_DNS_LEN = 20;

    // Build a packet
    this._mCRC = 0;
    this.flashData = new FlashData(options);
    // Length byte
    var wifiLength = 0;
    if (Bytes.utf8(networkConfig.ssid).length > 0) {
      wifiLength = HEADER_LEN + Bytes.utf8(networkConfig.ssid).length +
      HEADER_LEN + Bytes.utf8(networkConfig.password).length;
    }

    var length = wifiLength +
    HEADER_LEN + TOKEN_PLAN_LEN;
    if (networkConfig.addressing) {
      length += HEADER_LEN + (networkConfig.addressing.dns2 ? STATIC_IP_2_DNS_LEN : STATIC_IP_1_DNS_LEN);
    }
    if (networkConfig.proxy) {
      length += HEADER_LEN + 3 + Bytes.utf8(networkConfig.proxy.server).length;
      if (networkConfig.proxy.username) {
        length += 1 + Bytes.utf8(networkConfig.proxy.username).length;
      }
      if (networkConfig.proxy.password) {
        length += 1 + Bytes.utf8(networkConfig.proxy.password).length;
      }
    }
    this.appendByte(length);
    if (wifiLength > 0) {
      this.blinkupWifiCredentials(Bytes.utf8(networkConfig.ssid), Bytes.utf8(networkConfig.password));
    }

    if (networkConfig.addressing) {
      var sn = networkConfig.addressing;
      this.blinkupStaticIPConfig(sn.ip, sn.netmask, sn.gateway, sn.dns1, sn.dns2);
    }

    if (networkConfig.proxy) {
      var proxy = networkConfig.proxy;
      this.blinkupProxySettings(proxy.port, Bytes.utf8(proxy.server), Bytes.utf8(proxy.username), Bytes.utf8(proxy.password));
    }

    this.blinkupEnrolCredentials(configId.planId, configId.token);

    // Append CRC
    this.appendByteNoCRC(this._mCRC >> 8);
    this.appendByteNoCRC(this._mCRC & 0xff);

    return this;
  },
  initForClearWirelessConfiguration: function (options) {
    // Build a packet
    this._mCRC = 0;
    this.flashData = new FlashData(options);

    // Length of entire packet: 2 byte headers plus fields
    this.appendByte(0x02);
    this.appendByte(0x07);
    this.appendByte(0x00);

    // Append CRC
    this.appendByteNoCRC(this._mCRC >> 8);
    this.appendByteNoCRC(this._mCRC & 0xff);

    return this;
  },
  initForTest: function (options) {
    // Build a packet
    this._mCRC = 0;
    this.flashData = new FlashData(options);
    return this;
  },
  addToCRC: function (b) {
    this._mCRC = ((this._mCRC << 8) & 0xffff) ^ this.crc16Table[((this._mCRC >> 8) ^ b) & 0xff];
  },
  // Append bit by bit
  appendByteNoCRC: function (b) {
    this.flashData.byteArray.push(b);
  },
  // Append a byte and add it to the CRC
  appendByte: function (b) {
    this.appendByteNoCRC(b);
    this.addToCRC(b);
  },
  // Append an entry
  appendEntry: function (t, s) {
    this.appendByte(t);
    this.appendByte(s.length);
    // console.log("append type:"+t+" length:"+s.length);
    for (var b = 0; b < s.length; b++) {
      // console.log("b:"+b+":"+s.charCodeAt(b));
      this.appendByte(s.charCodeAt(b));
    }
  },
  blinkupEnrolCredentials: function (plan, token) {
    plan = Bytes.hexStringToLEBytes(plan);
    token = Bytes.hexStringToLEBytes(token);

    this.appendEntry(this.PACKET_ID.ENROLMENT, plan + token);
  },

  blinkupWifiCredentials: function (ssid, password) {
    this.appendEntry(this.PACKET_ID.WIFI_SSID, ssid);
    this.appendEntry(this.PACKET_ID.CLEAR_TEXT_PASSWORD, password);
  },

  blinkupStaticIPConfig: function (ip, netmask, gateway, dns1, dns2) {
    var buf = '';
    buf += Bytes.dottedQuadToBytes(ip);
    buf += Bytes.dottedQuadToBytes(netmask);
    buf += Bytes.dottedQuadToBytes(gateway);
    buf += Bytes.dottedQuadToBytes(dns1);

    if (dns2) {
      buf += Bytes.dottedQuadToBytes(dns2);
    }

    this.appendEntry(this.PACKET_ID.NETWORK_STATIC_CONFIG, buf);
  },

  blinkupProxySettings: function (port, address, uid, pwd) {
    var buf = '';
    buf += String.fromCharCode(port & 255);
    buf += String.fromCharCode(port >> 8 & 255);
    buf += String.fromCharCode(address.length);
    buf += address;

    if (uid) {
      buf += String.fromCharCode(uid.length);
      buf += uid;
    }

    if (pwd) {
      buf += String.fromCharCode(pwd.length);
      buf += pwd;
    }

    this.appendEntry(this.PACKET_ID.HTTP_PROXY_SETTINGS, buf);
  },
  crc16Table: [
    0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
    0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
    0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
    0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
    0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
    0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
    0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
    0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
    0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
    0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
    0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
    0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
    0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
    0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
    0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
    0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
    0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
    0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
    0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
    0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
    0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
    0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
    0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
    0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
    0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
    0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
    0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
    0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
    0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
    0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
    0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
    0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040 ]
};

module.exports = FlashPacket;

},{"./ByteOperations":3,"./FlashData":7}],9:[function(require,module,exports){
(function (global){
'use strict';
var env = require('./Environment');
var FlashPacket = require('./FlashPacket');

var flasher = {
  flashBits: null,
  preambleFlashBits: null,
  mPos: 0,
  mPreamblePos: 0,
  mWidth: 0,
  mHeight: 0,
  stopFlashing: false,
  cb: null,
  animator: null,
  drawNextFrame: null,
  alphaDiv: null,
  useAlphaFlash: false,
  currentProgress: 0,
  lastframeTime: 0,
  minFPSInterval: 50.0, // minimum interval between frames,
  maxFPS: 60,
  drawValues: null,
  preambleDrawValues: null,
  generateDrawValueArray: function (alphaFlash) {
    var values = [0x00, 0xbf, 0xff];

    var output = values.map(function (byte) {
      if (alphaFlash) {
        return 1.0 - byte / 255;
      } else {
        var str = ('0' + byte.toString(16)).slice(-2);
        return '#' + str + str + str;
      }
    });

    return output;
  },
  findAnimationMethod: function () {
    var nativeRAF = global.requestAnimationFrame;
    var vendors = ['Webkit', 'Moz', 'ms', 'O'];
    for (var i = 0; i < vendors.length && !nativeRAF; i++) {
      nativeRAF = global[vendors[i] + 'RequestAnimationFrame'];
    }

    if (!nativeRAF) {
      this.animator = global.AnimationFrame(this.maxFPS);
      this.drawNextFrame = this.animator.request;
    } else {
      this.animator = null;
      this.drawNextFrame = nativeRAF;
    }
  },
  forceToNewLayer: function (element) {
    var transform = 'translate3d(0,0,0)';
    element.style.webkitTransform = transform;
    element.style.MozTransform = transform;
    element.style.msTransform = transform;
    element.style.OTransform = transform;
    element.style.transform = transform;
    element.style.willChange = 'transform, opacity';
  },
  getAlphaDiv: function (box) {
    var backColor = global.getComputedStyle(box.parentElement).getPropertyValue('background-color');
    if (backColor !== 'rgb(255, 255, 255)') {
      box.parentElement.style.backgroundColor = '#FFFFFF';
      console.log('BU: BU-canvas must be placed in a parent that has a white background color.');  // eslint-disable-line no-console
    }
    return box;
  },
  getBox: function () {
    // Set stuff up to be hopefully faster
    var box = document.getElementById('BU-canvas');
    this.mWidth = box.width;
    this.mHeight = box.height;
    this.forceToNewLayer(box);
    box.style.zIndex = 0;

    var box_c = box.getContext('2d');
    box_c.imageSmoothingEnabled = false;
    box_c.msImageSmoothingEnabled = false;
    this.useAlphaFlash = env.isOnChrome();
    if (this.useAlphaFlash) {
      this.alphaDiv = this.getAlphaDiv(box);
    }

    box_c.fillStyle = this.black;
    box_c.fillRect(0, 0, this.mWidth, this.mHeight);
    // We set a global variable for the internal flash state
    // Although this isn't ideal, it is needed for performance
    global.BUInteralFlashState = this;
    return box_c;
  },
  // Should contain the same processing code as sendbit to return
  // the list of color or opacity data that will actually be outputted
  testSendBitData: function (self) {
    var output = [];
    var keepGoing = true;
    while (keepGoing) {
      var bitValue = 0;
      var drawValue = 0;

      if (self.mPreamblePos < self.preambleFlashBits.length) {
        // Draw the flashing box
        bitValue = parseInt(self.preambleFlashBits[self.mPreamblePos], 17);
        // Could be opacity or hex color
        drawValue = self.preambleDrawValues[bitValue];

        // Onto the next bit
        self.mPreamblePos++;
      } else {
        // Draw the flashing box
        bitValue = parseInt(self.flashBits[self.mPos], 17);
        // Could be opacity or hex color
        drawValue = self.drawValues[bitValue];

        // Onto the next bit
        self.mPos++;
      }

      output.push(drawValue);

      // Reschedule if there's anything left
      if (self.mPos < self.flashBits.length) {
        // Keep going
      } else {
        keepGoing = false;
      }
    }
    return output;
  },
  // use an internal object as memory so we never have to allocate during the run loop
  sendBitMem: {delta: 0, bitValue: 0, drawValue: 0, progress: 0.0},
  sendbit: function (time) { // DOMHighResTimeStamp
    var self = global.BUInteralFlashState;
    if (self._stopFlashing) {
      return;
    }

    self.sendBitMem.delta = time - self.lastframeTime;
    if (self.sendBitMem.delta > self.minFPSInterval) {
      // Get ready for next frame by setting lastDrawTime=now, but...
      // Also, adjust for fpsInterval not being multiple of 16.67
      self.lastframeTime = time - (self.sendBitMem.delta % self.minFPSInterval);

      if (self.mPreamblePos < self.preambleFlashBits.length) {
        // Draw the flashing box
        self.sendBitMem.bitValue = parseInt(self.preambleFlashBits[self.mPreamblePos], 17);
        // Could be opacity or hex color
        self.sendBitMem.drawValue = self.preambleDrawValues[self.sendBitMem.bitValue];

        // Onto the next bit
        self.mPreamblePos++;
      } else {
        // Draw the flashing box
        self.sendBitMem.bitValue = parseInt(self.flashBits[self.mPos], 17);
        // Could be opacity or hex color
        self.sendBitMem.drawValue = self.drawValues[self.sendBitMem.bitValue];

        // Onto the next bit
        self.mPos++;
      }

      if (self.useAlphaFlash) {
        self.alphaDiv.style.opacity = self.sendBitMem.drawValue;
      } else {
        self.mBox.fillStyle = self.sendBitMem.drawValue;
        self.mBox.fillRect(0, 0, self.mWidth, self.mHeight);
      }

      // Show progress bar
      self.sendBitMem.progress = parseInt(((self.mPos + self.mPreamblePos) / (self.flashBits.length + self.preambleFlashBits.length)) * 100, 10);
      if (self.currentProgress !== self.sendBitMem.progress) {
        self.currentProgress = self.sendBitMem.progress;
        self.progressCallback(self.sendBitMem.progress);
      }
    }

    // Reschedule if there's anything left
    if (self.mPos < self.flashBits.length) {
      self.drawNextFrame.call(self.animator, global.BUInteralFlashState.sendbit);
    } else {
      self.cb();
    }
  },

  // Reset the counters associated with sending bits
  resetFlashState: function () {
    this.mPos = 0;
    this.mPreamblePos = 0;
    this.currentProgress = 0;
    this.minFPSInterval = 1000.0 / this.maxFPS;
    this.progressCallback(0);
    this.lastframe = 0;
    this._stopFlashing = false;
  },
  start: function (configId, networkConfig, options, cb) {
    // Cache box
    this.mBox = this.getBox();
    this.cb = cb;
    var flashData = FlashPacket.init(configId, networkConfig, options).flashData;
    this.flashBits = flashData.asciiEncode();
    this.flashBits += '000000'; // Add some black to the end
    this.drawValues = this.generateDrawValueArray(this.useAlphaFlash);
    this.preambleFlashBits = flashData.asciiEncodePreamble();
    this.preambleDrawValues = this.generateDrawValueArray(this.useAlphaFlash);
    this.findAnimationMethod();
    this.resetFlashState();
    this.sendbit(this.lastframe);
  },
  startDisconnect: function (options, cb) {
    // Cache box
    this.mBox = this.getBox();
    this.cb = cb;
    var flashData = FlashPacket.initForClearWirelessConfiguration(options).flashData;
    this.flashBits = flashData.asciiEncode();
    this.flashBits += '000000'; // Add some black to the end
    this.drawValues = this.generateDrawValueArray(this.useAlphaFlash);
    this.preambleFlashBits = flashData.asciiEncodePreamble();
    this.preambleDrawValues = this.generateDrawValueArray(this.useAlphaFlash);
    this.findAnimationMethod();
    this.resetFlashState();
    this.sendbit(this.lastframe);
  },
  testDisconnect: function (options, useAlphaFlash) {
    var flashData = FlashPacket.initForClearWirelessConfiguration(options).flashData;
    this.flashBits = flashData.asciiEncode();
    this.flashBits += '000000'; // Add some black to the end
    this.drawValues = this.generateDrawValueArray(this.useAlphaFlash);
    this.preambleFlashBits = flashData.asciiEncodePreamble();
    this.preambleDrawValues = this.generateDrawValueArray(this.useAlphaFlash);
    this.resetFlashState();
    return this.testSendBitData(this);
  },
  stop: function () {
    this._stopFlashing = true;
  },
  // use a mem cache to prevent object allocation
  progressCallbackMem: {scale: '', element: null},
  progressCallback: function (progress) {
    if (this.maxFPS > 29 || env.isOnFirefox()) {
      return;
    }
    // Can be overwritten in exports
    // We use scale as it is a very fast gpu operation
    this.progressCallbackMem.scale = 'translateZ(0) scale(' + progress / 100.0 + ',1)';
    this.progressCallbackMem.element = document.getElementById('BU-progress');
    this.progressCallbackMem.element.style.webkitTransform = this.progressCallbackMem.scale;
    this.progressCallbackMem.element.style.MozTransform = this.progressCallbackMem.scale;
    this.progressCallbackMem.element.style.msTransform = this.progressCallbackMem.scale;
    this.progressCallbackMem.element.style.OTransform = this.progressCallbackMem.scale;
    this.progressCallbackMem.element.style.transform = this.progressCallbackMem.scale;
  }
};

module.exports = flasher;

}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{"./Environment":6,"./FlashPacket":8}],10:[function(require,module,exports){
'use strict';

var StaticAddressing = require('./StaticAddressing');
var NetworkProxy = require('./NetworkProxy');

/**
 * Represents the configuration for a network connection.
 * @class
 * @classdesc Represents the configuration for a network connection.
 * @memberof module:blinkupSDK~
 * @static
 * @param {object} params Initialization parameters
 * @param {string} [params.ssid] The SSID of the network
 * @param {string} [params.password] The password for the network
 * @param {StaticAddressing} [params.addressing] The static IP information for the network
 * @param {NetworkProxy} [params.proxy] The proxy information for the network
 * @see module:blinkupSDK~StaticAddressing
 * @see module:blinkupSDK~NetworkProxy
 * @example
 * // Network with SSID and password
 * var blinkup = require('blinkup/blinkupSDK');
 * var networkConfig = new blinkup.NetworkConfig({ssid: 'myWifi', password: 'secret'});
 * @example
 * // Network with SSID, password, static network, and proxy
 * var blinkup = require('blinkup/blinkupSDK');
 * var addressing = new blinkup.StaticAddressing({ip: '192.168.1.200', netmask: '255.255.0.0', gateway: '192.168.1.1', dns1: '8.8.8.8'});
 * var proxy = new blinkup.NetworkProxy({server: 'proxyServer2.local', port: '8000'});
 * var networkConfig = new blinkup.NetworkConfig({ssid: 'myWifi', password: 'secret', addressing: addressing, proxy: proxy});
 * @example
 * // Use Globals rather than modules
 * // Network with SSID, password, static network, and proxy
 * var networkConfig = new BU.NetworkConfig({ssid: 'myWifi', password: 'secret'});
 * @example
 * // Ethernet Network (no SSID or password)
 * var networkConfig = new BU.NetworkConfig({});
 * @example
 * // Ethernet Network with static ip and proxy (no SSID or password)
 * var blinkup = require('blinkup/blinkupSDK');
 * var addressing = new blinkup.StaticAddressing({ip: '192.168.1.200', netmask: '255.255.0.0', gateway: '192.168.1.1', dns1: '8.8.8.8'});
 * var proxy = new blinkup.NetworkProxy({server: 'proxyServer2.local', port: '8000'});
 * var networkConfig = new blinkup.NetworkConfig({addressing: addressing, proxy: proxy});
 */
function NetworkConfig (params) {
  /** (Optional) The SSID of the wifi network (not required for ethernet) */
  this.ssid = params.ssid || '';
  /** (Optional) The password for the wifi network (not required for ethernet) */
  this.password = params.password || '';
  /** (Optional) The static IP information for the wifi network */
  this.addressing = params.addressing ? new StaticAddressing(params.addressing) : null;
  /** (Optional) The proxy information for the wifi network */
  this.proxy = params.proxy ? new NetworkProxy(params.proxy) : null;
};

/** Validates that the object represents a valid network configuration */
// if password is set and ssid is set, this is a wifi network
// if password is set and ssid is not set, this is not a valid network
// if password is not set and ssid is set, this is a wifi network
// if password is not set and ssid is not set, this is an ethernet network
NetworkConfig.prototype.isComplete = function () {
  return typeof this.ssid === 'string' && (this.ssid !== '' || this.password === '');
};

module.exports = NetworkConfig;

},{"./NetworkProxy":11,"./StaticAddressing":12}],11:[function(require,module,exports){
'use strict';

/**
 * Represents the server proxy information for the device
 * @class
 * @classdesc Represents the server proxy information for the device
 * @memberof module:blinkupSDK~
 * @static
 * @param {object} params Initialization parameters
 * @param {string} params.server The server IP or hostname of the proxy
 * @param {string} params.port The server port running the proxy
 * @param {string} [params.username] The username of the proxy
 * @param {string} [params.password] The password of the proxy
 * @example
 * // Proxy without authentication
 * var blinkup = require('blinkup/blinkupSDK');
 * var proxy = new blinkup.NetworkProxy({server: 'proxyServer2.local', port: '8000'});
 * @example
 * // Proxy with authentication
 * var blinkup = require('blinkup/blinkupSDK');
 * var proxy = new blinkup.NetworkProxy({server: 'proxyServer2.local', port: '8000', username: 'user23', password: 'p@ssw0rd'});
 * @example
 * // Proxy using globals rather than modules
 * var proxy = new BU.NetworkProxy({server: 'proxyServer2.local', port: '8000', username: 'user23', password: 'p@ssw0rd'});
 */
function NetworkProxy (params) {
  /** (Required) The server IP or hostname of the proxy */
  this.server = params.server;
  /** (Required) The server port running the proxy */
  this.port = params.port;
  /** (Optional) The username of the proxy */
  this.username = params.username || '';
  /** (Optional) The password of the proxy */
  this.password = params.password || '';
};

/** Validates that the object represents a valid network configuration */
NetworkProxy.prototype.isComplete = function () {
  if (this.server !== '' || this.port !== '' || this.username !== '' || this.password !== '') {
    return (this.server !== '' && this.port !== '' && !isNaN(parseInt(this.port, 10)));
  } else {
    return true;
  }
};

module.exports = NetworkProxy;

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

/**
 * @class
 * @classdesc Configure static networking information for imp configuration.
 * @memberof module:blinkupSDK~
 * @static
 * @param {object} params Initialization parameters
 * @param {string} params.ip The IP of the device to be configured
 * @param {string} params.netmask The netmask of the device to be configured
 * @param {string} params.gateway The gateway of the device to be configured
 * @param {string} params.dns1 The seconday dns of the device to be configured
 * @param {string} [params.dns2] The seconday dns of the device to be configured
 * @example
 * // Use static network addressing with a single DNS
 * var blinkup = require('blinkup/blinkupSDK');
 * var addressing = new blinkup.StaticAddressing({ip: '192.168.1.200', netmask: '255.255.0.0', gateway: '192.168.1.1', dns1: '8.8.8.8'});
 * @example
 * // Use static network addressing with a two DNS servers
 * var blinkup = require('blinkup/blinkupSDK');
 * var addressing = new blinkup.StaticAddressing({ip: '192.168.1.200', netmask: '255.255.0.0', gateway: '192.168.1.1', dns1: '8.8.8.8', dns2: '8.8.4.4'});
 * @example
 * // Using globals rather than modules
 * var addressing = new BU.StaticAddressing({ip: '192.168.1.200', netmask: '255.255.0.0', gateway: '192.168.1.1', dns1: '8.8.8.8'});
 */
function StaticAddressing (params) {
  /** (Required) The IP of the device to be configured */
  this.ip = params.ip;
  /** (Required) The netmask of the device to be configured */
  this.netmask = params.netmask;
  /** (Required) The gateway of the device to be configured */
  this.gateway = params.gateway;
  /** (Required) The dns of the device to be configured */
  this.dns1 = params.dns1;
  /** (Optional) The seconday dns of the device to be configured */
  this.dns2 = params.dns2 || '';
};

/** Validates that the object represents a valid network configuration */
StaticAddressing.prototype.isComplete = function () {
  if (this.ip !== '' || this.netmask !== '' || this.gateway !== '' || this.dns1 !== '' || this.dns2 !== '') {
    return (!(this.ip === '' || this.netmask === '' || this.gateway === '' || this.dns1 === ''));
  } else {
    return true;
  }
};

module.exports = StaticAddressing;

},{}],13:[function(require,module,exports){
/**
 * JavaScript BlinkUp version <packageVersion>
 * blinkupSDK module.
 * @module blinkupSDK
 */

'use strict';

var ConfigId = require('./ConfigId');
var DeviceInfo = require('./DeviceInfo');
var flasher = require('./Flasher');
var env = require('./Environment');
var Base64 = require('./Base64');
var _apiBaseURL = 'https://api.electricimp.com';
var _stopPolling = false;

/** StaticAddressing class constructor for static addressing */
module.exports.StaticAddressing = require('./StaticAddressing');

/** NetworkConfig class constructor for imp network configuration */
module.exports.NetworkConfig = require('./NetworkConfig');

/** NetworkProxy class constructor for routing imp traffic through a proxy */
module.exports.NetworkProxy = require('./NetworkProxy');

/** Max time to poll for a device after flash in whole seconds */
module.exports.pollTimeout = 60;

/** If true, prevents the default behavior where a faster flasher is used on mobile devices */
module.exports.preventFastFlashing = false;

var estimatedFrameRate = function () {
  if (!(exports.preventFastFlashing) && env.isOnMobile()) {
    // return 30;
    if (env.isOnIOS()) {
      var iOSVersion = env.iOSMajorVersion();
      var isRetina = (window.devicePixelRatio >= 2);
      if (iOSVersion !== null && iOSVersion < 7) {
        // 30 FPS for iOS Safari less than 7
        return 30;
      } else if (!isRetina) {
        // 30 FPS for non-Retina devices, likely older
        return 30;
      }
    }

    // 60 FPS for general mobile
    return 60;
  } else {
    // 20 FPS for Desktop
    return 20;
  }
};

/**
* During the flashing process this function is called with the progress percentage.
*
* Setting this property will override the default progress bar behaviour.
* Care should be taken when creating the callback as any screen updates may cause
* the BlinkUp to fail on various devices. The SDK will call this method on each
* percentage point change in progress regardless of FPS.
*
* @param {Number} progress Specifies progress of the flash process
* @example
* var blinkup = require('blinkup/blinkupSDK');
* blinkup.progressCallback = function (progress) {
*   // Perform a very fast ui update.
*   // object.style = 'translateZ(0) scale(' + progress / 100.0 + ',1)'
* };
*/
module.exports.progressCallback = null;

/**
* Evaluate if the default progressCallback function will update the progress
* bar. If the progressCalback has been manually set the returned value isn't
* valid.
*
* @param {Number} [overrideFPS] FPS if you will be overridding the default fps
* @returns {Boolean} true if the default progress callback function will update the
*   progress bar, false otherwise.
*/
module.exports.progressCallbackWillOccurr = function (overrideFPS) {
  var fps = estimatedFrameRate();
  if (typeof overrideFPS === 'number') {
    fps = overrideFPS;
  }

  if (fps > 29 || env.isOnFirefox()) {
    return false;
  } else {
    return true;
  }
};

/**
* Get a ConfigId from the Electric Imp API.
*
* @param {string} apiKey Your apiKey from Electric Imp
* @param {string} existingPlanId For production environment, existing Id previously generated by Electric Imp, or null to auto-generate a new plan Id.
* @param {string} environment `production` environment
* @param {module:blinkupSDK~getConfigIdCompletion} callback Called on completion
* @example
* var blinkup = require('blinkup/blinkupSDK');
* blinkup.getConfigId('myElectricImpAPIKey', null, 'production', function (err, configId) {
*   if (err) {
*     // Handle error
*   } else {
*      // The configId has been retrieved.
*      // Generally it should be passed to the startNetworkFlash function
*      var theConfigId = configId;
*   }
* });
*/
module.exports.getConfigId = function (apiKey, existingPlanId, environment, callback) {
  if (apiKey === null) {
    console.log('BU: No API key provided.'); // eslint-disable-line no-console
    return callback('No API key provided.', null);
  }

  if (environment !== 'production') {
    console.log('BU: environment must be production'); // eslint-disable-line no-console
    return callback('Environment must be production', null);
  }

  var encodedKey = Base64.encode(apiKey);
  var url = _apiBaseURL;
  var data = {};

  if (environment === 'production') {
    url += '/v1/setup_tokens';

    if (existingPlanId !== null && typeof existingPlanId === 'string') {
      data.plan_id = existingPlanId;
    }
  } else {
    url += '/enrol';
    data.api_key = apiKey;
  }

  $.ajax({
    type: 'POST',
    url: url,
    data: data,
    crossDomain: true,
    beforeSend: function (xhr) {
      xhr.setRequestHeader('Authorization',
                              'Basic ' + encodedKey);
      xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
    },
    error: function (jqXHR, textStatus, errorThrown) {
      // 400 is returned by production, 403 is from development
      if (jqXHR.statusCode().status === 403 || jqXHR.statusCode().status === 400) {
        return callback('Your API key is invalid for this environment!', null);
      } else if (jqXHR.statusCode().status === 401) {
        return callback('The provided API key must be valid and at least 32 alphanumeric characters long.', null);
      } else if (errorThrown !== null && errorThrown !== '') {
        return callback(errorThrown, null);
      } else {
        return callback('Possible API Key Error', null);
      }
    },
    success: function (token_info) {
      if (token_info.valid_token === false) {
        return callback('Invalid API key', null);
      }

      var planId = token_info.plan_id || token_info.siteids[0];
      var token = token_info.id || token_info.token;

      var configId = new ConfigId({
        token: token,
        planId: planId,
        apiKey: apiKey,
        environment: environment
      });

      return callback(null, configId);
    }
  });
};

/**
* Callback used by getConfigId.
*
* @callback getConfigIdCompletion
* @param {string} error Specifies error, null on success
* @param {module:blinkupSDK~ConfigId} configId ConfigId object containing token and planId information returned by API (null on failure)
*/

/**
* Starts the BlinkUp flash process by targeting the BU-canvas element in the DOM.
*
* @param {module:blinkupSDK~ConfigId} configId The ConfigId with token, planId, apiKey, and type (retrieved by getConfigId)
* @param {module:blinkupSDK~NetworkConfig} networkConfig The network configuration for the wireless network to use
* @param {Object} Flashing parameters {fps: [10-60] (default:60 mobile, 20 browser)}
* @param {callback} callback Callback function for after the BlinkUp flash finishes (with success parameter)
* @example
* var blinkup = require('blinkup/blinkupSDK');
* // configId, networkConfig created elsewhere
* var options = {
* };
* blinkup.startNetworkFlash(configId, networkConfig, options, function () {
*   // Hide the canvas and progress bar now that BlinkUp is complete
*   // hideFlashingElements();
*
*   // Show status of device polling
*   // setInstruction('Gathering device data (' + blinkup.pollTimeout + 's max)');
*   // document.getElementById('status').style.display = 'block';
*   // showPolling();
*
*   // Poll the device for results of the BlinkUp process
*   // getDeviceStatus(configId);
* });
*/
module.exports.startNetworkFlash = function (configId, networkConfig, options, callback) {
  if (typeof callback === 'undefined') {
    callback = options;
    options = {};
  }

  options = options || {};

  if (typeof options.fps === 'number') {
    flasher.maxFPS = options.fps;
  } else {
    flasher.maxFPS = estimatedFrameRate();
  }

  if (typeof exports.progressCallback === 'function') {
    flasher.progressCallback = exports.progressCallback;
  }

  flasher.start(configId, networkConfig, options, function () {
    return callback();
  });
};

/**
* Starts the BlinkUp disconnect process by targeting the BU-canvas element in the DOM.
* @param {Object} options Flashing parameters {fps: [10-60] (default:60 mobile, 20 browser)}
* @param {callback} callback Callback function for after the BlinkUp flash finishes (no parameters)
* @example
* var blinkup = require('blinkup/blinkupSDK');
* blinkup.startDisconnectFlash({}, function () {
*   // Hide the canvas and progress bar now that BlinkUp is complete
*   // hideFlashingElements();
* });
*/
module.exports.startDisconnectFlash = function (options, callback) {
  if (typeof callback === 'undefined') {
    callback = options;
    options = {};
  }

  options = options || {};

  if (typeof options.fps === 'number') {
    flasher.maxFPS = options.fps;
  } else {
    flasher.maxFPS = estimatedFrameRate();
  }

  if (typeof exports.progressCallback === 'function') {
    flasher.progressCallback = exports.progressCallback;
  }

  flasher.startDisconnect(options, function () {
    return callback();
  });
};

/**
* Cancel any active Device Polling
*
*/
module.exports.stopPolling = function () {
  _stopPolling = true;
};

/**
* Cancel any active BlinkUp flashing
*
*/
module.exports.stopFlash = function () {
  flasher.stop();
};

/**
* Polls the Electric Imp server to gather information about the recently flashed
* device.
*
* @param {module:blinkupSDK~ConfigId} configId The ConfigId used during present
* @param {module:blinkupSDK~pollForDeviceInfoCompletion} callback Callback function for after device has been polled
* @example
* var blinkup = require('blinkup/blinkupSDK');
* blinkup.pollForDeviceInfo (configId, function(err, deviceInfo) {
*   if (err) {
*     // Handle error
*     // (device rejected or server connection timed out)
*   } else if (deviceInfo) {
*     // Do something with deviceInfo data
*   }
* });
*/
module.exports.pollForDeviceInfo = function (configId, callback) {
  var encodedKey = Base64.encode(configId.apiKey);
  var url = _apiBaseURL;
  if (configId.environment === 'production') {
    url += '/v1/setup_tokens/' + configId.token;
  }
  _stopPolling = false;
  var timedOut = false;
  // If we are using the dev endpoint, discard the first result if
  // it returns valid data as it is almost surely old data
  var discardBecauseFirstDev = true;
  var pollTimeoutId = setTimeout(function () {
    timedOut = true;
  }, exports.pollTimeout * 1000);

  var pollIntervalId = setInterval(function () {
    if (_stopPolling === true) {
      clearTimeout(pollTimeoutId);
      clearInterval(pollIntervalId);
      return;
    } else if (timedOut) {
      clearInterval(pollIntervalId);
      return callback('Timeout waiting for device to connect', null);
    } else {
      $.ajax({
        type: 'GET',
        url: url,
        beforeSend: function (xhr) {
          xhr.setRequestHeader('Authorization',
                                  'Basic ' + encodedKey);
        },
        error: function (jqXHR, textStatus, errorThrown) {
          return callback(errorThrown, null);
        },
        success: function (data) {
          if (_stopPolling === true || timedOut === true) {
            clearInterval(pollIntervalId);
            return;
          }


          if (configId.environment === 'production') {
            if (data.impee_id !== '') {
              clearInterval(pollIntervalId);
              clearTimeout(pollTimeoutId);
              var deviceInfo = new DeviceInfo({ // eslint-disable-line no-redeclare
                agentURL: data.agent_url,
                deviceId: data.impee_id,
                planId: data.plan_id,
                verificationDate: data.claimed_at
              });

              return callback(null, deviceInfo);
            }
          }
        }
      });
    }
  }, 1000);
};

/**
* Callback used by pollForDeviceInfo.
*
* @callback pollForDeviceInfoCompletion
* @param {string} error Specifies error, null on success
* @param {module:blinkupSDK~DeviceInfo} data Device information for successfully Blinked Up device (null on failure)
*/

},{"./Base64":2,"./ConfigId":4,"./DeviceInfo":5,"./Environment":6,"./Flasher":9,"./NetworkConfig":10,"./NetworkProxy":11,"./StaticAddressing":12}]},{},[1]);