//
//  BluetoothPlugin.m
//  BluetoothPlugin
//  支持 卡尔kt8000, kt8003, 森锐, 神思, 恒鸿达
//
//  Created by 奚敏辉 on 2017/7/10.
//  Copyright ? 2017年 奚敏辉. All rights reserved.
//

#import <objc/runtime.h>
#import "BluetoothDevicePlugin.h"
//恒鸿达sdk域名解析成ip需要以下系统库
#include <netdb.h>
#include <sys/socket.h>
#include <arpa/inet.h>

//下面这些import因为后缀是.mm，#import不能放.h 文件里，放这边
//卡尔需要引入的头文件-KT8000
#import <BLEIDCardReaderItem/BleTool.h>
//卡尔需要引入的头文件-KT8003
#import <KaerIDCardItem/KaerIDCardItem.h>
//森锐需要引入的头文件
#import <SRIDCardReader/SRIDCardReader.h>
//神思需要引入的头文件
#import "SerialGATT.h"
#import "BleTool.h"
#import "imageLib.h"
#import "IDbmplib.h"
#import "SdsesDes.h"
#import "Sdses_base64.h"
//恒鸿达需要引入的头文件
#import <SYDIDCardReader/SYDIDCardReader.h>
//江苏特供，加密工具类，神思提供
#import "EncryLibInterface.h"
//信通sdk
#import <STIDCardReader/STIDCardReader.h>

//Device Info service
#define UUIDSTR_DEVICE_INFO_SERVICE             @"180A"
#define UUIDSTR_MANUFACTURE_NAME_CHAR           @"2A29"
#define UUIDSTR_MODEL_NUMBER_CHAR               @"2A24"
#define UUIDSTR_SERIAL_NUMBER_CHAR              @"2A25"
#define UUIDSTR_HARDWARE_REVISION_CHAR          @"2A27"
#define UUIDSTR_FIRMWARE_REVISION_CHAR          @"2A26"
#define UUIDSTR_SOFTWARE_REVISION_CHAR          @"2A28"
#define UUIDSTR_SYSTEM_ID_CHAR                  @"2A23"

#define UUIDSTR_ISSC_PROPRIETARY_SERVICE        @"49535343-FE7D-4AE5-8FA9-9FAFD205E455"
#define UUIDSTR_CONNECTION_PARAMETER_CHAR       @"49535343-6DAA-4D02-ABF6-19569ACA69FE"
#define UUIDSTR_AIR_PATCH_CHAR                  @"49535343-ACA3-481C-91EC-D85E28A60318"
#define UUIDSTR_ISSC_TRANS_TX                   @"49535343-1E4D-4BD9-BA61-23C647249616"
#define UUIDSTR_ISSC_TRANS_RX                   @"49535343-8841-43F4-A8D4-ECBE34729BB3"

//品牌类型 0:其他 1:卡尔kt8000 2 森锐 3 神思 4恒鸿达 5卡尔kt8003 6信通
typedef enum {
    deviceType_ohter = 0,
    deviceType_kaer_kt8000,
    deviceType_sunrise,
    deviceType_sensor,
    deviceType_hhd,
    deviceType_kaer_kt8003,
    deviceType_xintong
} deviceType;

//蓝牙读卡器操作 0:初始化 1检查蓝牙连接状态 2搜索蓝牙设备 3连接蓝牙设备 4读身份证 5读iccid 6写卡
typedef enum {
    optType_init = 0,
    optType_checkStatus,
    optType_scanDevices,
    optType_conncetDevice,
    optType_readIDCard,
    optType_readICCID,
    optType_writeSim
} optType;


//类似private，只能本文件看见，改成后缀.mm文件后只能声明在.mm文件里不能声明在.h里
@interface BluetoothDevicePlugin ()<BR_Callback,STIDCardReaderDelegate>

//cordova 根据callbackid回调
@property (nonatomic, strong) NSString* normalCallbackId; /**普通同步操作用 */
@property (nonatomic, strong) NSString* scanDevicesCallbackId; /**异步操作用，神思搜索蓝牙设备是异步 */
@property (nonatomic, strong) NSString* readIDCardCallbackId; /**异步操作用，神思读取身份证是异步,恒鸿达也异步 */

@property int nowDeviceType; /**当前操作的蓝牙设备类型 */
@property int nowOptType; /**当前的蓝牙操作 */
@property NSDictionary *config; /**保存初始化蓝牙传进来的配置文件 */


//各个厂家sdk里的自有的对象
@property (nonatomic, strong) BleTool *kaerManagerKt8000; /**<卡尔控制中心-Kt8000 */
@property (nonatomic, strong) KaerAdapter *kaerManagerKt8003; /**<卡尔控制中心-Kt8003 */
@property (nonatomic, strong) SRIDCardReader *sunriseIdManager; /**<森锐控制中心 */
@property (nonatomic, strong) SerialGATT *sensorSerialGATT; /**<神思,负责搜索蓝牙设备 */
@property (nonatomic, strong) SdsesBleTool *sensorBletool; /**<神思，负责蓝牙操作*/
@property (nonatomic, strong) CBCentralManager *CBCenteralmanager; /**<系统自带 CoreBluetooth.framework，神思，森锐会用刀*/
//@property (nonatomic, strong) CBPeripheral *sensorPeripheral; /**<神思 设备实例对象*/
@property (nonatomic, strong) SYDIDCardReader* SYDScaleManager; /**<恒鸿达 设备实例对象*/
/**
 信通设备实例对象
 */
@property (nonatomic, strong) STIDCardReader *xtScaleManager;
/**
 当前连接的信通设备
 */
@property (nonatomic, strong) STMyPeripheral *curConnectPeripheral;
@property (nonatomic, strong)NSTimer *connectTimer;
@property (nonatomic, strong) NSMutableDictionary *SYDcertInfo; /**<恒鸿达 身份证读取文字和图片2次返回所以临时变量保存下，一起返回给前端。每次读取身份证前清空并初始化*/
@property (nonatomic, strong) NSMutableDictionary *STIDcertInfo; /**<信通 身份证读取文字和图片2次返回所以临时变量保存下，一起返回给前端。每次读取身份证前清空并初始化*/

@property (nonatomic, strong) NSMutableDictionary *devices; /**<搜索到的所有品牌设备列表，不用array而用dictionary，为了后面查询获取方便，而且附近也不会有太多设备，key为设备的name,value为字典，包含各个品牌的对象实例*/

@property (nonatomic, strong) NSMutableDictionary *sunriseIdInfo; /**森锐读身份证后返回信息，因为普通信息和照片信息会触发2次回调函数，这边汇总一起后统一返回一次给app，避免信息不全的时候返回2次*/

@property (nonatomic, strong) EncrylibInterface *encrylibInterface; /**<江苏特供，加密工具类，神思提供 */
@property (nonatomic, strong) NSString* encryptKey; //江苏特供，加密秘钥

@end

@implementation BluetoothDevicePlugin


/**
 初始化各个品牌的sdk
 
 @param command command description
 */
- (void)initBluetoothPlugins: (CDVInvokedUrlCommand *)command {
    NSLog(@"initPlugins......");
    
    self.normalCallbackId = command.callbackId;
    //初始化这个搜索到的设备字典，测试发现不初始化的话setObject不生效
    self.devices = [@{} mutableCopy];
    
    NSMutableDictionary *resp = [@{} mutableCopy]; //返回信息
    
    //江苏特供，加密工具类，神思提供
    self.encrylibInterface = [[EncrylibInterface alloc] init];
    
    // 这里加一个判断，只有当self.CBCenteralmanager为空的时候，才会创建self.CBCenteralmanager，一般情况下，中心设备只需要一个就行了，不需要多次创建
    if (nil == self.CBCenteralmanager) {
        //初始化蓝牙公共变量，原来放神思里的，挪出来.在central manager初始化时，如果当前蓝牙没打开，是否弹出alert框
        NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES],CBCentralManagerOptionShowPowerAlertKey,nil];
        self.CBCenteralmanager = [[CBCentralManager alloc] initWithDelegate:(id)self queue:nil options:options];
    }

    //从命令里获取参数,param 就是每个省的配置参数，里面有各个品牌型号的需要的初始化信息
    NSDictionary *param = [self paramsFromCommand:command];
    //保存蓝牙初始化传进来的配置文件，后面断连需要重连时要用
    self.config = param;
    
    NSDictionary *kt8000 = param[@"kt8000"];
    NSDictionary *kt8003 = param[@"kt8003"];
    NSDictionary *senri = param[@"senri"];
    NSDictionary *sensor = param[@"sensor"];
    NSDictionary *hhd = param[@"hhd"];
    NSDictionary *xintong = param[@"senter"];
    
    
    //搜索前初始化各个品牌的蓝牙读卡器
    [self initKaerDeviceKT8000:kt8000]; //卡尔KT8000
    [self initSunriseDevice:senri]; //森锐
    [self initSensorDevice:sensor]; //神思
    //改改改2.26，这里没传值进来会崩溃，先注掉
    [self initHhdDevice:hhd]; //恒鸿达
    [self initKaerDeviceKT8003:kt8003]; //卡尔KT8003
    [self initXintongDevice:xintong];
    
    
    [resp setValue:@"0000" forKey:@"respCode"];
    [resp setValue:@"蓝牙读卡器插件初始化成功" forKey:@"respDesc"];
    //返回数据
    [self sendRespInfo:resp withCallBackID: self.normalCallbackId];
    
}

/**
 判断手机蓝牙是否开启,用的是CoreBluetooth.framework，神思的sdk里回引用到了
 参考http://www.jianshu.com/p/8c2c99365cff
 返回respCode:0000表示开启 respCode:9999 表示关闭
 
 @param command command description
 */
- (void)checkBluetoothStatus: (CDVInvokedUrlCommand *)command {
    NSLog(@"checkBluetoothStatus......");
    
    self.normalCallbackId = command.callbackId;
    
    NSMutableDictionary *resp = [@{} mutableCopy]; //返回信息
    
    //判断CBCentralManager里能判断出蓝牙状态来，跟centralManagerDidUpdateState逻辑一样，神思init里已经初始化过了
    switch ([self.CBCenteralmanager state])
    {
        case CBCentralManagerStateUnknown:
        {
            [resp setValue:@"0020" forKey:@"respCode"];
            [resp setValue:@"手机蓝牙状态未知" forKey:@"respDesc"];
        }
            break;
        case CBCentralManagerStateUnsupported:
        {
            [resp setValue:@"0021" forKey:@"respCode"];
            [resp setValue:@"手机不支持蓝牙" forKey:@"respDesc"];
        }
            break;
        case CBCentralManagerStateUnauthorized:
        {
            [resp setValue:@"0022" forKey:@"respCode"];
            [resp setValue:@"手机蓝牙未授权" forKey:@"respDesc"];
        }
            break;
        case CBCentralManagerStatePoweredOff:
        {
            [resp setValue:@"0023" forKey:@"respCode"];
            [resp setValue:@"手机蓝牙未打开" forKey:@"respDesc"];
        }
            break;
        case CBCentralManagerStatePoweredOn:
        {
            [resp setValue:@"0000" forKey:@"respCode"];
            [resp setValue:@"手机蓝牙已打开" forKey:@"respDesc"];
        }
            break;
        default:
        {
            [resp setValue:@"0020" forKey:@"respCode"];
            [resp setValue:@"手机蓝牙状态未知" forKey:@"respDesc"];
        }
            break;
            ;
    }
    
    //返回数据
    [self sendRespInfo:resp withCallBackID: self.normalCallbackId];
    
}

/**
 搜索蓝牙读卡器
 卡尔是同步返回结果集的，神思是异步回调函数返回的，所以统一用异步返回，而且用单独的一个callbackid，避免影响其他调用
 
 @param command command description
 */
- (void)scanDevices: (CDVInvokedUrlCommand *)command {
    NSLog(@"scanDevices......");
    
    self.scanDevicesCallbackId = command.callbackId;
    
    //每次搜索前清空devices
    self.devices = [@{} mutableCopy];
    
    //搜索前初始化各个品牌的蓝牙读卡器,这个初始化不在这边执行，测试发现init后不能立马搜索蓝牙设备，可能有延时
    //[self initKaerDevice]; //卡尔
    //森锐
    //[self initSensorDevice]; //神思
    
    //搜索各个品牌的设备，其中卡尔是同步返回多list，神思是异步回调的，森锐也是异步回调的
    //    [self scanKaerDeviceListKT8000]; //卡尔kt8000,里面会同步返回搜到的 当前 所有设备的结果集
    //    [self scanSunriseDevice]; //森锐
    //    [self scanSensorDevice];//神思
    //    [self scanHhdDevice];//恒鸿达
    //    [self scanKaerDeviceListKT8003]; //卡尔kt8003,里面会同步返回搜到的 当前 所有设备的结果集
    
    //    [resp setObject:devices forKey:@"data"];
    //    //返回数据
    //    [self sendRespInfo:resp withCallBackID: self.scanDevicesCallbackId];
    
    //因为森锐demo使用了ios系统自带的搜索和回调，导致其他品牌也会执行系统的回调，那索性统一用系统的，不用各自sdk
    //神思init里已经初始化过了, 回调函数 didDiscoverPeripheral
    //注意这个会一直在后台执行搜索，我在连接函数connectDevice里控制，当点击连接某过设备时，停止搜索
    [self.CBCenteralmanager scanForPeripheralsWithServices:nil options:@{CBCentralManagerScanOptionAllowDuplicatesKey : @YES}];
    //恒宏达特殊，只能用sdk里的搜索，不然设备对象CBPeripheral无法转换成SYDMyPeripheral
    [self scanHhdDevice];//恒鸿达
    
    //改改改2.26，搜索5秒后停止搜索
    //    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    //        [self.CBCenteralmanager stopScan];
    //    });
    
}

/**
 连接蓝牙读卡器
 
 @param command <#command description#>
 */
- (void)connectDevice: (CDVInvokedUrlCommand *)command {
    NSLog(@"connectDevice......");
    
    self.normalCallbackId = command.callbackId;
    NSDictionary *param = [self paramsFromCommand:command];//从命令里获取参数
    
    //self.CBCenteralmanager scanForPeripheralsWithServices 会一直在后台执行搜索
    //我在连接函数connectDevice里控制，当点击连接某过设备时，停止搜索
    [self.CBCenteralmanager stopScan];
    
    //湖北特殊判断
    //    NSString *pluginID = param[@"pluginID"];
    //    if (![pluginID isEqualToString:@"201605201032HuBei"]) {
    //        [self sendErrorInfo:@"" errorCode:@"0018" withCallBackId:command.callbackId];
    //        return;
    //    }
    
    //根据设备name获取品牌类型 1:卡尔kt8000 2 森锐 3 神思 4恒鸿达 5卡尔kt8003 也可以根据devices里的deviceType来判断
    NSString *name = param[@"name"];
    NSDictionary *deviceInfo = self.devices[name]; //根据name找到该设备信息
    int deviceType = [self deviceTypeFromName:name];
    NSLog (@"deviceType is :%zi", deviceType);
    //当前蓝牙操作类型和当前蓝牙设备类型
    self.nowOptType = optType_conncetDevice;
    self.nowDeviceType = deviceType;
    
    switch (deviceType) {
        case deviceType_kaer_kt8000:
        {
            //[self initKaerDevice];
            //NSLog (@"deviceInfo is :%@", [self objToString:deviceInfo]);
            NSString *uuid = deviceInfo[@"uuid"];
            [self conectKaerDeviceKT8000:uuid];
        }
            break;
        case deviceType_sunrise:
        {
            CBPeripheral *peripheral = deviceInfo[@"model"];
            [self connectSunriseDevice: peripheral];
            //[self srDeviceModelHook];
            //[self initSRDevice];
        }
            break;
        case deviceType_sensor:
        {
            //[self initSensorDevice];
            CBPeripheral *peripheral = deviceInfo[@"model"];
            [self connectSensorDevice: peripheral];
        }
            break;
        case deviceType_hhd:
        {
            SYDMyPeripheral *peripheral = deviceInfo[@"model"];
            [self connectHhdDevice: peripheral];
        }
            break;
        case deviceType_kaer_kt8003:
        {
            NSString *uuid = deviceInfo[@"uuid"];
            [self conectKaerDeviceKT8003:uuid];
        }
            break;
        case deviceType_xintong: {
            //连接设备，并给self.curConnectPeripheral赋值
            CBPeripheral *peri = deviceInfo[@"model"];
            //如果存在，直接连接，如果不存在这个设备，返回失败
            if (peri) {
                self.curConnectPeripheral = [[STMyPeripheral alloc] init];
                self.curConnectPeripheral.advName = peri.name;
                self.curConnectPeripheral.peripheral = peri;
                [self.CBCenteralmanager connectPeripheral:peri options:@{CBConnectPeripheralOptionNotifyOnDisconnectionKey: @YES}];
            }
            else {
                NSMutableDictionary *resp = [@{} mutableCopy]; //返回信息
                [resp setValue:@"9998" forKey:@"respCode"];
                [resp setValue:@"该name没有匹配到品牌类型" forKey:@"respDesc"];
                //返回数据
                [self sendRespInfo:resp withCallBackID: self.normalCallbackId];
            }
        }
            break;
        default:
        {
            NSMutableDictionary *resp = [@{} mutableCopy]; //返回信息
            [resp setValue:@"9998" forKey:@"respCode"];
            [resp setValue:@"该name没有匹配到品牌类型" forKey:@"respDesc"];
            //返回数据
            [self sendRespInfo:resp withCallBackID: self.normalCallbackId];
        }
            break;
    }
    
}


/**
 读身份证信息
 
 @param command <#command description#>
 */
- (void)readIDCard: (CDVInvokedUrlCommand *)command {
    NSLog(@"readIDCard......");
    
    self.readIDCardCallbackId = command.callbackId;
    NSDictionary *param = [self paramsFromCommand:command];//从命令里获取参数
    self.encryptKey = param[@"encryptKey"];//加密秘钥，江苏特供，其他省可以不传或者传""
    
    //根据设备name获取品牌类型 1:卡尔kt8000 2 森锐 3 神思 4恒鸿达 5卡尔kt8003
    NSString *name = param[@"name"];
    NSDictionary *deviceInfo = self.devices[name]; //根据name找到该设备信息
    int deviceType = [self deviceTypeFromName:name];
    NSLog (@"deviceType is :%zi", deviceType);
    //当前蓝牙操作类型和当前蓝牙设备类型
    self.nowOptType = optType_readIDCard;
    self.nowDeviceType = deviceType;
    
    switch (deviceType) {
        case deviceType_kaer_kt8000:
        {
            NSString *uuid = deviceInfo[@"uuid"];
            [self kaerDeviceReadIDCardKT8000:uuid];
        }
            break;
        case deviceType_sunrise:
        {
            CBPeripheral *peripheral = deviceInfo[@"model"];
            [self sunriseDeviceReadIDCard: peripheral];
        }
            break;
        case deviceType_sensor:
        {
            //[self.bletool id2ShakeHand];
            [self sensorDeviceReadIDCard];
        }
            break;
        case deviceType_hhd:
        {
            [self hhdDeviceReadIDCard];
        }
            break;
        case deviceType_kaer_kt8003:
        {
            NSString *uuid = deviceInfo[@"uuid"];
            [self kaerDeviceReadIDCardKT8003:uuid];
        }
            break;
        case deviceType_xintong: {
            [self xintongDeviceReadIDCard];
        }
            break;
        default:
        {
            NSMutableDictionary *resp = [@{} mutableCopy]; //返回信息
            [resp setValue:@"9998" forKey:@"respCode"];
            [resp setValue:@"该name没有匹配到品牌类型" forKey:@"respDesc"];
            //返回数据
            [self sendRespInfo:resp withCallBackID: self.normalCallbackId];
        }
            break;
    }
    
    
}

/**
 读sim卡的ICCID
 
 @param command <#command description#>
 */
- (void)readICCID: (CDVInvokedUrlCommand *)command {
    NSLog(@"readICCID......");
    
    self.normalCallbackId = command.callbackId;
    NSDictionary *param = [self paramsFromCommand:command];//从命令里获取参数
    
    //根据设备name获取品牌类型 1:卡尔kt8000 2 森锐 3 神思 4恒鸿达 5卡尔kt8003
    NSString *name = param[@"name"];
    NSDictionary *deviceInfo = self.devices[name]; //根据name找到该设备信息
    int deviceType = [self deviceTypeFromName:name];
    NSLog (@"deviceType is :%zi", deviceType);
    //当前蓝牙操作类型和当前蓝牙设备类型
    self.nowOptType = optType_readICCID;
    self.nowDeviceType = deviceType;
    
    switch (deviceType) {
        case deviceType_kaer_kt8000:
        {
            NSString *uuid = deviceInfo[@"uuid"];
            [self kaerReadICCIDKT8000:uuid];
        }
            break;
        case deviceType_sunrise:
        {
            //[self srReadICCIDForCardType:params[@"cardType"] withCallbackID:command.callbackId];
            CBPeripheral *peripheral = deviceInfo[@"model"];
            [self sunriseReadICCID: peripheral];
        }
            break;
        case deviceType_sensor:
        {
            [self sensorReadICCID];
        }
            break;
        case deviceType_hhd:
        {
            [self hhdReadICCID];
        }
            break;
        case deviceType_kaer_kt8003:
        {
            NSString *uuid = deviceInfo[@"uuid"];
            [self kaerReadICCIDKT8003:uuid];
        }
            break;
        case deviceType_xintong: {
            [self xintongDeviceReadICCID];
        }
            break;
        default:
        {
            NSMutableDictionary *resp = [@{} mutableCopy]; //返回信息
            [resp setValue:@"9998" forKey:@"respCode"];
            [resp setValue:@"该name没有匹配到品牌类型" forKey:@"respDesc"];
            //返回数据
            [self sendRespInfo:resp withCallBackID: self.normalCallbackId];
        }
            break;
    }
    
}

/**
 写卡，包括写短信中心
 注意：短信中心11位不要+86，但是传了+86页没事，插件里会replace掉
 
 @param command command description
 */
- (void)writeSim: (CDVInvokedUrlCommand *)command {
    NSLog(@"writeSim......");
    
    self.normalCallbackId = command.callbackId;
    NSDictionary *param = [self paramsFromCommand:command];//从命令里获取参数
    
    //根据设备name获取品牌类型 1:卡尔kt8000 2 森锐 3 神思 4恒鸿达 5卡尔kt8003
    NSString *name = param[@"name"];
    NSDictionary *deviceInfo = self.devices[name]; //根据name找到该设备信息
    int deviceType = [self deviceTypeFromName:name];
    NSLog (@"deviceType is :%zi", deviceType);
    //当前蓝牙操作类型和当前蓝牙设备类型
    self.nowOptType = optType_writeSim;
    self.nowDeviceType = deviceType;
    
    switch (deviceType) {
        case deviceType_kaer_kt8000:
        {
            NSString *uuid = deviceInfo[@"uuid"];
            [self kaerWriteCardKT8000:param withUUid:uuid];
        }
            break;
        case deviceType_sunrise:
        {
            //[self.srIDCardManager startScaleCard:150];
            CBPeripheral *peripheral = deviceInfo[@"model"];
            [self sunriseWriteCard:param withPeripheral: peripheral];
        }
            break;
        case deviceType_sensor:
        {
            [self sensorWriteCard:param];
        }
            break;
        case deviceType_hhd:
        {
            [self hhdWriteCard:param];
        }
            break;
        case deviceType_kaer_kt8003:
        {
            NSString *uuid = deviceInfo[@"uuid"];
            [self kaerWriteCardKT8003:param withUUid:uuid];
        }
            break;
        case deviceType_xintong: {
            [self xintongDeviceWriteICCID:param];
        }
            break;
        default:
        {
            NSMutableDictionary *resp = [@{} mutableCopy]; //返回信息
            [resp setValue:@"9998" forKey:@"respCode"];
            [resp setValue:@"该name没有匹配到品牌类型" forKey:@"respDesc"];
            //返回数据
            [self sendRespInfo:resp withCallBackID: self.normalCallbackId];
        }
            break;
    }
    
    
}




#pragma mark - 卡尔kt8000

/**
 卡尔-初始化卡尔读卡器
 */
- (void)initKaerDeviceKT8000:(NSDictionary *) param{
    self.kaerManagerKt8000 = [BleTool getInstance:self];
    self.kaerManagerKt8000.brcallback = self;
    NSLog (@"kaerManager init success");
}

/**
 卡尔-搜索蓝牙读卡器
 */
//- (void)searchKaerDeviceList: (NSMutableArray *) devices {
//    NSArray *deviceList = [self.kaerManager ScanDeviceList:2];
//    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name BEGINSWITH[c] %@", @"KT"];
//    deviceList = [deviceList filteredArrayUsingPredicate:predicate];
//    //NSMutableArray *results = [@[] mutableCopy];
//    for (NSDictionary *item in deviceList) {
//        NSMutableDictionary *device = [@{} mutableCopy]; //重新封装每一个设备
//        [device setValue:item[@"name"] forKey:@"name"];
//        [device setValue:@"" forKey:@"mac"];
//        [device setValue:item[@"uuid"] forKey:@"uuid"];
//        [devices addObject:device]; //添加到所有的列表里
//    }
//
////    NSMutableDictionary *device = [@{} mutableCopy]; //重新封装每一个设备
////    [device setValue:@"abcd" forKey:@"name"];
////    [device setValue:@"" forKey:@"mac"];
////    [device setValue:@"1234567" forKey:@"uuid"];
////    [devices addObject:device]; //添加到所有的列表里
//
//}

- (void)scanKaerDeviceListKT8000 {
    NSLog(@"scanKaerDeviceList......");
    
    NSArray *deviceList = [self.kaerManagerKt8000 ScanDeviceList:2];
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name BEGINSWITH[c] %@", @"KT8000"];
    deviceList = [deviceList filteredArrayUsingPredicate:predicate];
    NSLog (@"scanKaerDeviceListKT8000 is :%@", [self objToString:deviceList]);
    
    //NSLog (@"self.devices is :%@", [self objToString:[self.devices allKeys]]);
    for (NSDictionary *item in deviceList) {
        NSLog (@"item name is :%@", item[@"name"]);
        //如果设备列表里没有，则添加进去，否则不处理
        if([self.devices objectForKey: item[@"name"] ]){
            NSLog (@"item exists :%@", item[@"name"]);
            continue;
        }
        else{
            NSLog (@"item not exists :%@", item[@"name"]);
            
            NSMutableDictionary *deviceInfo = [@{} mutableCopy]; //重新封装每一个设备
            [deviceInfo setValue:item[@"name"] forKey:@"name"];
            [deviceInfo setValue:@"" forKey:@"mac"];
            [deviceInfo setValue:item[@"uuid"] forKey:@"uuid"];
            [deviceInfo setValue:@(deviceType_kaer_kt8000) forKey:@"deviceType"]; //1
            
            [self.devices setObject:deviceInfo forKey:item[@"name"]]; //添加到所有的列表里,key是name，value是个字典
        }
    }
    //NSLog (@"self.devices is :%@", [self objToString:[self.devices allKeys]]);
    
    //返回信息
    NSMutableDictionary *resp = [@{} mutableCopy];
    [resp setValue:@"0000" forKey:@"respCode"];
    [resp setValue:@"卡尔蓝牙读卡器设备搜索成功" forKey:@"respDesc"];
    NSArray *data = [self.devices allKeys]; //返回给前端的是给list，而且只返回name的list，其他信息不需要
    if ([data isKindOfClass:[NSArray class]] && data.count > 0)
    {
        [resp setObject:data forKey:@"data"];
    }
    else{
        [resp setObject:[@[] mutableCopy] forKey:@"data"];
    }
    //返回数据
    [self sendDevicesInfo:resp];
}


/**
 卡尔-根据uuid连接蓝牙设备
 BR_connectResult 回调函数里也会被触发，所以注释掉返回，这边同步返回，避免返回2次
 另外卡尔和神思都会触发这个BR_connectResult 回调函数
 
 @param uuid uuid description
 */
- (void)conectKaerDeviceKT8000:(NSString *) uuid {
    NSLog (@"conectKaerDevice......");
    NSLog (@"conectKaerDevice uuid is :%@", uuid);
    
    NSMutableDictionary *resp = [@{} mutableCopy]; //返回信息
    
    BOOL result = [self.kaerManagerKt8000 connectBt:uuid];
    if (result) {
        NSLog (@"conectKaerDeviceKT8000 success");
        
        [resp setValue:@"0000" forKey:@"respCode"];
        [resp setValue:@"卡尔kt8000蓝牙读卡器连接成功" forKey:@"respDesc"];
    } else {
        NSLog (@"conectKaerDeviceKT8000 failed");
        
        [resp setValue:@"0001" forKey:@"respCode"];
        [resp setValue:@"卡尔kt8000蓝牙读卡器连接失败" forKey:@"respDesc"];
    }
    
    //返回数据
    [self sendRespInfo:resp withCallBackID:self.normalCallbackId];
}

/**
 卡尔-读身份证信息
 发现卡尔隔20分钟左右会断连，所以每次操作前先连接再操作
 */
- (void)kaerDeviceReadIDCardKT8000:(NSString *) uuid  {
    NSLog (@"kaerDeviceReadIDCard......");
    
    NSMutableDictionary *resp = [@{} mutableCopy]; //返回信息
    
    //先判断连接状态，断了先重连下.如果连接成功则继续操作，连接失败直接返回app
    BOOL status = [self.kaerManagerKt8000 connectStatus];
    if(!status){
        //1.重新初始化
        [self initKaerDeviceKT8000:self.config[@"kt8000"]];
        //2.重新连接
        BOOL result = [self.kaerManagerKt8000 connectBt:uuid];
        if (result) {
            NSLog (@"kaerDeviceReadIDCardKT8000...conectKaerDeviceKT8000 success");
        }
        else{
            NSLog (@"kaerDeviceReadIDCardKT8000...conectKaerDeviceKT8000 faild");
            [resp setValue:@"0001" forKey:@"respCode"];
            [resp setValue:@"卡尔kt8000蓝牙读卡器连接失败" forKey:@"respDesc"];
            //返回数据
            [self sendIDCardInfo:resp];
            return;
        }
    }
    
    
    NSDictionary *idInfo = [self.kaerManagerKt8000 readIDCard]; //身份证读取出的信息
    NSMutableDictionary *data = [@{} mutableCopy]; //返回data信息，需要把不同品牌读卡器读出的字段统一
    
    [resp setValue:@"0000" forKey:@"respCode"];
    [resp setValue:@"读取身份证成功" forKey:@"respDesc"];
    
    [data setValue:idInfo[@"name"] forKey:@"name"]; //姓名
    [data setValue:idInfo[@"sex_code"] forKey:@"sexName"]; //性别名称
    [data setValue:([idInfo[@"sex_code"] isEqualToString:@"男"] ? @"1":@"0") forKey:@"sexCode"]; //性别编码
    [data setValue:idInfo[@"birth"] forKey:@"birth"]; //生日yyyymmdd
    [data setValue:@"" forKey:@"nationCode"]; //民族编码,卡尔没有
    [data setValue:idInfo[@"nation_code"] forKey:@"nationName"]; //民族汉字
    //[data setValue:[self nationNameFromCode:idInfo[@"nation_code"]] forKey:@"nationName"]; //民族汉字
    [data setValue:idInfo[@"address"] forKey:@"address"]; //住址
    [data setValue:idInfo[@"id_num"] forKey:@"idNum"]; //身份证号
    [data setValue:idInfo[@"sign_office"] forKey:@"signOffice"]; //发证机关
    [data setValue:idInfo[@"useful_s_date"] forKey:@"usefulStartDate"]; //有效期开始yyyymmdd
    [data setValue:idInfo[@"useful_e_date"] forKey:@"usefulEndDate"]; //有效期结束yyyymmdd
    
    //        NSData *picData = idInfo[@"picBitmap"]; //照片原始数据
    //        NSString *base64Encoded = [picData base64EncodedStringWithOptions:0];//转Base64字符串
    //        [data setValue:base64Encoded forKey:@"pic"]; //照片base64字符串
    
    NSData *picData1 = idInfo[@"picBitmap"];
    if(picData1!=nil){
        NSString *picdecUrl = @"http://218.56.11.180:6045/unpackwlt";
        NSDictionary *imgdecodeDict=[self.kaerManagerKt8000 getDecodedPicDataOnServerUrl:picdecUrl];
        
        NSString *errorCode = imgdecodeDict[@"errCode"];
        if ([errorCode isEqualToString:@"0"]) {
            NSData *picData2 = imgdecodeDict[@"DecPicData"];
            NSString *base64Encoded = [picData2 base64EncodedStringWithOptions:0];
            base64Encoded = [self replaceBlank:base64Encoded]; //替换掉\r\n
            [data setValue:base64Encoded forKey:@"pic"]; //返回照片base64字符串
        }
    }
    else{
        [data setValue:@"" forKey:@"pic"]; //没读到返回空字符串
    }
    
    //江苏特供：加密秘钥不为空时对身份证号，姓名，住址 3个字段分别加密，其他省可以不传或者传""，
    [self jiangsuSpecialEncryptionWithResult:idInfo data:&data];
    //    if(![self isBlankString:self.encryptKey]){
    //        NSData *encryptKeyData = [self.encryptKey dataUsingEncoding:NSUTF8StringEncoding];//
    //        Byte *encryptKeyByte = (Byte *)[encryptKeyData bytes];//key要转成Byte
    //
    //        NSString *nameEncript = [self.encrylibInterface Id2DataEncry:encryptKeyByte :idInfo[@"name"]];
    //        NSString *idNumEncript = [self.encrylibInterface Id2DataEncry:encryptKeyByte :idInfo[@"id_num"]];
    //        NSString *addressEncript = [self.encrylibInterface Id2DataEncry:encryptKeyByte :idInfo[@"address"]];
    //
    //        [data setValue:nameEncript forKey:@"nameEncript"]; //姓名加密后
    //        [data setValue:idNumEncript forKey:@"idNumEncript"]; //身份证号加密后
    //        [data setValue:addressEncript forKey:@"addressEncript"]; //住址加密后
    //    }
    
    [resp setObject:data forKey:@"data"];
    
    //返回数据
    [self sendIDCardInfo:resp];
}

/**
 卡尔-读sim卡iccid
 发现卡尔隔20分钟左右会断连，所以每次操作前先连接再操作
 */
- (void)kaerReadICCIDKT8000:(NSString *) uuid {
    NSLog (@"kaerReadICCID......");
    
    NSMutableDictionary *resp = [@{} mutableCopy]; //返回信息
    
    //先判断连接状态，断了先重连下.如果连接成功则继续操作，连接失败直接返回app
    BOOL status = [self.kaerManagerKt8000 connectStatus];
    if(!status){
        //1.重新初始化
        [self initKaerDeviceKT8000:self.config[@"kt8000"]];
        //2.重新连接
        BOOL result = [self.kaerManagerKt8000 connectBt:uuid];
        if (result) {
            NSLog (@"kaerDeviceReadIDCardKT8000...conectKaerDeviceKT8000 success");
        }
        else{
            NSLog (@"kaerDeviceReadIDCardKT8000...conectKaerDeviceKT8000 faild");
            [resp setValue:@"0001" forKey:@"respCode"];
            [resp setValue:@"卡尔kt8000蓝牙读卡器连接失败" forKey:@"respDesc"];
            //返回数据
            [self sendIDCardInfo:resp];
            return;
        }
    }
    
    NSDictionary *ICCID = [self.kaerManagerKt8000 readICCID];
    //1 成功，0 失败
    if ([ICCID[@"errCode"] isEqualToString:@"1"]) {
        [resp setValue:@"0000" forKey:@"respCode"];
        [resp setValue:@"读取iccid成功" forKey:@"respDesc"];
        
        NSMutableDictionary *data = [@{} mutableCopy]; //返回data信息，需要把不同品牌读卡器读出的字段统一
        NSData *iccidData = ICCID[@"IccidData"];
        NSString *iccidStr = [[NSString alloc] initWithData:iccidData encoding:NSUTF8StringEncoding];
        [data setValue:iccidStr forKey:@"iccid"]; //iccid字符串
        [resp setObject:data forKey:@"data"];
        
    } else {
        [resp setValue:@"0003" forKey:@"respCode"];
        [resp setValue:@"读取iccid失败" forKey:@"respDesc"];
    }
    
    
    //返回数据
    [self sendRespInfo:resp withCallBackID:self.normalCallbackId];
    
}

/**
 卡尔-写sim卡，包括写imsi 和 写短信中心smsc
 发现卡尔隔20分钟左右会断连，所以每次操作前先连接再操作
 @param param <#param description#>
 */
- (void)kaerWriteCardKT8000:(nonnull NSDictionary *)param withUUid:(NSString *) uuid {
    NSLog (@"kaerWriteCard......");
    
    NSMutableDictionary *resp = [@{} mutableCopy]; //返回信息
    
    //先判断连接状态，断了先重连下.如果连接成功则继续操作，连接失败直接返回app
    BOOL status = [self.kaerManagerKt8000 connectStatus];
    if(!status){
        //1.重新初始化
        [self initKaerDeviceKT8000:self.config[@"kt8000"]];
        //2.重新连接
        BOOL result = [self.kaerManagerKt8000 connectBt:uuid];
        if (result) {
            NSLog (@"kaerDeviceReadIDCardKT8000...conectKaerDeviceKT8000 success");
        }
        else{
            NSLog (@"kaerDeviceReadIDCardKT8000...conectKaerDeviceKT8000 faild");
            [resp setValue:@"0001" forKey:@"respCode"];
            [resp setValue:@"卡尔kt8000蓝牙读卡器连接失败" forKey:@"respDesc"];
            //返回数据
            [self sendIDCardInfo:resp];
            return;
        }
    }
    
    NSData *imsiData = [param[@"imsi"] dataUsingEncoding:NSUTF8StringEncoding];//写imsi要转成data
    NSString *smsc = param[@"smsc"];//短信中心，写短信中心用,11位短信中心号不要+86
    if([smsc hasPrefix:@"+86"]==YES){
        smsc = [smsc substringFromIndex:3];
    }
    int imsiResult = [self.kaerManagerKt8000 writeIMSI:imsiData andIMSI2:imsiData];//imsi1和imsi2一样
    if (1 == imsiResult) {
        //imsi写成功后才 写短信中心
        int smscResult = [self.kaerManagerKt8000 writeSMSC:smsc withNumberIndex:(Byte)0x01];
        if (1 == smscResult) {
            [resp setValue:@"0000" forKey:@"respCode"];
            [resp setValue:@"写入imsi成功,写入smsc短信中心成功" forKey:@"respDesc"];
        } else {
            if(smscResult==0){
                [resp setValue:@"0010" forKey:@"respCode"];
                [resp setValue:@"写入smsc失败" forKey:@"respDesc"];
            }else if(smscResult==-2){
                [resp setValue:@"0011" forKey:@"respCode"];
                [resp setValue:@"写入smsc失败,入参非法" forKey:@"respDesc"];
            }else if(smscResult==2){
                [resp setValue:@"0012" forKey:@"respCode"];
                [resp setValue:@"写入smsc失败,卡未插入" forKey:@"respDesc"];
            }else if(smscResult==3){
                [resp setValue:@"0013" forKey:@"respCode"];
                [resp setValue:@"写入smsc失败,不识别的sim卡" forKey:@"respDesc"];
            }else if(smscResult==4){
                [resp setValue:@"0014" forKey:@"respCode"];
                [resp setValue:@"写入smsc失败,卡插入但还未初始化" forKey:@"respDesc"];
            }
        }
    } else {
        if(imsiResult==0){
            [resp setValue:@"0010" forKey:@"respCode"];
            [resp setValue:@"写入imsi失败" forKey:@"respDesc"];
        }else if(imsiResult==-2){
            [resp setValue:@"0011" forKey:@"respCode"];
            [resp setValue:@"写入imsi失败,入参非法" forKey:@"respDesc"];
        }else if(imsiResult==2){
            [resp setValue:@"0012" forKey:@"respCode"];
            [resp setValue:@"写入imsi失败,卡未插入" forKey:@"respDesc"];
        }else if(imsiResult==3){
            [resp setValue:@"0013" forKey:@"respCode"];
            [resp setValue:@"写入imsi失败,不识别的sim卡" forKey:@"respDesc"];
        }else if(imsiResult==4){
            [resp setValue:@"0014" forKey:@"respCode"];
            [resp setValue:@"写入imsi失败,卡插入但还未初始化" forKey:@"respDesc"];
        }
    }
    
    //返回数据
    [self sendRespInfo:resp withCallBackID:self.normalCallbackId];
    
}

/**
 卡尔-库的委托回调函数 ，返回蓝牙连接状态
 注意：神思的有个回调函数和卡尔这个名字一样，共用这一个函数,都会触发这个函数
 
 20180725 xmh
 注意：这边虽然被触发了，但不再返回结果给前端，由卡尔和神思各自的连接函数里返回结果
 
 @param isconnected <#isconnected description#>
 */
- (void)BR_connectResult:(BOOL)isconnected {
    NSLog (@"BR_connectResult......");
    //[self bleDeviceConnectResult:isconnected];
}

- (void)bleDeviceConnectResult:(BOOL)status {
    NSLog (@"bleDeviceConnectResult......");
    
    NSMutableDictionary *resp = [@{} mutableCopy]; //返回信息
    
    if (status) {
        [resp setValue:@"0000" forKey:@"respCode"];
        [resp setValue:@"卡尔or神思蓝牙设备连接状态正常" forKey:@"respDesc"];
    } else {
        [resp setValue:@"0002" forKey:@"respCode"];
        [resp setValue:@"卡尔or神思蓝牙设备连接已断开" forKey:@"respDesc"];
    }
    
    //返回数据
    [self sendRespInfo:resp withCallBackID:self.normalCallbackId];
}


#pragma mark - 森锐

/**
 森锐-初始化森锐设备
 */
- (void)initSunriseDevice:(NSDictionary *) param {
    
    //设置服务器url
    //    NSString *acct = @"test03";
    //    NSString *pwd = @"12315aA..1";
    //    NSString *key = @"FE870B0163113409C134283661490AEF"; //demo里没用到
    //    NSString *ip = @"59.41.39.51";
    //    NSString *port = @"6000";
    
    NSString *acct = param[@"acct"];
    NSString *pwd = param[@"password"];
    NSString *key = param[@"key"]; //demo里没用到
    NSString *ip = param[@"ip"];
    NSString *port = param[@"port"];
    
    //[self.sunriseIdManager setUpAccount:acct password:pwd];
    //self.sunriseIdManager = [SRIDCardReader instanceWithManager];
    //self.sunriseIdManager.delegate = (id)self;
    //[self.sunriseIdManager setServerIP:ip andPort:[port intValue]];
    
    self.sunriseIdManager = [SRIDCardReader instanceWithManagerIP:ip port:[port intValue] account:acct password:pwd key:key];
    self.sunriseIdManager.delegate = (id)self;
    
    NSLog(@"initSunriseDevice success");
}


/**
 森锐-搜索森锐设备
 通过回调函数 didDiscoverPeripheral 返回结果
 */
- (void)scanSunriseDevice {
    NSLog(@"scanSunriseDevice......");
    
    [self.sunriseIdManager refreshDeviceList];
    //森锐demo里使用了ios系统自带的搜索
    //[self.CBCenteralmanager scanForPeripheralsWithServices:nil options:@{CBCentralManagerScanOptionAllowDuplicatesKey : @YES}];
}


/**
 森锐-搜索森锐设备-回调函数
 其实这个是ios 自带的CBCentralManager 的蓝牙搜索到设备后的回调函数
 */
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheraln advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI{
    
    NSLog(@"scanDevices didDiscoverPeripheral......%@", peripheraln.name);
    
    int deviceType = [self deviceTypeFromName:peripheraln.name];
    NSLog (@"deviceType is :%zi", deviceType);
    if(deviceType == deviceType_ohter){
        NSLog(@"scanDevices didDiscoverPeripheral......不是支持的蓝牙设备，抛弃");
        return;
    }
    //恒宏达特殊，只能用sdk里的搜索，不然设备对象CBPeripheral无法转换成SYDMyPeripheral
    if(deviceType == deviceType_hhd){
        NSLog(@"scanDevices didDiscoverPeripheral......恒宏达蓝牙设备，抛弃，用sdk里的搜索");
        return;
    }
    
    //如果设备列表里没有，则添加进去，否则不处理
    if([self.devices objectForKey: peripheraln.name ]){
        return;
    }
    else{
        NSMutableDictionary *deviceInfo = [@{} mutableCopy]; //重新封装每一个设备
        [deviceInfo setObject:peripheraln forKey:@"model"];
        [deviceInfo setValue:peripheraln.name forKey:@"name"];
        [deviceInfo setValue:@"" forKey:@"mac"];
        [deviceInfo setValue:[peripheraln.identifier UUIDString] forKey:@"uuid"]; //注意转成string
        [deviceInfo setValue:@(deviceType) forKey:@"deviceType"]; //
        
        //添加到所有的列表里,key是name，value是设备的实例对象
        [self.devices setObject:deviceInfo forKey: peripheraln.name];
    }
    
    //返回信息
    NSMutableDictionary *resp = [@{} mutableCopy];
    [resp setValue:@"0000" forKey:@"respCode"];
    [resp setValue:@"设备搜索到一个蓝牙读卡器设备" forKey:@"respDesc"];
    NSArray *data = [self.devices allKeys]; //返回给前端的是给list，而且只返回name的list，其他信息不需要
    if ([data isKindOfClass:[NSArray class]] && data.count > 0)
    {
        [resp setObject:data forKey:@"data"];
    }
    else{
        [resp setObject:[@[] mutableCopy] forKey:@"data"];
    }
    //返回数据
    [self sendDevicesInfo:resp];
    
}

/**
 森锐-连接设备
 连接回调函数是 didConnectPeripheral
 @param peripheral <#peripheral description#>
 */
- (void)connectSunriseDevice:(CBPeripheral *) peripheral  {
    NSLog (@"connectSunriseDevice......");
    
    BOOL result = [self.sunriseIdManager setLisentPeripheral:peripheral withCBManager:self.CBCenteralmanager];
    
    NSMutableDictionary *resp = [@{} mutableCopy]; //返回信息
    if(result){
        NSLog(@"connectSunriseDevice success");
        
        [resp setValue:@"0000" forKey:@"respCode"];
        [resp setValue:@"森锐蓝牙设备连接成功" forKey:@"respDesc"];
    }
    else{
        NSLog(@"connectSunriseDevice fail");
        
        [resp setValue:@"0002" forKey:@"respCode"];
        [resp setValue:@"森锐蓝牙设备连接失败" forKey:@"respDesc"];
    }
    
    //返回数据
    [self sendRespInfo:resp withCallBackID:self.normalCallbackId];
}

/**
 森锐-连接设备-成功回调函数， 作废，测试发现没有执行回调，直接同步返回了
 @param peripheral <#peripheral description#>
 */
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral{
    if (deviceType_xintong == self.nowDeviceType) {
        NSLog(@"xintong didConnectPeripheral has connected success");
        
        //信通设备需要继续搜索服务和特征
        NSArray *uuids = [NSArray arrayWithObjects:[CBUUID UUIDWithString:UUIDSTR_DEVICE_INFO_SERVICE], [CBUUID UUIDWithString:UUIDSTR_ISSC_PROPRIETARY_SERVICE], nil];
        
        peripheral.delegate = (id)self;
        [peripheral discoverServices:uuids];
    }
    else {
        NSLog(@"sunrise didConnectPeripheral has connected success");
        
        NSMutableDictionary *resp = [@{} mutableCopy]; //返回信息
        [resp setValue:@"0000" forKey:@"respCode"];
        [resp setValue:@"森锐蓝牙设备连接成功" forKey:@"respDesc"];
        
        //返回数据
        [self sendRespInfo:resp withCallBackID:self.normalCallbackId];
    }
}

/**
 森锐-连接设备-失败回调函数， 作废，测试发现没有执行回调，直接同步返回了
 @param peripheral <#peripheral description#>
 */
- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error{
    
    NSLog(@"sunrise didFailToConnectPeripheral has connected error, :%@", error.domain);
    
    NSMutableDictionary *resp = [@{} mutableCopy]; //返回信息
    [resp setValue:@"0002" forKey:@"respCode"];
    [resp setValue:@"森锐蓝牙设备连接失败" forKey:@"respDesc"];
    
    //返回数据
    [self sendRespInfo:resp withCallBackID:self.normalCallbackId];
}

#pragma mark - CBPeripheral delegate methods，信通设备需要
/*
 Invoked upon completion of a -[discoverServices:] request.
 Discover available characteristics on interested services
 */
- (void) peripheral:(CBPeripheral *)aPeripheral didDiscoverServices:(NSError *)error{
    
    for (CBService *aService in aPeripheral.services){
        NSLog(@"找到Service: %@", aService.UUID);
        //查找蓝牙的特征值 （读写）
        [aPeripheral discoverCharacteristics:nil forService:aService];
    }
}

- (void) peripheral:(CBPeripheral *)aPeripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error{
    
    if ([service.UUID isEqual:[CBUUID UUIDWithString:UUIDSTR_ISSC_PROPRIETARY_SERVICE]]) {
        
        for (CBCharacteristic *aChar in service.characteristics){
            if ([aChar.UUID isEqual:[CBUUID UUIDWithString:UUIDSTR_ISSC_TRANS_RX]]) {
                [self.curConnectPeripheral setTransparentDataWriteChar:aChar];
                
                NSLog(@"found TRANS_RX");
                
            }else if ([aChar.UUID isEqual:[CBUUID UUIDWithString:UUIDSTR_ISSC_TRANS_TX]]) {
                
                NSLog(@"found TRANS_TX");
                [self.curConnectPeripheral setTransparentDataReadChar:aChar];
            }
        }
        
        //连接成功
        if(self.curConnectPeripheral.transparentDataReadChar && self.curConnectPeripheral.transparentDataWriteChar){
            
            if(self.curConnectPeripheral && self.curConnectPeripheral.peripheral == aPeripheral){
                
                [self.xtScaleManager setLisentPeripheral:self.curConnectPeripheral];
                
                NSMutableDictionary *resp = [@{} mutableCopy]; //返回信息
                [resp setValue:@"0000" forKey:@"respCode"];
                [resp setValue:@"信通蓝牙设备连接成功" forKey:@"respDesc"];
                
                //返回数据
                [self sendRespInfo:resp withCallBackID:self.normalCallbackId];
                
            }
            
        }
    }
}


/**
 森锐-读身份证信息
 回调函数 SRsuccessBack
 */
- (void) sunriseDeviceReadIDCard:(CBPeripheral *) peripheral {
    NSLog(@"sunriseDeviceReadIDCard......");
    
    //每次读身份证，返回信息重新初始化，相当于清空,data部分也初始化好，因为基本信息和照片信息都放data里
    self.sunriseIdInfo = [@{} mutableCopy];
    NSMutableDictionary *data = [@{} mutableCopy]; //返回data信息，需要把不同品牌读卡器读出的字段统一
    [self.sunriseIdInfo setObject:data forKey:@"data"];
    
    [self.sunriseIdManager startScaleCard:15];
}

/**
 森锐-读身份证信息-回调函数
 功能： 代理方法，读取身份证成功时可以通过这个代理方法获取身份证的文本信息和照片信息。
 参数：peripheral代表蓝牙设备的对象
 data 如果data是NSDictionary类型，则里面包含的信息是文本信息，具体获取各字段信息见下表；如果data是NSData类型，则里面包含的是照片的二进制数据流
 返回值：无
 */
- (void)SRsuccessBack:(SRMyPeripheral *)peripheral withData:(id)data
{
    //1.先存储data节点部分,把基本信息和照片信息合起来
    if([data isKindOfClass:[NSDictionary class]]){
        NSLog(@"sunriseDeviceReadIDCard SRsuccessBack......isKindOfClass NSDictionary");
        
        NSDictionary *idInfo=(NSDictionary *)data; //转换成NSDictionary
        
        //I表示外国人身份证，这边不处理，应该不会遇到
        if ([[idInfo objectForKey:@"idType"] isEqualToString:@"I"]) {
            NSLog(@"sunriseDeviceReadIDCard SRsuccessBack......isKindOfClass NSDictionary, idType=I");
        }else{
            NSMutableDictionary *dataDict = [@{} mutableCopy]; //返回data信息，需要把不同品牌读卡器读出的字段统一
            [dataDict setValue:idInfo[@"Name"] forKey:@"name"]; //姓名
            [dataDict setValue:idInfo[@"Sex"] forKey:@"sexName"]; //性别名称
            [dataDict setValue:([idInfo[@"Sex"] isEqualToString:@"男"] ? @"1":@"0") forKey:@"sexCode"]; //性别编码
            [dataDict setValue:idInfo[@"Born"] forKey:@"birth"]; //生日yyyymmdd
            [dataDict setValue:@"" forKey:@"nationCode"]; //民族编码,卡尔没有
            [dataDict setValue:idInfo[@"Nation"] forKey:@"nationName"]; //民族汉字
            //[data setValue:[self nationNameFromCode:idInfo[@"nation_code"]] forKey:@"nationName"]; //民族汉字
            [dataDict setValue:idInfo[@"Address"] forKey:@"address"]; //住址
            [dataDict setValue:idInfo[@"CardNo"] forKey:@"idNum"]; //身份证号
            [dataDict setValue:idInfo[@"IssuedAt"] forKey:@"signOffice"]; //发证机关
            [dataDict setValue:idInfo[@"EffectedDate"] forKey:@"usefulStartDate"]; //有效期开始yyyymmdd
            [dataDict setValue:idInfo[@"ExpiredDate"] forKey:@"usefulEndDate"]; //有效期结束yyyymmdd
            
            //江苏特供：加密秘钥不为空时对身份证号，姓名，住址 3个字段分别加密，其他省可以不传或者传""，
            [self jiangsuSpecialEncryptionWithResult:idInfo data:&dataDict];
            //            if(![self isBlankString:self.encryptKey]){
            //                NSData *encryptKeyData = [self.encryptKey dataUsingEncoding:NSUTF8StringEncoding];//
            //                Byte *encryptKeyByte = (Byte *)[encryptKeyData bytes];//key要转成Byte
            //
            //                NSString *nameEncript = [self.encrylibInterface Id2DataEncry:encryptKeyByte :idInfo[@"Name"]];
            //                NSString *idNumEncript = [self.encrylibInterface Id2DataEncry:encryptKeyByte :idInfo[@"CardNo"]];
            //                NSString *addressEncript = [self.encrylibInterface Id2DataEncry:encryptKeyByte :idInfo[@"Address"]];
            //
            //                [dataDict setValue:nameEncript forKey:@"nameEncript"]; //姓名加密后
            //                [dataDict setValue:idNumEncript forKey:@"idNumEncript"]; //身份证号加密后
            //                [dataDict setValue:addressEncript forKey:@"addressEncript"]; //住址加密后
            //            }
            [self.sunriseIdInfo setObject:dataDict forKey:@"data"];
        }
        
    }else{
        NSLog(@"sunriseDeviceReadIDCard SRsuccessBack......isKindOfClass NSData");
        
        NSData *imageData = (NSData *)data;
        NSString *imageString = [imageData base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
        imageString = [self replaceBlank:imageString]; //替换掉\r\n
        [self.sunriseIdInfo[@"data"]  setValue:imageString forKey:@"pic"]; //返回照片base64字符串
    }
    
    //2.判断是否data部分完整了，完整就统一一次返回给app，不完整则继续等待
    if(self.sunriseIdInfo[@"data"][@"name"] !=nil && self.sunriseIdInfo[@"data"][@"pic"] !=nil){
        NSLog(@"sunriseDeviceReadIDCard SRsuccessBack......sunriseIdInfo is all");
        
        [self.sunriseIdInfo setValue:@"0000" forKey:@"respCode"];
        [self.sunriseIdInfo setValue:@"读取身份证成功" forKey:@"respDesc"];
        
        //返回数据
        [self sendIDCardInfo:self.sunriseIdInfo];
        //[self.sunriseIdManager closeReader]; //停止读身份证
    }
    else{
        NSLog(@"sunriseDeviceReadIDCard SRsuccessBack......sunriseIdInfo is not all");
        return;
    }
    
}

/**
 森锐-读sim卡iccid
 回调函数 ReadICCIDsuccessBack
 */
- (void) sunriseReadICCID:(CBPeripheral *) peripheral {
    NSLog (@"sunriseReadICCID......");
    
    NSMutableDictionary *resp = [@{} mutableCopy]; //返回信息
    
    BOOL result = [self.sunriseIdManager readSimICCID:@""];//读iccid
}

/**
 森锐-读sim卡iccid-回调函数(信通读sim卡成功后也走这个回调)
 功能:代理方法,读取卡号时通过该方法返回结果
 参数:结果信息
 返回值:无
 */
- (void)ReadICCIDsuccessBack:(SRIDReadCardInfo*)peripheral withData:(id)data{
    
    if ([peripheral isKindOfClass:[SRIDReadCardInfo class]]) {//森锐返回结果
        NSLog (@"sunrise and xintong ReadICCID ReadICCIDsuccessBack......:%@", peripheral.ICCID);
        
        NSMutableDictionary *resp = [@{} mutableCopy]; //返回信息
        [resp setValue:@"0000" forKey:@"respCode"];
        [resp setValue:@"读取iccid成功" forKey:@"respDesc"];
        NSMutableDictionary *data2 = [@{} mutableCopy]; //返回data信息，需要把不同品牌读卡器读出的字段统一
        NSString *iccidStr = peripheral.ICCID;
        [data2 setValue:iccidStr forKey:@"iccid"]; //iccid字符串
        [resp setObject:data2 forKey:@"data"];
        
        //返回数据
        [self sendRespInfo:resp withCallBackID:self.normalCallbackId];
    }
    else if ([peripheral isKindOfClass:[STIDReadCardInfo class]]) {
        NSLog(@"信通读sim卡成功，data======%@",data);
        NSMutableDictionary* resp = [NSMutableDictionary dictionary]; //返回信息
        if (peripheral.ICCID)
        {
            int cardType = (int)peripheral.isWhiteCard;
            if (cardType >= 0)
            {
                NSString* cardStr = cardType == 1 ? @"成卡" : @"白卡";
                NSLog(@"SIM卡是%@", cardStr);
                resp[@"respCode"] = @"0000";
                resp[@"respDesc"] = @"读取iccid成功";
                NSMutableDictionary* dataDic = [NSMutableDictionary dictionary];
                dataDic[@"iccid"] = peripheral.ICCID;
                resp[@"data"] = dataDic;
            }
            else
            {
                NSLog(@"读卡失败");
                resp[@"respCode"] = @"0002";
                resp[@"respDesc"] = @"读取iccid失败";
            }
        }
        else
        {
            NSLog(@"读卡失败");
            resp[@"respCode"] = @"0002";
            resp[@"respDesc"] = @"读取iccid失败";
        }
        //返回数据
        [self sendRespInfo:resp withCallBackID:self.normalCallbackId];
    }
    //[self.sunriseIdManager closeReader];
}

/**
 森锐-写sim卡，包括写imsi 和 写短信中心smsc
 回调函数 writeCardResultBack
 @param param <#param description#>
 */
- (void)sunriseWriteCard:(nonnull NSDictionary *)param withPeripheral:(CBPeripheral *) peripheral {
    NSLog (@"sunriseWriteCard......");
    
    //森锐短信中心不需要+86
    NSString *smsc = param[@"smsc"];
    if([smsc hasPrefix:@"+86"]==YES){
        smsc = [smsc substringFromIndex:3];
    }
    NSLog (@"sunriseWriteCard......smsc:%@", smsc);
    [self.sunriseIdManager writeSimCard:param[@"imsi"] withNo:smsc];
}

/**
 森锐-写sim卡，包括写imsi 和 写短信中心smsc-回调函数
 功能:代理方法,写卡时通过该方法返回结果
 参数:结果信息
 返回值:无
 */
- (void)writeCardResultBack:(SRIDReadCardInfo*)peripheral withData:(id)data{
    NSLog (@"sunrise and xintong WriteCard......writeCardResultBack");
    
    NSMutableDictionary *resp = [@{} mutableCopy]; //返回信息
    if (peripheral.writeCardResult == 0)
    {
        [resp setValue:@"0000" forKey:@"respCode"];
        [resp setValue:@"写入imsi 和 smsc短信中心成功" forKey:@"respDesc"];
    }
    else{
        [resp setValue:@"0011" forKey:@"respCode"];
        [resp setValue:@"写入imsi 和 smsc短信中心失败" forKey:@"respDesc"];
    }
    
    //返回数据
    [self sendRespInfo:resp withCallBackID:self.normalCallbackId];
    //[self.sunriseIdManager closeReader];
}




#pragma mark - 神思

/**
 初始化神思设备
 */
- (void)initSensorDevice:(NSDictionary *) param {
    
    self.sensorSerialGATT = [[SerialGATT alloc] init];
    [self.sensorSerialGATT Init];
    self.sensorSerialGATT.delegate = (id)self;
    
    ///新增的读写卡功能
    self.sensorBletool = [[SdsesBleTool alloc]init:self];
    self.sensorBletool.delegate = (id)self;
    //self.CBCenteralmanager = [[CBCentralManager alloc] initWithDelegate:(id)self queue:nil];
    
    NSLog(@"initSensorDevice success");
}

/**
 神思-初始化CBCentralManager的回调函数
 其实这个是ios 自带的CBCentralManager 的蓝牙状态改变的回调函数
 
 @param central <#central description#>
 */
- (void)centralManagerDidUpdateState:(CBCentralManager *)central
{
    NSString * state = nil;
    NSDictionary *dictionary ;
    
    switch ([central state])
    {
        case CBCentralManagerStateUnsupported:
            state = @"The platform/hardware doesn't support Bluetooth Low Energy.";
            break;
        case CBCentralManagerStateUnauthorized:
            state = @"The app is not authorized to use Bluetooth Low Energy.";
            break;
        case CBCentralManagerStatePoweredOff:
            state = @"Bluetooth is currently powered off.";
            break;
        case CBCentralManagerStatePoweredOn:
            state = @"work";
            break;
        case CBCentralManagerStateUnknown:
            state = @"unknown";
            
        default:
            ;
    }
    
    NSLog(@"Central manager state: %@", state);
}



/**
 神思-搜索蓝牙设备
 通过回调函数 peripheralFound 返回结果集, 看 SerialGATT BTSmartSensorDelegate
 */
- (void)scanSensorDevice {
    NSLog(@"scanSensorDevice......");
    
    [self.sensorSerialGATT ScanDeviceList:30];
}


/**
 scanSensorDevice 的回调函数, SerialGATT 里的
 因为深思的是每搜到一个设备回调一次，所以可能会返回多次，页面也可能会刷新多次，每次都是全集
 
 @param peripheral <#peripheral description#>
 @param Name <#Name description#>
 */
-(void) peripheralFound:(CBPeripheral *)peripheral :(NSString *)Name{
    NSLog(@"peripheralFound......%@",Name);
    
    if (![peripheral.name hasPrefix:@"SS"]) {
        NSLog(@"peripheralFound......不是神思设备");
        return;
    }
    
    //如果设备列表里没有，则添加进去，否则不处理
    if([self.devices objectForKey: peripheral.name ]){
        return;
    }
    else{
        NSMutableDictionary *deviceInfo = [@{} mutableCopy]; //重新封装每一个设备
        [deviceInfo setObject:peripheral forKey:@"model"];
        [deviceInfo setValue:@(deviceType_sensor) forKey:@"deviceType"]; //2
        
        //添加到所有的列表里,key是name，value是神思设备的实例对象
        [self.devices setObject:deviceInfo forKey:peripheral.name];
    }
    
    //返回信息
    NSMutableDictionary *resp = [@{} mutableCopy];
    [resp setValue:@"0000" forKey:@"respCode"];
    [resp setValue:@"神思蓝牙读卡器设备搜索成功" forKey:@"respDesc"];
    NSArray *data = [self.devices allKeys]; //返回给前端的是给list，而且只返回name的list，其他信息不需要
    if ([data isKindOfClass:[NSArray class]] && data.count > 0)
    {
        [resp setObject:data forKey:@"data"];
    }
    else{
        [resp setObject:[@[] mutableCopy] forKey:@"data"];
    }
    //返回数据
    [self sendDevicesInfo:resp];
}

/**
 作废
 scanSensorDevice 的回调函数, SdsesBleTool 里的，因为上面已经有搜索后的回调函数里，这个地方就不需要逻辑了
 
 @param peripheral <#peripheral description#>
 */
- (void) BR_getPeripheral:(CBPeripheral *)peripheral{
    NSLog(@"BR_getPeripheral......");
}


/**
 神思-连接设备
 原本 连接是否成功 通过回调函数 recvConnectCallback 返回结果
 但回调函数里没法判断是否成功，反而connectBT有返回bool，所以直接这边同步返回
 测试发现 这个地方和 BR_connectResult 回调函数都会执行返回resp，所以BR_connectResult注释掉不返回
 @param peripheral <#peripheral description#>
 */
- (void)connectSensorDevice:(CBPeripheral *) peripheral  {
    NSLog (@"connectSensorDevice......");
    
    NSMutableDictionary *resp = [@{} mutableCopy]; //返回信息
    
    BOOL result = [self.sensorBletool connectBt:peripheral :peripheral.name usingCBManager:self.CBCenteralmanager];
    if (result) {
        NSLog (@"connectSensorDevice success");
        [resp setValue:@"0000" forKey:@"respCode"];
        [resp setValue:@"神思蓝牙读卡器连接成功" forKey:@"respDesc"];
    } else {
        NSLog (@"connectSensorDevice failed");
        [resp setValue:@"0001" forKey:@"respCode"];
        [resp setValue:@"神思蓝牙读卡器连接失败" forKey:@"respDesc"];
    }
    
    //返回数据
    [self sendRespInfo:resp withCallBackID:self.normalCallbackId];
    
}

/**
 作废
 神思-连接设备-connectSensorDevice 的回调函数, SerialGATT 里的
 */
- (void) recvConnectCallback {
    NSLog(@"connectSensorDevice 回调 recvConnectCallback......");
}

/**
 作废
 神思-连接设备-connectSensorDevice 的回调函数, SerialGATT 里的
 */
- (void) recvDisconnectCallback {
    NSLog(@"connectSensorDevice 回调 recvDisconnectCallback......");
}

/**
 作废,名字和卡尔的冲突,就和上面卡尔的共用一个
 神思-连接设备-connectSensorDevice 的回调函数, SerialGATT 里的
 */
//- (void)BR_connectResult:(BOOL)isconnected {
//    NSLog(@"connectSensorDevice 回调 BR_connectResult......");
//}

/**
 神思-读身份证信息
 最新：id2ShakeHand可以不调用直接读身份证
 神思需要先调用握手 id2ShakeHand，然后在握手的回调函数里获取身份证信息
 */
- (void) sensorDeviceReadIDCard {
    NSLog(@"sensorDeviceReadIDCard......");
    [self newSSReadCard]; //握手成功后开始读身份证信息
    //[self.sensorBletool id2ShakeHand]; //王新杰确认id2ShakeHand可以不调用
}

/**
 作废
 神思-读身份证信息-回调函数
 
 @param bOk <#bOk description#>
 */
- (void) recvShakeHandCallback:(bool)bOk {
    NSLog(@"sensorDeviceReadIDCard id2ShakeHand recvShakeHandCallback......%@", bOk?@"YES":@"NO");
    
    if (!bOk) {
        NSMutableDictionary *resp = [@{} mutableCopy]; //返回信息
        [resp setValue:@"0007" forKey:@"respCode"];
        [resp setValue:@"神思蓝牙读卡器握手id2ShakeHand失败" forKey:@"respDesc"];
        //返回数据
        [self sendIDCardInfo:resp];
    } else {
        [self newSSReadCard]; //握手成功后开始读身份证信息
    }
}

/**
 神思-读身份证信息-回调函数-握手成功后读取身份证信息
 出自神思demo id2ViewController btnQsjsPress
 非加密方式使用,兼容100WT/100WS设备
 */
-(void) newSSReadCard
{
    NSLog (@"sensorDeviceReadIDCard id2ShakeHand recvShakeHandCallback newSSReadCard......");
    
    unsigned char data[4096];
    NSInteger nRet = [self.sensorBletool id2ReadCard:(Byte*)data];
    
    if(nRet > 0){
        struct id2Info id2data ;
        id2data.bHaveId2data = true;
        memcpy(&id2data.id2txt, &data[14],256);
        memcpy(&id2data.zpwlt, &data[14+256],1024);
        
        NSDictionary *dic = [self createId2Dictionary:id2data];
        [self recvReadCard:dic]; //组装成统一返回对象resp
        
        
        /*  char bmpBuff[38862];
         NSInteger nRet = [bletool id2GetBmpBuff:(char*)&id2data.zpwlt[0] :&bmpBuff[0]];
         NSLog(@"id2GetBmpBuff  nRet= %zi",nRet);
         if(nRet == -5)
         {
         self._info.text = @"授权文件不正确";
         return;
         }
         NSData * bmpData = [[NSData alloc]initWithBytes:bmpBuff length:38862];
         UIImage *zpImg=[UIImage imageWithData:bmpData];
         [self._imgView setImage:zpImg];*/
        
    }
    else{
        NSMutableDictionary *resp = [@{} mutableCopy]; //返回信息
        [resp setValue:@"0008" forKey:@"respCode"];
        [resp setValue:@"神思设备读身份证失败" forKey:@"respDesc"];
        //返回数据
        [self sendIDCardInfo:resp];
    }
    
    
}


-(NSDictionary*) createId2Dictionary:(struct id2Info)id2info {
    NSMutableDictionary * dictionary ;
    if(id2info.bHaveId2data){
        NSString * strXm= [[NSString alloc]initWithBytes:id2info.id2txt.idname length:30 encoding:NSUTF16LittleEndianStringEncoding ];
        NSLog(@"strXm is:%@",strXm);
        //神思-姓名去除空格
        strXm = [strXm stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
        NSString * Xb =  [[NSString alloc]initWithBytes:id2info.id2txt.idsex length:2 encoding:NSUTF16LittleEndianStringEncoding];//03160316需转换
        NSString * strXb = @"其他";
        if ([Xb isEqualToString:@"1"]){
            strXb = @"男";
        }else  if ([Xb isEqualToString:@"2"]){
            strXb = @"女";
        }
        
        NSString * strMz =  [[NSString alloc]initWithBytes:id2info.id2txt.idfolk length:4 encoding:
                             NSUTF16LittleEndianStringEncoding];
        
        NSString * strCsNian = [[NSString alloc]initWithBytes:id2info.id2txt.idyearBirth length:8 encoding:NSUTF16LittleEndianStringEncoding];
        
        NSString * strCsYue  = [[NSString alloc]initWithBytes:id2info.id2txt.idmonthBirth length:4 encoding:NSUTF16LittleEndianStringEncoding];
        NSString * strCsRi = [[NSString alloc]initWithBytes:id2info.id2txt.iddayBirth length:4 encoding:NSUTF16LittleEndianStringEncoding];
        NSString * strZz  = [[NSString alloc]initWithBytes:id2info.id2txt.idaddress length:70 encoding:NSUTF16LittleEndianStringEncoding];
        //神思-住址去除空格
        strZz = [strZz stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
        NSString * strSfzh= [[NSString alloc]initWithBytes:id2info.id2txt.idnum length:36 encoding:NSUTF16LittleEndianStringEncoding];
        NSLog(@"strSfzh is:%@",strSfzh);
        
        NSString *strStart = [[NSString alloc]initWithBytes:id2info.id2txt.idstart length:16 encoding:NSUTF16LittleEndianStringEncoding];
        NSString *strEnd = [[NSString alloc]initWithBytes:id2info.id2txt.idend length:16 encoding:NSUTF16LittleEndianStringEncoding];
        NSString *strFzjg = [[NSString alloc]initWithBytes:id2info.id2txt.idissue length:30 encoding:NSUTF16LittleEndianStringEncoding];
        //神思-发证机构去除空格
        strFzjg = [strFzjg stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
        NSLog(@"strFzjg is:%@",strFzjg);
        NSString * strYxq = [strStart stringByAppendingString:@"-"];
        strYxq = [strYxq stringByAppendingString:strEnd];
        NSString *strCs = [strCsNian stringByAppendingString:strCsYue];
        strCs = [strCs stringByAppendingString:strCsRi];
        
        NSInteger gRq = 20150729;//data1
        NSInteger gBh = [[[NSString alloc]initWithBytes:id2info.id2txt.deviceid length:10 encoding:NSUTF8StringEncoding] longLongValue];//data2
        dictionary = [NSMutableDictionary dictionaryWithObjectsAndKeys:strXm,@"name",strXb,@"sex",strZz,@"address"
                      ,strSfzh,@"idCardNo",strFzjg,@"authority",strYxq,@"validate",strCs,@"birth",strMz,@"nation",NULL,@"image",@"0",@"getIdCardInfoStatus",nil];
        
        //03160316
        //         char bmpBuff[38862];
        //         char base64BmpBuff[60000];
        //         NSInteger nRet = [self.sensorBletool id2GetBmpBuff:(char*)&id2info.zpwlt :&bmpBuff[0]];
        //         int baseLen = sdses_base64_encode( bmpBuff, base64BmpBuff, 38862 );
        //         NSLog(@"id2GetBmpBuff  baseLen= %zi",baseLen);
        //         NSData * base64BmpData = [[NSData alloc]initWithBytes:base64BmpBuff length:baseLen];
        //         [dictionary setObject:(id)base64BmpData forKey:@"image"];
        
        //处理图片
        NSData * id2wltData = [[NSData alloc]initWithBytes:&id2info.zpwlt length:1024];
        NSString * base64BmpStr = [self parseImageDataForSensor:id2wltData];
        [dictionary setObject:base64BmpStr forKey:@"image"];
    }
    return dictionary;
}

- (void) recvReadCard:(NSDictionary*)idInfo {
    NSLog (@"sensorDeviceReadIDCard id2ShakeHand recvShakeHandCallback newSSReadCard recvReadCard......");
    
    NSMutableDictionary *resp = [@{} mutableCopy]; //返回信息
    NSMutableDictionary *data = [@{} mutableCopy]; //返回data信息，需要把不同品牌读卡器读出的字段统一
    
    [resp setValue:@"0000" forKey:@"respCode"];
    [resp setValue:@"读取身份证成功" forKey:@"respDesc"];
    
    [data setValue:idInfo[@"name"] forKey:@"name"]; //姓名
    [data setValue:([idInfo[@"sex"] isEqualToString:@"男"] ? @"1":@"0") forKey:@"sexCode"]; //性别编码
    [data setValue:idInfo[@"sex"] forKey:@"sexName"]; //性别名称
    [data setValue:idInfo[@"birth"] forKey:@"birth"]; //生日yyyymmdd
    [data setValue:idInfo[@"nation"] forKey:@"nationCode"]; //民族编码
    [data setValue:[self nationNameFromCode:idInfo[@"nation"]] forKey:@"nationName"]; //民族汉字
    [data setValue:idInfo[@"address"] forKey:@"address"]; //住址
    [data setValue:idInfo[@"idCardNo"] forKey:@"idNum"]; //身份证号
    [data setValue:idInfo[@"authority"] forKey:@"signOffice"]; //发证机关
    
    NSString *validate = idInfo[@"validate"];
    NSArray *dates = [validate componentsSeparatedByString:@"-"];
    [data setValue:[dates firstObject] forKey:@"usefulStartDate"]; //有效期开始yyyymmdd
    if (dates.count > 1) {
        [data setValue:dates[1] forKey:@"usefulEndDate"]; //有效期结束yyyymmdd
    }
    else{
        [data setValue:@"20991231" forKey:@"usefulEndDate"]; //有效期结束yyyymmdd
    }
    
    [data setValue:idInfo[@"image"] forKey:@"pic"]; //照片base64字符串
    
    //江苏特供：加密秘钥不为空时对身份证号，姓名，住址 3个字段分别加密，其他省可以不传或者传""，
    [self jiangsuSpecialEncryptionWithResult:idInfo data:&data];
    //    if(![self isBlankString:self.encryptKey]){
    //        NSData *encryptKeyData = [self.encryptKey dataUsingEncoding:NSUTF8StringEncoding];//
    //        Byte *encryptKeyByte = (Byte *)[encryptKeyData bytes];//key要转成Byte
    //
    //        NSString *nameEncript = [self.encrylibInterface Id2DataEncry:encryptKeyByte :idInfo[@"name"]];
    //        NSString *idNumEncript = [self.encrylibInterface Id2DataEncry:encryptKeyByte :idInfo[@"idCardNo"]];
    //        NSString *addressEncript = [self.encrylibInterface Id2DataEncry:encryptKeyByte :idInfo[@"address"]];
    //
    //        [data setValue:nameEncript forKey:@"nameEncript"]; //姓名加密后
    //        [data setValue:idNumEncript forKey:@"idNumEncript"]; //身份证号加密后
    //        [data setValue:addressEncript forKey:@"addressEncript"]; //住址加密后
    //    }
    
    [resp setObject:data forKey:@"data"];
    
    //返回数据
    [self sendIDCardInfo:resp];
}

- (NSString *)parseImageDataForSensor:(NSData *)data {
    NSString *documentDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES) objectAtIndex: 0];
    NSString *fileName = [documentDirectory stringByAppendingPathComponent:@"zp.wlt"];
    NSString *outPutFile = [documentDirectory stringByAppendingPathComponent:@"zp.bmp"];
    NSFileManager *manager = [NSFileManager defaultManager];
    if ([manager fileExistsAtPath:outPutFile]) {
        [manager removeItemAtPath:outPutFile error:nil];
    }
    [data writeToFile:fileName atomically:YES];
    if ([manager fileExistsAtPath:fileName]) {
        char *inputFile = (char *)[fileName UTF8String];
        char *outputFile = (char *)[outPutFile UTF8String];
        Unpack(inputFile, outputFile);
        NSData *tempData = [NSData dataWithContentsOfFile:outPutFile];
        return [tempData base64EncodedStringWithOptions:0]; //返回base64字符串
    }
    return @"";
}

/**
 神思-读sim卡iccid
 */
- (void) sensorReadICCID {
    NSLog (@"sensorReadICCID......");
    
    NSMutableDictionary *resp = [@{} mutableCopy]; //返回信息
    
    NSDictionary *dic = [self.sensorBletool readICCID];//读iccid
    NSLog (@"sensorReadICCID......is :%@", [self objToString:dic]);
    if(dic!=nil){
        NSNumber* STObj = [dic objectForKey:@"ST"];
        int ST = [STObj intValue];
        if (ST==0) {
            [resp setValue:@"0000" forKey:@"respCode"];
            [resp setValue:@"读取iccid成功" forKey:@"respDesc"];
            
            NSMutableDictionary *data = [@{} mutableCopy]; //返回data信息，需要把不同品牌读卡器读出的字段统一
            NSString *iccidStr = [dic objectForKey:@"ICCID"];
            [data setValue:iccidStr forKey:@"iccid"]; //iccid字符串
            [resp setObject:data forKey:@"data"];
        }
        else if(ST==-9){
            [resp setValue:@"0003" forKey:@"respCode"];
            [resp setValue:@"该神思设备不支持此功能" forKey:@"respDesc"];
        }
        else{
            [resp setValue:@"0003" forKey:@"respCode"];
            [resp setValue:@"读取iccid失败" forKey:@"respDesc"];
        }
    }
    else{
        [resp setValue:@"0003" forKey:@"respCode"];
        [resp setValue:@"读取iccid失败" forKey:@"respDesc"];
    }
    
    
    //返回数据
    [self sendRespInfo:resp withCallBackID:self.normalCallbackId];
    
}

/**
 神思-写sim卡，包括写imsi 和 写短信中心smsc
 
 @param param <#param description#>
 */
- (void)sensorWriteCard:(nonnull NSDictionary *)param {
    NSLog (@"sensorWriteCard......");
    
    NSMutableDictionary *resp = [@{} mutableCopy]; //返回信息
    
    //写imsi
    NSData *imsi1 = [param[@"imsi"] dataUsingEncoding:NSUTF8StringEncoding];//写imsi要转成data
    //NSData *imsi2=[[NSString stringWithFormat:@""] dataUsingEncoding:NSUTF8StringEncoding];//因为是必传，所以用空字符串
    NSData *imsi2 = [param[@"imsi"] dataUsingEncoding:NSUTF8StringEncoding];//写imsi要转成data
    Boolean aRet =[self.sensorBletool writeBlankSim:(Byte *)[imsi1 bytes]:imsi1.length :(Byte *)[imsi2 bytes] :imsi2.length];
    
    
    //写imsi成功了才写短信中心
    if(aRet){
        //写短信中心smsc
        NSString *smsc = param[@"smsc"];//短信中心，写短信中心用,11位短信中心号不要+86
        if([smsc hasPrefix:@"+86"]==YES){
            smsc = [smsc substringFromIndex:3];
        }
        NSData* smscData = [smsc dataUsingEncoding:NSUTF8StringEncoding];
        Boolean bRet = [self.sensorBletool writeSmsCenter:(Byte *)[smscData bytes] :[smscData length]];
        
        if(bRet){
            [resp setValue:@"0000" forKey:@"respCode"];
            [resp setValue:@"写入imsi成功,写入smsc短信中心成功" forKey:@"respDesc"];
        }
        else{
            [resp setValue:@"0010" forKey:@"respCode"];
            [resp setValue:@"写入imsi成功，写入smsc失败" forKey:@"respDesc"];
        }
    }
    else{
        [resp setValue:@"0011" forKey:@"respCode"];
        [resp setValue:@"写入imsi失败, smsc没写" forKey:@"respDesc"];
    }
    
    //返回数据
    [self sendRespInfo:resp withCallBackID:self.normalCallbackId];
    
}

#pragma mark - 恒鸿达

/**
 恒鸿达-初始化恒鸿达设备
 */
- (void)initHhdDevice:(NSDictionary *) param {
    
    self.SYDScaleManager = [SYDIDCardReader instance];
    self.SYDScaleManager.delegate = (id)self;
    
    //设置服务器url
    //    NSString *server_ip = [self getIPWithHostName:@"hodiddec.com"]; //根据hodiddec.com解析成ip
    //    NSString *server_port = @"18000";
    //    NSString *server_url = @"http://hodpicdec.com:18080/Inter-Real/photoDecode";
    
    NSString *server_ip = [self getIPWithHostName:param[@"ip"]]; //根据hodiddec.com解析成ip
    NSString *server_port = param[@"port"];
    NSString *server_url = param[@"imageDecUrl"];
    
    [self.SYDScaleManager  setServerIp:server_ip andPort:[server_port intValue] serimageDecodeIp:server_url];
    
    NSLog(@"initHhdDevice success");
}

/**
 恒鸿达-搜索蓝牙设备
 通过回调函数 SYDdidUpdatePeripheralList 返回结果集
 */
- (void)scanHhdDevice {
    NSLog(@"scanHhdDevice......");
    
    [self.SYDScaleManager refreshDeviceListWithTime:4]; //搜索4秒
}

/**
 恒鸿达-搜索蓝牙设备-回调函数
 
 @param peripherals peripherals description
 */
- (void)SYDdidUpdatePeripheralList:(NSArray *)peripherals {
    NSLog(@"SYDdidUpdatePeripheralList......%zi", [peripherals count]);
    
    for(int i = 0; i < [peripherals count]; i++)
    {
        SYDMyPeripheral *peripheral = [peripherals objectAtIndex:i];
        NSLog(@"SYDdidUpdatePeripheralList......%@",  [peripheral advName]);
        //NSLog(@"SYDdidUpdatePeripheralList......%@",  [peripheral mac]);
        
        if (![[peripheral advName] hasPrefix:@"HOD"]) {
            NSLog(@"SYDdidUpdatePeripheralList......不是恒鸿达设备");
            continue;
        }
        
        //如果设备列表里没有，则添加进去，否则不处理
        if([self.devices objectForKey: [peripheral advName] ]){
            continue;
        }
        else{
            NSMutableDictionary *deviceInfo = [@{} mutableCopy]; //重新封装每一个设备
            [deviceInfo setObject:peripheral forKey:@"model"];
            [deviceInfo setValue:@(deviceType_hhd) forKey:@"deviceType"]; //4
            
            //添加到所有的列表里,key是name，value是设备的实例对象
            [self.devices setObject:deviceInfo forKey: [peripheral advName]];
        }
        
    }
    
    //返回信息
    NSMutableDictionary *resp = [@{} mutableCopy];
    [resp setValue:@"0000" forKey:@"respCode"];
    [resp setValue:@"恒鸿达蓝牙读卡器设备搜索成功" forKey:@"respDesc"];
    NSArray *data = [self.devices allKeys]; //返回给前端的是给list，而且只返回name的list，其他信息不需要
    if ([data isKindOfClass:[NSArray class]] && data.count > 0)
    {
        [resp setObject:data forKey:@"data"];
    }
    else{
        [resp setObject:[@[] mutableCopy] forKey:@"data"];
    }
    //返回数据
    [self sendDevicesInfo:resp];
    
}

/**
 恒鸿达-连接设备
 连接回调函数是
 @param peripheral <#peripheral description#>
 */
- (void)connectHhdDevice:(SYDMyPeripheral *) peripheral  {
    NSLog (@"connectHhdDevice......");
    
    [self.SYDScaleManager setLisentPeripheral:peripheral];
    
}

/**
 恒鸿达-连接设备-回调函数
 
 @param error <#error description#>
 */
-(void)SYDblueToothConnectCallBackWithError:(NSError *)error{
    
    NSMutableDictionary *resp = [@{} mutableCopy]; //返回信息
    //error=nil表示连接成功，否则表示失败
    if (error==nil) {
        [resp setValue:@"0000" forKey:@"respCode"];
        [resp setValue:@"恒鸿达蓝牙设备连接成功" forKey:@"respDesc"];
    } else {
        NSLog (@"SYDblueToothConnectCallBackWithError error is :%@", error.domain);
        [resp setValue:@"0002" forKey:@"respCode"];
        [resp setValue:@"恒鸿达蓝牙设备连接失败" forKey:@"respDesc"];
    }
    
    //返回数据
    [self sendRespInfo:resp withCallBackID:self.normalCallbackId];
    
}

/**
 恒鸿达-读身份证信息
 
 */
- (void) hhdDeviceReadIDCard {
    NSLog(@"hhdDeviceReadIDCard......");
    //恒鸿达 身份证读取文字和图片2次返回所以临时变量保存下，一起返回给前端。每次读取身份证前清空并初始化
    self.SYDcertInfo = [@{} mutableCopy];
    
    [self.SYDScaleManager startScaleCard:15];
}

/**
 恒鸿达-读身份证信息-成功回调
 文字信息和图片信息会分2次返回给回调函数，这边做处理照片和文字信息都全的时候才返回给前端
 
 @param peripheral <#peripheral description#>
 @param data <#data description#>
 */
- (void)SYDsuccessBack:(SYDMyPeripheral *)peripheral withData:(id)data
{
    //NSDictionary时表示返回的是文字信息
    if(data && [data isKindOfClass:[NSDictionary class]])
    {
        NSLog(@"hhdDeviceReadIDCard......SYDsuccessBack......文字信息");
        [self.SYDcertInfo setObject:data forKey:@"textInfo"]; //暂存起来
    }
    //NSData表示返回的是图片信息
    else if (data &&[data isKindOfClass:[NSData class]])
    {
        NSLog(@"hhdDeviceReadIDCard......SYDsuccessBack......图片信息");
        [self.SYDcertInfo setObject:data forKey:@"picInfo"]; //暂存起来
    }
    
    //如果文字和图片信息都全了才返回给前端
    if([self.SYDcertInfo objectForKey: @"textInfo"] && [self.SYDcertInfo objectForKey: @"picInfo"]){
        NSDictionary *textInfo = [self.SYDcertInfo objectForKey: @"textInfo"];
        NSData *picInfo = [self.SYDcertInfo objectForKey: @"picInfo"];
        
        NSMutableDictionary *resp = [@{} mutableCopy]; //返回信息
        NSMutableDictionary *data = [@{} mutableCopy]; //返回data信息，需要把不同品牌读卡器读出的字段统一
        
        [resp setValue:@"0000" forKey:@"respCode"];
        [resp setValue:@"读取身份证成功" forKey:@"respDesc"];
        
        [data setValue:textInfo[@"Name"] forKey:@"name"]; //姓名
        [data setValue:([textInfo[@"Sex"] isEqualToString:@"男"] ? @"1":@"0") forKey:@"sexCode"]; //性别编码
        [data setValue:textInfo[@"Sex"] forKey:@"sexName"]; //性别名称
        [data setValue:textInfo[@"Born"] forKey:@"birth"]; //生日yyyymmdd
        [data setValue:@"" forKey:@"nationCode"]; //民族编码
        [data setValue:textInfo[@"Nation"] forKey:@"nationName"]; //民族汉字
        [data setValue:textInfo[@"Address"] forKey:@"address"]; //住址
        [data setValue:textInfo[@"CardNo"] forKey:@"idNum"]; //身份证号
        [data setValue:textInfo[@"IssuedAt"] forKey:@"signOffice"]; //发证机关
        
        [data setValue:textInfo[@"EffectedDate"] forKey:@"usefulStartDate"]; //有效期开始yyyymmdd
        NSString *ExpiredDate = textInfo[@"ExpiredDate"];
        if ([ExpiredDate isEqualToString:@""]) {
            [data setValue:@"20991231" forKey:@"usefulEndDate"]; //有效期结束yyyymmdd
        }
        else{
            [data setValue:ExpiredDate forKey:@"usefulEndDate"]; //有效期结束yyyymmdd
        }
        
        NSString *base64Encoded = [picInfo base64EncodedStringWithOptions:0];
        base64Encoded = [self replaceBlank:base64Encoded]; //替换掉\r\n
        [data setValue:base64Encoded forKey:@"pic"]; //返回照片base64字符串
        
        //江苏特供：加密秘钥不为空时对身份证号，姓名，住址 3个字段分别加密，其他省可以不传或者传""，
        [self jiangsuSpecialEncryptionWithResult:textInfo data:&data];
        //        if(![self isBlankString:self.encryptKey]){
        //            NSData *encryptKeyData = [self.encryptKey dataUsingEncoding:NSUTF8StringEncoding];
        //            Byte *encryptKeyByte = (Byte *)[encryptKeyData bytes];//key要转成Byte
        //
        //            NSString *nameEncript = [self.encrylibInterface Id2DataEncry:encryptKeyByte :textInfo[@"Name"]];
        //            NSString *idNumEncript = [self.encrylibInterface Id2DataEncry:encryptKeyByte :textInfo[@"CardNo"]];
        //            NSString *addressEncript = [self.encrylibInterface Id2DataEncry:encryptKeyByte :textInfo[@"Address"]];
        //
        //            [data setValue:nameEncript forKey:@"nameEncript"]; //姓名加密后
        //            [data setValue:idNumEncript forKey:@"idNumEncript"]; //身份证号加密后
        //            [data setValue:addressEncript forKey:@"addressEncript"]; //住址加密后
        //        }
        
        [resp setObject:data forKey:@"data"];
        
        //返回数据
        [self sendIDCardInfo:resp];
    }
}

/**
 恒鸿达-读身份证信息-失败回调
 可能会返回多次
 
 @param peripheral <#peripheral description#>
 @param error <#error description#>
 */
- (void)SYDfailedBack:(SYDMyPeripheral *)peripheral withError:(NSError *)error
{
    NSLog(@"hhdDeviceReadIDCard......SYDfailedBack......%zi", error.code);
    
    NSMutableDictionary *resp = [@{} mutableCopy]; //返回信息
    [resp setValue:@"0008" forKey:@"respCode"];
    [resp setValue:@"恒鸿达设备读身份证失败" forKey:@"respDesc"];
    //返回数据
    [self sendIDCardInfo:resp];
    
    //如果只需要读取身份证，请忽略错误码为-420的错误
    //    if(error.code!=-420){
    //    }
    
    /*-------------错误码对应-----------------
     读头连接失败        -1
     寻卡失败           -4
     连接服务器失败      -11
     读取超时           -7
     获取dn信息失败      -211
     身份证头像解析失败   -420
     ---------------------------------------*/
    
}

/**
 恒鸿达-读sim卡iccid
 */
- (void) hhdReadICCID {
    NSLog (@"hhdReadICCID......");
    
    [self.SYDScaleManager readSimICCID];//读iccid
}

/**
 恒鸿达-读sim卡iccid-回调函数
 
 @param peripheral <#peripheral description#>
 @param data <#data description#>
 */
- (void)SYDReadICCIDsuccessBack:(SYDIDReadCardInfo*)peripheral withData:(id)data {
    NSLog (@"hhdReadICCID......SYDReadICCIDsuccessBack");
    
    NSMutableDictionary *resp = [@{} mutableCopy]; //返回信息
    
    //peripheral.ICCID ,
    if(data && [data isKindOfClass:[NSError class]]){
        [resp setValue:@"0003" forKey:@"respCode"];
        [resp setValue:@"读取iccid失败" forKey:@"respDesc"];
    }
    else
    {
        if(peripheral.ICCID == nil||[data isEqualToString:@"-1"])
        {
            [resp setValue:@"0003" forKey:@"respCode"];
            [resp setValue:@"读取iccid失败" forKey:@"respDesc"];
        }
        else
        {
            [resp setValue:@"0000" forKey:@"respCode"];
            [resp setValue:@"读取iccid成功" forKey:@"respDesc"];
            
            NSMutableDictionary *data = [@{} mutableCopy]; //返回data信息，需要把不同品牌读卡器读出的字段统一
            NSString *iccidStr = peripheral.ICCID;
            [data setValue:iccidStr forKey:@"iccid"]; //iccid字符串
            [resp setObject:data forKey:@"data"];
            
            //data:@"1" 成卡 @"0" 白卡 ，其他失败
            //            if([data isEqualToString:@"1"])
            //            {
            //                NSString *str=[NSString stringWithFormat:@"ICCID:%@\n成卡\nIMSI:%@",_tmpStr,peripheral.IMSI];
            //            }
            //            else if ([data isEqualToString:@"0"])
            //            {
            //                NSString *str=[NSString stringWithFormat:@"ICCID:%@\n白卡",_tmpStr];
            //            }
        }
    }
    
    //返回数据
    [self sendRespInfo:resp withCallBackID:self.normalCallbackId];
}

/**
 恒鸿达-写sim卡，包括写imsi 和 写短信中心smsc
 
 @param param <#param description#>
 */
- (void)hhdWriteCard:(nonnull NSDictionary *)param {
    NSLog (@"hhdWriteCard......");
    
    //恒鸿达达短信中心 需要+86,如果没传，则加上。[smsc hasPrefix:@"+86"]==YES
    NSString *smsc = param[@"smsc"];
    if([smsc hasPrefix:@"+86"]==NO){
        smsc = [NSString stringWithFormat:@"%@%@", @"+86", smsc];
    }
    NSLog (@"hhdWriteCard......smsc:%@", smsc);
    [self.SYDScaleManager writeSimCard:param[@"imsi"] withNo:smsc];
    
}

/**
 恒鸿达-写sim卡，包括写imsi 和 写短信中心smsc - 回调函数
 
 @param peripheral <#peripheral description#>
 @param data <#data description#>
 */
- (void)SYDwriteCardResultBack:(SYDIDReadCardInfo*)peripheral withData:(id)data {
    NSLog (@"hhdWriteCard......SYDwriteCardResultBack");
    
    NSMutableDictionary *resp = [@{} mutableCopy]; //返回信息
    
    //先判断data返回错误原因，nil为写卡正常，
    //再取peripheral写卡业务返回的结果messageResult表示短信中心是否成功，writeCardResult表示imsi是否成功
    if(data && [data isKindOfClass:[NSError class]]){
        [resp setValue:@"0011" forKey:@"respCode"];
        [resp setValue:@"写入imsi和smsc失败" forKey:@"respDesc"];
    }
    else {
        if (peripheral.messageResult) {
            if (peripheral.writeCardResult)
            {
                [resp setValue:@"0000" forKey:@"respCode"];
                [resp setValue:@"写入imsi成功,写smsc短信中心成功" forKey:@"respDesc"];
            }
            else{
                [resp setValue:@"0011" forKey:@"respCode"];
                [resp setValue:@"写入imsi失败,写smsc短信中心成功" forKey:@"respDesc"];
            }
        }
        else {
            if (peripheral.writeCardResult)
            {
                [resp setValue:@"0010" forKey:@"respCode"];
                [resp setValue:@"写入imsi成功，写入smsc短信中心失败" forKey:@"respDesc"];
            }
            else{
                [resp setValue:@"0010" forKey:@"respCode"];
                [resp setValue:@"写入imsi失败，写入smsc短信中心失败" forKey:@"respDesc"];
            }
            
        }
    }
    
    //返回数据
    [self sendRespInfo:resp withCallBackID:self.normalCallbackId];
}

#pragma mark - 卡尔kt8003

/**
 卡尔kt8003-初始化卡尔读卡器
 */
- (void)initKaerDeviceKT8003:(NSDictionary *) param {
    self.kaerManagerKt8003 = [KaerAdapter getInstance:self];
    
    NSString *acct = param[@"acct"];
    NSString *pwd = param[@"password"];
    NSString *ip = param[@"ip"];
    NSString *port = param[@"port"];
    
    //kt8003分体式需要连接服务器解码
    BOOL connstatus=[self.kaerManagerKt8003 connectStatusSSL];//是检查sdk有没有连接解码服务器的
    BOOL isnetworktype=[self.kaerManagerKt8003 connectedIsNetworkType];//是检查连接的蓝牙是不是分体阅读器的,就是判断了一下kt8003 和kt8000
    NSLog (@"kaerManager kt8003 connstatus=:%@", connstatus?@"YES":@"NO");
    NSLog (@"kaerManager kt8003 isnetworktype=:%@", isnetworktype?@"YES":@"NO");
    //demo里 !connstatus && isnetworktype 测试发现isnetworktype 是no
    if(!connstatus){
        //ip, port, 账号，密码，是否wss连接，默认true，这边写的是测试服务器，取自demo
        //        NSString *wssUrl = @"wss://115.28.2.173:7443"; //websocket.io 地址
        //        NSString *acct = @"admin";
        //        NSString *password = @"www.kaer.cn";
        
        //websocket.io 地址
        NSString *wssUrl = [NSString stringWithFormat:@"%@%@:%@",@"wss://", ip, port];
        NSLog (@"kaerManager kt8003 init wssUrl :%@", wssUrl);
        
        int connResult= [self.kaerManagerKt8003 connectServer:wssUrl withUser:acct andPwd:pwd];
        if(connResult==KT8003_Success){
            NSLog (@"kaerManager kt8003 init success, connect to server success");
        }else {
            NSLog (@"kaerManager kt8003 init error, connect to server error");
        }
    }
    else{
        NSLog (@"kaerManager kt8003 init success, donot connect to server");
    }
    
}

/**
 卡尔kt8003-搜索蓝牙读卡器
 */
- (void)scanKaerDeviceListKT8003 {
    NSLog(@"scanKaerDeviceList KT8003......");
    
    NSArray *deviceList = [self.kaerManagerKt8003 ScanDeviceList:2];
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name BEGINSWITH[c] %@", @"KT8003"];
    deviceList = [deviceList filteredArrayUsingPredicate:predicate];
    NSLog (@"scanKaerDeviceListKT8003 is :%@", [self objToString:deviceList]);
    
    //NSLog (@"self.devices is :%@", [self objToString:[self.devices allKeys]]);
    for (NSDictionary *item in deviceList) {
        //NSLog (@"item name is :%@", item[@"name"]);
        //如果设备列表里没有，则添加进去，否则不处理
        if([self.devices objectForKey: item[@"name"] ]){
            NSLog (@"item exists :%@", item[@"name"]);
            continue;
        }
        else{
            NSLog (@"item not exists :%@", item[@"name"]);
            
            NSMutableDictionary *deviceInfo = [@{} mutableCopy]; //重新封装每一个设备
            [deviceInfo setValue:item[@"name"] forKey:@"name"];
            [deviceInfo setValue:@"" forKey:@"mac"];
            [deviceInfo setValue:item[@"uuid"] forKey:@"uuid"];
            [deviceInfo setValue:@(deviceType_kaer_kt8003) forKey:@"deviceType"]; //5
            
            [self.devices setObject:deviceInfo forKey:item[@"name"]]; //添加到所有的列表里,key是name，value是个字典
        }
    }
    //NSLog (@"self.devices is :%@", [self objToString:[self.devices allKeys]]);
    
    //返回信息
    NSMutableDictionary *resp = [@{} mutableCopy];
    [resp setValue:@"0000" forKey:@"respCode"];
    [resp setValue:@"卡尔蓝牙读卡器设备搜索成功" forKey:@"respDesc"];
    NSArray *data = [self.devices allKeys]; //返回给前端的是给list，而且只返回name的list，其他信息不需要
    if ([data isKindOfClass:[NSArray class]] && data.count > 0)
    {
        [resp setObject:data forKey:@"data"];
    }
    else{
        [resp setObject:[@[] mutableCopy] forKey:@"data"];
    }
    //返回数据
    [self sendDevicesInfo:resp];
}

/**
 卡尔kt8003-根据uuid连接蓝牙设备
 BR_connectResult 回调函数里会返回，这边就注释调返回，避免返回2次
 另外卡尔和神思共用这个BR_connectResult 回调函数
 
 @param uuid uuid description
 */
- (void)conectKaerDeviceKT8003:(NSString *) uuid {
    NSLog (@"conectKaerDeviceKT8003......");
    NSLog (@"conectKaerDeviceKT8003 uuid is :%@", uuid);
    
    //NSMutableDictionary *resp = [@{} mutableCopy]; //返回信息
    
    BOOL result = [self.kaerManagerKt8003 connectBt:uuid];
    
    NSMutableDictionary *resp = [@{} mutableCopy]; //返回信息
    if (result) {
        [resp setValue:@"0000" forKey:@"respCode"];
        [resp setValue:@"卡尔KT8003设备连接状态正常" forKey:@"respDesc"];
    } else {
        [resp setValue:@"0002" forKey:@"respCode"];
        [resp setValue:@"卡尔KT8003设备连接已断开" forKey:@"respDesc"];
    }
    
    //返回数据
    [self sendRespInfo:resp withCallBackID:self.normalCallbackId];
}

/**
 卡尔kt8003-读身份证信息
 发现卡尔隔20分钟左右会断连，所以每次操作前先连接再操作
 */
- (void)kaerDeviceReadIDCardKT8003:(NSString *) uuid  {
    NSLog (@"kaerDeviceReadIDCardKT8003......");
    
    NSMutableDictionary *resp = [@{} mutableCopy]; //返回信息
    
    //先判断连接状态，断了先重连下.如果连接成功则继续操作，连接失败直接返回app
    BOOL status = [self.kaerManagerKt8003 connectStatus];
    if(!status){
        //1.重新初始化
        [self initKaerDeviceKT8003: self.config[@"kt8003"]];
        //2.重新连接
        BOOL result = [self.kaerManagerKt8003 connectBt:uuid];
        if (result) {
            NSLog (@"kaerDeviceReadIDCardKT8003...conectKaerDeviceKT8003 success");
        }
        else{
            NSLog (@"kaerDeviceReadIDCardKT8003...conectKaerDeviceKT8003 faild");
            [resp setValue:@"0001" forKey:@"respCode"];
            [resp setValue:@"卡尔kt8003蓝牙读卡器连接失败" forKey:@"respDesc"];
            //返回数据
            [self sendIDCardInfo:resp];
            return;
        }
    }
    
    IDCardItem *idInfo = [self.kaerManagerKt8003 readCert]; //身份证读取出的信息
    NSString *idInfoStr = [idInfo toString]; //转化成str打印
    NSLog (@"kaerDeviceReadIDCardKT8003......:%@", idInfoStr);
    
    if(idInfo.resultCode == KT8003_Success){
        NSMutableDictionary *data = [@{} mutableCopy]; //返回data信息，需要把不同品牌读卡器读出的字段统一
        
        [resp setValue:@"0000" forKey:@"respCode"];
        [resp setValue:@"读取身份证成功" forKey:@"respDesc"];
        
        [data setValue:idInfo.partyName forKey:@"name"]; //姓名
        [data setValue:idInfo.gender forKey:@"sexName"]; //性别名称
        [data setValue:([idInfo.gender isEqualToString:@"男"] ? @"1":@"0") forKey:@"sexCode"]; //性别编码
        [data setValue:idInfo.bornDay forKey:@"birth"]; //生日yyyymmdd
        [data setValue:@"" forKey:@"nationCode"]; //民族编码,卡尔没有
        [data setValue:idInfo.nation forKey:@"nationName"]; //民族汉字
        //[data setValue:[self nationNameFromCode:idInfo[@"nation_code"]] forKey:@"nationName"]; //民族汉字
        [data setValue:idInfo.certAddress forKey:@"address"]; //住址
        [data setValue:idInfo.certNumber forKey:@"idNum"]; //身份证号
        [data setValue:idInfo.certOrg forKey:@"signOffice"]; //发证机关
        [data setValue:idInfo.effDate forKey:@"usefulStartDate"]; //有效期开始yyyymmdd
        [data setValue:idInfo.expDate forKey:@"usefulEndDate"]; //有效期结束yyyymmdd
        
        NSData *picData1 = idInfo.picImgData;
        if(picData1!=nil){
            NSString *picdecUrl = @"https://121.42.36.16:6443/unpackwlt"; //取自demo
            NSDictionary *imgdecodeDict=[self.kaerManagerKt8003 getDecodedPicDataOnServerUrl:picdecUrl];
            
            NSString *errorCode = imgdecodeDict[@"errCode"];
            if ([errorCode isEqualToString:@"0"]) {
                NSData *picData2 = imgdecodeDict[@"DecPicData"];
                NSString *base64Encoded = [picData2 base64EncodedStringWithOptions:0];
                base64Encoded = [self replaceBlank:base64Encoded]; //替换掉\r\n
                [data setValue:base64Encoded forKey:@"pic"]; //返回照片base64字符串
            }
        }
        else{
            [data setValue:@"" forKey:@"pic"]; //没读到返回空字符串
        }
        
        //江苏特供：加密秘钥不为空时对身份证号，姓名，住址 3个字段分别加密，其他省可以不传或者传""，
        [self jiangsuSpecialEncryptionWithResult:@{@"Name":idInfo.partyName,@"CardNo":idInfo.certNumber,@"Address":idInfo.certAddress} data:&data];
        //        if(![self isBlankString:self.encryptKey]){
        //            NSData *encryptKeyData = [self.encryptKey dataUsingEncoding:NSUTF8StringEncoding];//
        //            Byte *encryptKeyByte = (Byte *)[encryptKeyData bytes];//key要转成Byte
        //
        //            NSString *nameEncript = [self.encrylibInterface Id2DataEncry:encryptKeyByte :idInfo.partyName];
        //            NSString *idNumEncript = [self.encrylibInterface Id2DataEncry:encryptKeyByte :idInfo.certNumber];
        //            NSString *addressEncript = [self.encrylibInterface Id2DataEncry:encryptKeyByte :idInfo.certAddress];
        //
        //            [data setValue:nameEncript forKey:@"nameEncript"]; //姓名加密后
        //            [data setValue:idNumEncript forKey:@"idNumEncript"]; //身份证号加密后
        //            [data setValue:addressEncript forKey:@"addressEncript"]; //住址加密后
        //        }
        
        [resp setObject:data forKey:@"data"];
        
    }
    else{
        [resp setValue:@"0003" forKey:@"respCode"];
        [resp setValue:@"卡尔蓝牙kt8003读取身份证失败" forKey:@"respDesc"];
    }
    
    //返回数据
    [self sendIDCardInfo:resp];
}

/**
 卡尔kt8003-读sim卡iccid
 发现卡尔隔20分钟左右会断连，所以每次操作前先连接再操作
 */
- (void)kaerReadICCIDKT8003:(NSString *) uuid {
    NSLog (@"kaerReadICCIDKT8003......");
    
    NSMutableDictionary *resp = [@{} mutableCopy]; //返回信息
    
    //先判断连接状态，断了先重连下.如果连接成功则继续操作，连接失败直接返回app
    BOOL status = [self.kaerManagerKt8003 connectStatus];
    if(!status){
        //1.重新初始化
        [self initKaerDeviceKT8003: self.config[@"kt8003"]];
        //2.重新连接
        BOOL result = [self.kaerManagerKt8003 connectBt:uuid];
        if (result) {
            NSLog (@"kaerDeviceReadIDCardKT8003...conectKaerDeviceKT8003 success");
        }
        else{
            NSLog (@"kaerDeviceReadIDCardKT8003...conectKaerDeviceKT8003 faild");
            [resp setValue:@"0001" forKey:@"respCode"];
            [resp setValue:@"卡尔kt8003蓝牙读卡器连接失败" forKey:@"respDesc"];
            //返回数据
            [self sendIDCardInfo:resp];
            return;
        }
    }
    
    NSDictionary *ICCID = [self.kaerManagerKt8003 readICCID];
    //1 成功，0 失败
    if ([ICCID[@"errCode"] isEqualToString:@"0"]) {
        [resp setValue:@"0000" forKey:@"respCode"];
        [resp setValue:@"读取iccid成功" forKey:@"respDesc"];
        
        NSMutableDictionary *data = [@{} mutableCopy]; //返回data信息，需要把不同品牌读卡器读出的字段统一
        NSData *iccidData = ICCID[@"ICCIDData"];
        NSString *iccidStr = [[NSString alloc] initWithData:iccidData encoding:NSUTF8StringEncoding];
        [data setValue:iccidStr forKey:@"iccid"]; //iccid字符串
        [resp setObject:data forKey:@"data"];
        
    } else {
        [resp setValue:@"0003" forKey:@"respCode"];
        [resp setValue:@"读取iccid失败" forKey:@"respDesc"];
    }
    
    //返回数据
    [self sendRespInfo:resp withCallBackID:self.normalCallbackId];
    
}

/**
 卡尔kt8003-写sim卡，包括写imsi 和 写11位短信中心smsc
 发现卡尔隔20分钟左右会断连，所以每次操作前先连接再操作
 @param param <#param description#>
 */
- (void)kaerWriteCardKT8003:(nonnull NSDictionary *)param withUUid:(NSString *) uuid{
    NSLog (@"kaerWriteCardKT8003......");
    
    NSMutableDictionary *resp = [@{} mutableCopy]; //返回信息
    
    //先判断连接状态，断了先重连下.如果连接成功则继续操作，连接失败直接返回app
    BOOL status = [self.kaerManagerKt8003 connectStatus];
    if(!status){
        //1.重新初始化
        [self initKaerDeviceKT8003: self.config[@"kt8003"]];
        //2.重新连接
        BOOL result = [self.kaerManagerKt8003 connectBt:uuid];
        if (result) {
            NSLog (@"kaerDeviceReadIDCardKT8003...conectKaerDeviceKT8003 success");
        }
        else{
            NSLog (@"kaerDeviceReadIDCardKT8003...conectKaerDeviceKT8003 faild");
            [resp setValue:@"0001" forKey:@"respCode"];
            [resp setValue:@"卡尔kt8003蓝牙读卡器连接失败" forKey:@"respDesc"];
            //返回数据
            [self sendIDCardInfo:resp];
            return;
        }
    }
    
    NSString *imsi = param[@"imsi"];//写imsi，kt8003和kt8000不一样，要字符串不要data
    NSString *smsc = param[@"smsc"];//短信中心，写短信中心用,11位短信中心号不要+86
    if([smsc hasPrefix:@"+86"]==YES){
        smsc = [smsc substringFromIndex:3];
    }
    int imsiResult = [self.kaerManagerKt8003 writeIMSI:imsi andIMSI2:imsi];//imsi1和imsi2一样
    if (KT8003_Success == imsiResult) {
        //imsi写成功后才 写短信中心
        int smscResult = [self.kaerManagerKt8003 writeSMSC:smsc withNumberIndex:(Byte)0x01];
        if (KT8003_Success == smscResult) {
            [resp setValue:@"0000" forKey:@"respCode"];
            [resp setValue:@"写入imsi成功,写入smsc短信中心成功" forKey:@"respDesc"];
        } else {
            [resp setValue:@"0010" forKey:@"respCode"];
            [resp setValue:@"写入smsc失败" forKey:@"respDesc"];
        }
    } else {
        [resp setValue:@"0010" forKey:@"respCode"];
        [resp setValue:@"写入imsi失败" forKey:@"respDesc"];
    }
    
    //返回数据
    [self sendRespInfo:resp withCallBackID:self.normalCallbackId];
    
}

#pragma mark - 信通
/**
 初始化信通连接
 
 @param param 参数
 */
- (void)initXintongDevice:(NSDictionary *)param {
    self.xtScaleManager = [STIDCardReader instance];
    self.xtScaleManager.delegate = (id)self;
    [self.xtScaleManager setServerIp:param[@"ip"] andPort:[param[@"port"] intValue]];
}

/**
 信通读取身份证信息
 */
- (void)xintongDeviceReadIDCard {
    self.STIDcertInfo = [NSMutableDictionary dictionary];
    [self.xtScaleManager startScaleCard];
}

/**
 信通读取sim卡信息
 */
- (void)xintongDeviceReadICCID {
    //信通读取sim卡的回调方法名与森锐的相同，在ReadICCIDsuccessBack:withData:方法中回调
    [self.xtScaleManager readSimICCID];
}

/**
 信通写入sim卡信息
 
 @param param 需要写入卡中的数据
 */
- (void)xintongDeviceWriteICCID:(NSDictionary *)param {
    //信通写入sim卡的回调方法名与森锐的相同，在writeCardResultBack:withData:方法中回调
    NSString* smsc = param[@"smsc"];
    //信通写卡，前面不需要加上+86，这里需要自动检测，如果有的话，自动删除
    if([smsc hasPrefix:@"+86"]) {
        smsc = [smsc substringFromIndex:3];
    }
    [self.xtScaleManager writeSimCard:param[@"imsi"] SMSNO:smsc];
}

#pragma mark - 信通读卡信息回调
/**
 读取失败回调
 
 @param peripheral 当前连接的设备
 @param error 错误信息
 */
- (void)failedBack:(STMyPeripheral *)peripheral withError:(NSError *)error {
    NSLog(@"错误代码:%ld,错误信息:%@!", (long)[error code], [error localizedDescription]);
    NSMutableDictionary *resp = [NSMutableDictionary dictionary];
    [resp setValue:@"0003" forKey:@"respCode"];
    [resp setValue:error.localizedDescription forKey:@"respDesc"];
    [self sendIDCardInfo:resp];
}

/**
 读取身份证成功回调
 
 @param peripheral 当前设备
 @param data 返回的身份证信息，NSDictionary类型的为文字信息，NSData类型的为图片信息
 */
- (void)successBack:(STMyPeripheral *)peripheral withData:(id)data {
    NSLog(@"读取身份证data======%@",data);
    
    //NSDictionary时表示返回的是文字信息
    if(data && [data isKindOfClass:[NSDictionary class]])
    {
        NSLog(@"xintongDeviceReadIDCard......STIDSuccessBack......文字信息");
        [self.STIDcertInfo setObject:data forKey:@"textInfo"]; //暂存起来
    }
    //NSData表示返回的是图片信息
    else if (data &&[data isKindOfClass:[NSData class]])
    {
        NSLog(@"hhdDeviceReadIDCard......SYDsuccessBack......图片信息");
        [self.STIDcertInfo setObject:data forKey:@"picInfo"]; //暂存起来
    }
    
    //如果文字和图片信息都全了才返回给前端
    if([self.STIDcertInfo objectForKey: @"textInfo"] && [self.STIDcertInfo objectForKey: @"picInfo"]){
        NSDictionary *textInfo = [self.STIDcertInfo objectForKey: @"textInfo"];
        NSData *picInfo = [self.STIDcertInfo objectForKey: @"picInfo"];
        
        NSMutableDictionary *resp = [@{} mutableCopy]; //返回信息
        NSMutableDictionary *dataDict = [@{} mutableCopy]; //返回data信息，需要把不同品牌读卡器读出的字段统一
        
        [resp setObject:@"0000" forKey:@"respCode"];
        [resp setObject:@"读取身份证成功" forKey:@"respDesc"];
        
        [dataDict setObject:textInfo[@"Name"] forKey:@"name"]; //姓名
        [dataDict setObject:([textInfo[@"Sex"] isEqualToString:@"男"] ? @"1":@"0") forKey:@"sexCode"]; //性别编码
        [dataDict setObject:textInfo[@"Sex"] forKey:@"sexName"]; //性别名称
        [dataDict setObject:textInfo[@"Born"] forKey:@"birth"]; //生日yyyymmdd
        [dataDict setObject:@"" forKey:@"nationCode"]; //民族编码
        [dataDict setObject:textInfo[@"Nation"] forKey:@"nationName"]; //民族汉字
        [dataDict setObject:textInfo[@"Address"] forKey:@"address"]; //住址
        [dataDict setObject:textInfo[@"CardNo"] forKey:@"idNum"]; //身份证号
        [dataDict setObject:textInfo[@"IssuedAt"] forKey:@"signOffice"]; //发证机关
        
        [dataDict setObject:textInfo[@"EffectedDate"] forKey:@"usefulStartDate"]; //有效期开始yyyymmdd
        NSString *ExpiredDate = textInfo[@"ExpiredDate"];
        if ([ExpiredDate isEqualToString:@""]) {
            [dataDict setObject:@"20991231" forKey:@"usefulEndDate"]; //有效期结束yyyymmdd
        }
        else{
            [dataDict setObject:ExpiredDate forKey:@"usefulEndDate"]; //有效期结束yyyymmdd
        }
        
        NSString *base64Encoded = [picInfo base64EncodedStringWithOptions:0];
        base64Encoded = [self replaceBlank:base64Encoded]; //替换掉\r\n
        [dataDict setObject:base64Encoded forKey:@"pic"]; //返回照片base64字符串
        
        //江苏特供：加密秘钥不为空时对身份证号，姓名，住址 3个字段分别加密，其他省可以不传或者传""，
        [self jiangsuSpecialEncryptionWithResult:textInfo data:&dataDict];
        
        
        [resp setObject:dataDict forKey:@"data"];
        
        //返回数据
        [self sendIDCardInfo:resp];
    }
    
    
    
}


#pragma mark - 公共方法

/*!
 *  从命令里取出参数, app端传 json 对象
 *
 *  @param command 命理
 *
 *  @return 取出结果
 */
- (nullable NSDictionary *)paramsFromCommand:(nonnull CDVInvokedUrlCommand *)command {
    //NSString *params = command.arguments.firstObject;
    //NSLog (@"params is :%@", params);
    //if ([params isKindOfClass:[NSString class]]) {
    //    NSDictionary *info = (NSDictionary *)[NSJSONSerialization JSONObjectWithData:[params dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingMutableContainers error:nil];
    //    return info;
    //}
    //return nil;
    
    NSJSONSerialization* params = command.arguments.firstObject;;
    NSData* paramsData = [NSJSONSerialization dataWithJSONObject:params options:NSJSONWritingPrettyPrinted error:nil];
    NSDictionary *paramsDict = [NSJSONSerialization JSONObjectWithData:paramsData options:kNilOptions error:nil];
    NSLog (@"params is :%@", [self objToString:paramsDict]);
    return paramsDict;
}

/**
 根据设备name是什么开头的，判断属于什么牌子的设备，用于调用不同的sdk
 
 @param name <#name description#>
 @return <#return value description#>
 */
-(int)deviceTypeFromName:(NSString *) name
{
    //KT：卡尔 SS：神思 SR：森锐 HOD:恒鸿达
    if([name hasPrefix:@"KT8000"]==YES){
        return deviceType_kaer_kt8000;
    }else if([name hasPrefix:@"SR"]==YES){
        return deviceType_sunrise;
    }else if([name hasPrefix:@"SS"]==YES){
        return deviceType_sensor;
    }else if([name hasPrefix:@"HOD"]==YES){
        return deviceType_hhd;
    }else if([name hasPrefix:@"KT8003"]==YES){
        return deviceType_kaer_kt8003;
    }else if([name hasPrefix:@"ST"] == YES) {
        return deviceType_xintong;
    }
    else{
        return deviceType_ohter; //都不匹配返回0
    }
}


/**
 返回错误信息
 
 @param errorInfo <#errorInfo description#>
 @param errorCode errorCode description
 @param callBackID callBackID description
 */
//- (void)sendErrorInfo:(NSString *)errorInfo errorCode:(NSString *)errorCode withCallBackId:(NSString *)callBackID {
//    CDVPluginResult *result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:@{@"errorCode" : errorCode, @"errorMsg" : errorInfo}];
//    [self sendPluginResult:result withCallBackID:callBackID];
//}

/**
 返回当前搜索到的全部设备信息
 主要是这个callbackid 特别，统一封装一个函数，避免写错
 
 @param resp <#resp description#>
 */
- (void)sendDevicesInfo:(NSDictionary *)resp {
    NSLog (@"sendDevicesInfo is :%@", [self objToString:resp]);
    
    CDVPluginResult *result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:resp];
    [result setKeepCallbackAsBool:true];
    
    [self sendPluginResult:result withCallBackID:self.scanDevicesCallbackId];//
}

/**
 返回身份证读取信息
 主要是这个callbackid 特别，统一封装一个函数，避免写错
 
 @param resp <#resp description#>
 */
- (void)sendIDCardInfo:(NSDictionary *)resp {
    NSLog (@"sendIDCardInfo is :%@", [self objToString:resp]);
    
    CDVPluginResult *result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:resp];
    [result setKeepCallbackAsBool:true];
    
    [self sendPluginResult:result withCallBackID:self.readIDCardCallbackId];//
}


/**
 普通接口返回信息
 
 @param resp <#resp description#>
 @param callbackId <#callbackId description#>
 */
- (void)sendRespInfo:(NSDictionary *)resp withCallBackID: (NSString *)callbackId {
    NSLog (@"sendRespInfo is :%@", [self objToString:resp]);
    
    CDVPluginResult *result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:resp];
    [result setKeepCallbackAsBool:true];
    
    [self sendPluginResult:result withCallBackID:callbackId];
    //[self.commandDelegate sendPluginResult:result callbackId:self.callbackId];
}

/**
 返回信息,支持异步返回，因为神思，森锐等有些函数是通过异步回调函数返回结果集
 
 @param result <#result description#>
 @param callbackId callbackId description
 */
- (void)sendPluginResult:(CDVPluginResult *)result withCallBackID: (NSString *)callbackId {
    dispatch_async(dispatch_get_main_queue(), ^{
        [self.commandDelegate sendPluginResult:result callbackId:callbackId];
    });
}


/**
 对象转json字符串
 
 @param object <#object description#>
 @return <#return value description#>
 */
-(NSString*)objToString:(id)object
{
    NSString *jsonString = nil;
    NSError *error;
    NSData *jsonData = [NSJSONSerialization dataWithJSONObject:object
                                                       options:NSJSONWritingPrettyPrinted // Pass 0 if you don't care about the readability of the generated string
                                                         error:&error];
    if (! jsonData) {
        NSLog(@"objToString get an error: %@", error);
    } else {
        jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
    }
    return jsonString;
}

-(NSString *)nationNameFromCode:(NSString *) str
{
    NSString * nationalStr = @"";
    NSInteger n =  [str intValue];
    switch (n) {
        case 1:
            return @"汉族";
        case 2:
            return @"蒙古族";
        case 3:
            return @"回族";
        case 4:
            return @"藏族";
        case 5:
            return @"维吾尔族";
        case 6:
            return @"苗族";
        case 7:
            return @"彝族";
        case 8:
            return @"壮族";
        case 9:
            return @"布依族";
        case 10:
            return @"朝鲜族";
        case 11:
            return @"满族";
        case 12:
            return @"侗族";
        case 13:
            return @"瑶族";
        case 14:
            return @"白族";
        case 15:
            return @"土家族";
        case 16:
            return @"哈尼族";
        case 17:
            return @"哈萨克族";
        case 18:
            return @"傣族";
        case 19:
            return @"黎族";
        case 20:
            return @"傈僳族";
        case 21:
            return @"佤族";
        case 22:
            return @"畲族";
        case 23:
            return @"高山族";
        case 24:
            return @"拉祜族";
        case 25:
            return @"水族";
        case 26:
            return @"东乡族";
        case 27:
            return @"纳西族";
        case 28:
            return @"景颇族";
        case 29:
            return @"柯尔克孜族";
        case 30:
            return @"土族";
        case 31:
            return @"达斡尔族";
        case 32:
            return @"仫佬族";
        case 33:
            return @"羌族";
        case 34:
            return @"布朗族";
        case 35:
            return @"撒拉族";
        case 36:
            return @"毛难族";
        case 37:
            return @"仡佬族";
        case 38:
            return @"锡伯族";
        case 39:
            return @"阿昌族";
        case 40:
            return @"普米族";
        case 41:
            return @"塔吉克族";
        case 42:
            return @"怒族";
        case 43:
            return @"乌孜别克族";
        case 44:
            return @"俄罗斯族";
        case 45:
            return @"鄂温克族";
        case 46:
            return @"崩龙族";
        case 47:
            return @"保安族";
        case 48:
            return @"裕固族";
        case 49:
            return @"京族";
        case 50:
            return @"塔塔尔族";
        case 51:
            return @"独龙族";
        case 52:
            return @"鄂伦春族";
        case 53:
            return @"赫哲族";
        case 54:
            return @"门巴族";
        case 55:
            return @"珞巴族";
        case 56:
            return @"基诺族";
        default:
            return @"其他";
    }
    return nationalStr;
}


/**
 根据域名获取ip地址
 
 @param hostName <#hostName description#>
 @return <#return value description#>
 */
-(NSString*)getIPWithHostName:(const NSString*)hostName
{
    const char *hostN= [hostName UTF8String];
    struct hostent* phot;
    
    @try {
        phot = gethostbyname(hostN);
        
    }
    @catch (NSException *exception) {
        return nil;
    }
    
    struct in_addr ip_addr;
    memcpy(&ip_addr, phot->h_addr_list[0], 4);
    char ip[20] = {0};
    inet_ntop(AF_INET, &ip_addr, ip, sizeof(ip));
    
    NSString* strIPAddress = [NSString stringWithUTF8String:ip];
    return strIPAddress;
}

/**
 判断字符串是否为空
 */
- (BOOL)isBlankString:(NSString *)str {
    NSString *string = str;
    if (string == nil || string == NULL) {
        return YES;
    }
    if ([string isKindOfClass:[NSNull class]]) {
        return YES;
    }
    if ([[string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]] length]==0) {
        return YES;
    }
    
    return NO;
}

/**
 将某字符串中的 所有 str1 替换为 str2
 身份证读取出的照片base64字符串里会有\r\n,替换掉
 */
- (NSString*)replaceBlank:(NSString *)oldStr {
    NSString *newStr = [oldStr stringByReplacingOccurrencesOfString:@"\r\n" withString:@""];
    return newStr;
}

/**
 江苏特供：加密秘钥不为空时对身份证号，姓名，住址 3个字段分别加密，其他省可以不传或者传""
 
 @param resultDict 数据源
 @param data 需要拼接参数的可变字典地址
 */
- (void)jiangsuSpecialEncryptionWithResult:(NSDictionary *)resultDict data:(NSMutableDictionary **)data {
    if(![self isBlankString:self.encryptKey]){
        NSData *encryptKeyData = [self.encryptKey dataUsingEncoding:NSUTF8StringEncoding];
        Byte *encryptKeyByte = (Byte *)[encryptKeyData bytes];//key要转成Byte
        
        NSString *nameEncript = [self.encrylibInterface Id2DataEncry:encryptKeyByte :resultDict[@"Name"]];
        NSString *idNumEncript = [self.encrylibInterface Id2DataEncry:encryptKeyByte :resultDict[@"CardNo"]];
        NSString *addressEncript = [self.encrylibInterface Id2DataEncry:encryptKeyByte :resultDict[@"Address"]];
        
        [*data setObject:nameEncript forKey:@"nameEncript"]; //姓名加密后
        [*data setObject:idNumEncript forKey:@"idNumEncript"]; //身份证号加密后
        [*data setObject:addressEncript forKey:@"addressEncript"]; //住址加密后
    }
}


@end

