const {isCN} = require('./../util.js');
const {TextEncoder} = require('text-encoding');
let tempTimer = 0;
let client = null;
let util = null
let mDeviceEvent = null
let crypto = null
let md5 = null
let aesjs = null
const timeOut = 20; //超时时间
var timeId = "";
let sequenceControl = 0;
let sequenceNumber = -1;
let itue = true;

let self = {
  data: {
    deviceId: null,
    isConnected: false,
    failure: false,
    value: 0,
    desc: "请耐心等待...",
    isChecksum: true,
    isEncrypt: true,
    flagEnd: false,
    defaultData: 1,
    ssidType: 2,
    passwordType: 3,
    meshIdType: 3,
    deviceId: "",
    ssid: "",
    uuid: "",
    serviceId: "",
    password: "",
    meshId: "",
    processList: [],
    result: [],
    service_uuid: "0000FFFF-0000-1000-8000-00805F9B34FB",
    characteristic_write_uuid: "0000FF01-0000-1000-8000-00805F9B34FB",
    characteristic_read_uuid: "0000FF02-0000-1000-8000-00805F9B34FB",
    customData: null,
    md5Key: 0,
  }
}

function buf2hex(buffer) {
  return Array.prototype.map.call(new Uint8Array(buffer), x => ('00' + x.toString(16)).slice(-2)).join('');
}

function buf2string(buffer) {
  var arr = Array.prototype.map.call(new Uint8Array(buffer), x => x);
  var str = '';
  for (var i = 0; i < arr.length; i++) {
    str += String.fromCharCode(arr[i]);
  }
  return str;
}

function getSsids(str) {
  var list = [],
    strs = str.split(":");
  for (var i = 0; i < strs.length; i++) {
    list.push(parseInt(strs[i], 16));
  }
  return list;
}

function getCharCodeat(str) {
  var list = [];
  const encoder = new TextEncoder('utf8');
  console.log(encoder);
  for (var i = 0; i < str.length; i++) {
    if(isCN(str[i])) {
      const t = encoder.encode(str[i]);
      for (var j = 0; j < t.length; j++) {
        list.push(t[j]);
      }
    } else {
      list.push(str.charCodeAt(i));
    }
  }
  return list;
}


//判断返回的数据是否加密
function isEncrypt(fragNum, list, md5Key) {
  var checksum = [],
    checkData = [];
  if (fragNum[7] == "1") { //返回数据加密
    if (fragNum[6] == "1") {
      var len = list.length - 2;
      list = list.slice(0, len);
    }
    var iv = this.generateAESIV(parseInt(list[2], 16));
    if (fragNum[3] == "0") { //未分包
      list = list.slice(4);
      self.data.flagEnd = true
    } else { //分包
      list = list.slice(6);
    }
  } else { //返回数据未加密
    if (fragNum[6] == "1") {
      var len = list.length - 2;
      list = list.slice(0, len);
    }
    if (fragNum[3] == "0") { //未分包
      list = list.slice(4);
      self.data.flagEnd = true
    } else { //分包
      list = list.slice(6);
    }
  }
  return list;
}

function getSecret(deviceId, serviceId, characteristicId, client, kBytes, pBytes, gBytes, data) {

  var obj = [],
    frameControl = 0;
  sequenceControl = parseInt(sequenceControl) + 1;
  if (!util._isEmpty(data)) {
    obj = util.isSubcontractor(data, true, sequenceControl);
    frameControl = util.getFrameCTRLValue(false, true, util.DIRECTION_OUTPUT, false, obj.flag);
  } else {
    data = [];
    data.push(util.NEG_SET_SEC_ALL_DATA);
    var pLength = pBytes.length;
    var pLen1 = (pLength >> 8) & 0xff;
    var pLen2 = pLength & 0xff;
    data.push(pLen1);
    data.push(pLen2);
    data = data.concat(pBytes);
    var gLength = gBytes.length;
    var gLen1 = (gLength >> 8) & 0xff;
    var gLen2 = gLength & 0xff;
    data.push(gLen1);
    data.push(gLen2);
    data = data.concat(gBytes);
    var kLength = kBytes.length;
    var kLen1 = (kLength >> 8) & 0xff;
    var kLen2 = kLength & 0xff;
    data.push(kLen1);
    data.push(kLen2);
    data = data.concat(kBytes);
    obj = util.isSubcontractor(data, true, sequenceControl);
    frameControl = util.getFrameCTRLValue(false, true, util.DIRECTION_OUTPUT, false, obj.flag);
  }
  var value = util.writeData(util.PACKAGE_VALUE, util.SUBTYPE_NEG, frameControl, sequenceControl, obj.len, obj.lenData);
  var typedArray = new Uint8Array(value);
  wx.writeBLECharacteristicValue({
    deviceId: deviceId,
    serviceId: serviceId,
    characteristicId: characteristicId,
    value: typedArray.buffer,
    success: function(res) {
      if (obj.flag) {
        getSecret(deviceId, serviceId, characteristicId, client, kBytes, pBytes, gBytes, obj.laveData);
      }
    },
    fail: function(res) {}
  })
}

function writeDeviceRouterInfoStart(deviceId, serviceId, characteristicId, data) {
  var obj = {},
    frameControl = 0;
  sequenceControl = parseInt(sequenceControl) + 1;
  if (!util._isEmpty(data)) {
    obj = util.isSubcontractor(data, self.data.isChecksum, sequenceControl, self.data.isEncrypt);
    frameControl = util.getFrameCTRLValue(self.data.isEncrypt, self.data.isChecksum, util.DIRECTION_OUTPUT, false, obj.flag);
  } else {
    obj = util.isSubcontractor([self.data.defaultData], self.data.isChecksum, sequenceControl, true);
    frameControl = util.getFrameCTRLValue(self.data.isEncrypt, self.data.isChecksum, util.DIRECTION_OUTPUT, false, obj.flag);
  }
  var defaultData = util.encrypt(aesjs, self.data.md5Key, sequenceControl, obj.lenData, true);
  var value = util.writeData(util.PACKAGE_CONTROL_VALUE, util.SUBTYPE_WIFI_MODEl, frameControl, sequenceControl, obj.len, defaultData);
  var typedArray = new Uint8Array(value);
  wx.writeBLECharacteristicValue({
    deviceId: deviceId,
    serviceId: serviceId,
    characteristicId: characteristicId,
    value: typedArray.buffer,
    success: function(res) {
      if (obj.flag) {
        writeDeviceRouterInfoStart(deviceId, serviceId, characteristicId, obj.laveData);
      } else {
        writeRouterSsid(deviceId, serviceId, characteristicId, null);
      }
    },
    fail: function(res) {
    }
  })
}

function writeCutomsData(deviceId, serviceId, characteristicId, data) {
  var obj = {},
    frameControl = 0;
  sequenceControl = parseInt(sequenceControl) + 1;
  if (!util._isEmpty(data)) {
    obj = util.isSubcontractor(data, self.data.isChecksum, sequenceControl, self.data.isEncrypt);
    frameControl = util.getFrameCTRLValue(self.data.isEncrypt, self.data.isChecksum, util.DIRECTION_OUTPUT, false, obj.flag);
  } else {
    var ssidData = getCharCodeat(self.data.customData);
    obj = util.isSubcontractor(ssidData, self.data.isChecksum, sequenceControl, self.data.isEncrypt);
    frameControl = util.getFrameCTRLValue(self.data.isEncrypt, self.data.isChecksum, util.DIRECTION_OUTPUT, false, obj.flag);
  }
  var defaultData = util.encrypt(aesjs, self.data.md5Key, sequenceControl, obj.lenData, true);
  var value = util.writeData(util.PACKAGE_VALUE, util.SUBTYPE_CUSTOM_DATA, frameControl, sequenceControl, obj.len, defaultData);
  var typedArray = new Uint8Array(value);
  wx.writeBLECharacteristicValue({
    deviceId: deviceId,
    serviceId: serviceId,
    characteristicId: characteristicId,
    value: typedArray.buffer,
    success: function(res) {
      if (obj.flag) {
        writeCutomsData(deviceId, serviceId, characteristicId, obj.laveData);
      }
    },
    fail: function(res) {
      //console.log(257);
    }
  })
}




function writeRouterSsid(deviceId, serviceId, characteristicId, data) {
  var obj = {},
    frameControl = 0;
  sequenceControl = parseInt(sequenceControl) + 1;
  if (!util._isEmpty(data)) {
    obj = util.isSubcontractor(data, self.data.isChecksum, sequenceControl, self.data.isEncrypt);
    frameControl = util.getFrameCTRLValue(self.data.isEncrypt, self.data.isChecksum, util.DIRECTION_OUTPUT, false, obj.flag);
  } else {
    var ssidData = getCharCodeat(self.data.ssid);
    obj = util.isSubcontractor(ssidData, self.data.isChecksum, sequenceControl, self.data.isEncrypt);
    frameControl = util.getFrameCTRLValue(self.data.isEncrypt, self.data.isChecksum, util.DIRECTION_OUTPUT, false, obj.flag);
  }
  var defaultData = util.encrypt(aesjs, self.data.md5Key, sequenceControl, obj.lenData, true);
  var value = util.writeData(util.PACKAGE_VALUE, util.SUBTYPE_SET_SSID, frameControl, sequenceControl, obj.len, defaultData);
  var typedArray = new Uint8Array(value);
  wx.writeBLECharacteristicValue({
    deviceId: deviceId,
    serviceId: serviceId,
    characteristicId: characteristicId,
    value: typedArray.buffer,
    success: function(res) {
      if (obj.flag) {
        writeRouterSsid(deviceId, serviceId, characteristicId, obj.laveData);
      } else {
        writeDevicePwd(deviceId, serviceId, characteristicId, null);
      }
    },
    fail: function(res) {
      //console.log(257);
    }
  })
}

function writeDevicePwd(deviceId, serviceId, characteristicId, data) {
  var obj = {},
    frameControl = 0;
  sequenceControl = parseInt(sequenceControl) + 1;
  if (!util._isEmpty(data)) {
    obj = util.isSubcontractor(data, self.data.isChecksum, sequenceControl, self.data.isEncrypt);
    frameControl = util.getFrameCTRLValue(self.data.isEncrypt, self.data.isChecksum, util.DIRECTION_OUTPUT, false, obj.flag);
  } else {
    var pwdData = getCharCodeat(self.data.password);
    obj = util.isSubcontractor(pwdData, self.data.isChecksum, sequenceControl, self.data.isEncrypt);
    frameControl = util.getFrameCTRLValue(self.data.isEncrypt, self.data.isChecksum, util.DIRECTION_OUTPUT, false, obj.flag);
  }
  var defaultData = util.encrypt(aesjs, self.data.md5Key, sequenceControl, obj.lenData, true);
  var value = util.writeData(util.PACKAGE_VALUE, util.SUBTYPE_SET_PWD, frameControl, sequenceControl, obj.len, defaultData);
  var typedArray = new Uint8Array(value);
  wx.writeBLECharacteristicValue({
    deviceId: deviceId,
    serviceId: serviceId,
    characteristicId: characteristicId,
    value: typedArray.buffer,
    success: function(res) {
      if (obj.flag) {
        writeDevicePwd(deviceId, serviceId, characteristicId, obj.laveData);
      } else {
        writeDeviceEnd(deviceId, serviceId, characteristicId, null);
      }
    },
    fail: function(res) {}
  })
}

function writeDeviceEnd(deviceId, serviceId, characteristicId) {
  sequenceControl = parseInt(sequenceControl) + 1;
  var frameControl = util.getFrameCTRLValue(self.data.isEncrypt, false, util.DIRECTION_OUTPUT, false, false);
  var value = util.writeData(self.data.PACKAGE_CONTROL_VALUE, util.SUBTYPE_END, frameControl, sequenceControl, 0, null);
  var typedArray = new Uint8Array(value);
  wx.writeBLECharacteristicValue({
    deviceId: deviceId,
    serviceId: serviceId,
    characteristicId: characteristicId,
    value: typedArray.buffer,
    success: function(res) {

    },
    fail: function(res) {

    }
  })
}

function init() {

  let mOnFire = require("other/onfire.js");
  mDeviceEvent = require('xBlufi.js');

  util = require('../../utils/blufi/util.js');
  crypto = require('../../utils/blufi/crypto/crypto-dh.js');
  md5 = require('../../utils/blufi/crypto/md5.min.js');
  aesjs = require('../../utils/blufi/crypto/aes.js');

  wx.onBLEConnectionStateChange(function(res) {
    let obj = {
      'type': mDeviceEvent.XBLUFI_TYPE.TYPE_STATUS_CONNECTED,
      'result': res.connected,
      'data': res
    }
    mDeviceEvent.notifyDeviceMsgEvent(obj);
  })

  mDeviceEvent.listenStartDiscoverBle(true, function(options) {

    if (options.isStart) {
      //第一步检查蓝牙适配器是否可用
      wx.onBluetoothAdapterStateChange(function(res) {
        if (!res.available) {

        }
      });
      if(!itue) {
        return;
      };
      itue = false;
      //第二步关闭适配器，重新来搜索
      wx.closeBluetoothAdapter({
        complete: function(res) {
          wx.openBluetoothAdapter({
            success: function(res) {
              wx.getBluetoothAdapterState({
                success: function(res) {
                  wx.stopBluetoothDevicesDiscovery({
                    success: function(res) {
                      itue = true;
                        let devicesList = [];
                        let countsTimes = 0;
                        wx.onBluetoothDeviceFound(function(devices) {
                          //剔除重复设备，兼容不同设备API的不同返回值
                          var isnotexist = true;
                          if (devices.deviceId) {
                            if (devices.advertisData) {
                              devices.advertisData = buf2hex(devices.advertisData)
                            } else {
                              devices.advertisData = ''
                            }
                            for (var i = 0; i < devicesList.length; i++) {
                              if (devices.deviceId === devicesList[i].deviceId) {
                                isnotexist = false
                              }
                            }
                            if (isnotexist) {
                              devicesList.push(devices)
                            }
                          } else if (devices.devices) {
                            if (devices.devices[0].advertisData) {
                              devices.devices[0].advertisData = buf2hex(devices.devices[0].advertisData)
                            } else {
                              devices.devices[0].advertisData = ''
                            }
                            for (var i = 0; i < devicesList.length; i++) {
                              if (devices.devices[0].deviceId == devicesList[i].deviceId) {
                                isnotexist = false
                              }
                            }
                            if (isnotexist) {
                              devicesList.push(devices.devices[0])
                            }
                          } else if (devices[0]) {
                            if (devices[0].advertisData) {
                              devices[0].advertisData = buf2hex(devices[0].advertisData)
                            } else {
                              devices[0].advertisData = ''
                            }
                            for (var i = 0; i < devices_list.length; i++) {
                              if (devices[0].deviceId == devicesList[i].deviceId) {
                                isnotexist = false
                              }
                            }
                            if (isnotexist) {
                              devicesList.push(devices[0])
                            }
                          }

                          let obj = {
                            'type': mDeviceEvent.XBLUFI_TYPE.TYPE_GET_DEVICE_LISTS,
                            'result': true,
                            'data': devicesList
                          }
                          mDeviceEvent.notifyDeviceMsgEvent(obj);
                        })
                        wx.startBluetoothDevicesDiscovery({
                          allowDuplicatesKey: true,
                          success: function(res) {
                            let obj = {
                              'type': mDeviceEvent.XBLUFI_TYPE.TYPE_GET_DEVICE_LISTS_START,
                              'result': true,
                              'data': res
                            }
                            mDeviceEvent.notifyDeviceMsgEvent(obj);
                            //开始扫码，清空列表
                            devicesList.length = 0;
                            
                          },
                          fail: function(res) {
                            let obj = {
                              'type': mDeviceEvent.XBLUFI_TYPE.TYPE_GET_DEVICE_LISTS_START,
                              'result': false,
                              'data': res
                            }
                            mDeviceEvent.notifyDeviceMsgEvent(obj);
                          }
                        });
                    },
                    fail: function(res) {
                      itue = true;
                      let obj = {
                        'type': mDeviceEvent.XBLUFI_TYPE.TYPE_GET_DEVICE_LISTS_START,
                        'result': false,
                        'data': res
                      }
                      mDeviceEvent.notifyDeviceMsgEvent(obj);
                    }
                  });
                },
                fail: function(res) {
                  itue = true;
                  let obj = {
                    'type': mDeviceEvent.XBLUFI_TYPE.TYPE_GET_DEVICE_LISTS_START,
                    'result': false,
                    'data': res
                  }
                  mDeviceEvent.notifyDeviceMsgEvent(obj);
                }
              });
            },
            fail: function(res) {
              itue = true;
              let obj = {
                'type': mDeviceEvent.XBLUFI_TYPE.TYPE_GET_DEVICE_LISTS_START,
                'result': false,
                'data': res
              }
              mDeviceEvent.notifyDeviceMsgEvent(obj);
            }
          });
        }
      });
    } else {
      wx.stopBluetoothDevicesDiscovery({
        success: function(res) {
          clearInterval(tempTimer);
          let obj = {
            'type': mDeviceEvent.XBLUFI_TYPE.TYPE_GET_DEVICE_LISTS_STOP,
            'result': true,
            'data': res
          }
          mDeviceEvent.notifyDeviceMsgEvent(obj);
        },
        fail: function(res) {
          let obj = {
            'type': mDeviceEvent.XBLUFI_TYPE.TYPE_GET_DEVICE_LISTS_STOP,
            'result': false,
            'data': res
          }
          mDeviceEvent.notifyDeviceMsgEvent(obj);
        }
      })
    }
  })


  mDeviceEvent.listenConnectBle(true, function(options) {
    // console.log("我要连接？", (options.isStart))
    
    if (options.isStart)
      wx.createBLEConnection({
        deviceId: options.deviceId,
        success: function(res) {
          self.data.deviceId = options.deviceId
          mDeviceEvent.notifyDeviceMsgEvent({
            'type': mDeviceEvent.XBLUFI_TYPE.TYPE_CONNECTED,
            'result': true,
            'data': {
              deviceId: options.deviceId,
              name: options.name
            },
          });
        },
        fail: function(res) {
          self.data.deviceId = null
          mDeviceEvent.notifyDeviceMsgEvent({
            'type': mDeviceEvent.XBLUFI_TYPE.TYPE_CONNECTED,
            'result': false,
            'data': res,
          });
        }
      });
    else wx.closeBLEConnection({
      deviceId: options.deviceId,
      success: function(res) {
        console.log('断开成功')
        self.data.deviceId = null
        mDeviceEvent.notifyDeviceMsgEvent({
          'type': mDeviceEvent.XBLUFI_TYPE.TYPE_CLOSE_CONNECTED,
          'result': true,
          'data': {
            deviceId: options.deviceId,
            name: options.name
          }
        });
      },
      fail: function(res) {
        self.data.deviceId = null
        mDeviceEvent.notifyDeviceMsgEvent({
          'type': mDeviceEvent.XBLUFI_TYPE.TYPE_CLOSE_CONNECTED,
          'result': false,
          'data': res,
        });
      }
    })
  })

  mDeviceEvent.listenInitBleEsp32(true, function(options) {
    sequenceControl = 0;
    sequenceNumber = -1;
    self = null
    self = {
      data: {
        deviceId: null,
        isConnected: false,
        failure: false,
        value: 0,
        desc: "请耐心等待...",
        isChecksum: true,
        isEncrypt: true,
        flagEnd: false,
        defaultData: 1,
        ssidType: 2,
        passwordType: 3,
        meshIdType: 3,
        deviceId: "",
        ssid: "",
        uuid: "",
        serviceId: "",
        password: "",
        meshId: "",
        processList: [],
        result: [],
        service_uuid: "0000FFFF-0000-1000-8000-00805F9B34FB",
        characteristic_write_uuid: "0000FF01-0000-1000-8000-00805F9B34FB",
        characteristic_read_uuid: "0000FF02-0000-1000-8000-00805F9B34FB",
        customData: null,
        md5Key: 0,
      }
    }
    let deviceId = options.deviceId
    self.data.deviceId = options.deviceId
    wx.getBLEDeviceServices({
      // 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接
      deviceId: deviceId,
      success: function(res) {
        var services = res.services;
        if (services.length > 0) {
          for (var i = 0; i < services.length; i++) {
            if (services[i].uuid === self.data.service_uuid) {
              var serviceId = services[i].uuid;
              wx.getBLEDeviceCharacteristics({
                // 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接
                deviceId: deviceId,
                serviceId: serviceId,
                success: function(res) {
                  var list = res.characteristics;
                  if (list.length > 0) {
                    for (var i = 0; i < list.length; i++) {
                      var uuid = list[i].uuid;
                      if (uuid == self.data.characteristic_write_uuid) {
                        self.data.serviceId = serviceId;
                        self.data.uuid = uuid;
                        wx.notifyBLECharacteristicValueChange({
                          state: true, // 启用 notify 功能
                          deviceId: deviceId,
                          serviceId: serviceId,
                          characteristicId: list[1].uuid,
                          success: function(res) {
                            let characteristicId = self.data.characteristic_write_uuid
                            //通知设备交互方式（是否加密） start
                            client = util.blueDH(util.DH_P, util.DH_G, crypto);
                            var kBytes = util.uint8ArrayToArray(client.getPublicKey());
                            var pBytes = util.hexByInt(util.DH_P);
                            var gBytes = util.hexByInt(util.DH_G);
                            var pgkLength = pBytes.length + gBytes.length + kBytes.length + 6;
                            var pgkLen1 = (pgkLength >> 8) & 0xff;
                            var pgkLen2 = pgkLength & 0xff;
                            var data = [];
                            data.push(util.NEG_SET_SEC_TOTAL_LEN);
                            data.push(pgkLen1);
                            data.push(pgkLen2);
                            var frameControl = util.getFrameCTRLValue(false, false, util.DIRECTION_OUTPUT, false, false);
                            var value = util.writeData(util.PACKAGE_VALUE, util.SUBTYPE_NEG, frameControl, sequenceControl, data.length, data);
                            var typedArray = new Uint8Array(value);
                            wx.writeBLECharacteristicValue({
                              deviceId: deviceId,
                              serviceId: serviceId,
                              characteristicId: characteristicId,
                              value: typedArray.buffer,
                              success: function(res) {
                                getSecret(deviceId, serviceId, characteristicId, client, kBytes, pBytes, gBytes, null);
                              },
                              fail: function(res) {
                                let obj = {
                                  'type': mDeviceEvent.XBLUFI_TYPE.TYPE_INIT_ESP32_RESULT,
                                  'result': false,
                                  'data': res
                                }
                                mDeviceEvent.notifyDeviceMsgEvent(obj);
                              }
                            })
                            //通知设备交互方式（是否加密） end
                            wx.onBLECharacteristicValueChange(function(res) {
                              let list2 = (util.ab2hex(res.value));
                              // start
                              let result = self.data.result;
                              if (list2.length < 4) {
                                cosnole.log(407);
                                return false;
                              }
                              var val = parseInt(list2[0], 16),
                                type = val & 3,
                                subType = val >> 2;
                              var dataLength = parseInt(list2[3], 16);
                              if (dataLength == 0) {
                                return false;
                              }
                              var fragNum = util.hexToBinArray(list2[1]);
                              list2 = isEncrypt(fragNum, list2, self.data.md5Key);
                              result = result.concat(list2);
                              self.data.result = result
                              if (self.data.flagEnd) {
                                self.data.flagEnd = false
                                if (type == 1) {
                                  let what = [];
                                  switch (subType) {
                                    case 15:
                                      if (result.length == 3) {
                                        mDeviceEvent.notifyDeviceMsgEvent({
                                          'type': mDeviceEvent.XBLUFI_TYPE.TYPE_CONNECT_ROUTER_RESULT,
                                          'result': false,
                                          'data': {
                                            'progress': 0,
                                            'ssid': what.join('')
                                          }
                                        });
                                      } else {
                                        for (var i = 0; i <= result.length; i++) {
                                          var num = parseInt(result[i], 16) + "";
                                          if (i > 12) what.push(String.fromCharCode(parseInt(result[i], 16)));
                                        }
                                        mDeviceEvent.notifyDeviceMsgEvent({
                                          'type': mDeviceEvent.XBLUFI_TYPE.TYPE_CONNECT_ROUTER_RESULT,
                                          'result': true,
                                          'data': {
                                            'progress': 100,
                                            'ssid': what.join('')
                                          }
                                        });
                                      }

                                      break;
                                    case 19: //自定义数据
                                      let customData = [];
                                      for (var i = 0; i <= result.length; i++) {
                                        customData.push(String.fromCharCode(parseInt(result[i], 16)));
                                      }
                                      let obj = {
                                        'type': mDeviceEvent.XBLUFI_TYPE.TYPE_RECIEVE_CUSTON_DATA,
                                        'result': true,
                                        'data': customData.join('')
                                      }
                                      mDeviceEvent.notifyDeviceMsgEvent(obj);

                                      break;
                                    case util.SUBTYPE_NEGOTIATION_NEG:

                                      var arr = util.hexByInt(result.join(""));
                                      var clientSecret = client.computeSecret(new Uint8Array(arr));
                                      var md5Key = md5.array(clientSecret);
                                      self.data.md5Key = md5Key;
                                      mDeviceEvent.notifyDeviceMsgEvent({
                                        'type': mDeviceEvent.XBLUFI_TYPE.TYPE_INIT_ESP32_RESULT,
                                        'result': true,
                                        'data': {
                                          deviceId,
                                          serviceId,
                                          characteristicId
                                        }
                                      });
                                      break;

                                    default:
                                      console.log(468);
                                      //self.setFailProcess(true, util.descFailList[4])
                                      console.log("入网失败 468 :", util.failList[4]);
                                      break;
                                  }
                                  self.data.result = []
                                } else {
                                  //console.log(472);
                                  console.log("入网失败 472:", util.failList[4]);
                                }
                              }
                              // end

                            })

                          },
                          fail: function(res) {
                            let obj = {
                              'type': mDeviceEvent.XBLUFI_TYPE.TYPE_INIT_ESP32_RESULT,
                              'result': false,
                              'data': res
                            }
                            mDeviceEvent.notifyDeviceMsgEvent(obj);
                          }
                        })
                      }
                    }
                  }
                },
                fail: function(res) {
                  let obj = {
                    'type': mDeviceEvent.XBLUFI_TYPE.TYPE_INIT_ESP32_RESULT,
                    'result': false,
                    'data': res
                  }
                  mDeviceEvent.notifyDeviceMsgEvent(obj);
                  console.log("fail getBLEDeviceCharacteristics:" + JSON.stringify(res))
                }
              })
              break;
            }
          }
        }
      },
      fail: function(res) {
        let obj = {
          'type': mDeviceEvent.XBLUFI_TYPE.TYPE_INIT_ESP32_RESULT,
          'result': false,
          'data': res
        }
        mDeviceEvent.notifyDeviceMsgEvent(obj);
        console.log("fail getBLEDeviceServices:" + JSON.stringify(res))
      }
    })
  })

  mDeviceEvent.listenSendRouterSsidAndPassword(true, function(options) {
    self.data.password = options.password
    self.data.ssid = options.ssid
    writeDeviceRouterInfoStart(self.data.deviceId, self.data.service_uuid, self.data.characteristic_write_uuid, null);
  })


  mDeviceEvent.listenSendCustomData(true, function(options) {
    self.data.customData = options.customData
    writeCutomsData(self.data.deviceId, self.data.service_uuid, self.data.characteristic_write_uuid, null);
  })
}


function ab2hex(buffer) {
  var hexArr = Array.prototype.map.call(
    new Uint8Array(buffer),
    function (bit) {
      return ('00' + bit.toString(16)).slice(-2)
    }
  )
  return hexArr.join('');
}

/****************************** 对外  ***************************************/
module.exports = {
  init: init,
};