elinkthings 4 лет назад
Сommit
e6d8ffbe57
40 измененных файлов: 3113 добавлений и 0 удалений
  1. Двоичные данные
      AILinkSecretTool.framework/AILinkSecretTool
  2. 42
    0
      AILinkSecretTool.framework/Headers/ELEncryptTool.h
  3. 388
    0
      AILinkSecretTool.framework/Headers/ELSDKHeader.h
  4. Двоичные данные
      AILinkSecretTool.framework/Info.plist
  5. Двоичные данные
      AILinkSecretTool.framework/_CodeSignature/CodeDirectory
  6. Двоичные данные
      AILinkSecretTool.framework/_CodeSignature/CodeRequirements
  7. Двоичные данные
      AILinkSecretTool.framework/_CodeSignature/CodeRequirements-1
  8. 132
    0
      AILinkSecretTool.framework/_CodeSignature/CodeResources
  9. Двоичные данные
      AILinkSecretTool.framework/_CodeSignature/CodeSignature
  10. Двоичные данные
      AILinkSecretToolDemo/AILinkSecretTool/Products/AILinkSecretTool.framework/AILinkSecretTool
  11. 42
    0
      AILinkSecretToolDemo/AILinkSecretTool/Products/AILinkSecretTool.framework/Headers/ELEncryptTool.h
  12. 388
    0
      AILinkSecretToolDemo/AILinkSecretTool/Products/AILinkSecretTool.framework/Headers/ELSDKHeader.h
  13. Двоичные данные
      AILinkSecretToolDemo/AILinkSecretTool/Products/AILinkSecretTool.framework/Info.plist
  14. Двоичные данные
      AILinkSecretToolDemo/AILinkSecretTool/Products/AILinkSecretTool.framework/_CodeSignature/CodeDirectory
  15. Двоичные данные
      AILinkSecretToolDemo/AILinkSecretTool/Products/AILinkSecretTool.framework/_CodeSignature/CodeRequirements
  16. Двоичные данные
      AILinkSecretToolDemo/AILinkSecretTool/Products/AILinkSecretTool.framework/_CodeSignature/CodeRequirements-1
  17. 132
    0
      AILinkSecretToolDemo/AILinkSecretTool/Products/AILinkSecretTool.framework/_CodeSignature/CodeResources
  18. Двоичные данные
      AILinkSecretToolDemo/AILinkSecretTool/Products/AILinkSecretTool.framework/_CodeSignature/CodeSignature
  19. 375
    0
      AILinkSecretToolDemo/AILinkSecretToolDemo.xcodeproj/project.pbxproj
  20. 7
    0
      AILinkSecretToolDemo/AILinkSecretToolDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata
  21. 8
    0
      AILinkSecretToolDemo/AILinkSecretToolDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
  22. 6
    0
      AILinkSecretToolDemo/AILinkSecretToolDemo.xcodeproj/xcuserdata/stevenwu.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist
  23. 14
    0
      AILinkSecretToolDemo/AILinkSecretToolDemo/AppDelegate.h
  24. 40
    0
      AILinkSecretToolDemo/AILinkSecretToolDemo/AppDelegate.m
  25. 11
    0
      AILinkSecretToolDemo/AILinkSecretToolDemo/Assets.xcassets/AccentColor.colorset/Contents.json
  26. 98
    0
      AILinkSecretToolDemo/AILinkSecretToolDemo/Assets.xcassets/AppIcon.appiconset/Contents.json
  27. 6
    0
      AILinkSecretToolDemo/AILinkSecretToolDemo/Assets.xcassets/Contents.json
  28. 25
    0
      AILinkSecretToolDemo/AILinkSecretToolDemo/Base.lproj/LaunchScreen.storyboard
  29. 59
    0
      AILinkSecretToolDemo/AILinkSecretToolDemo/Base.lproj/Main.storyboard
  30. 97
    0
      AILinkSecretToolDemo/AILinkSecretToolDemo/ELBluetoothManager.h
  31. 726
    0
      AILinkSecretToolDemo/AILinkSecretToolDemo/ELBluetoothManager.m
  32. 89
    0
      AILinkSecretToolDemo/AILinkSecretToolDemo/ELPeripheralModel.h
  33. 48
    0
      AILinkSecretToolDemo/AILinkSecretToolDemo/ELPeripheralModel.m
  34. 68
    0
      AILinkSecretToolDemo/AILinkSecretToolDemo/Info.plist
  35. 16
    0
      AILinkSecretToolDemo/AILinkSecretToolDemo/MyTableViewController.h
  36. 103
    0
      AILinkSecretToolDemo/AILinkSecretToolDemo/MyTableViewController.m
  37. 15
    0
      AILinkSecretToolDemo/AILinkSecretToolDemo/SceneDelegate.h
  38. 57
    0
      AILinkSecretToolDemo/AILinkSecretToolDemo/SceneDelegate.m
  39. 18
    0
      AILinkSecretToolDemo/AILinkSecretToolDemo/main.m
  40. 103
    0
      ReadMe.md

Двоичные данные
AILinkSecretTool.framework/AILinkSecretTool Просмотреть файл


+ 42
- 0
AILinkSecretTool.framework/Headers/ELEncryptTool.h Просмотреть файл

@@ -0,0 +1,42 @@
//
// ELEncryptTool.h
// AILinkSDK
//
// Created by iot_user on 2019/5/7.
// Copyright © 2019 IOT. All rights reserved.
//

#import <Foundation/Foundation.h>



NS_ASSUME_NONNULL_BEGIN


@interface ELEncryptTool : NSObject

/**
app发送此A6数据主动开始与ble进行握手
*/
+(NSData *)handshake;

/**
此方法将ble检验app的A6数据进行加密,app发给设备,否则设备将断开app
*/
+(NSData *)blueToothHandshakeWithData:(NSData *)receiveData;


/**
A7数据加/解密方法

@param macXOR mac地址对应的数据,传ELPeripheralModel的macXOR
@param deviceTypeXOR 设备类型对应的数据,传ELPeripheralModel的deviceTypeXOR
@param dataXOR 要加/解密的数据
@return 加/解密后的数据
*/
+ (NSData *)encryptXOR:(NSData *)macXOR deviceTypeXOR:(NSData *)deviceTypeXOR withXORData:(NSData *)dataXOR;


@end

NS_ASSUME_NONNULL_END

+ 388
- 0
AILinkSecretTool.framework/Headers/ELSDKHeader.h Просмотреть файл

@@ -0,0 +1,388 @@
//
// ELSDKHeader.h
// AILinkSDKDemo
//
// Created by iot_user on 2019/5/10.
// Copyright © 2019 IOT. All rights reserved.
//

#ifndef ELSDKHeader_h
#define ELSDKHeader_h


//Bluetooth command type(蓝牙指令类型)
typedef NS_ENUM(NSUInteger, ELInetBleDataType) {
ELInetBleDataPackHead_A6 = 0xA6,
ELInetBleDataPackTail_6A = 0x6A,
ELInetBleDataPackHead_A7 = 0xA7,
ELInetBleDataPackTail_7A = 0x7A,
};

//The type of instruction acquired by Inet(Inet获取的指令类型)
typedef NS_ENUM(NSUInteger, ELInetGetCmdType) {
ELInetGetCmdTypeGetName = 0x02, //-Get the Bluetooth name(获取蓝牙名称)
ELInetGetCmdTypeGetBroadcastInterval = 0x06, //-Get broadcast interval (unit: ms)(获取广播间隔时间(单位:ms))
ELInetGetCmdTypeGetConnectedInterval = 0x08, //-Get Bluetooth connection interval(获取蓝牙连接间隔)
ELInetGetCmdTypeGetTransmittingPower = 0x0A, //-Get Bluetooth transmit power(获取蓝牙发射功率)
ELInetGetCmdTypeGetSerialPortbaudRate = 0x0C, //-Get the serial port baud rate(获取串口波特率)
ELInetGetCmdTypeGetMACAddress = 0x0D, //-Read MAC address value(读取MAC地址值)
ELInetGetCmdTypeGetBMVersion = 0x0E, //-Read the BM module software and hardware version number(读取BM模块软硬件版本号)
ELInetGetCmdTypeGetMCUVersion = 0x10, //-Obtain the MCU software and hardware version number(获取MCU软硬件版本号)
ELInetGetCmdTypeGetMACAddressType = 0x12, //-Get the big endian or little endian of the Mac address in the broadcast manufacturer's custom data(获取广播厂家自定义数据中Mac地址的大端序或小端序)
ELInetGetCmdTypeGetUUID = 0x14, //-Get service and feature UUID(获取服务和特征UUID)
ELInetGetCmdTypeGetMCUMode = 0x16, //-Get master-slave mode(获取主从模式)
ELInetGetCmdTypeGetAutoSleepTime = 0x18, //-Get automatic sleep time value(获取自动睡眠时间值)
ELInetGetCmdTypeGetMCUDate = 0x1C, //-Get the current time of the system(获取系统当前时间)
ELInetGetCmdTypeGetC_V_P_ID = 0x1E, //-Read CID, VID, PID(读取CID、VID、PID)
ELInetGetCmdTypeGetCommunicationMode = 0x20, //-Get module communication mode(获取模块通信模式)
ELInetGetCmdTypeGetConnectState = 0x26, //-Get Bluetooth and WiFi connection status(获取蓝牙和WiFi连接状态)
ELInetGetCmdTypeGetBatteryState = 0x28, //-Get MCU battery status(获取MCU电池状态)
ELInetGetCmdTypeGetHandshake = 0x24, //-Encrypted handshake data returned by Bluetooth(蓝牙返回的加密的握手数据)
ELInetGetCmdTypeGetBodyFatScaleA6Data = 0x2B, //-Body fat scale 0x2B stands for A6 protocol (see the second level instructions for details)(体脂秤0x2B代表A6协议(具体见二级指令))
ELInetGetCmdTypeReadDeviceSupportUnit = 0x2C, //-APP reads the MCU end unit instruction(APP读取MCU端单位指令)
ELInetGetCmdTypeGetSendKeyState = 0x31, //-APP reads the result of sending the decoding key(APP读取下发解码秘钥的结果)
ELInetGetCmdTypeGetSmartLockA6Data = 0x34, //-Door lock 0x34 represents the A6 protocol (see the second level command for details)(门锁0x34代表A6协议(具体见二级指令))
ELInetGetCmdTypeGetBasicInfoData = 0x36, //Obtain basic device information data(获取设备基本信息数据)
#pragma mark ============ Begin 蓝牙Wifi ==============
ELInetGetCmdTypeBleWifiGetNearbyWifi = 0x80, //Get nearby Wifi(获取附近Wifi)
ELInetGetCmdTypeBleWifiReceiveWifiName = 0x81, //Reply to wifi name(回复wifi名字)
ELInetGetCmdTypeBleWifiReceiveWifiMac = 0x82, //Reply to wifi mac(回复wifi mac)
ELInetGetCmdTypeBleWifiReceiveScanResult = 0x83, //Reply to scan Wifi result(回复扫描Wifi结果)
ELInetGetCmdTypeBleWifiGetWifiMac = 0x85, //Get Wifi Mac address(获取Wifi的Mac地址)
ELInetGetCmdTypeBleWifiGetWifiPwd = 0x87, //Get Wifi password(获取Wifi密码)
ELInetGetCmdTypeBleWifiGetDTIMInterval = 0x8A, //Get DTIM interval(获取DTIM间隔)
ELInetGetCmdTypeBleWifiGetURL = 0x8C, //Get visited sites(获取访问的网站)
ELInetGetCmdTypeBleWifiGetPort = 0x8E, //Get access port number(获取访问的端口号)
ELInetGetCmdTypeBleWifiGetSNNumber = 0x93, //Get SN number (session code:deviceId)(获取SN号(会话码:设备ID))
ELInetGetCmdTypeBleWifiName = 0x94, //获取wifi名称
#pragma mark ============End 蓝牙Wifi ==============
ELInetGetCmdTypeRequestAuthorize = 0x7F, //Request device authorization (请求设备授权)
ELInetGetCmdTypeToothbrushA6Data = 0xC0, //A6 data for toothbrush(牙刷专用A6数据,详情请见协议的2级指令)(See the second order for details)
};
//Instruction type set by Inet(Inet设置的指令类型)
typedef NS_ENUM(NSUInteger, ELInetSetCmdType) {
ELInetSetCmdTypeSetName = 0x01, //Set the broadcast name(设置广播名称)
ELInetSetCmdTypeSetBroadcastInterval = 0x05, //Set the broadcast interval(设置广播间隔时间)
ELInetSetCmdTypeSetConnectedInterval = 0x07, //Set the connection interval(设置连接间隔)
ELInetSetCmdTypeSetTransmittingPower = 0x09, //Set the transmit power(设置发射功率)
ELInetSetCmdTypeSetSerialPortbaudRate = 0x0B, //Set the serial port baud rate(设置串口波特率)
ELInetSetCmdTypeSetMCUVersion = 0x0F, //Set the MCU software and hardware version number(设置MCU软硬件版本号)
ELInetSetCmdTypeSetMACAddressType = 0x11, //Set the big endian or little endian of the Mac address in the broadcast manufacturer's custom data.(设置广播厂家自定义数据中Mac地址的大端序或小端序)
ELInetSetCmdTypeSetUUID = 0x13, //Set the module's service and feature UUID(设置模块的服务和特征UUID)
ELInetSetCmdTypeSetMCUMode = 0x15, //Set the master-slave mode of the module(设置模块的主从模式)
ELInetSetCmdTypeSetAutoSleepTime = 0x17, //Set the module's automatic sleep time without connection(设置模块无连接的自动休眠时间)
ELInetSetCmdTypeSetGotoSleep = 0x19, //Set to sleep(设置进入睡眠)
ELInetSetCmdTypeSetMCUWakeUp = 0x1A, //Set module wake up(设置模块唤醒)
ELInetSetCmdTypeSetMCUNowDate = 0x1B, //Set the current time of the system(设置系统当前时间)
ELInetSetCmdTypeSetC_V_P_ID = 0x1D, //Set CID, VID, PID(设置CID、VID、PID)
ELInetSetCmdTypeSetCommunicationMode = 0x1F, //Set module serial port mode, I2C mode, SPI mode(设置模块串口模式、I2C模式、SPI模式)
ELInetSetCmdTypeSetMCURestart = 0x21, //Set module restart(设置模块重启)
ELInetSetCmdTypeSetFactoryDataReset = 0x22, //Set factory reset(设置恢复出厂设置)
ELInetSetCmdTypeSetConnectState = 0x25, //Set the Bluetooth connection status(设置蓝牙连接状态)
ELInetSetCmdTypeSetHandshake = 0x23, //Encrypted handshake data returned by Bluetooth(蓝牙返回的加密的握手数据)
ELInetSetCmdTypeSetKey = 0x31, //APP sends the decoding key(APP下发解码秘钥)
ELInetSetCmdTypeSetSmartLockA6Data = 0x34, //Door lock 0x34 represents the A6 protocol (see the second level command for details)(门锁0x34代表A6协议(具体见二级指令))
ELInetSetCmdTypeSyncMCUNowDate = 0x37, //Sync the current time of the system(设置系统当前时间)
#pragma mark ============ 蓝牙Wifi ==============
ELInetSetCmdTypeBleWifiSetWifiMac = 0x84, //设置WIFI Mac地址
ELInetSetCmdTypeBleWifiSetWifiPwd = 0x86, //设置WIFI 密码
ELInetSetCmdTypeBleWifiSetConnectWifi = 0x88, //设置设备连接WIFI
ELInetSetCmdTypeBleWifiSetDTIMInterval = 0x89, //设置DTIM间隔
ELInetSetCmdTypeBleWifiSetWifiURL = 0x8B, //设置访问的URL
ELInetSetCmdTypeBleWifiSetWifiPort = 0x8D, //设置端口号
};

//Response to Bluetooth after device(给蓝牙进行设置后的响应)
typedef NS_ENUM(NSUInteger, ELSetBluetoothResponseType) {
ELSetBluetoothResponseTypeSuccess =0 , //success(成功)
ELSetBluetoothResponseTypeFailure =1 , //failure(失败)
ELSetBluetoothResponseTypeNoSupport =2 , //not support(不支持)
};

//Device types supported by Elink: Please communicate with the hardware to set(Elink支持的设备类型:请与硬件沟通后设置)
typedef NS_ENUM(NSUInteger, ELSupportDeviceType) {
ELSupportDeviceTypeUnkonwn = 0x0000 , //unknown(未知)
ELSupportDeviceTypeBlood = 0x0001 , //sphygmomanometer(血压计)
ELSupportDeviceTypeForehead = 0x0002 , //Temperature gun(额温枪)
ELSupportDeviceTypeThermometer = 0x0003 , //thermometer(体温计)
ELSupportDeviceTypeBabyScale = 0x0004 , //Baby scale(婴儿秤)
ELSupportDeviceTypeHeightGauge = 0x0005 , //Height meter(身高仪)
ELSupportDeviceTypeSmartLock = 0x000B , //Smart door lock(智能门锁)
ELSupportDeviceTypeRemoteControl = 0x000C , //Internal projection vision tester(内投影视力检查仪)
ELSupportDeviceTypeWheelMonitor = 0x000D , //TPMS(胎压转接板)
ELSupportDeviceTypeBodyFatScale = 0x000E , //Body fat scale(体脂秤)
ELSupportDeviceTypeSmatLockRemote = 0x0010 , //Smart door lock remote control(智能门锁遥控器)
ELSupportDeviceTypeBLE_WIFIScale = 0x0011 , //Ble and wifi Scale(蓝牙Wifi体脂秤)
ELSupportDeviceTypeBLE_WIFIToothbrush = 0x0012, //Bluetooth and wifi toothbrush(蓝牙wifi牙刷)
ELSupportDeviceTypeBLE_EightScale = 0x0013 , //Eight electrode scale(八电极蓝牙秤)
ELSupportDeviceTypeAnemometer = 0x0014 , //anemometer(风速计),0x0015
ELSupportDeviceTypeClampMeter = 0x0015 , //clamp meter(钳表)
ELSupportDeviceTypeOximeter = 0x0021 , //Oximeter (血氧仪)
ELSupportDeviceTypeWatch = 0x001D , //华盛达手表
ELSupportDeviceTypeBloodSugar = 0x001C , //blood sugar(血糖仪)
ELSupportDeviceTypeInfThermt = 0x0020 , //Infrared Thermometer(红外测温仪)
ELSupportDeviceTypeFaceMask = 0x0022 , //face mask(智能口罩)
ELSupportDeviceTypeElectricScooter= 0x0025 , //滑板车
ELSupportDeviceTypeBroadcastScale = (0xffff +0x01) , //655536 Broadcast body fat scale(AILink广播体脂秤)
ELSupportDeviceTypeBroadcastHeightGauge = (0xffff + 0x03) , //65538 广播身高仪
ELSupportDeviceTypeBroadcastScale_Lingyang = (0xffff +0x16) , //65557 凌阳广播体脂秤
};
//Communication mode(通信模式)
typedef NS_ENUM(NSInteger, ELCommunicationModeType) {
ELCommunicationModeTypeSerialPort = 0, //Serial port mode(串口模式)
ELCommunicationModeTypeI2C = 1, //I2C mode(I2C模式)
ELCommunicationModeTypeSPI = 2, //SPI mode( SPI模式)
};
//Battery charge status (电池充电状态)
typedef NS_ENUM(NSUInteger, ELBatteryChargingState) {
ELBatteryChargingStateDefault = 0x00, //No charging (default)(没有充电(默认))
ELBatteryChargingStateWorking = 0x01, //charging(充电中)
ELBatteryChargingStateComplete = 0x02, //full charge(充满电)
ELBatteryChargingStateException = 0x03, //Abnormal charging(充电异常)
ELBatteryChargingStatePowerLow = 0x04, //Low battery(电量过低)
};


//CID,VID,PID
struct ELDIDStruct {
ELSupportDeviceType deviceType; //CID
int vendorID; //VID
int productID; //PID
};
//Battery charging state and power structur(电池充电状态和电量的结构体)
struct ELBatteryStruct {
ELBatteryChargingState state; //charging(充电状态)
int power; //Electricity(电量)(0—100%)
};
//Connection interval structure(连接间隔时间的结构体)
struct ELConnectIntervalStruct {
int interval; //Connection interval, unit: ms; range: 20-2000(连接间隔,单位:ms;范围:20-2000)
int latency; //Slave delay, value: 0-4(从设备延时,取值:0-4)
int timeout; //Connection timeout, unit: ms; Range: 1000~6000(连接超时,单位:ms; 范围: 1000~6000)
};

struct ELUUIDStruct {
char *serviceUUID; //Service UUID(服务UUID)
char *writeUUID; //For APP to send data to MCU (write)(用于 APP 下发数据到 MCU(write))
char *notifyUUID; //Used for MCU data transfer to APP (notify)(用于 MCU 数据传输到 APP (notify))
};

struct ELAutoSleepTimeStruct {
int sleepTime; //Automatic sleep time, unit: s(自动睡眠时间,单位:s)
int open; //Whether to enable low frequency broadcast after sleep: 0: not open, 1: open(睡眠后是否开启低频广播: 0:不开启 ,1:开启)
int interval; //Low frequency broadcast interval, unit: ms; range 20~2000(低频广播间隔,单位 :ms ;范围 20~2000)
};
//WiFi连接状态
typedef NS_ENUM(NSUInteger, BleWiFiConnectState) {
BleWiFiConnectStateNoWiFi = 0,//0:没有连接,0: No connection
BleWiFiConnectStateConnectFail = 1 ,//1:尝试连接热点,但是失败1: Attempt to connect to the hotspot, but failed
BleWiFiConnectStateNoNetwork = 2 ,//2:连接热点,热点无网络,2: Connected to the hotspot, the hotspot has no network
BleWiFiConnectStateSuccess = 3 ,//3:连接热点,热点有网络,3: Connected to the hotspot, the hotspot has a network
BleWiFiConnectStateNoConnect = 4 ,//4:有热点信息,未连接,4: There is hotspot information, not connected
};


struct ELMCUStateStruct {
int connectState; //Connection status: 0: no connection 1: connected(蓝牙连接状态: 0:无连接 1:已连接 2:配对完成)
BleWiFiConnectState wifiState; //
int workState; //Working status: 0: Wake 1: Go to sleep 2: Module is ready(工作状态: 0:唤醒 1:进入休眠 2:模块准备就绪)
};

#pragma mark - AiLink unit

/** Type key of unit string(单位字符串的type key) */
#define ELDeviceUnitTypeKey @"type"
/** supportUnit key */
#define ELDeviceUnitSupportUnitKey @"supportUnit"

/** Ailink unit */
typedef NS_ENUM(NSInteger, ELDeviceUnitType) {
/** Weight(重量) */
ELDeviceUnitType_Weight = 1 ,
/** length(长度) */
ELDeviceUnitType_Height = 2 ,
/** temperature(温度) */
ELDeviceUnitType_Temperature = 3 ,
/** Pressure(血压) */
ELDeviceUnitType_BloodPressure = 4 ,
/** Tire pressure(轮胎胎压压力) */
ELDeviceUnitType_Pressure = 5 ,
/**Blood sugar(血糖单位)*/
ELDeviceUnitType_BloodSugar = 6 ,
};

#define AiLinkBleWeightUnit_KG_Str @"kg"
#define AiLinkBleWeightUnit_Jin_Str @"斤"
#define AiLinkBleWeightUnit_LB_OZ_Str @"lb:oz"
#define AiLinkBleWeightUnit_OZ_Str @"oz"
#define AiLinkBleWeightUnit_ST_LB_Str @"st:lb"
#define AiLinkBleWeightUnit_G_Str @"g"
#define AiLinkBleWeightUnit_LB_Str @"lb"

#define AiLinkBleWeightUnitStrDic(key) [@{AiLinkBleWeightUnit_KG_Str:@(ELDeviceWeightUnit_KG),AiLinkBleWeightUnit_Jin_Str:@(ELDeviceWeightUnit_JIN),AiLinkBleWeightUnit_LB_OZ_Str:@(ELDeviceWeightUnit_LB_OZ),AiLinkBleWeightUnit_OZ_Str:@(ELDeviceWeightUnit_OZ),AiLinkBleWeightUnit_ST_LB_Str:@(ELDeviceWeightUnit_ST_LB),AiLinkBleWeightUnit_G_Str:@(ELDeviceWeightUnit_G),AiLinkBleWeightUnit_LB_Str:@(ELDeviceWeightUnit_LB)}[key] integerValue]

#define AiLinkBleWeightUnitDic @{@(ELDeviceWeightUnit_KG):AiLinkBleWeightUnit_KG_Str,@(ELDeviceWeightUnit_JIN):AiLinkBleWeightUnit_Jin_Str,@(ELDeviceWeightUnit_LB_OZ):AiLinkBleWeightUnit_LB_OZ_Str,@(ELDeviceWeightUnit_OZ):AiLinkBleWeightUnit_OZ_Str,@(ELDeviceWeightUnit_ST_LB):AiLinkBleWeightUnit_ST_LB_Str,@(ELDeviceWeightUnit_G):AiLinkBleWeightUnit_G_Str,@(ELDeviceWeightUnit_LB):AiLinkBleWeightUnit_LB_Str}
/** AiLink Weight unit(体重单位)*/
typedef NS_ENUM(NSInteger, ELDeviceWeightUnit) {
/** kg */
ELDeviceWeightUnit_KG = 0x00 ,
/** 斤 */
ELDeviceWeightUnit_JIN = 0x01 ,
/** lb:oz */
ELDeviceWeightUnit_LB_OZ = 0x02 ,
/** oz */
ELDeviceWeightUnit_OZ = 0x03 ,
/** st:lb */
ELDeviceWeightUnit_ST_LB = 0x04 ,
/** g */
ELDeviceWeightUnit_G = 0x05 ,
/** lb */
ELDeviceWeightUnit_LB = 0x06 ,
/** Unsupported unit */
ELDeviceWeightUnit_Fail = 0xFF ,
};

#define AiLinkBleHeightUnit_CMStr @"cm"
#define AiLinkBleHeightUnit_InchStr @"inch"
#define AiLinkBleHeightUnit_FeetStr @"feet"

#define AiLinkBleHeightUnitDic @{@(ELDeviceHeightUnit_CM):AiLinkBleHeightUnit_CMStr,@(ELDeviceHeightUnit_Inch):AiLinkBleHeightUnit_InchStr,@(ELDeviceHeightUnit_FT_IN):AiLinkBleHeightUnit_FeetStr}
/** AiLink Length unit(长度单位) */
typedef NS_ENUM(NSInteger, ELDeviceHeightUnit) {
/** cm */
ELDeviceHeightUnit_CM = 0x00 ,
/** inch */
ELDeviceHeightUnit_Inch = 0x01 ,
/** feet:inch */
ELDeviceHeightUnit_FT_IN = 0x02 ,
//
ELDeviceHeightUnit_M = 0x03 ,
/** Unsupported unit */
ELDeviceHeightUnit_Fail = 0xFF ,
};

#define AiLinkBleSpeedUnit_M_S @"m/s"
#define AiLinkBleSpeedUnit_KM_H @"km/h"
#define AiLinkBleSpeedUnit_FT_Min @"ft/min"
#define AiLinkBleSpeedUnit_Knots @"knots"
#define AiLinkBleSpeedUnit_MPH @"MPH"

#define AiLinkBleSpeedUnitDic @{@(ELDeviceSpeedUnit_M_S):AiLinkBleSpeedUnit_M_S,@(ELDeviceSpeedUnit_KM_H):AiLinkBleSpeedUnit_KM_H,@(ELDeviceSpeedUnit_FT_Min):AiLinkBleSpeedUnit_FT_Min,@(ELDeviceSpeedUnit_Knots):AiLinkBleSpeedUnit_Knots,@(ELDeviceSpeedUnit_MPH):AiLinkBleSpeedUnit_MPH}

/** AiLink速度单位 */
typedef NS_ENUM(NSInteger, ELDeviceSpeedUnit) {
/** m/s */
ELDeviceSpeedUnit_M_S = 0x00 ,
/** km/h */
ELDeviceSpeedUnit_KM_H = 0x01 ,
/** ft/min */
ELDeviceSpeedUnit_FT_Min = 0x02 ,
/** knots(节,海里/小时,1节=1海里/小时=1.852公里/小时) */
ELDeviceSpeedUnit_Knots = 0x03 ,
/** MPH(1 迈= 1.609344 千米/小时) */
ELDeviceSpeedUnit_MPH = 0x04 ,
/** Unsupported unit */
ELDeviceSpeedUnit_Fail = 0xFF ,
};

#define AiLinkBleTempUnit_CStr @"℃"

#define AiLinkBleTempUnit_FStr @"℉"

#define AiLinkBleTempUnitDic @{@(ELDeviceTemperatureUnit_C):AiLinkBleTempUnit_CStr,@(ELDeviceTemperatureUnit_F):AiLinkBleTempUnit_FStr}
/** AiLink Temperature unit(温度单位)*/
typedef NS_ENUM(NSInteger, ELDeviceTemperatureUnit) {
/** ℃ */
ELDeviceTemperatureUnit_C = 0x00 ,
/** ℉ */
ELDeviceTemperatureUnit_F = 0x01 ,
/** Unsupported unit */
ELDeviceTemperatureUnit_Fail = 0xFF ,
};

#define AiLinkBloodUnit_mmHgStr @"mmHg"
#define AiLinkBloodUnit_kPaStr @"kPa"

#define AiLinkBloodUnitDic @{\
@(ELDeviceBloodPressureUnit_mmhg):AiLinkBloodUnit_mmHgStr,\
@(ELDeviceBloodPressureUnit_kPa):AiLinkBloodUnit_kPaStr\
}
/** AiLink Blood pressure unit(血压单位) */
typedef NS_ENUM(NSInteger, ELDeviceBloodPressureUnit) {
/** mmhg */
ELDeviceBloodPressureUnit_mmhg = 0x00 ,
/** kPa */
ELDeviceBloodPressureUnit_kPa ,
/** Unsupported unit */
ELDeviceBloodPressureUnit_Fail ,
};

#define AiLinkBlePressureUnit_BarStr @"Bar"
#define AiLinkBlePressureUnit_PsiStr @"Psi"
#define AiLinkBlePressureUnit_KpaStr @"Kpa"

#define AiLinkBlePressureUnitDic @{@(ELDevicePressureUnit_Bar):AiLinkBlePressureUnit_BarStr,@(ELDevicePressureUnit_Psi):AiLinkBlePressureUnit_PsiStr,@(ELDevicePressureUnit_kPa):AiLinkBlePressureUnit_KpaStr}
/** AiLink Tire tire pressure unit(轮胎胎压单位) */
typedef NS_ENUM(NSInteger, ELDevicePressureUnit) {
/** kPa */
ELDevicePressureUnit_kPa = 0x00 ,
/** Psi */
ELDevicePressureUnit_Psi = 0x01 ,
/** Bar */
ELDevicePressureUnit_Bar = 0x02 ,
/** Unsupported unit */
ELDevicePressureUnit_Fail ,
};

#define AiLinkBleBloodSugarUnit_mmolStr @"mmol/L"
#define AiLinkBleBloodSugarUnit_mgStr @"mg/dL"

#define AiLinkBleBloodSugarUnitDic @{@(ELDeviceBloodSugarUnit_mmol_L):AiLinkBleBloodSugarUnit_mmolStr,@(ELDeviceBloodSugarUnit_mg_dL):AiLinkBleBloodSugarUnit_mgStr,}

typedef NS_ENUM(NSUInteger, ELDeviceBloodSugarUnit) {
ELDeviceBloodSugarUnit_mmol_L = 0x01,//mmol/L 毫摩尔/升
ELDeviceBloodSugarUnit_mg_dL = 0x02,//mg/dL 毫克/分升
ELDeviceBloodSugarUnit_Fail ,
};


#pragma mark ============ 枚举 ==============
typedef NS_ENUM(NSUInteger, ELBluetoothState) {
ELBluetoothStateUnavailable, //Bluetooth is not available(蓝牙不可用)
ELBluetoothStateAvailable, //Bluetooth available(蓝牙可用)
ELBluetoothStateStopScan, //Stop scanning(停止扫描)
ELBluetoothStateScaning, //Scanning(正在扫描)
ELBluetoothStateWillConnect, //Will connect(将要连接)
ELBluetoothStateDidConnect, //Already connected(已经连接)
ELBluetoothStateConnectFail, //Connection error(连接出错)
ELBluetoothStateDidDiscoverCharacteristics, //Peripheral feature callback(外设特征回调)
ELBluetoothStateDidDisconnect, //Disconnect(断开连接)
ELBluetoothStateDidValidationPass, //approved(通过验证)
ELBluetoothStateFailedValidation, //Failed verification(未通过验证)
};

//sex(性别)
typedef NS_ENUM(NSUInteger, ELBluetoothUserSex) {
ELBluetoothUserSex_Woman = 0x00,//female(女)
ELBluetoothUserSex_Man = 0x01,//male(男)
};
//设备授权结果
typedef NS_ENUM(NSUInteger, ELBluetoothDeviceAuthorizeResult) {
ELBluetoothDeviceAuthorizeResultNoAuth =0,//No(没有)
ELBluetoothDeviceAuthorizeResultAuthorized ,//Authorized(已经授权)
ELBluetoothDeviceAuthorizeResultNoNeed ,//No authorization required(不需要授权)
ELBluetoothDeviceAuthorizeResultSuccess ,//Authorization succeeded(授权成功)
};


#endif /* ELSDKHeader_h */

Двоичные данные
AILinkSecretTool.framework/Info.plist Просмотреть файл


Двоичные данные
AILinkSecretTool.framework/_CodeSignature/CodeDirectory Просмотреть файл


Двоичные данные
AILinkSecretTool.framework/_CodeSignature/CodeRequirements Просмотреть файл


Двоичные данные
AILinkSecretTool.framework/_CodeSignature/CodeRequirements-1 Просмотреть файл


+ 132
- 0
AILinkSecretTool.framework/_CodeSignature/CodeResources Просмотреть файл

@@ -0,0 +1,132 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>files</key>
<dict>
<key>Headers/ELEncryptTool.h</key>
<data>
9l+9JY8Tj2oxZTOPq1Cm+CDSw3c=
</data>
<key>Headers/ELSDKHeader.h</key>
<data>
ejAY32FgoNU+zZf8aBd9zLtAUO8=
</data>
<key>Info.plist</key>
<data>
q8e+xJ5jPYwRAEuak+WUQE/cGXE=
</data>
</dict>
<key>files2</key>
<dict>
<key>Headers/ELEncryptTool.h</key>
<dict>
<key>hash</key>
<data>
9l+9JY8Tj2oxZTOPq1Cm+CDSw3c=
</data>
<key>hash2</key>
<data>
ys5z9HLJkLqfOhszinVfZTB8fdeuEAd66bW0q4tfv6o=
</data>
</dict>
<key>Headers/ELSDKHeader.h</key>
<dict>
<key>hash</key>
<data>
ejAY32FgoNU+zZf8aBd9zLtAUO8=
</data>
<key>hash2</key>
<data>
9wOXdqCgmBcbRln9k+tJwQwTtPld9CTCUYcHpOq4hRM=
</data>
</dict>
</dict>
<key>rules</key>
<dict>
<key>^.*</key>
<true/>
<key>^.*\.lproj/</key>
<dict>
<key>optional</key>
<true/>
<key>weight</key>
<real>1000</real>
</dict>
<key>^.*\.lproj/locversion.plist$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>1100</real>
</dict>
<key>^Base\.lproj/</key>
<dict>
<key>weight</key>
<real>1010</real>
</dict>
<key>^version.plist$</key>
<true/>
</dict>
<key>rules2</key>
<dict>
<key>.*\.dSYM($|/)</key>
<dict>
<key>weight</key>
<real>11</real>
</dict>
<key>^(.*/)?\.DS_Store$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>2000</real>
</dict>
<key>^.*</key>
<true/>
<key>^.*\.lproj/</key>
<dict>
<key>optional</key>
<true/>
<key>weight</key>
<real>1000</real>
</dict>
<key>^.*\.lproj/locversion.plist$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>1100</real>
</dict>
<key>^Base\.lproj/</key>
<dict>
<key>weight</key>
<real>1010</real>
</dict>
<key>^Info\.plist$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>20</real>
</dict>
<key>^PkgInfo$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>20</real>
</dict>
<key>^embedded\.provisionprofile$</key>
<dict>
<key>weight</key>
<real>20</real>
</dict>
<key>^version\.plist$</key>
<dict>
<key>weight</key>
<real>20</real>
</dict>
</dict>
</dict>
</plist>

Двоичные данные
AILinkSecretTool.framework/_CodeSignature/CodeSignature Просмотреть файл


Двоичные данные
AILinkSecretToolDemo/AILinkSecretTool/Products/AILinkSecretTool.framework/AILinkSecretTool Просмотреть файл


+ 42
- 0
AILinkSecretToolDemo/AILinkSecretTool/Products/AILinkSecretTool.framework/Headers/ELEncryptTool.h Просмотреть файл

@@ -0,0 +1,42 @@
//
// ELEncryptTool.h
// AILinkSDK
//
// Created by iot_user on 2019/5/7.
// Copyright © 2019 IOT. All rights reserved.
//

#import <Foundation/Foundation.h>



NS_ASSUME_NONNULL_BEGIN


@interface ELEncryptTool : NSObject

/**
app发送此A6数据主动开始与ble进行握手
*/
+(NSData *)handshake;

/**
此方法将ble检验app的A6数据进行加密,app发给设备,否则设备将断开app
*/
+(NSData *)blueToothHandshakeWithData:(NSData *)receiveData;


/**
A7数据加/解密方法

@param macXOR mac地址对应的数据,传ELPeripheralModel的macXOR
@param deviceTypeXOR 设备类型对应的数据,传ELPeripheralModel的deviceTypeXOR
@param dataXOR 要加/解密的数据
@return 加/解密后的数据
*/
+ (NSData *)encryptXOR:(NSData *)macXOR deviceTypeXOR:(NSData *)deviceTypeXOR withXORData:(NSData *)dataXOR;


@end

NS_ASSUME_NONNULL_END

+ 388
- 0
AILinkSecretToolDemo/AILinkSecretTool/Products/AILinkSecretTool.framework/Headers/ELSDKHeader.h Просмотреть файл

@@ -0,0 +1,388 @@
//
// ELSDKHeader.h
// AILinkSDKDemo
//
// Created by iot_user on 2019/5/10.
// Copyright © 2019 IOT. All rights reserved.
//

#ifndef ELSDKHeader_h
#define ELSDKHeader_h


//Bluetooth command type(蓝牙指令类型)
typedef NS_ENUM(NSUInteger, ELInetBleDataType) {
ELInetBleDataPackHead_A6 = 0xA6,
ELInetBleDataPackTail_6A = 0x6A,
ELInetBleDataPackHead_A7 = 0xA7,
ELInetBleDataPackTail_7A = 0x7A,
};

//The type of instruction acquired by Inet(Inet获取的指令类型)
typedef NS_ENUM(NSUInteger, ELInetGetCmdType) {
ELInetGetCmdTypeGetName = 0x02, //-Get the Bluetooth name(获取蓝牙名称)
ELInetGetCmdTypeGetBroadcastInterval = 0x06, //-Get broadcast interval (unit: ms)(获取广播间隔时间(单位:ms))
ELInetGetCmdTypeGetConnectedInterval = 0x08, //-Get Bluetooth connection interval(获取蓝牙连接间隔)
ELInetGetCmdTypeGetTransmittingPower = 0x0A, //-Get Bluetooth transmit power(获取蓝牙发射功率)
ELInetGetCmdTypeGetSerialPortbaudRate = 0x0C, //-Get the serial port baud rate(获取串口波特率)
ELInetGetCmdTypeGetMACAddress = 0x0D, //-Read MAC address value(读取MAC地址值)
ELInetGetCmdTypeGetBMVersion = 0x0E, //-Read the BM module software and hardware version number(读取BM模块软硬件版本号)
ELInetGetCmdTypeGetMCUVersion = 0x10, //-Obtain the MCU software and hardware version number(获取MCU软硬件版本号)
ELInetGetCmdTypeGetMACAddressType = 0x12, //-Get the big endian or little endian of the Mac address in the broadcast manufacturer's custom data(获取广播厂家自定义数据中Mac地址的大端序或小端序)
ELInetGetCmdTypeGetUUID = 0x14, //-Get service and feature UUID(获取服务和特征UUID)
ELInetGetCmdTypeGetMCUMode = 0x16, //-Get master-slave mode(获取主从模式)
ELInetGetCmdTypeGetAutoSleepTime = 0x18, //-Get automatic sleep time value(获取自动睡眠时间值)
ELInetGetCmdTypeGetMCUDate = 0x1C, //-Get the current time of the system(获取系统当前时间)
ELInetGetCmdTypeGetC_V_P_ID = 0x1E, //-Read CID, VID, PID(读取CID、VID、PID)
ELInetGetCmdTypeGetCommunicationMode = 0x20, //-Get module communication mode(获取模块通信模式)
ELInetGetCmdTypeGetConnectState = 0x26, //-Get Bluetooth and WiFi connection status(获取蓝牙和WiFi连接状态)
ELInetGetCmdTypeGetBatteryState = 0x28, //-Get MCU battery status(获取MCU电池状态)
ELInetGetCmdTypeGetHandshake = 0x24, //-Encrypted handshake data returned by Bluetooth(蓝牙返回的加密的握手数据)
ELInetGetCmdTypeGetBodyFatScaleA6Data = 0x2B, //-Body fat scale 0x2B stands for A6 protocol (see the second level instructions for details)(体脂秤0x2B代表A6协议(具体见二级指令))
ELInetGetCmdTypeReadDeviceSupportUnit = 0x2C, //-APP reads the MCU end unit instruction(APP读取MCU端单位指令)
ELInetGetCmdTypeGetSendKeyState = 0x31, //-APP reads the result of sending the decoding key(APP读取下发解码秘钥的结果)
ELInetGetCmdTypeGetSmartLockA6Data = 0x34, //-Door lock 0x34 represents the A6 protocol (see the second level command for details)(门锁0x34代表A6协议(具体见二级指令))
ELInetGetCmdTypeGetBasicInfoData = 0x36, //Obtain basic device information data(获取设备基本信息数据)
#pragma mark ============ Begin 蓝牙Wifi ==============
ELInetGetCmdTypeBleWifiGetNearbyWifi = 0x80, //Get nearby Wifi(获取附近Wifi)
ELInetGetCmdTypeBleWifiReceiveWifiName = 0x81, //Reply to wifi name(回复wifi名字)
ELInetGetCmdTypeBleWifiReceiveWifiMac = 0x82, //Reply to wifi mac(回复wifi mac)
ELInetGetCmdTypeBleWifiReceiveScanResult = 0x83, //Reply to scan Wifi result(回复扫描Wifi结果)
ELInetGetCmdTypeBleWifiGetWifiMac = 0x85, //Get Wifi Mac address(获取Wifi的Mac地址)
ELInetGetCmdTypeBleWifiGetWifiPwd = 0x87, //Get Wifi password(获取Wifi密码)
ELInetGetCmdTypeBleWifiGetDTIMInterval = 0x8A, //Get DTIM interval(获取DTIM间隔)
ELInetGetCmdTypeBleWifiGetURL = 0x8C, //Get visited sites(获取访问的网站)
ELInetGetCmdTypeBleWifiGetPort = 0x8E, //Get access port number(获取访问的端口号)
ELInetGetCmdTypeBleWifiGetSNNumber = 0x93, //Get SN number (session code:deviceId)(获取SN号(会话码:设备ID))
ELInetGetCmdTypeBleWifiName = 0x94, //获取wifi名称
#pragma mark ============End 蓝牙Wifi ==============
ELInetGetCmdTypeRequestAuthorize = 0x7F, //Request device authorization (请求设备授权)
ELInetGetCmdTypeToothbrushA6Data = 0xC0, //A6 data for toothbrush(牙刷专用A6数据,详情请见协议的2级指令)(See the second order for details)
};
//Instruction type set by Inet(Inet设置的指令类型)
typedef NS_ENUM(NSUInteger, ELInetSetCmdType) {
ELInetSetCmdTypeSetName = 0x01, //Set the broadcast name(设置广播名称)
ELInetSetCmdTypeSetBroadcastInterval = 0x05, //Set the broadcast interval(设置广播间隔时间)
ELInetSetCmdTypeSetConnectedInterval = 0x07, //Set the connection interval(设置连接间隔)
ELInetSetCmdTypeSetTransmittingPower = 0x09, //Set the transmit power(设置发射功率)
ELInetSetCmdTypeSetSerialPortbaudRate = 0x0B, //Set the serial port baud rate(设置串口波特率)
ELInetSetCmdTypeSetMCUVersion = 0x0F, //Set the MCU software and hardware version number(设置MCU软硬件版本号)
ELInetSetCmdTypeSetMACAddressType = 0x11, //Set the big endian or little endian of the Mac address in the broadcast manufacturer's custom data.(设置广播厂家自定义数据中Mac地址的大端序或小端序)
ELInetSetCmdTypeSetUUID = 0x13, //Set the module's service and feature UUID(设置模块的服务和特征UUID)
ELInetSetCmdTypeSetMCUMode = 0x15, //Set the master-slave mode of the module(设置模块的主从模式)
ELInetSetCmdTypeSetAutoSleepTime = 0x17, //Set the module's automatic sleep time without connection(设置模块无连接的自动休眠时间)
ELInetSetCmdTypeSetGotoSleep = 0x19, //Set to sleep(设置进入睡眠)
ELInetSetCmdTypeSetMCUWakeUp = 0x1A, //Set module wake up(设置模块唤醒)
ELInetSetCmdTypeSetMCUNowDate = 0x1B, //Set the current time of the system(设置系统当前时间)
ELInetSetCmdTypeSetC_V_P_ID = 0x1D, //Set CID, VID, PID(设置CID、VID、PID)
ELInetSetCmdTypeSetCommunicationMode = 0x1F, //Set module serial port mode, I2C mode, SPI mode(设置模块串口模式、I2C模式、SPI模式)
ELInetSetCmdTypeSetMCURestart = 0x21, //Set module restart(设置模块重启)
ELInetSetCmdTypeSetFactoryDataReset = 0x22, //Set factory reset(设置恢复出厂设置)
ELInetSetCmdTypeSetConnectState = 0x25, //Set the Bluetooth connection status(设置蓝牙连接状态)
ELInetSetCmdTypeSetHandshake = 0x23, //Encrypted handshake data returned by Bluetooth(蓝牙返回的加密的握手数据)
ELInetSetCmdTypeSetKey = 0x31, //APP sends the decoding key(APP下发解码秘钥)
ELInetSetCmdTypeSetSmartLockA6Data = 0x34, //Door lock 0x34 represents the A6 protocol (see the second level command for details)(门锁0x34代表A6协议(具体见二级指令))
ELInetSetCmdTypeSyncMCUNowDate = 0x37, //Sync the current time of the system(设置系统当前时间)
#pragma mark ============ 蓝牙Wifi ==============
ELInetSetCmdTypeBleWifiSetWifiMac = 0x84, //设置WIFI Mac地址
ELInetSetCmdTypeBleWifiSetWifiPwd = 0x86, //设置WIFI 密码
ELInetSetCmdTypeBleWifiSetConnectWifi = 0x88, //设置设备连接WIFI
ELInetSetCmdTypeBleWifiSetDTIMInterval = 0x89, //设置DTIM间隔
ELInetSetCmdTypeBleWifiSetWifiURL = 0x8B, //设置访问的URL
ELInetSetCmdTypeBleWifiSetWifiPort = 0x8D, //设置端口号
};

//Response to Bluetooth after device(给蓝牙进行设置后的响应)
typedef NS_ENUM(NSUInteger, ELSetBluetoothResponseType) {
ELSetBluetoothResponseTypeSuccess =0 , //success(成功)
ELSetBluetoothResponseTypeFailure =1 , //failure(失败)
ELSetBluetoothResponseTypeNoSupport =2 , //not support(不支持)
};

//Device types supported by Elink: Please communicate with the hardware to set(Elink支持的设备类型:请与硬件沟通后设置)
typedef NS_ENUM(NSUInteger, ELSupportDeviceType) {
ELSupportDeviceTypeUnkonwn = 0x0000 , //unknown(未知)
ELSupportDeviceTypeBlood = 0x0001 , //sphygmomanometer(血压计)
ELSupportDeviceTypeForehead = 0x0002 , //Temperature gun(额温枪)
ELSupportDeviceTypeThermometer = 0x0003 , //thermometer(体温计)
ELSupportDeviceTypeBabyScale = 0x0004 , //Baby scale(婴儿秤)
ELSupportDeviceTypeHeightGauge = 0x0005 , //Height meter(身高仪)
ELSupportDeviceTypeSmartLock = 0x000B , //Smart door lock(智能门锁)
ELSupportDeviceTypeRemoteControl = 0x000C , //Internal projection vision tester(内投影视力检查仪)
ELSupportDeviceTypeWheelMonitor = 0x000D , //TPMS(胎压转接板)
ELSupportDeviceTypeBodyFatScale = 0x000E , //Body fat scale(体脂秤)
ELSupportDeviceTypeSmatLockRemote = 0x0010 , //Smart door lock remote control(智能门锁遥控器)
ELSupportDeviceTypeBLE_WIFIScale = 0x0011 , //Ble and wifi Scale(蓝牙Wifi体脂秤)
ELSupportDeviceTypeBLE_WIFIToothbrush = 0x0012, //Bluetooth and wifi toothbrush(蓝牙wifi牙刷)
ELSupportDeviceTypeBLE_EightScale = 0x0013 , //Eight electrode scale(八电极蓝牙秤)
ELSupportDeviceTypeAnemometer = 0x0014 , //anemometer(风速计),0x0015
ELSupportDeviceTypeClampMeter = 0x0015 , //clamp meter(钳表)
ELSupportDeviceTypeOximeter = 0x0021 , //Oximeter (血氧仪)
ELSupportDeviceTypeWatch = 0x001D , //华盛达手表
ELSupportDeviceTypeBloodSugar = 0x001C , //blood sugar(血糖仪)
ELSupportDeviceTypeInfThermt = 0x0020 , //Infrared Thermometer(红外测温仪)
ELSupportDeviceTypeFaceMask = 0x0022 , //face mask(智能口罩)
ELSupportDeviceTypeElectricScooter= 0x0025 , //滑板车
ELSupportDeviceTypeBroadcastScale = (0xffff +0x01) , //655536 Broadcast body fat scale(AILink广播体脂秤)
ELSupportDeviceTypeBroadcastHeightGauge = (0xffff + 0x03) , //65538 广播身高仪
ELSupportDeviceTypeBroadcastScale_Lingyang = (0xffff +0x16) , //65557 凌阳广播体脂秤
};
//Communication mode(通信模式)
typedef NS_ENUM(NSInteger, ELCommunicationModeType) {
ELCommunicationModeTypeSerialPort = 0, //Serial port mode(串口模式)
ELCommunicationModeTypeI2C = 1, //I2C mode(I2C模式)
ELCommunicationModeTypeSPI = 2, //SPI mode( SPI模式)
};
//Battery charge status (电池充电状态)
typedef NS_ENUM(NSUInteger, ELBatteryChargingState) {
ELBatteryChargingStateDefault = 0x00, //No charging (default)(没有充电(默认))
ELBatteryChargingStateWorking = 0x01, //charging(充电中)
ELBatteryChargingStateComplete = 0x02, //full charge(充满电)
ELBatteryChargingStateException = 0x03, //Abnormal charging(充电异常)
ELBatteryChargingStatePowerLow = 0x04, //Low battery(电量过低)
};


//CID,VID,PID
struct ELDIDStruct {
ELSupportDeviceType deviceType; //CID
int vendorID; //VID
int productID; //PID
};
//Battery charging state and power structur(电池充电状态和电量的结构体)
struct ELBatteryStruct {
ELBatteryChargingState state; //charging(充电状态)
int power; //Electricity(电量)(0—100%)
};
//Connection interval structure(连接间隔时间的结构体)
struct ELConnectIntervalStruct {
int interval; //Connection interval, unit: ms; range: 20-2000(连接间隔,单位:ms;范围:20-2000)
int latency; //Slave delay, value: 0-4(从设备延时,取值:0-4)
int timeout; //Connection timeout, unit: ms; Range: 1000~6000(连接超时,单位:ms; 范围: 1000~6000)
};

struct ELUUIDStruct {
char *serviceUUID; //Service UUID(服务UUID)
char *writeUUID; //For APP to send data to MCU (write)(用于 APP 下发数据到 MCU(write))
char *notifyUUID; //Used for MCU data transfer to APP (notify)(用于 MCU 数据传输到 APP (notify))
};

struct ELAutoSleepTimeStruct {
int sleepTime; //Automatic sleep time, unit: s(自动睡眠时间,单位:s)
int open; //Whether to enable low frequency broadcast after sleep: 0: not open, 1: open(睡眠后是否开启低频广播: 0:不开启 ,1:开启)
int interval; //Low frequency broadcast interval, unit: ms; range 20~2000(低频广播间隔,单位 :ms ;范围 20~2000)
};
//WiFi连接状态
typedef NS_ENUM(NSUInteger, BleWiFiConnectState) {
BleWiFiConnectStateNoWiFi = 0,//0:没有连接,0: No connection
BleWiFiConnectStateConnectFail = 1 ,//1:尝试连接热点,但是失败1: Attempt to connect to the hotspot, but failed
BleWiFiConnectStateNoNetwork = 2 ,//2:连接热点,热点无网络,2: Connected to the hotspot, the hotspot has no network
BleWiFiConnectStateSuccess = 3 ,//3:连接热点,热点有网络,3: Connected to the hotspot, the hotspot has a network
BleWiFiConnectStateNoConnect = 4 ,//4:有热点信息,未连接,4: There is hotspot information, not connected
};


struct ELMCUStateStruct {
int connectState; //Connection status: 0: no connection 1: connected(蓝牙连接状态: 0:无连接 1:已连接 2:配对完成)
BleWiFiConnectState wifiState; //
int workState; //Working status: 0: Wake 1: Go to sleep 2: Module is ready(工作状态: 0:唤醒 1:进入休眠 2:模块准备就绪)
};

#pragma mark - AiLink unit

/** Type key of unit string(单位字符串的type key) */
#define ELDeviceUnitTypeKey @"type"
/** supportUnit key */
#define ELDeviceUnitSupportUnitKey @"supportUnit"

/** Ailink unit */
typedef NS_ENUM(NSInteger, ELDeviceUnitType) {
/** Weight(重量) */
ELDeviceUnitType_Weight = 1 ,
/** length(长度) */
ELDeviceUnitType_Height = 2 ,
/** temperature(温度) */
ELDeviceUnitType_Temperature = 3 ,
/** Pressure(血压) */
ELDeviceUnitType_BloodPressure = 4 ,
/** Tire pressure(轮胎胎压压力) */
ELDeviceUnitType_Pressure = 5 ,
/**Blood sugar(血糖单位)*/
ELDeviceUnitType_BloodSugar = 6 ,
};

#define AiLinkBleWeightUnit_KG_Str @"kg"
#define AiLinkBleWeightUnit_Jin_Str @"斤"
#define AiLinkBleWeightUnit_LB_OZ_Str @"lb:oz"
#define AiLinkBleWeightUnit_OZ_Str @"oz"
#define AiLinkBleWeightUnit_ST_LB_Str @"st:lb"
#define AiLinkBleWeightUnit_G_Str @"g"
#define AiLinkBleWeightUnit_LB_Str @"lb"

#define AiLinkBleWeightUnitStrDic(key) [@{AiLinkBleWeightUnit_KG_Str:@(ELDeviceWeightUnit_KG),AiLinkBleWeightUnit_Jin_Str:@(ELDeviceWeightUnit_JIN),AiLinkBleWeightUnit_LB_OZ_Str:@(ELDeviceWeightUnit_LB_OZ),AiLinkBleWeightUnit_OZ_Str:@(ELDeviceWeightUnit_OZ),AiLinkBleWeightUnit_ST_LB_Str:@(ELDeviceWeightUnit_ST_LB),AiLinkBleWeightUnit_G_Str:@(ELDeviceWeightUnit_G),AiLinkBleWeightUnit_LB_Str:@(ELDeviceWeightUnit_LB)}[key] integerValue]

#define AiLinkBleWeightUnitDic @{@(ELDeviceWeightUnit_KG):AiLinkBleWeightUnit_KG_Str,@(ELDeviceWeightUnit_JIN):AiLinkBleWeightUnit_Jin_Str,@(ELDeviceWeightUnit_LB_OZ):AiLinkBleWeightUnit_LB_OZ_Str,@(ELDeviceWeightUnit_OZ):AiLinkBleWeightUnit_OZ_Str,@(ELDeviceWeightUnit_ST_LB):AiLinkBleWeightUnit_ST_LB_Str,@(ELDeviceWeightUnit_G):AiLinkBleWeightUnit_G_Str,@(ELDeviceWeightUnit_LB):AiLinkBleWeightUnit_LB_Str}
/** AiLink Weight unit(体重单位)*/
typedef NS_ENUM(NSInteger, ELDeviceWeightUnit) {
/** kg */
ELDeviceWeightUnit_KG = 0x00 ,
/** 斤 */
ELDeviceWeightUnit_JIN = 0x01 ,
/** lb:oz */
ELDeviceWeightUnit_LB_OZ = 0x02 ,
/** oz */
ELDeviceWeightUnit_OZ = 0x03 ,
/** st:lb */
ELDeviceWeightUnit_ST_LB = 0x04 ,
/** g */
ELDeviceWeightUnit_G = 0x05 ,
/** lb */
ELDeviceWeightUnit_LB = 0x06 ,
/** Unsupported unit */
ELDeviceWeightUnit_Fail = 0xFF ,
};

#define AiLinkBleHeightUnit_CMStr @"cm"
#define AiLinkBleHeightUnit_InchStr @"inch"
#define AiLinkBleHeightUnit_FeetStr @"feet"

#define AiLinkBleHeightUnitDic @{@(ELDeviceHeightUnit_CM):AiLinkBleHeightUnit_CMStr,@(ELDeviceHeightUnit_Inch):AiLinkBleHeightUnit_InchStr,@(ELDeviceHeightUnit_FT_IN):AiLinkBleHeightUnit_FeetStr}
/** AiLink Length unit(长度单位) */
typedef NS_ENUM(NSInteger, ELDeviceHeightUnit) {
/** cm */
ELDeviceHeightUnit_CM = 0x00 ,
/** inch */
ELDeviceHeightUnit_Inch = 0x01 ,
/** feet:inch */
ELDeviceHeightUnit_FT_IN = 0x02 ,
//
ELDeviceHeightUnit_M = 0x03 ,
/** Unsupported unit */
ELDeviceHeightUnit_Fail = 0xFF ,
};

#define AiLinkBleSpeedUnit_M_S @"m/s"
#define AiLinkBleSpeedUnit_KM_H @"km/h"
#define AiLinkBleSpeedUnit_FT_Min @"ft/min"
#define AiLinkBleSpeedUnit_Knots @"knots"
#define AiLinkBleSpeedUnit_MPH @"MPH"

#define AiLinkBleSpeedUnitDic @{@(ELDeviceSpeedUnit_M_S):AiLinkBleSpeedUnit_M_S,@(ELDeviceSpeedUnit_KM_H):AiLinkBleSpeedUnit_KM_H,@(ELDeviceSpeedUnit_FT_Min):AiLinkBleSpeedUnit_FT_Min,@(ELDeviceSpeedUnit_Knots):AiLinkBleSpeedUnit_Knots,@(ELDeviceSpeedUnit_MPH):AiLinkBleSpeedUnit_MPH}

/** AiLink速度单位 */
typedef NS_ENUM(NSInteger, ELDeviceSpeedUnit) {
/** m/s */
ELDeviceSpeedUnit_M_S = 0x00 ,
/** km/h */
ELDeviceSpeedUnit_KM_H = 0x01 ,
/** ft/min */
ELDeviceSpeedUnit_FT_Min = 0x02 ,
/** knots(节,海里/小时,1节=1海里/小时=1.852公里/小时) */
ELDeviceSpeedUnit_Knots = 0x03 ,
/** MPH(1 迈= 1.609344 千米/小时) */
ELDeviceSpeedUnit_MPH = 0x04 ,
/** Unsupported unit */
ELDeviceSpeedUnit_Fail = 0xFF ,
};

#define AiLinkBleTempUnit_CStr @"℃"

#define AiLinkBleTempUnit_FStr @"℉"

#define AiLinkBleTempUnitDic @{@(ELDeviceTemperatureUnit_C):AiLinkBleTempUnit_CStr,@(ELDeviceTemperatureUnit_F):AiLinkBleTempUnit_FStr}
/** AiLink Temperature unit(温度单位)*/
typedef NS_ENUM(NSInteger, ELDeviceTemperatureUnit) {
/** ℃ */
ELDeviceTemperatureUnit_C = 0x00 ,
/** ℉ */
ELDeviceTemperatureUnit_F = 0x01 ,
/** Unsupported unit */
ELDeviceTemperatureUnit_Fail = 0xFF ,
};

#define AiLinkBloodUnit_mmHgStr @"mmHg"
#define AiLinkBloodUnit_kPaStr @"kPa"

#define AiLinkBloodUnitDic @{\
@(ELDeviceBloodPressureUnit_mmhg):AiLinkBloodUnit_mmHgStr,\
@(ELDeviceBloodPressureUnit_kPa):AiLinkBloodUnit_kPaStr\
}
/** AiLink Blood pressure unit(血压单位) */
typedef NS_ENUM(NSInteger, ELDeviceBloodPressureUnit) {
/** mmhg */
ELDeviceBloodPressureUnit_mmhg = 0x00 ,
/** kPa */
ELDeviceBloodPressureUnit_kPa ,
/** Unsupported unit */
ELDeviceBloodPressureUnit_Fail ,
};

#define AiLinkBlePressureUnit_BarStr @"Bar"
#define AiLinkBlePressureUnit_PsiStr @"Psi"
#define AiLinkBlePressureUnit_KpaStr @"Kpa"

#define AiLinkBlePressureUnitDic @{@(ELDevicePressureUnit_Bar):AiLinkBlePressureUnit_BarStr,@(ELDevicePressureUnit_Psi):AiLinkBlePressureUnit_PsiStr,@(ELDevicePressureUnit_kPa):AiLinkBlePressureUnit_KpaStr}
/** AiLink Tire tire pressure unit(轮胎胎压单位) */
typedef NS_ENUM(NSInteger, ELDevicePressureUnit) {
/** kPa */
ELDevicePressureUnit_kPa = 0x00 ,
/** Psi */
ELDevicePressureUnit_Psi = 0x01 ,
/** Bar */
ELDevicePressureUnit_Bar = 0x02 ,
/** Unsupported unit */
ELDevicePressureUnit_Fail ,
};

#define AiLinkBleBloodSugarUnit_mmolStr @"mmol/L"
#define AiLinkBleBloodSugarUnit_mgStr @"mg/dL"

#define AiLinkBleBloodSugarUnitDic @{@(ELDeviceBloodSugarUnit_mmol_L):AiLinkBleBloodSugarUnit_mmolStr,@(ELDeviceBloodSugarUnit_mg_dL):AiLinkBleBloodSugarUnit_mgStr,}

typedef NS_ENUM(NSUInteger, ELDeviceBloodSugarUnit) {
ELDeviceBloodSugarUnit_mmol_L = 0x01,//mmol/L 毫摩尔/升
ELDeviceBloodSugarUnit_mg_dL = 0x02,//mg/dL 毫克/分升
ELDeviceBloodSugarUnit_Fail ,
};


#pragma mark ============ 枚举 ==============
typedef NS_ENUM(NSUInteger, ELBluetoothState) {
ELBluetoothStateUnavailable, //Bluetooth is not available(蓝牙不可用)
ELBluetoothStateAvailable, //Bluetooth available(蓝牙可用)
ELBluetoothStateStopScan, //Stop scanning(停止扫描)
ELBluetoothStateScaning, //Scanning(正在扫描)
ELBluetoothStateWillConnect, //Will connect(将要连接)
ELBluetoothStateDidConnect, //Already connected(已经连接)
ELBluetoothStateConnectFail, //Connection error(连接出错)
ELBluetoothStateDidDiscoverCharacteristics, //Peripheral feature callback(外设特征回调)
ELBluetoothStateDidDisconnect, //Disconnect(断开连接)
ELBluetoothStateDidValidationPass, //approved(通过验证)
ELBluetoothStateFailedValidation, //Failed verification(未通过验证)
};

//sex(性别)
typedef NS_ENUM(NSUInteger, ELBluetoothUserSex) {
ELBluetoothUserSex_Woman = 0x00,//female(女)
ELBluetoothUserSex_Man = 0x01,//male(男)
};
//设备授权结果
typedef NS_ENUM(NSUInteger, ELBluetoothDeviceAuthorizeResult) {
ELBluetoothDeviceAuthorizeResultNoAuth =0,//No(没有)
ELBluetoothDeviceAuthorizeResultAuthorized ,//Authorized(已经授权)
ELBluetoothDeviceAuthorizeResultNoNeed ,//No authorization required(不需要授权)
ELBluetoothDeviceAuthorizeResultSuccess ,//Authorization succeeded(授权成功)
};


#endif /* ELSDKHeader_h */

Двоичные данные
AILinkSecretToolDemo/AILinkSecretTool/Products/AILinkSecretTool.framework/Info.plist Просмотреть файл


Двоичные данные
AILinkSecretToolDemo/AILinkSecretTool/Products/AILinkSecretTool.framework/_CodeSignature/CodeDirectory Просмотреть файл


Двоичные данные
AILinkSecretToolDemo/AILinkSecretTool/Products/AILinkSecretTool.framework/_CodeSignature/CodeRequirements Просмотреть файл


Двоичные данные
AILinkSecretToolDemo/AILinkSecretTool/Products/AILinkSecretTool.framework/_CodeSignature/CodeRequirements-1 Просмотреть файл


+ 132
- 0
AILinkSecretToolDemo/AILinkSecretTool/Products/AILinkSecretTool.framework/_CodeSignature/CodeResources Просмотреть файл

@@ -0,0 +1,132 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>files</key>
<dict>
<key>Headers/ELEncryptTool.h</key>
<data>
9l+9JY8Tj2oxZTOPq1Cm+CDSw3c=
</data>
<key>Headers/ELSDKHeader.h</key>
<data>
ejAY32FgoNU+zZf8aBd9zLtAUO8=
</data>
<key>Info.plist</key>
<data>
q8e+xJ5jPYwRAEuak+WUQE/cGXE=
</data>
</dict>
<key>files2</key>
<dict>
<key>Headers/ELEncryptTool.h</key>
<dict>
<key>hash</key>
<data>
9l+9JY8Tj2oxZTOPq1Cm+CDSw3c=
</data>
<key>hash2</key>
<data>
ys5z9HLJkLqfOhszinVfZTB8fdeuEAd66bW0q4tfv6o=
</data>
</dict>
<key>Headers/ELSDKHeader.h</key>
<dict>
<key>hash</key>
<data>
ejAY32FgoNU+zZf8aBd9zLtAUO8=
</data>
<key>hash2</key>
<data>
9wOXdqCgmBcbRln9k+tJwQwTtPld9CTCUYcHpOq4hRM=
</data>
</dict>
</dict>
<key>rules</key>
<dict>
<key>^.*</key>
<true/>
<key>^.*\.lproj/</key>
<dict>
<key>optional</key>
<true/>
<key>weight</key>
<real>1000</real>
</dict>
<key>^.*\.lproj/locversion.plist$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>1100</real>
</dict>
<key>^Base\.lproj/</key>
<dict>
<key>weight</key>
<real>1010</real>
</dict>
<key>^version.plist$</key>
<true/>
</dict>
<key>rules2</key>
<dict>
<key>.*\.dSYM($|/)</key>
<dict>
<key>weight</key>
<real>11</real>
</dict>
<key>^(.*/)?\.DS_Store$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>2000</real>
</dict>
<key>^.*</key>
<true/>
<key>^.*\.lproj/</key>
<dict>
<key>optional</key>
<true/>
<key>weight</key>
<real>1000</real>
</dict>
<key>^.*\.lproj/locversion.plist$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>1100</real>
</dict>
<key>^Base\.lproj/</key>
<dict>
<key>weight</key>
<real>1010</real>
</dict>
<key>^Info\.plist$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>20</real>
</dict>
<key>^PkgInfo$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>20</real>
</dict>
<key>^embedded\.provisionprofile$</key>
<dict>
<key>weight</key>
<real>20</real>
</dict>
<key>^version\.plist$</key>
<dict>
<key>weight</key>
<real>20</real>
</dict>
</dict>
</dict>
</plist>

Двоичные данные
AILinkSecretToolDemo/AILinkSecretTool/Products/AILinkSecretTool.framework/_CodeSignature/CodeSignature Просмотреть файл


+ 375
- 0
AILinkSecretToolDemo/AILinkSecretToolDemo.xcodeproj/project.pbxproj Просмотреть файл

@@ -0,0 +1,375 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 50;
objects = {

/* Begin PBXBuildFile section */
95A4E0C5261EAE6900B52FB7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 95A4E0C4261EAE6900B52FB7 /* AppDelegate.m */; };
95A4E0C8261EAE6900B52FB7 /* SceneDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 95A4E0C7261EAE6900B52FB7 /* SceneDelegate.m */; };
95A4E0CE261EAE6900B52FB7 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 95A4E0CC261EAE6900B52FB7 /* Main.storyboard */; };
95A4E0D0261EAE6B00B52FB7 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 95A4E0CF261EAE6B00B52FB7 /* Assets.xcassets */; };
95A4E0D3261EAE6B00B52FB7 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 95A4E0D1261EAE6B00B52FB7 /* LaunchScreen.storyboard */; };
95A4E0D6261EAE6B00B52FB7 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 95A4E0D5261EAE6B00B52FB7 /* main.m */; };
95A4E10D261EB17C00B52FB7 /* AILinkSecretTool.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 95A4E10B261EB17C00B52FB7 /* AILinkSecretTool.framework */; };
95A4E111261EB1B000B52FB7 /* ELBluetoothManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 95A4E110261EB1B000B52FB7 /* ELBluetoothManager.m */; };
95A4E115261EB1D300B52FB7 /* ELPeripheralModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 95A4E114261EB1D300B52FB7 /* ELPeripheralModel.m */; };
95C3FF962626CEB6008358D0 /* MyTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 95C3FF952626CEB6008358D0 /* MyTableViewController.m */; };
/* End PBXBuildFile section */

/* Begin PBXFileReference section */
95A4E0C0261EAE6900B52FB7 /* AILinkSecretToolDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = AILinkSecretToolDemo.app; sourceTree = BUILT_PRODUCTS_DIR; };
95A4E0C3261EAE6900B52FB7 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
95A4E0C4261EAE6900B52FB7 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
95A4E0C6261EAE6900B52FB7 /* SceneDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SceneDelegate.h; sourceTree = "<group>"; };
95A4E0C7261EAE6900B52FB7 /* SceneDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SceneDelegate.m; sourceTree = "<group>"; };
95A4E0CD261EAE6900B52FB7 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
95A4E0CF261EAE6B00B52FB7 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
95A4E0D2261EAE6B00B52FB7 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
95A4E0D4261EAE6B00B52FB7 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
95A4E0D5261EAE6B00B52FB7 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
95A4E10B261EB17C00B52FB7 /* AILinkSecretTool.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AILinkSecretTool.framework; path = AILinkSecretTool/Products/AILinkSecretTool.framework; sourceTree = SOURCE_ROOT; };
95A4E10F261EB1B000B52FB7 /* ELBluetoothManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ELBluetoothManager.h; sourceTree = "<group>"; };
95A4E110261EB1B000B52FB7 /* ELBluetoothManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ELBluetoothManager.m; sourceTree = "<group>"; };
95A4E113261EB1D300B52FB7 /* ELPeripheralModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ELPeripheralModel.h; sourceTree = "<group>"; };
95A4E114261EB1D300B52FB7 /* ELPeripheralModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ELPeripheralModel.m; sourceTree = "<group>"; };
95C3FF942626CEB6008358D0 /* MyTableViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MyTableViewController.h; sourceTree = "<group>"; };
95C3FF952626CEB6008358D0 /* MyTableViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MyTableViewController.m; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
95A4E0BD261EAE6900B52FB7 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
95A4E10D261EB17C00B52FB7 /* AILinkSecretTool.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */

/* Begin PBXGroup section */
95A4E0B7261EAE6900B52FB7 = {
isa = PBXGroup;
children = (
95A4E0C2261EAE6900B52FB7 /* AILinkSecretToolDemo */,
95A4E0C1261EAE6900B52FB7 /* Products */,
);
sourceTree = "<group>";
};
95A4E0C1261EAE6900B52FB7 /* Products */ = {
isa = PBXGroup;
children = (
95A4E0C0261EAE6900B52FB7 /* AILinkSecretToolDemo.app */,
);
name = Products;
sourceTree = "<group>";
};
95A4E0C2261EAE6900B52FB7 /* AILinkSecretToolDemo */ = {
isa = PBXGroup;
children = (
95A4E10B261EB17C00B52FB7 /* AILinkSecretTool.framework */,
95A4E0C3261EAE6900B52FB7 /* AppDelegate.h */,
95A4E0C4261EAE6900B52FB7 /* AppDelegate.m */,
95A4E0C6261EAE6900B52FB7 /* SceneDelegate.h */,
95A4E0C7261EAE6900B52FB7 /* SceneDelegate.m */,
95C3FF942626CEB6008358D0 /* MyTableViewController.h */,
95C3FF952626CEB6008358D0 /* MyTableViewController.m */,
95A4E113261EB1D300B52FB7 /* ELPeripheralModel.h */,
95A4E114261EB1D300B52FB7 /* ELPeripheralModel.m */,
95A4E10F261EB1B000B52FB7 /* ELBluetoothManager.h */,
95A4E110261EB1B000B52FB7 /* ELBluetoothManager.m */,
95A4E0CC261EAE6900B52FB7 /* Main.storyboard */,
95A4E0CF261EAE6B00B52FB7 /* Assets.xcassets */,
95A4E0D1261EAE6B00B52FB7 /* LaunchScreen.storyboard */,
95A4E0D4261EAE6B00B52FB7 /* Info.plist */,
95A4E0D5261EAE6B00B52FB7 /* main.m */,
);
path = AILinkSecretToolDemo;
sourceTree = "<group>";
};
/* End PBXGroup section */

/* Begin PBXNativeTarget section */
95A4E0BF261EAE6900B52FB7 /* AILinkSecretToolDemo */ = {
isa = PBXNativeTarget;
buildConfigurationList = 95A4E0D9261EAE6B00B52FB7 /* Build configuration list for PBXNativeTarget "AILinkSecretToolDemo" */;
buildPhases = (
95A4E0BC261EAE6900B52FB7 /* Sources */,
95A4E0BD261EAE6900B52FB7 /* Frameworks */,
95A4E0BE261EAE6900B52FB7 /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = AILinkSecretToolDemo;
productName = AILinkSecretToolDemo;
productReference = 95A4E0C0261EAE6900B52FB7 /* AILinkSecretToolDemo.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */

/* Begin PBXProject section */
95A4E0B8261EAE6900B52FB7 /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 1230;
TargetAttributes = {
95A4E0BF261EAE6900B52FB7 = {
CreatedOnToolsVersion = 12.3;
};
};
};
buildConfigurationList = 95A4E0BB261EAE6900B52FB7 /* Build configuration list for PBXProject "AILinkSecretToolDemo" */;
compatibilityVersion = "Xcode 9.3";
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = 95A4E0B7261EAE6900B52FB7;
productRefGroup = 95A4E0C1261EAE6900B52FB7 /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
95A4E0BF261EAE6900B52FB7 /* AILinkSecretToolDemo */,
);
};
/* End PBXProject section */

/* Begin PBXResourcesBuildPhase section */
95A4E0BE261EAE6900B52FB7 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
95A4E0D3261EAE6B00B52FB7 /* LaunchScreen.storyboard in Resources */,
95A4E0D0261EAE6B00B52FB7 /* Assets.xcassets in Resources */,
95A4E0CE261EAE6900B52FB7 /* Main.storyboard in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */

/* Begin PBXSourcesBuildPhase section */
95A4E0BC261EAE6900B52FB7 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
95A4E0C5261EAE6900B52FB7 /* AppDelegate.m in Sources */,
95A4E115261EB1D300B52FB7 /* ELPeripheralModel.m in Sources */,
95A4E0D6261EAE6B00B52FB7 /* main.m in Sources */,
95C3FF962626CEB6008358D0 /* MyTableViewController.m in Sources */,
95A4E0C8261EAE6900B52FB7 /* SceneDelegate.m in Sources */,
95A4E111261EB1B000B52FB7 /* ELBluetoothManager.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */

/* Begin PBXVariantGroup section */
95A4E0CC261EAE6900B52FB7 /* Main.storyboard */ = {
isa = PBXVariantGroup;
children = (
95A4E0CD261EAE6900B52FB7 /* Base */,
);
name = Main.storyboard;
sourceTree = "<group>";
};
95A4E0D1261EAE6B00B52FB7 /* LaunchScreen.storyboard */ = {
isa = PBXVariantGroup;
children = (
95A4E0D2261EAE6B00B52FB7 /* Base */,
);
name = LaunchScreen.storyboard;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */

/* Begin XCBuildConfiguration section */
95A4E0D7261EAE6B00B52FB7 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 14.3;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
};
name = Debug;
};
95A4E0D8261EAE6B00B52FB7 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 14.3;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
SDKROOT = iphoneos;
VALIDATE_PRODUCT = YES;
};
name = Release;
};
95A4E0DA261EAE6B00B52FB7 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_TEAM = ZS5NB5WV7X;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/AILinkSecretTool/Products",
);
INFOPLIST_FILE = AILinkSecretToolDemo/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = com.elinkthings.AILinkSecretToolDemo;
PRODUCT_NAME = "$(TARGET_NAME)";
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
95A4E0DB261EAE6B00B52FB7 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_TEAM = ZS5NB5WV7X;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/AILinkSecretTool/Products",
);
INFOPLIST_FILE = AILinkSecretToolDemo/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = com.elinkthings.AILinkSecretToolDemo;
PRODUCT_NAME = "$(TARGET_NAME)";
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Release;
};
/* End XCBuildConfiguration section */

/* Begin XCConfigurationList section */
95A4E0BB261EAE6900B52FB7 /* Build configuration list for PBXProject "AILinkSecretToolDemo" */ = {
isa = XCConfigurationList;
buildConfigurations = (
95A4E0D7261EAE6B00B52FB7 /* Debug */,
95A4E0D8261EAE6B00B52FB7 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
95A4E0D9261EAE6B00B52FB7 /* Build configuration list for PBXNativeTarget "AILinkSecretToolDemo" */ = {
isa = XCConfigurationList;
buildConfigurations = (
95A4E0DA261EAE6B00B52FB7 /* Debug */,
95A4E0DB261EAE6B00B52FB7 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 95A4E0B8261EAE6900B52FB7 /* Project object */;
}

+ 7
- 0
AILinkSecretToolDemo/AILinkSecretToolDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata Просмотреть файл

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:">
</FileRef>
</Workspace>

+ 8
- 0
AILinkSecretToolDemo/AILinkSecretToolDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist Просмотреть файл

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>

+ 6
- 0
AILinkSecretToolDemo/AILinkSecretToolDemo.xcodeproj/xcuserdata/stevenwu.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist Просмотреть файл

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Bucket
uuid = "CB62D28A-8EEA-44A2-9241-F22EA0BC3FEF"
type = "1"
version = "2.0">
</Bucket>

+ 14
- 0
AILinkSecretToolDemo/AILinkSecretToolDemo/AppDelegate.h Просмотреть файл

@@ -0,0 +1,14 @@
//
// AppDelegate.h
// AILinkSecretToolDemo
//
// Created by steven wu on 2021/4/8.
//

#import <UIKit/UIKit.h>

@interface AppDelegate : UIResponder <UIApplicationDelegate>


@end


+ 40
- 0
AILinkSecretToolDemo/AILinkSecretToolDemo/AppDelegate.m Просмотреть файл

@@ -0,0 +1,40 @@
//
// AppDelegate.m
// AILinkSecretToolDemo
//
// Created by steven wu on 2021/4/8.
//

#import "AppDelegate.h"

@interface AppDelegate ()

@end

@implementation AppDelegate


- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
return YES;
}


#pragma mark - UISceneSession lifecycle


- (UISceneConfiguration *)application:(UIApplication *)application configurationForConnectingSceneSession:(UISceneSession *)connectingSceneSession options:(UISceneConnectionOptions *)options {
// Called when a new scene session is being created.
// Use this method to select a configuration to create the new scene with.
return [[UISceneConfiguration alloc] initWithName:@"Default Configuration" sessionRole:connectingSceneSession.role];
}


- (void)application:(UIApplication *)application didDiscardSceneSessions:(NSSet<UISceneSession *> *)sceneSessions {
// Called when the user discards a scene session.
// If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
// Use this method to release any resources that were specific to the discarded scenes, as they will not return.
}


@end

+ 11
- 0
AILinkSecretToolDemo/AILinkSecretToolDemo/Assets.xcassets/AccentColor.colorset/Contents.json Просмотреть файл

@@ -0,0 +1,11 @@
{
"colors" : [
{
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

+ 98
- 0
AILinkSecretToolDemo/AILinkSecretToolDemo/Assets.xcassets/AppIcon.appiconset/Contents.json Просмотреть файл

@@ -0,0 +1,98 @@
{
"images" : [
{
"idiom" : "iphone",
"scale" : "2x",
"size" : "20x20"
},
{
"idiom" : "iphone",
"scale" : "3x",
"size" : "20x20"
},
{
"idiom" : "iphone",
"scale" : "2x",
"size" : "29x29"
},
{
"idiom" : "iphone",
"scale" : "3x",
"size" : "29x29"
},
{
"idiom" : "iphone",
"scale" : "2x",
"size" : "40x40"
},
{
"idiom" : "iphone",
"scale" : "3x",
"size" : "40x40"
},
{
"idiom" : "iphone",
"scale" : "2x",
"size" : "60x60"
},
{
"idiom" : "iphone",
"scale" : "3x",
"size" : "60x60"
},
{
"idiom" : "ipad",
"scale" : "1x",
"size" : "20x20"
},
{
"idiom" : "ipad",
"scale" : "2x",
"size" : "20x20"
},
{
"idiom" : "ipad",
"scale" : "1x",
"size" : "29x29"
},
{
"idiom" : "ipad",
"scale" : "2x",
"size" : "29x29"
},
{
"idiom" : "ipad",
"scale" : "1x",
"size" : "40x40"
},
{
"idiom" : "ipad",
"scale" : "2x",
"size" : "40x40"
},
{
"idiom" : "ipad",
"scale" : "1x",
"size" : "76x76"
},
{
"idiom" : "ipad",
"scale" : "2x",
"size" : "76x76"
},
{
"idiom" : "ipad",
"scale" : "2x",
"size" : "83.5x83.5"
},
{
"idiom" : "ios-marketing",
"scale" : "1x",
"size" : "1024x1024"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

+ 6
- 0
AILinkSecretToolDemo/AILinkSecretToolDemo/Assets.xcassets/Contents.json Просмотреть файл

@@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}

+ 25
- 0
AILinkSecretToolDemo/AILinkSecretToolDemo/Base.lproj/LaunchScreen.storyboard Просмотреть файл

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13122.16" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13104.12"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="EHf-IW-A2E">
<objects>
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" xcode11CocoaTouchSystemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="53" y="375"/>
</scene>
</scenes>
</document>

+ 59
- 0
AILinkSecretToolDemo/AILinkSecretToolDemo/Base.lproj/Main.storyboard Просмотреть файл

@@ -0,0 +1,59 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="17701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="osP-2y-1PA">
<device id="retina6_1" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17701"/>
<capability name="System colors in document resources" minToolsVersion="11.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--My Table View Controller-->
<scene sceneID="MLu-Ec-AhJ">
<objects>
<tableViewController id="osP-2y-1PA" customClass="MyTableViewController" sceneMemberID="viewController">
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="50" estimatedRowHeight="-1" sectionHeaderHeight="28" sectionFooterHeight="28" id="c6X-Ib-ti7">
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
<prototypes>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" reuseIdentifier="MyCellID" id="phr-mV-z7u">
<rect key="frame" x="0.0" y="28" width="414" height="50"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="phr-mV-z7u" id="nkI-z3-wYW">
<rect key="frame" x="0.0" y="0.0" width="414" height="50"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" tag="1000" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Qo6-2q-f3H">
<rect key="frame" x="0.0" y="0.0" width="414" height="50"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<constraints>
<constraint firstItem="Qo6-2q-f3H" firstAttribute="top" secondItem="nkI-z3-wYW" secondAttribute="top" id="Lmu-3Y-x7i"/>
<constraint firstAttribute="bottom" secondItem="Qo6-2q-f3H" secondAttribute="bottom" id="WW5-hg-gwX"/>
<constraint firstAttribute="trailing" secondItem="Qo6-2q-f3H" secondAttribute="trailing" id="XWz-Wp-L0O"/>
<constraint firstItem="Qo6-2q-f3H" firstAttribute="leading" secondItem="nkI-z3-wYW" secondAttribute="leading" id="mno-aA-hDa"/>
</constraints>
</tableViewCellContentView>
</tableViewCell>
</prototypes>
<connections>
<outlet property="dataSource" destination="osP-2y-1PA" id="Ne4-2B-yqt"/>
<outlet property="delegate" destination="osP-2y-1PA" id="3aE-Pn-sHY"/>
</connections>
</tableView>
</tableViewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="DHp-br-NXW" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="-446" y="49"/>
</scene>
</scenes>
<resources>
<systemColor name="systemBackgroundColor">
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</systemColor>
</resources>
</document>

+ 97
- 0
AILinkSecretToolDemo/AILinkSecretToolDemo/ELBluetoothManager.h Просмотреть файл

@@ -0,0 +1,97 @@
//
// ELBluetoothManager.h
// Elink
//
// Created by iot_user on 2019/4/22.
// Copyright © 2019 iot_iMac. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "ELPeripheralModel.h"
#import <AILinkSecretTool/ELSDKHeader.h>

//MARK:蓝牙通用协议
@protocol ELBluetoothManagerDelegate <NSObject>
@optional

//Callback Bluetooth status(回调蓝牙状态)
-(void)bluetoothManagerUpdateBleState:(ELBluetoothState)state;
//Callback to scanned device(回调扫描到的设备)
-(void)bluetoothManagerScanedPeripherals:(NSArray<ELPeripheralModel *> *_Nonnull)peripherals;

//Callback decrypted transparent data (A7 decrypted payload data)(回调解密后的数据(A7解密后payload数据))
-(void)bluetoothManagerReceiveData:(NSData *_Nonnull)data deviceType:(ELSupportDeviceType)type;

/**
Callback transparent transmission data(回调透传数据)

@param data Transparent data transmission (this data cannot start with A6 or A7)(透传数据(此数据不能以A6或A7开头))
*/
-(void)bluetoothManagerReceivePassData:(NSData *_Nullable)data;

@end



NS_ASSUME_NONNULL_BEGIN

@interface ELBluetoothManager : NSObject

@property (nonatomic, assign, readonly) BOOL isOn;
//Bluetooth status(蓝牙状态)
@property (nonatomic, assign, readonly) ELBluetoothState state;
//version number(版本号)
@property (nonatomic, copy, readonly) NSString *bmVersion;
/**
Save the model corresponding to the currently connected device
保存当前连接的设备对应的模型
*/
@property (nonatomic, strong, readonly) ELPeripheralModel *peripheralModel;
//Bluetooth proxy(蓝牙代理)
@property (nonatomic, weak) id<ELBluetoothManagerDelegate> delegate;


/** 需要搜索与系统绑定的蓝牙设备 */
@property (nonatomic, assign) BOOL needScanBindSysDevice;

//设置appkey和secret
+(void)setAppKey:(NSString *)key appSecret:(NSString *)secret;

//
+(__kindof ELBluetoothManager * _Nonnull)shareManager;

//Start scanning(开始扫描)
-(void)startScan;
//Start scanning all (开始扫描附近所有设备)
- (void)startScanAll;
//Stop scanning(停止扫描)
-(void)stopScan;
//Connecting device(连接设备)
-(void)connectPeripheral:(ELPeripheralModel *)peripheralModel;
//Disconnect device(断开设备)
-(void)disconnectPeripheral;

#pragma mark ============ 发送指令的3种方法 ==============
/**
Shortcut method to send A6 data to BLE(发送A6数据给BLE的快捷方法)
@param data The stitched payload part(拼接好的payload部分)
*/
-(void)sendCmdToMCUWithA6PayloadData:(NSData *)data;
/**
Shortcut method of sending A7 data to MCU(发送A7数据给MCU的快捷方法)
@param data The stitched payload part(拼接好的payload部分)
@param type Equipment type(设备类型)
*/
-(void)sendCmdToMCUWithA7PayloadData:(NSData *)data deviceType:(ELSupportDeviceType)type;

/**
General method of sending data (support data transparent transmission)(发送数据通用方法(支持数据透传))
@param data 数据
*/
-(void)sendData:(NSData *)data;


@end
NS_ASSUME_NONNULL_END


+ 726
- 0
AILinkSecretToolDemo/AILinkSecretToolDemo/ELBluetoothManager.m Просмотреть файл

@@ -0,0 +1,726 @@
//
// ELBluetoothManager.m
// Elink
//
// Created by iot_user on 2019/4/22.
// Copyright © 2019 iot_iMac. All rights reserved.
//

#import "ELBluetoothManager.h"
#import <CoreBluetooth/CoreBluetooth.h>
#import <AILinkSecretTool/ELEncryptTool.h>

//服务UUID
static NSString *const serviceUUID = @"FFE0";//
//APP -> MCU
static NSString *const writeCharactisticUUID = @"FFE1";
//MCU -> APP
static NSString *const notifyCharactisticUUID = @"FFE2";
//APP <-> BLE 二者双向交互的UUID,同时有write和notify
static NSString *const writeAndNotifyCharactisticUUID = @"FFE3";

//握手超时时间
static NSInteger const HandShakeTimeout = 5.0;


@interface ELBluetoothManager()<CBCentralManagerDelegate,CBPeripheralDelegate>

@property (nonatomic, strong) CBCentralManager *centralManager;
//@property (nonatomic, strong) CBPeripheral *peripheral;
@property (nonatomic, strong) CBCharacteristic *notifyCharateristic;//MCU->APP
@property (nonatomic, strong) CBCharacteristic *writeCharateristic; //APP->MCU: A7
@property (nonatomic, strong) CBCharacteristic *notifiWriteCharateristic; //APP <-> BLE: A6


@property (nonatomic, strong) NSMutableArray<ELPeripheralModel *> *peripheralArray;//扫描到的外设


@property (nonatomic, assign) ELBluetoothState state;//蓝牙状态
@property (nonatomic, assign) BOOL isOn;//


///**
// 服务器是否打开蓝牙开关
// */
//@property (nonatomic, assign) BOOL serverOpen;

/**
保存发送给蓝牙的握手指令
*/
@property (nonatomic, strong) NSData *handshake;

/**
保存当前连接的设备对应的模型
*/
@property (nonatomic, strong) ELPeripheralModel *peripheralModel;


@end


@implementation ELBluetoothManager


+(__kindof ELBluetoothManager * _Nonnull)shareManager{
static ELBluetoothManager *manager = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
manager = [[self alloc]init];
});
return manager;
}

-(instancetype)init{
if (self = [super init]) {
[self centralManager];
}
return self;
}

-(CBCentralManager *)centralManager{
if (_centralManager == nil) {
_centralManager = [[CBCentralManager alloc]initWithDelegate:self queue:dispatch_queue_create("BluetoothManagerQueue", DISPATCH_QUEUE_CONCURRENT)];
}
return _centralManager;
}


-(NSMutableArray<ELPeripheralModel *> *)peripheralArray{
if (_peripheralArray == nil) {
_peripheralArray = [[NSMutableArray alloc]init];
}
return _peripheralArray;
}


- (void)setNeedScanBindSysDevice:(BOOL)needScanBindSysDevice {
_needScanBindSysDevice = needScanBindSysDevice;
}

#pragma mark ============ 自定义方法 ==============
-(void)startScan{
if (self.centralManager.state == CBCentralManagerStatePoweredOn) {
[self.peripheralArray removeAllObjects];//移除之前扫描的设备

CBUUID *uuid = [CBUUID UUIDWithString:serviceUUID];//serviceUUID
[self.centralManager scanForPeripheralsWithServices:@[uuid] options:@{CBCentralManagerScanOptionAllowDuplicatesKey:[NSNumber numberWithBool:YES]}];
}else{
NSLog(@"please open bluetooth");
}
}

- (void)startScanAll {
if (self.centralManager.state == CBCentralManagerStatePoweredOn) {
// self.markGetBindDevice = YES;
[self.peripheralArray removeAllObjects];//移除之前扫描的设备
[self.centralManager scanForPeripheralsWithServices:nil options:@{CBCentralManagerScanOptionAllowDuplicatesKey:@(YES)}];
[self respondToSelectorUpdateState:(ELBluetoothStateScaning)];
}else{
NSLog(@"please open bluetooth");
}
}


-(void)stopScan{

[self.peripheralArray removeAllObjects];
[self.centralManager stopScan];
// [self respondToSelectorUpdateState:ELBluetoothStateStopScan];
}

-(void)connectPeripheral:(ELPeripheralModel *)peripheralModel{
[self stopScan];
self.peripheralModel = peripheralModel;

if (self.peripheralModel.peripheral) {
NSLog(@"Start will connect");
[self.centralManager connectPeripheral:self.peripheralModel.peripheral options:nil];
[self respondToSelectorUpdateState:(ELBluetoothStateWillConnect)];
}else{
[self respondToSelectorUpdateState:(ELBluetoothStateConnectFail)];
}
}

-(void)disconnectPeripheral{
[self stopScan];
if (self.peripheralModel.peripheral == nil || self.notifyCharateristic == nil) {
self.centralManager = nil;
return;
}
if (self.centralManager && self.peripheralModel) {
[self.peripheralModel.peripheral setNotifyValue:NO forCharacteristic:self.notifyCharateristic];

if (self.peripheralModel.peripheral) {
[self.centralManager cancelPeripheralConnection:self.peripheralModel.peripheral];
}
}
// self.centralManager = nil;
// [self respondToSelectorUpdateState:ELBluetoothStateDidDisconnect];
}

#pragma mark ============ CBCentralManagerDelegate ==============
//获取蓝牙状态
-(void)centralManagerDidUpdateState:(CBCentralManager *)central{
switch (central.state) {
case CBCentralManagerStatePoweredOn:
{
NSLog(@"Powered On");
break;
}
case CBCentralManagerStatePoweredOff:
NSLog(@"Powered Off");
break;
case CBCentralManagerStateResetting:
NSLog(@"Resetting");
break;
case CBCentralManagerStateUnsupported:
NSLog(@"Unsupported");
break;
case CBCentralManagerStateUnknown:
NSLog(@"Unknown");
break;
case CBCentralManagerStateUnauthorized:
NSLog(@"Unauthorized");
break;
default:
break;
}
if (central.state == CBCentralManagerStatePoweredOn) {
[self startScan];
self.isOn = YES;
[self respondToSelectorUpdateState:ELBluetoothStateAvailable];
}else{
[self stopScan];
self.isOn = NO;
[self respondToSelectorUpdateState:ELBluetoothStateUnavailable];
}
}

//扫描到设备
-(void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary<NSString *,id> *)advertisementData RSSI:(NSNumber *)RSSI{
@synchronized(self) {
//外围制造商数据
NSData *manufactureData = [advertisementData valueForKey:CBAdvertisementDataManufacturerDataKey];
//外围设备名称
NSString *peripheralName = [advertisementData valueForKey:CBAdvertisementDataLocalNameKey];
//服务UUID:所有AILINK设备只使用FFE0、另一个FEE0是蓝牙预留
NSArray *serviceUUIDs = [advertisementData valueForKey:CBAdvertisementDataServiceUUIDsKey];
//Company ID:496e
Byte * byte = (Byte *)[manufactureData bytes];
if ([serviceUUIDs.description rangeOfString:serviceUUID].length ) {
NSLog(@"Scaned AILink bluetooth devices:%@",advertisementData.description);
if (manufactureData.length<14) {
//小于12个byte 说明数据有误
return;
}
if (byte[0] == 0x6e && byte[1] == 0x49) {
//判断是否是我们的AILink设备
//广播数据解析
///<6e49/0001/0001/0001/aabbccddeeff>
//mac地址
NSString * macAddress = [self getMacAddressWithByte:manufactureData];
//设备类型
ELSupportDeviceType deviceType = (byte[2] << 8)+byte[3];
//厂商id
NSInteger vendorID = (byte[4]<<8)+byte[5];
//产品id
NSInteger productID = (byte[6]<<8)+byte[7];
//macXOR
NSUInteger len = manufactureData.length;
NSData *macXOR = [manufactureData subdataWithRange:NSMakeRange(len-6, 6)];
//deviceTypeXOR
NSData *deviceTypeXOR = [manufactureData subdataWithRange:NSMakeRange(2, 2)];
[self addPeriphralWithName:peripheralName withMacAddress:macAddress withRSSI:[RSSI integerValue] withPeripheral:peripheral withVendorID:vendorID withProductID:productID withDeviceType:deviceType withMacXOR:macXOR withDeviceTypeXOR:deviceTypeXOR];
} else {
NSLog(@"Other perpheral = %@",advertisementData.description);
}
}
}
}


//MARK: 回调可连接设备
-(void)addPeriphralWithName:(NSString *)name withMacAddress:(NSString *)mac withRSSI:(NSInteger)rssi withPeripheral:(CBPeripheral *)peripheral withVendorID:(NSInteger)vendorID withProductID:(NSInteger)productID withDeviceType:(ELSupportDeviceType)deviceType withMacXOR:(NSData *)macXOR withDeviceTypeXOR:(NSData *)deviceTypeXOR{
NSArray *array = [self.peripheralArray copy];
for (ELPeripheralModel *model in array) {
if ([model.macAddress isEqualToString:mac]) {
return;
}
}

ELPeripheralModel * model = [[ELPeripheralModel alloc]init];
model.deviceName = name;
model.macAddress = mac;
model.rssi = rssi;
model.peripheral = peripheral;
model.deviceType = deviceType;
model.vendorID = vendorID;
model.productID = productID;
model.macData = macXOR;
model.deviceTypeData = deviceTypeXOR;
[self.peripheralArray addObject:model];
// [self.peripheralArray sortUsingFunction:bluetoothManagerPeriphelRSSIsortUsingFunction context:NULL];
dispatch_async(dispatch_get_main_queue(), ^{
if ([self.delegate respondsToSelector:@selector(bluetoothManagerScanedPeripherals:)]) {
[self.delegate bluetoothManagerScanedPeripherals:[self.peripheralArray copy]];
}

});
}


//MARK: 获取连接类设备mac地址
-(NSString *)getMacAddressWithByte:(NSData *)data{
///<6e49/0001/0001/0001/aabbccddeeff>
//6:6
NSUInteger len = data.length;
Byte *byte = (Byte *)[data bytes];
NSString * macAddress = @"";
//拿到的原始MAC小端序,需要转成大端序
for (NSInteger i=len-1; i>=len-6; i--) {
NSString * mac = [NSString stringWithFormat:@"%02x",byte[i]];
if (i==len-1) {
macAddress = [NSString stringWithFormat:@"%@",mac];
}else{
macAddress = [NSString stringWithFormat:@"%@:%@",macAddress,mac];
}
}
macAddress = [macAddress uppercaseString];
NSLog(@"macAddress===%@",macAddress);
return macAddress;//转成大写
}

//用代理将蓝牙状态回调给外面
-(void)respondToSelectorUpdateState:(ELBluetoothState)state{
dispatch_async(dispatch_get_main_queue(), ^{
self.state = state;
if ([self.delegate respondsToSelector:@selector(bluetoothManagerUpdateBleState:)]) {
[self.delegate bluetoothManagerUpdateBleState:state];
}
});
}

//与外设连接成功
-(void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral{
NSLog(@"Connected:%@",peripheral.name);
self.peripheralModel.peripheral.delegate = self;
//发现服务UUID
// [self.peripheralModel.peripheral discoverServices:@[[CBUUID UUIDWithString:serviceUUID]]];

[self.peripheralModel.peripheral discoverServices:nil];
[self respondToSelectorUpdateState:(ELBluetoothStateDidConnect)];
// [peripheral discoverServices:nil];
}

//与外设连接失败
-(void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error{
NSLog(@"Connect error:%@",error);
self.centralManager = nil;
self.peripheralModel = nil;
[self.peripheralArray removeAllObjects];
[self respondToSelectorUpdateState:(ELBluetoothStateConnectFail)];
}

-(void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error{
NSLog(@"didDisconnectPeripheral:%@",error);
//
self.centralManager = nil;
//
self.peripheralModel = nil;
[self.peripheralArray removeAllObjects];
[self respondToSelectorUpdateState:(ELBluetoothStateDidDisconnect)];
}

#pragma mark ============ CBPeripheralDelegate ==============
//外设发现服务回调
-(void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error{
NSLog(@"didDiscoverServices = %@",peripheral.description);
for (CBService *service in peripheral.services) {
[self.peripheralModel.peripheral discoverCharacteristics:nil forService:service];
}
}

//外设发现特征回调
-(void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(nonnull CBService *)service error:(nullable NSError *)error{
NSLog(@"didDiscoverCharacteristicsForService = %@",service.description);
if ([service.UUID.UUIDString containsString:serviceUUID]) {
for (CBCharacteristic *characteristic in service.characteristics) {
if (characteristic.properties & CBCharacteristicPropertyNotify) {
[peripheral setNotifyValue:YES forCharacteristic:characteristic];
}
if ([characteristic.UUID.UUIDString containsString:notifyCharactisticUUID]) {
self.notifyCharateristic = characteristic;
}
if ([characteristic.UUID.UUIDString containsString:writeCharactisticUUID]) {
self.writeCharateristic = characteristic;
}
if ([characteristic.UUID.UUIDString containsString:writeAndNotifyCharactisticUUID]) {
self.notifiWriteCharateristic = characteristic;
}
[self respondToSelectorUpdateState:(ELBluetoothStateDidDiscoverCharacteristics)];
}
}
}

-(void)peripheral:(CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error{
NSLog(@"characteristic.isNotifying:%@",characteristic);

if (characteristic.isNotifying) {
//MARK:发送握手指令
if ([characteristic.UUID.UUIDString containsString:writeAndNotifyCharactisticUUID]) {

//开始握手:app主动发送握手指令
self.handshake = [ELEncryptTool handshake];
[self sendData:self.handshake];
//app开始握手5s后,蓝牙不回复,则不是合法蓝牙模组,直接断开超时
[self performSelector:@selector(disconnectPeripheral) withObject:nil afterDelay:HandShakeTimeout];
}
}else{
//没有,断开
[self.centralManager cancelPeripheralConnection:self.peripheralModel.peripheral];
}

}

-(void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error{
//NSLog(@"---didUpdateValueForCharacteristic:%@",characteristic.value);
NSData *data = characteristic.value;
Byte * dataByte = (Byte *)[data bytes];
//MARK:校验和
if ([self.class checksum:data]) {
dispatch_async(dispatch_get_main_queue(), ^{
if (dataByte[0] == ELInetBleDataPackHead_A6) { //A6透传指令(明文,不需要解密)
NSLog(@"->app(A6_1):%@",data);

//MARK:Inet指令
[self analyzeBLEBackA6Data:data];
}
else if (dataByte[0] == ELInetBleDataPackHead_A7){ //A7透传指令
//NSLog(@"->app(A7加密数据):%@",data); //这是加密数据,打印没什么用
[self analyzeMCUBackA7Data:data];
}else {
//透传数据
NSLog(@"->app(透传数据):%@",data);
if ([self.delegate respondsToSelector:@selector(bluetoothManagerReceivePassData:)]) {
[self.delegate bluetoothManagerReceivePassData:data];
}

}
});
}else{
}
}



#pragma mark ============ 解密A7(MCU)原始数据并回调给子类处理 ==============
-(void)analyzeMCUBackA7Data:(NSData *)data {
Byte * dataByte = (Byte *)[data bytes];
if (data.length<7) {
//数据小于7个长度,丢掉
NSLog(@"->app: 数据小于7个长度,丢掉:%@",data);
}else{
ELSupportDeviceType deviceType = (dataByte[1]<<8) + dataByte[2];
NSData *originData = [data subdataWithRange:NSMakeRange(4, data.length-6)];
//对数据进行解密
NSData *encryptData = [ELEncryptTool encryptXOR:self.peripheralModel.macData deviceTypeXOR:self.peripheralModel.deviceTypeData withXORData:originData];
//回调A7解密后的透传数据:第4到第data.length-3个数据需要解密
if ([self.delegate respondsToSelector:@selector(bluetoothManagerReceiveData:deviceType:)]) {
[self.delegate bluetoothManagerReceiveData:encryptData deviceType:deviceType];
}

//以下仅仅是打印使用: A7协议是公开的(重新计算校验Byte)
NSUInteger sum = dataByte[1] + dataByte[2] + encryptData.length;
Byte *bytes = (Byte *)encryptData.bytes;
for (int i = 0; i < encryptData.length; i++) {
sum = sum + bytes[i];
}
Byte checksum[1] = {sum & 0xff}; //从新计算校验核: payload + 2Byte设备类型 + payload长度

NSMutableData *dataM = [NSMutableData dataWithData:data];
[dataM replaceBytesInRange:NSMakeRange(4, data.length-6) withBytes:encryptData.bytes]; //替换payload
[dataM replaceBytesInRange:NSMakeRange(data.length-2, 1) withBytes:checksum]; //替换倒数第2个Byte校验和
NSLog(@"mcu->app(A7_1): %@",dataM.copy);
}
}

#pragma mark ============ 解析A6(BLE模块)回调数据 ==============
-(void)analyzeBLEBackA6Data:(NSData *)data{
Byte * dataByte = (Byte *)[data bytes];
//数据类型
Byte type = dataByte[2];
if (type == ELInetGetCmdTypeGetHandshake){ //MARK:收到ble握手数据
//取消app握手超时
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(disconnectPeripheral) object:nil];
//预留500ms给蓝牙校验app,等蓝牙握手成功后再回调验证成功
[self performSelector:@selector(sureDidValidationPass) withObject:nil afterDelay:0.5];
} else if (type == ELInetSetCmdTypeSetHandshake){ //MARK:收到蓝牙发送的校验数据,加密后发给蓝牙
//对蓝牙返回的20Byte随机数进行加密,加密后发送给蓝牙
NSData *sendData = [ELEncryptTool blueToothHandshakeWithData:data];
[self sendData:sendData];
} else {
//其他A6指令
}
}



-(void)sureDidValidationPass{
[self respondToSelectorUpdateState:(ELBluetoothStateDidValidationPass)];
//双向握手成功后,才能同步时间
[self setMCUNowDateWithEnable:YES];
}

#pragma mark ============ 发送指令的2种方法 ==============

-(void)setMCUNowDateWithEnable:(BOOL)enable{
NSDate *theDate = [NSDate date];
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
//公历
[formatter setLocale:[NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"]];
[formatter setDateFormat:@"yyyy"];
NSString * yearStr = [formatter stringFromDate:theDate];
//month
[formatter setDateFormat:@"MM"];
NSString * monthStr = [formatter stringFromDate:theDate];
//
//day
[formatter setDateFormat:@"dd"];
NSString * dayStr = [formatter stringFromDate:theDate];
//hour
[formatter setDateFormat:@"HH"];
NSString *hourStr = [formatter stringFromDate:theDate];
//min
[formatter setDateFormat:@"mm"];
NSString *minStr = [formatter stringFromDate:theDate];
//sec
[formatter setDateFormat:@"ss"];
NSString *secStr = [formatter stringFromDate:theDate];
int year = [yearStr intValue];
int month = [monthStr intValue];
int day = [dayStr intValue];
int hour = [hourStr intValue];
int min = [minStr intValue];
int sec = [secStr intValue];
Byte dateByte[8] ={0x00};
dateByte[0] = ELInetSetCmdTypeSetMCUNowDate;
dateByte[1] = enable;
dateByte[2] = year - 2000;
dateByte[3] = month;
dateByte[4] = day;
dateByte[5] = hour;
dateByte[6] = min;
dateByte[7] = sec;
NSData *playload = [[NSData alloc] initWithBytes:dateByte length:sizeof(dateByte)];
[self sendCmdToMCUWithA6PayloadData:playload];
}

-(void)sendCmdToMCUWithA6PayloadData:(NSData * _Nonnull)data{
if (data.length>16) {
NSLog(@"The length of data sent should be less than 16 bytes");
return;
}else{
///<a6 01 69 6a 6a>
Byte inetByte[20] = {0};
//Inet指令:0xA6
inetByte[0] = ELInetBleDataPackHead_A6;
Byte *dataByte = (Byte *)[data bytes];
NSInteger len = data.length;
//Payload长度
inetByte[1] = len;
//校验和:1~n-2位,n是数据总长度
inetByte[len+2] = inetByte[1];
//给2+i位byte赋值
for (int i=0; i<len; i++) {
inetByte[i+2] = dataByte[i];
//校验和累加
inetByte[len+2] += dataByte[i];
}
//总的数据长度
NSInteger sendLength = 2+len+2;
//固定值
inetByte[sendLength-1] = ELInetBleDataPackTail_6A;
NSData * sendData = [[NSData alloc]initWithBytes:inetByte length:sendLength];
[self sendData:sendData];
}
}



-(void)sendCmdToMCUWithA7PayloadData:(NSData *)data deviceType:(ELSupportDeviceType)type{
NSLog(@"->ble(A7_p):%@",data);

NSData *macData = [self.peripheralModel.macData mutableCopy];
NSData *typeData = [self.peripheralModel.deviceTypeData mutableCopy];
if (data.length>14 || macData.length!=6 || typeData.length != 2) {
return;
}else{
//
Byte inetByte[20] = {0};
inetByte[0] = ELInetBleDataPackHead_A7;
//设备类型
//0x0001
//0xff00
inetByte[1] = (type & 0xFF00)>>8;
inetByte[2] = type & 0xFF;
//Payload长度(最大14byte)
NSInteger len = data.length;
inetByte[3] = len;
//A7000102 1122367A
//校验和
inetByte[len+4] = inetByte[1] + inetByte[2] +inetByte[3];

//MARK:对A7的payload 数据进行XOR加密
data = [ELEncryptTool encryptXOR:macData deviceTypeXOR:typeData withXORData:data];
Byte *dataByte = (Byte *)[data bytes];
for (int i=0; i<len; i++) {
inetByte[4+i] = dataByte[i];
inetByte[len+4] += dataByte[i];
}


//总数据长度
NSInteger sendLen = 4+len+2;
//固定值
inetByte[sendLen-1] = ELInetBleDataPackTail_7A;
NSData * sendData = [[NSData alloc]initWithBytes:inetByte length:sendLen];
[self sendData:sendData];
}
}

#pragma mark ============ 发指令队列(A6/A7都走这里) ==============
//MARK:发送数据
-(void)sendData:(NSData *)data{

Byte *dataByte = (Byte *)[data bytes];
if (dataByte[0]==ELInetBleDataPackHead_A7) {
//MARK:发送A7数据
if (self.writeCharateristic && self.peripheralModel.peripheral) {
[self.peripheralModel.peripheral writeValue:data forCharacteristic:self.writeCharateristic type:(CBCharacteristicWriteWithoutResponse)];
NSLog(@"->ble(A7) send success:%@",data);
}else{
NSLog(@"->ble(A7) send failure:%@",data);
}
}
else if (dataByte[0] == ELInetBleDataPackHead_A6){
//MARK:发送A6数据
if (self.notifiWriteCharateristic && self.peripheralModel.peripheral) {
[self.peripheralModel.peripheral writeValue:data forCharacteristic:self.notifiWriteCharateristic type:(CBCharacteristicWriteWithoutResponse)];
NSLog(@"->ble(A6_1):%@",data);
}else{
NSLog(@"->ble(A6_0):%@",data);
}
}
else{
//MARK:发送透传数据
if (self.writeCharateristic && self.peripheralModel.peripheral) {
[self.peripheralModel.peripheral writeValue:data forCharacteristic:self.writeCharateristic type:(CBCharacteristicWriteWithoutResponse)];
NSLog(@"->ble(Passthrough data) send success:%@",data);
}else{
NSLog(@"->ble(Passthrough data) send failure:%@",data);
}
}

}


#pragma mark ============ 校验核 ==============
//MARK:校验和
+(BOOL)checksum:(NSData *)data{
if (data.length <= 3) { //至少要4个byte才解析
return NO;
}

Byte *dataByte = (Byte *)[data bytes];
NSUInteger location;
if (dataByte[0] == ELInetBleDataPackHead_A6 && dataByte[1] == 0x11 && (dataByte[2] == ELInetGetCmdTypeGetHandshake || dataByte[2] == ELInetSetCmdTypeSetHandshake)) {
//握手指令,从第0位校验到倒数第二位
///<a6/ 112330 44f7b4d3 496731cf bfc8062b 9382ef /92>
location = 1;
}else{
//其他数据,从第0位校验到倒数第三位
///<a7 /000002 6a5a/ c67a>
location = 2;
}
if ( data.length < (2+location) ) {
return NO;
}
NSUInteger len = data.length;//数据长度
Byte checksum = 0;//校验和
//00 00 00
for (int i = 1; i<len-location; i++) {
checksum += dataByte[i];
}
if (checksum == dataByte[len-location]) {
return YES;
}else{
return NO;
}
}




@end

+ 89
- 0
AILinkSecretToolDemo/AILinkSecretToolDemo/ELPeripheralModel.h Просмотреть файл

@@ -0,0 +1,89 @@
//
// ELPeripheralModel.h
// Elink
//
// Created by iot_user on 2019/4/22.
// Copyright © 2019 iot_iMac. All rights reserved.
//

#import <Foundation/Foundation.h>
#import <CoreBluetooth/CoreBluetooth.h>
#import <AILinkSecretTool/ELSDKHeader.h>



NS_ASSUME_NONNULL_BEGIN

/**
Bluetooth peripheral out model(蓝牙扫描出来的外设模型)
*/
@interface ELPeripheralModel : NSObject
/**
CID
*/
@property (nonatomic, assign) ELSupportDeviceType deviceType;

/**
VID
*/
@property (nonatomic, assign) NSInteger vendorID;

/**
PID
*/
@property (nonatomic, assign) NSInteger productID;
@property (nonatomic, copy) NSString *deviceName;
@property (nonatomic, copy) NSString *macAddress;

@property (nonatomic, assign) NSInteger rssi;
@property (nonatomic, strong) CBPeripheral *peripheral;

/**
6 bytes: small endian(6个byte:小端序)
*/
@property (nonatomic, copy) NSData *macData;

/**
2 bytes
*/
@property (nonatomic, copy) NSData *deviceTypeData;



/** Device with unit: support unit string
     Unitless equipment
        Smart Door Lock: Supported unlock type
有单位的设备:支持单位字符串
无单位的设备
智能门锁:支持的开锁类型
*/
@property (nonatomic, copy) NSString *supportUnit;

/** Device version numbe(设备版本号) */
@property (nonatomic, copy) NSString *version;

/**
* 华盛达手表要用这个属性: 是否已经跟系统配对
*/
@property(nonatomic, assign) BOOL paired;

/** 广播秤的广播数据 */
@property (nonatomic, strong) NSData *manufactureData;

/**
Screening equipment(筛选设备)

@param peripherals All devices scanned by the parent class(父类扫描到的所有设备)
@param type Equipment type(设备类型)
@return Array of corresponding devices(对应设备的数组)
*/
+(NSArray<ELPeripheralModel *> *)getDevicesWithPeripherals:(NSArray<__kindof ELPeripheralModel *> *)peripherals supportDeviceType:(ELSupportDeviceType)type;

//MARK:Screen multiple devices(筛选多个设备)
+(NSArray<ELPeripheralModel *> *)getDevicesWithPeripherals:(NSArray<__kindof ELPeripheralModel *> *)peripherals supportDeviceTypes:(NSArray<NSNumber *> *)types;

//Descending order(降序)
-(NSComparisonResult)compareRSSI:(ELPeripheralModel *)model;
@end

NS_ASSUME_NONNULL_END

+ 48
- 0
AILinkSecretToolDemo/AILinkSecretToolDemo/ELPeripheralModel.m Просмотреть файл

@@ -0,0 +1,48 @@
//
// ELPeripheralModel.m
// Elink
//
// Created by iot_user on 2019/4/22.
// Copyright © 2019 iot_iMac. All rights reserved.
//

#import "ELPeripheralModel.h"

@implementation ELPeripheralModel
-(void)setDeviceTypeData:(NSData *)deviceTypeData{
_deviceTypeData = deviceTypeData;
}
//MARK:筛选设备
+(NSArray<ELPeripheralModel *> *)getDevicesWithPeripherals:(NSArray<__kindof ELPeripheralModel *> *)peripherals supportDeviceType:(ELSupportDeviceType)type{
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"deviceType == %ld",type];
NSArray *devices = [peripherals filteredArrayUsingPredicate:predicate];
return devices;
}
//MARK:筛选多个设备
+(NSArray<ELPeripheralModel *> *)getDevicesWithPeripherals:(NSArray<__kindof ELPeripheralModel *> *)peripherals supportDeviceTypes:(NSArray<NSNumber *> *)types{
NSString *predicateStr;
if (types.count == 0) {
return peripherals;
}
for (NSNumber *num in types) {
ELSupportDeviceType type = [num integerValue];
if (predicateStr.length==0) {
predicateStr = [NSString stringWithFormat:@"deviceType == %ld",type];
}else{
predicateStr = [NSString stringWithFormat:@"%@ or deviceType == %ld",predicateStr,type];
}
}

NSPredicate *predicate = [NSPredicate predicateWithFormat:predicateStr];
NSArray *devices = [peripherals filteredArrayUsingPredicate:predicate];
return devices;
}

-(NSComparisonResult)compareRSSI:(ELPeripheralModel *)model{
NSNumber *number1 = [NSNumber numberWithInteger:self.rssi];
NSNumber *number2 = [NSNumber numberWithInteger:model.rssi];
NSComparisonResult result = [number1 compare:number2];
return result == NSOrderedAscending;//NSOrderedDescending
}
@end

+ 68
- 0
AILinkSecretToolDemo/AILinkSecretToolDemo/Info.plist Просмотреть файл

@@ -0,0 +1,68 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UIApplicationSceneManifest</key>
<dict>
<key>UIApplicationSupportsMultipleScenes</key>
<false/>
<key>UISceneConfigurations</key>
<dict>
<key>UIWindowSceneSessionRoleApplication</key>
<array>
<dict>
<key>UISceneConfigurationName</key>
<string>Default Configuration</string>
<key>UISceneDelegateClassName</key>
<string>SceneDelegate</string>
<key>UISceneStoryboardFile</key>
<string>Main</string>
</dict>
</array>
</dict>
</dict>
<key>UIApplicationSupportsIndirectInputEvents</key>
<true/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>NSBluetoothAlwaysUsageDescription</key>
<string>connect ble device</string>
</dict>
</plist>

+ 16
- 0
AILinkSecretToolDemo/AILinkSecretToolDemo/MyTableViewController.h Просмотреть файл

@@ -0,0 +1,16 @@
//
// MyTableViewController.h
// AILinkSecretToolDemo
//
// Created by steven wu on 2021/4/14.
//

#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

@interface MyTableViewController : UITableViewController

@end

NS_ASSUME_NONNULL_END

+ 103
- 0
AILinkSecretToolDemo/AILinkSecretToolDemo/MyTableViewController.m Просмотреть файл

@@ -0,0 +1,103 @@
//
// MyTableViewController.m
// AILinkSecretToolDemo
//
// Created by steven wu on 2021/4/14.
//

#import "MyTableViewController.h"
#import "ELBluetoothManager.h"

@interface MyTableViewController ()<ELBluetoothManagerDelegate>

@property (nonatomic, strong) NSArray<ELPeripheralModel *> *devices;

@end

@implementation MyTableViewController

- (void)viewDidLoad {
[super viewDidLoad];
[ELBluetoothManager shareManager].delegate = self;
}

#pragma mark ============ ELBluetoothManagerDelegate ==============
-(void)bluetoothManagerUpdateBleState:(ELBluetoothState)state {
if (state == ELBluetoothStateAvailable) {
[[ELBluetoothManager shareManager] startScan];
}
}

-(void)bluetoothManagerScanedPeripherals:(NSArray<ELPeripheralModel *> *_Nonnull)peripherals {
self.devices = peripherals;
[self.tableView reloadData];
}

#pragma mark - Table view data source

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.devices.count;
}


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"MyCellID" forIndexPath:indexPath];
UILabel *label = [cell.contentView viewWithTag:1000];
ELPeripheralModel *model = self.devices[indexPath.row];
label.text = [NSString stringWithFormat:@"%@(%@)",model.deviceName,model.macAddress];
return cell;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
ELPeripheralModel *model = self.devices[indexPath.row];
[[ELBluetoothManager shareManager] connectPeripheral:model];
}

/*
// Override to support conditional editing of the table view.
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
// Return NO if you do not want the specified item to be editable.
return YES;
}
*/

/*
// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
// Delete the row from the data source
[tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
} else if (editingStyle == UITableViewCellEditingStyleInsert) {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
}
}
*/

/*
// Override to support rearranging the table view.
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath {
}
*/

/*
// Override to support conditional rearranging of the table view.
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath {
// Return NO if you do not want the item to be re-orderable.
return YES;
}
*/

/*
#pragma mark - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/

@end

+ 15
- 0
AILinkSecretToolDemo/AILinkSecretToolDemo/SceneDelegate.h Просмотреть файл

@@ -0,0 +1,15 @@
//
// SceneDelegate.h
// AILinkSecretToolDemo
//
// Created by steven wu on 2021/4/8.
//

#import <UIKit/UIKit.h>

@interface SceneDelegate : UIResponder <UIWindowSceneDelegate>

@property (strong, nonatomic) UIWindow * window;

@end


+ 57
- 0
AILinkSecretToolDemo/AILinkSecretToolDemo/SceneDelegate.m Просмотреть файл

@@ -0,0 +1,57 @@
//
// SceneDelegate.m
// AILinkSecretToolDemo
//
// Created by steven wu on 2021/4/8.
//

#import "SceneDelegate.h"

@interface SceneDelegate ()

@end

@implementation SceneDelegate


- (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions {
// Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
// If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
// This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
}


- (void)sceneDidDisconnect:(UIScene *)scene {
// Called as the scene is being released by the system.
// This occurs shortly after the scene enters the background, or when its session is discarded.
// Release any resources associated with this scene that can be re-created the next time the scene connects.
// The scene may re-connect later, as its session was not necessarily discarded (see `application:didDiscardSceneSessions` instead).
}


- (void)sceneDidBecomeActive:(UIScene *)scene {
// Called when the scene has moved from an inactive state to an active state.
// Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
}


- (void)sceneWillResignActive:(UIScene *)scene {
// Called when the scene will move from an active state to an inactive state.
// This may occur due to temporary interruptions (ex. an incoming phone call).
}


- (void)sceneWillEnterForeground:(UIScene *)scene {
// Called as the scene transitions from the background to the foreground.
// Use this method to undo the changes made on entering the background.
}


- (void)sceneDidEnterBackground:(UIScene *)scene {
// Called as the scene transitions from the foreground to the background.
// Use this method to save data, release shared resources, and store enough scene-specific state information
// to restore the scene back to its current state.
}


@end

+ 18
- 0
AILinkSecretToolDemo/AILinkSecretToolDemo/main.m Просмотреть файл

@@ -0,0 +1,18 @@
//
// main.m
// AILinkSecretToolDemo
//
// Created by steven wu on 2021/4/8.
//

#import <UIKit/UIKit.h>
#import "AppDelegate.h"

int main(int argc, char * argv[]) {
NSString * appDelegateClassName;
@autoreleasepool {
// Setup code that might create autoreleased objects goes here.
appDelegateClassName = NSStringFromClass([AppDelegate class]);
}
return UIApplicationMain(argc, argv, nil, appDelegateClassName);
}

+ 103
- 0
ReadMe.md Просмотреть файл

@@ -0,0 +1,103 @@
# AILinkSecretTool_iOS



### 1. Usage description
AILinkSecretTool.framework is a Bluetooth encryption and decryption toolkit developed using ObjectiveC on the iOS platform. The development toolkit can scan and connect to smart devices using AILink Bluetooth module, and is responsible for the handshake between App and Bluetooth module and the encryption and decryption of A7 data. .

### 2. Necessary condition
+ 1. Acquired AILink Bluetooth communication protocol
+ 2. Have smart devices that support AILink Bluetooth module
+ 3. Have knowledge of iOS native development and debugging

### 3. Applicable conditions
+ 1. Develop your own native platform app
+ 2. Use RN, Uniapp, Flutter and other cross-platform technologies to develop apps

### 4. SDK interface
```

@interface ELEncryptTool: NSObject

/**
The app sends this A6 data to actively start a handshake with ble
*/
+(NSData *)handshake;

/**
This method encrypts the A6 data of the ble test app and sends the app to the device, otherwise the device will disconnect the app
*/
+(NSData *)blueToothHandshakeWithData:(NSData *)receiveData;


/**
A7 data encryption/decryption method
*/
+ (NSData *)encryptXOR:(NSData *)macXOR deviceTypeXOR:(NSData *)deviceTypeXOR withXORData:(NSData *)dataXOR;

@end

```

### 5. How to use

For specific usage, please refer to AILinkSecretToolDemo




-------------------------------------------


#AILinkSecretTool_iOS


### 一、用途说明
AILinkSecretTool.framework是在iOS平台使用ObjectiveC开发的蓝牙加解密工具包,该开发工具包能够扫描、连接使用AILink蓝牙模组的智能设备,负责App与蓝牙模组之间的握手与A7数据的加解密。

### 二、必备条件
+ 1. 已获取AILink蓝牙通讯协议
+ 2. 拥有支持AILink蓝牙模块的智能设备
+ 3. 具备iOS原生开发和调试知识

### 三、适用场景
+ 1. 开发自己的原生平台app
+ 2. 使用RN、Uniapp、Flutter等跨平台技术开发app

### 四、SDK提供接口
```

@interface ELEncryptTool : NSObject

/**
app发送此A6数据主动开始与ble进行握手
*/
+(NSData *)handshake;

/**
此方法将ble检验app的A6数据进行加密,app发给设备,否则设备将断开app
*/
+(NSData *)blueToothHandshakeWithData:(NSData *)receiveData;


/**
A7数据加/解密方法
*/
+ (NSData *)encryptXOR:(NSData *)macXOR deviceTypeXOR:(NSData *)deviceTypeXOR withXORData:(NSData *)dataXOR;


@end

```

### 五、使用方法

具体用法详见AILinkSecretToolDemo






Загрузка…
Отмена
Сохранить