| @@ -22,6 +22,14 @@ | |||
| 78DC4DF62990FB40006C6911 /* ELDeviceScanCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 78DC4DF02990FB40006C6911 /* ELDeviceScanCell.xib */; }; | |||
| 78DC4DFB2990FC10006C6911 /* HeightBodyFatScaleVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 78DC4DF82990FC10006C6911 /* HeightBodyFatScaleVC.m */; }; | |||
| 78DC4DFC2990FC10006C6911 /* HeightBodyFatScaleVC.xib in Resources */ = {isa = PBXBuildFile; fileRef = 78DC4DF92990FC10006C6911 /* HeightBodyFatScaleVC.xib */; }; | |||
| 78E07B6A2A49664000E68200 /* BroadcastHeightGuage.m in Sources */ = {isa = PBXBuildFile; fileRef = 78E07B672A49663F00E68200 /* BroadcastHeightGuage.m */; }; | |||
| 78E07B6B2A49664000E68200 /* BroadcastHeightGuage.xib in Resources */ = {isa = PBXBuildFile; fileRef = 78E07B682A49663F00E68200 /* BroadcastHeightGuage.xib */; }; | |||
| 78E07B7A2A49664E00E68200 /* MeatProbeVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 78E07B6D2A49664D00E68200 /* MeatProbeVC.m */; }; | |||
| 78E07B7B2A49664E00E68200 /* MeatProbeVC.xib in Resources */ = {isa = PBXBuildFile; fileRef = 78E07B6E2A49664D00E68200 /* MeatProbeVC.xib */; }; | |||
| 78E07B7C2A49664E00E68200 /* ELAILinkBleManager+MeatProbeBox.m in Sources */ = {isa = PBXBuildFile; fileRef = 78E07B742A49664E00E68200 /* ELAILinkBleManager+MeatProbeBox.m */; }; | |||
| 78E07B7D2A49664E00E68200 /* ELMeatProbeBoxBleParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 78E07B752A49664E00E68200 /* ELMeatProbeBoxBleParser.m */; }; | |||
| 78E07B7E2A49664E00E68200 /* MeatProbeBoxVC.xib in Resources */ = {isa = PBXBuildFile; fileRef = 78E07B782A49664E00E68200 /* MeatProbeBoxVC.xib */; }; | |||
| 78E07B7F2A49664E00E68200 /* MeatProbeBoxVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 78E07B792A49664E00E68200 /* MeatProbeBoxVC.m */; }; | |||
| 952D19A1276DE80000ED3A0C /* AILinkBleSDK.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 952D19A0276DE80000ED3A0C /* AILinkBleSDK.framework */; }; | |||
| 95565B792786EA3B000265EA /* SkipConnectionViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 95565B752786EA3B000265EA /* SkipConnectionViewController.m */; }; | |||
| 95565B7A2786EA3B000265EA /* SkipScanViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 95565B782786EA3B000265EA /* SkipScanViewController.m */; }; | |||
| @@ -133,6 +141,20 @@ | |||
| 78DC4DF82990FC10006C6911 /* HeightBodyFatScaleVC.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HeightBodyFatScaleVC.m; sourceTree = "<group>"; }; | |||
| 78DC4DF92990FC10006C6911 /* HeightBodyFatScaleVC.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = HeightBodyFatScaleVC.xib; sourceTree = "<group>"; }; | |||
| 78DC4DFA2990FC10006C6911 /* HeightBodyFatScaleVC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HeightBodyFatScaleVC.h; sourceTree = "<group>"; }; | |||
| 78E07B672A49663F00E68200 /* BroadcastHeightGuage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BroadcastHeightGuage.m; sourceTree = "<group>"; }; | |||
| 78E07B682A49663F00E68200 /* BroadcastHeightGuage.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = BroadcastHeightGuage.xib; sourceTree = "<group>"; }; | |||
| 78E07B692A49663F00E68200 /* BroadcastHeightGuage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BroadcastHeightGuage.h; sourceTree = "<group>"; }; | |||
| 78E07B6D2A49664D00E68200 /* MeatProbeVC.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MeatProbeVC.m; sourceTree = "<group>"; }; | |||
| 78E07B6E2A49664D00E68200 /* MeatProbeVC.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MeatProbeVC.xib; sourceTree = "<group>"; }; | |||
| 78E07B6F2A49664D00E68200 /* MeatProbeVC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MeatProbeVC.h; sourceTree = "<group>"; }; | |||
| 78E07B722A49664E00E68200 /* ELMeatProbeBoxBleParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ELMeatProbeBoxBleParser.h; sourceTree = "<group>"; }; | |||
| 78E07B732A49664E00E68200 /* ELMeatProbeBoxBleHeader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ELMeatProbeBoxBleHeader.h; sourceTree = "<group>"; }; | |||
| 78E07B742A49664E00E68200 /* ELAILinkBleManager+MeatProbeBox.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "ELAILinkBleManager+MeatProbeBox.m"; sourceTree = "<group>"; }; | |||
| 78E07B752A49664E00E68200 /* ELMeatProbeBoxBleParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ELMeatProbeBoxBleParser.m; sourceTree = "<group>"; }; | |||
| 78E07B762A49664E00E68200 /* ELAILinkBleManager+MeatProbeBox.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ELAILinkBleManager+MeatProbeBox.h"; sourceTree = "<group>"; }; | |||
| 78E07B772A49664E00E68200 /* MeatProbeBoxVC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MeatProbeBoxVC.h; sourceTree = "<group>"; }; | |||
| 78E07B782A49664E00E68200 /* MeatProbeBoxVC.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MeatProbeBoxVC.xib; sourceTree = "<group>"; }; | |||
| 78E07B792A49664E00E68200 /* MeatProbeBoxVC.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MeatProbeBoxVC.m; sourceTree = "<group>"; }; | |||
| 952D19A0276DE80000ED3A0C /* AILinkBleSDK.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = AILinkBleSDK.framework; sourceTree = "<group>"; }; | |||
| 95565B752786EA3B000265EA /* SkipConnectionViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SkipConnectionViewController.m; sourceTree = "<group>"; }; | |||
| 95565B762786EA3B000265EA /* SkipScanViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SkipScanViewController.h; sourceTree = "<group>"; }; | |||
| @@ -309,6 +331,7 @@ | |||
| 955725E0276C38CC003BFBAC /* 04_BabyScale */, | |||
| 955725BA276C38CC003BFBAC /* 05_BloodPressure */, | |||
| 955725E5276C38CC003BFBAC /* 06_HeightGuage */, | |||
| 78E07B662A49663F00E68200 /* 06B_BroadcastHeightGuage */, | |||
| 9557261E276C38CD003BFBAC /* 07_RemoteControl */, | |||
| 95572614276C38CD003BFBAC /* 08_Forehead */, | |||
| 955725F9276C38CD003BFBAC /* 09_Thermometer */, | |||
| @@ -329,6 +352,8 @@ | |||
| 955725F4276C38CD003BFBAC /* 23_FaceMask */, | |||
| 95565B742786EA3B000265EA /* 24_Skip */, | |||
| 78DC4DF72990FC10006C6911 /* 25_HeightBodyFatScale */, | |||
| 78E07B6C2A49664D00E68200 /* 26_MeatProbe */, | |||
| 78E07B702A49664E00E68200 /* 27_MeatProbeBox */, | |||
| ); | |||
| path = DeviceDemo; | |||
| sourceTree = "<group>"; | |||
| @@ -395,6 +420,49 @@ | |||
| path = AILinkBleSDKDemo/DeviceDemo/25_HeightBodyFatScale; | |||
| sourceTree = SOURCE_ROOT; | |||
| }; | |||
| 78E07B662A49663F00E68200 /* 06B_BroadcastHeightGuage */ = { | |||
| isa = PBXGroup; | |||
| children = ( | |||
| 78E07B692A49663F00E68200 /* BroadcastHeightGuage.h */, | |||
| 78E07B672A49663F00E68200 /* BroadcastHeightGuage.m */, | |||
| 78E07B682A49663F00E68200 /* BroadcastHeightGuage.xib */, | |||
| ); | |||
| path = 06B_BroadcastHeightGuage; | |||
| sourceTree = "<group>"; | |||
| }; | |||
| 78E07B6C2A49664D00E68200 /* 26_MeatProbe */ = { | |||
| isa = PBXGroup; | |||
| children = ( | |||
| 78E07B6F2A49664D00E68200 /* MeatProbeVC.h */, | |||
| 78E07B6D2A49664D00E68200 /* MeatProbeVC.m */, | |||
| 78E07B6E2A49664D00E68200 /* MeatProbeVC.xib */, | |||
| ); | |||
| path = 26_MeatProbe; | |||
| sourceTree = "<group>"; | |||
| }; | |||
| 78E07B702A49664E00E68200 /* 27_MeatProbeBox */ = { | |||
| isa = PBXGroup; | |||
| children = ( | |||
| 78E07B712A49664E00E68200 /* Ble */, | |||
| 78E07B772A49664E00E68200 /* MeatProbeBoxVC.h */, | |||
| 78E07B792A49664E00E68200 /* MeatProbeBoxVC.m */, | |||
| 78E07B782A49664E00E68200 /* MeatProbeBoxVC.xib */, | |||
| ); | |||
| path = 27_MeatProbeBox; | |||
| sourceTree = "<group>"; | |||
| }; | |||
| 78E07B712A49664E00E68200 /* Ble */ = { | |||
| isa = PBXGroup; | |||
| children = ( | |||
| 78E07B762A49664E00E68200 /* ELAILinkBleManager+MeatProbeBox.h */, | |||
| 78E07B742A49664E00E68200 /* ELAILinkBleManager+MeatProbeBox.m */, | |||
| 78E07B732A49664E00E68200 /* ELMeatProbeBoxBleHeader.h */, | |||
| 78E07B722A49664E00E68200 /* ELMeatProbeBoxBleParser.h */, | |||
| 78E07B752A49664E00E68200 /* ELMeatProbeBoxBleParser.m */, | |||
| ); | |||
| path = Ble; | |||
| sourceTree = "<group>"; | |||
| }; | |||
| 95565B742786EA3B000265EA /* 24_Skip */ = { | |||
| isa = PBXGroup; | |||
| children = ( | |||
| @@ -869,11 +937,14 @@ | |||
| files = ( | |||
| 78DC4DF42990FB40006C6911 /* ELDeviceTypeCell.xib in Resources */, | |||
| E622E287243F1D41003C319D /* Main.storyboard in Resources */, | |||
| 78E07B7E2A49664E00E68200 /* MeatProbeBoxVC.xib in Resources */, | |||
| 78DC4DE32990FB2E006C6911 /* ELDemoScanVC.xib in Resources */, | |||
| E622E26E243F1CA6003C319D /* LaunchScreen.storyboard in Resources */, | |||
| E622E26B243F1CA6003C319D /* Assets.xcassets in Resources */, | |||
| 78DC4DF62990FB40006C6911 /* ELDeviceScanCell.xib in Resources */, | |||
| 78E07B7B2A49664E00E68200 /* MeatProbeVC.xib in Resources */, | |||
| 78350BBD29D28C1200456695 /* README.md in Resources */, | |||
| 78E07B6B2A49664000E68200 /* BroadcastHeightGuage.xib in Resources */, | |||
| 78DC4DFC2990FC10006C6911 /* HeightBodyFatScaleVC.xib in Resources */, | |||
| ); | |||
| runOnlyForDeploymentPostprocessing = 0; | |||
| @@ -930,16 +1001,19 @@ | |||
| 95572641276C38CD003BFBAC /* ELEightScaleRecordModel.m in Sources */, | |||
| 95572634276C38CD003BFBAC /* HeightGuageScanViewController.m in Sources */, | |||
| 958B4EA7263C08E800476BAE /* UIButton+WZAdd.m in Sources */, | |||
| 78E07B7C2A49664E00E68200 /* ELAILinkBleManager+MeatProbeBox.m in Sources */, | |||
| 958B4EA9263C08E800476BAE /* ELSelectView.m in Sources */, | |||
| 95572635276C38CD003BFBAC /* HeightGuageConnectViewController.m in Sources */, | |||
| 95572639276C38CD003BFBAC /* NutritionScaleConnectionViewController.m in Sources */, | |||
| 95572647276C38CD003BFBAC /* ForeheadConnectViewController.m in Sources */, | |||
| E622E271243F1CA6003C319D /* main.m in Sources */, | |||
| 78E07B7F2A49664E00E68200 /* MeatProbeBoxVC.m in Sources */, | |||
| 95572646276C38CD003BFBAC /* FoodThermometerConnectionViewController.m in Sources */, | |||
| 958B4EB3263C08E800476BAE /* View+MASAdditions.m in Sources */, | |||
| 958B4EB1263C08E800476BAE /* MASLayoutConstraint.m in Sources */, | |||
| 9557263A276C38CD003BFBAC /* FaceMaskConnectionViewController.m in Sources */, | |||
| 95572636276C38CD003BFBAC /* OximeterScanViewController.m in Sources */, | |||
| 78E07B7D2A49664E00E68200 /* ELMeatProbeBoxBleParser.m in Sources */, | |||
| 958B4EA4263C08E800476BAE /* ELInputAlertView.m in Sources */, | |||
| 958B4EB6263C08E800476BAE /* MASViewAttribute.m in Sources */, | |||
| 958B4EBB263C08E800476BAE /* InheritConnectViewController.m in Sources */, | |||
| @@ -949,6 +1023,7 @@ | |||
| 78DC4DF32990FB40006C6911 /* ELDemoButton.m in Sources */, | |||
| 958B4EA5263C08E800476BAE /* UILabel+WZAdd.m in Sources */, | |||
| 95572633276C38CD003BFBAC /* BabyScaleConnectViewController.m in Sources */, | |||
| 78E07B7A2A49664E00E68200 /* MeatProbeVC.m in Sources */, | |||
| 95572644276C38CD003BFBAC /* BodyFatScaleConnectViewController.m in Sources */, | |||
| 958B4EBD263C08E800476BAE /* AppDelegate.m in Sources */, | |||
| 95565B792786EA3B000265EA /* SkipConnectionViewController.m in Sources */, | |||
| @@ -962,6 +1037,7 @@ | |||
| 95572645276C38CD003BFBAC /* FoodThermometerScanViewController.m in Sources */, | |||
| 958B4EA6263C08E800476BAE /* UIView+Category.m in Sources */, | |||
| 9557262E276C38CD003BFBAC /* ELBfsWifiConnectVC.m in Sources */, | |||
| 78E07B6A2A49664000E68200 /* BroadcastHeightGuage.m in Sources */, | |||
| 95572637276C38CD003BFBAC /* OximeterConnectionViewController.m in Sources */, | |||
| 95572648276C38CD003BFBAC /* ForeheadScanViewController.m in Sources */, | |||
| 78DC4DE42990FB2E006C6911 /* ELDemoDeviceModel.m in Sources */, | |||
| @@ -1117,7 +1193,7 @@ | |||
| buildSettings = { | |||
| ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; | |||
| CODE_SIGN_STYLE = Automatic; | |||
| CURRENT_PROJECT_VERSION = 20230427; | |||
| CURRENT_PROJECT_VERSION = 20230626; | |||
| DEVELOPMENT_TEAM = YEU77XR292; | |||
| FRAMEWORK_SEARCH_PATHS = ( | |||
| "$(inherited)", | |||
| @@ -1139,7 +1215,7 @@ | |||
| "$(PROJECT_DIR)/AILinkBleSDKDemo/DeviceDemo/13_EightScale/HTBodyfat_SDK", | |||
| "$(PROJECT_DIR)/AILinkBleSDKDemo/DeviceDemo/13_EightScale/BhBodyComposition120", | |||
| ); | |||
| MARKETING_VERSION = 1.5.15; | |||
| MARKETING_VERSION = 1.6.1; | |||
| OTHER_LDFLAGS = "-ObjC"; | |||
| PRODUCT_BUNDLE_IDENTIFIER = com.pingwang.AILinkBleSDKDemo; | |||
| PRODUCT_NAME = "$(TARGET_NAME)"; | |||
| @@ -1152,7 +1228,7 @@ | |||
| buildSettings = { | |||
| ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; | |||
| CODE_SIGN_STYLE = Automatic; | |||
| CURRENT_PROJECT_VERSION = 20230427; | |||
| CURRENT_PROJECT_VERSION = 20230626; | |||
| DEVELOPMENT_TEAM = YEU77XR292; | |||
| FRAMEWORK_SEARCH_PATHS = ( | |||
| "$(inherited)", | |||
| @@ -1174,7 +1250,7 @@ | |||
| "$(PROJECT_DIR)/AILinkBleSDKDemo/DeviceDemo/13_EightScale/HTBodyfat_SDK", | |||
| "$(PROJECT_DIR)/AILinkBleSDKDemo/DeviceDemo/13_EightScale/BhBodyComposition120", | |||
| ); | |||
| MARKETING_VERSION = 1.5.15; | |||
| MARKETING_VERSION = 1.6.1; | |||
| OTHER_LDFLAGS = "-ObjC"; | |||
| PRODUCT_BUNDLE_IDENTIFIER = com.pingwang.AILinkBleSDKDemo; | |||
| PRODUCT_NAME = "$(TARGET_NAME)"; | |||
| @@ -18,12 +18,6 @@ | |||
| #import "NELBleManagerHeader.h" | |||
| #import "NELMacAddressModel.h" | |||
| #import "NSData+AILinkBle.h" | |||
| #import "ELAILinkBleManager+AirDetector.h" | |||
| #import "ELAirDetectorBleFunctionModel.h" | |||
| #import "ELAirDetectorBleHeader.h" | |||
| #import "ELAirDetectorBleParser.h" | |||
| #import "ELAirDetectorBleSettingModel.h" | |||
| #import "ELAirDetectorBleStatusModel.h" | |||
| #import "ELAILinkBleManager+MeatProbe.h" | |||
| #import "ELMeatProbeBleTool.h" | |||
| #import "ELAILinkBleManager+NoiseMeter.h" | |||
| @@ -71,6 +65,7 @@ | |||
| #import "ELBroadcastNutritionFoodScaleBleManager.h" | |||
| #import "ELBroadcastNutritionFoodScaleDataModel.h" | |||
| #import "ELBfsLeaOneDataModel.h" | |||
| #import "ELBfsOKOKDataModel.h" | |||
| #import "ELBroadcastScaleBleHeader.h" | |||
| #import "ELBroadcastScaleBleManager.h" | |||
| #import "ELBroadcastScaleDataModel.h" | |||
| @@ -9,6 +9,6 @@ | |||
| #define AILinkBleSDK_Version_h | |||
| //版本号 SDK Version | |||
| #define AiLinkBleSDKVersion @"1.5.15" //20230427 增加 蓝牙牙刷防飞溅 | |||
| #define AiLinkBleSDKVersion @"1.6.1" //20230626 增加 广播身高仪 食物探针 食物探针盒子 支持 | |||
| #endif /* AILinkBleSDK_Version_h */ | |||
| @@ -1,136 +0,0 @@ | |||
| // | |||
| // ELAILinkBleManager+AirDetector.h | |||
| // AILinkBleSDK | |||
| // | |||
| // Created by LarryZhang on 2022/12/12. | |||
| // | |||
| #import "ELAILinkBleManager.h" | |||
| #import "ELTLVModel.h" | |||
| #import "ELAirDetectorBleHeader.h" | |||
| #import "ELAirDetectorBleParser.h" | |||
| NS_ASSUME_NONNULL_BEGIN | |||
| @interface ELAILinkBleManager (AirDetector) | |||
| - (NSData *)xxx; | |||
| //APP获取设备功能列表 //0x01 CMD:获取设备支持的功能列表 | |||
| - (void)airDetectorRequestDeviceFunctions; | |||
| - (NSData *)airDetectorRequestDeviceFunctionsPacketWithMac:(NSData *)mac withCid:(UInt16)cid; | |||
| //APP获取设备状态 //0x03 CMD:获取设备状态 | |||
| - (void)airDetectorRequestDeviceStatus; | |||
| - (NSData *)airDetectorRequestDeviceStatusPacketWithMac:(NSData *)mac withCid:(UInt16)cid; | |||
| //APP设置/获取参数 //0x05 CMD:设置/获取参数功能 | |||
| - (void)airDetectorRequestDeviceSettings; | |||
| - (NSData *)airDetectorRequestDeviceSettingsPacketWithMac:(NSData *)mac withCid:(UInt16)cid; | |||
| - (void)airDetectorSendDeviceSettings:(NSArray<ELTLVModel *> *)tlvs; | |||
| - (NSData *)airDetectorSendDeviceSettingsData:(NSArray<ELTLVModel *> *)tlvs; | |||
| //APP与模块心跳 //0x07 CMD:定时心跳包 | |||
| - (void)airDetectorSendHeartbeat; | |||
| - (NSData *)airDetectorSendHeartbeatPacketWithMac:(NSData *)mac withCid:(UInt16)cid; | |||
| @end | |||
| @interface ELAILinkBleManager (AirDetectorTLV) | |||
| //0x01:甲醛 | |||
| + (ELTLVModel *)tlvHCHOAlarmOn:(BOOL)on value:(NSInteger)value; | |||
| //0x02:温度 //参数: scale(标度) 表示小数点位数 | |||
| + (ELTLVModel *)tlvTemperatureMinValue:(NSInteger)minValue maxValue:(NSInteger)maxValue uint:(ELDeviceTemperatureUnit)unit scale:(NSInteger)scale; | |||
| //0x03:湿度 | |||
| + (ELTLVModel *)tlvHumidityMinValue:(NSInteger)minValue maxValue:(NSInteger)maxValue; | |||
| //0x04:PM2.5 | |||
| + (ELTLVModel *)tlvPM2_5AlarmOn:(BOOL)on value:(NSInteger)value; | |||
| //0x05:PM1.0 | |||
| + (ELTLVModel *)tlvPM1AlarmOn:(BOOL)on value:(NSInteger)value; | |||
| //0x06:PM10 | |||
| + (ELTLVModel *)tlvPM10AlarmOn:(BOOL)on value:(NSInteger)value; | |||
| //0x07:VOC | |||
| + (ELTLVModel *)tlvVOCAlarmOn:(BOOL)on value:(NSInteger)value; | |||
| //0x08:CO2 | |||
| + (ELTLVModel *)tlvCO2AlarmOn:(BOOL)on value:(NSInteger)value; | |||
| //0x09:AQI | |||
| + (ELTLVModel *)tlvAQIAlarmOn:(BOOL)on value:(NSInteger)value; | |||
| //0x0B:音量状态 | |||
| + (ELTLVModel *)tlvVolumeOn:(BOOL)on value:(NSInteger)value; | |||
| //0x0C:报警时长 | |||
| + (ELTLVModel *)tlvAlertDuration:(NSInteger)duration; | |||
| //0x0D:报警铃声 | |||
| + (ELTLVModel *)tlvAlertRing:(NSInteger)ringValue; | |||
| //0x0F:设备自检 ?? | |||
| + (ELTLVModel *)tlvSelf:(NSInteger)ringValue; | |||
| //0x10:TVOC | |||
| + (ELTLVModel *)tlvTVOCAlarmOn:(BOOL)on value:(NSInteger)value; | |||
| //0x11:单位切换 | |||
| + (ELTLVModel *)tlvTemperatureUint:(ELDeviceTemperatureUnit)unit; | |||
| //0x13:设备绑定 | |||
| + (ELTLVModel *)tlvBindDeviceRequest; | |||
| + (ELTLVModel *)tlvBindDeviceCancel; | |||
| //0x15:CO | |||
| + (ELTLVModel *)tlvCOAlarmOn:(BOOL)on value:(NSInteger)value; | |||
| //0x16:闹钟设置 | |||
| + (ELTLVModel *)tlvSetupAlarms:(NSArray *)alarms; | |||
| //0x17:恢复出厂设置 | |||
| + (ELTLVModel *)tlvRestoreFactory; | |||
| //0x18:参数校准设置 | |||
| + (ELTLVModel *)tlvCalibrationUp:(ELAirDetectorTLVType)type; | |||
| + (ELTLVModel *)tlvCalibrationDown:(ELAirDetectorTLVType)type; | |||
| + (ELTLVModel *)tlvCalibrationReset:(ELAirDetectorTLVType)type; | |||
| //0x19:时间格式设置 | |||
| + (ELTLVModel *)tlvTimeFormat12H; | |||
| + (ELTLVModel *)tlvTimeFormat24H; | |||
| //0x1A:设备亮度设置 | |||
| + (ELTLVModel *)tlvDeviceBrightnessOn:(BOOL)on value:(NSInteger)value; | |||
| //0x1B:按键音效设置 | |||
| + (ELTLVModel *)tlvKeySoundOn; | |||
| + (ELTLVModel *)tlvKeySoundOff; | |||
| //0x1C:报警音效设置 | |||
| + (ELTLVModel *)tlvAlertSoundOn; | |||
| + (ELTLVModel *)tlvAlertSoundOff; | |||
| //0x1D:图标显示设置 | |||
| + (ELTLVModel *)tlvIconDisplayOn; | |||
| + (ELTLVModel *)tlvIconDisplayOff; | |||
| //0x1E:监控显示数据 | |||
| + (ELTLVModel *)tlvMonitoringDisplayDataOn; | |||
| + (ELTLVModel *)tlvMonitoringDisplayDataOff; | |||
| //0x1F:数据显示模式设置 | |||
| + (ELTLVModel *)tlvDataDisplayMode:(NSInteger)mode; | |||
| @end | |||
| NS_ASSUME_NONNULL_END | |||
| @@ -13,17 +13,13 @@ NS_ASSUME_NONNULL_BEGIN | |||
| //MeatProbe 设置设备信息 0x35 | |||
| - (void)meatProbeSendCustomData:(NSData *_Nonnull)customData; | |||
| - (NSData *)meatProbeSendCustomData:(NSData *)customData; | |||
| //MeatProbe 设置设备信息 0x35 请求 | |||
| - (void)meatProbeRequestCustomData; | |||
| - (NSData *)meatProbeRequestCustomData; | |||
| //切换温度单位 A7 | |||
| - (void)meatProbeSwitchUint:(ELDeviceTemperatureUnit)unit; | |||
| //关闭自动关机指令 A7 **调试阶段使用 | |||
| //- (void)meatProbeCloseAutoOff; | |||
| - (NSData *)meatProbeSwitchUint:(ELDeviceTemperatureUnit)unit; | |||
| @end | |||
| @@ -11,11 +11,6 @@ NS_ASSUME_NONNULL_BEGIN | |||
| @interface ELAILinkBleManager (WIFI) | |||
| //============ wifi 分包数据 ============== | |||
| @property(nonatomic, strong) ELBleWifiDetailModel *_Nullable wifiDetailModel; | |||
| @property(nonatomic, strong) NSMutableData *_Nullable urlBuffData; | |||
| @property(nonatomic, strong) NSMutableData *_Nullable pathBuffData; | |||
| //============ Bluetooth WIFI calling method(蓝牙WIFI 设置命令) ============== | |||
| /** | |||
| @@ -31,9 +31,13 @@ NS_ASSUME_NONNULL_BEGIN | |||
| - (NSString *)sdkVersion; | |||
| + (NSString *)sdkVersion; | |||
| //扫描状态 | |||
| @property(nonatomic, assign, readonly, getter=isScanning) BOOL scanning; | |||
| @property(nonatomic, assign, readonly) CBCentralManager *central; | |||
| //BLE设备连接状态 | |||
| @property(nonatomic, assign, readonly) NELBleManagerConnectState connectState; | |||
| @property(nonatomic, strong, readonly) CBCentralManager *central; | |||
| @property (nonatomic, weak) id<ELAILinkBleManagerDelegate> delegate DEPRECATED_MSG_ATTRIBUTE("use 'ailinkDelegate' only"); | |||
| @@ -150,12 +154,4 @@ NS_ASSUME_NONNULL_BEGIN | |||
| @end | |||
| #pragma mark - specialMethod | |||
| @interface ELAILinkBleManager (specialMethod) | |||
| - (BOOL)specialMethodWithCid:(UInt16)cid vid:(UInt16)vid pid:(UInt16)pid secret:(NSString *)secret; | |||
| @end | |||
| NS_ASSUME_NONNULL_END | |||
| @@ -1,126 +0,0 @@ | |||
| // | |||
| // ELAirDetectorBleFunctionModel.h | |||
| // AILinkBleSDK | |||
| // | |||
| // Created by LarryZhang on 2022/12/13. | |||
| // | |||
| #import <Foundation/Foundation.h> | |||
| NS_ASSUME_NONNULL_BEGIN | |||
| @interface ELAirDetectorBleFunctionModel : NSObject | |||
| //0x01:甲醛 | |||
| @property (nonatomic, assign) NSInteger HCHOScale; | |||
| @property (nonatomic, assign) NSInteger HCHOMin; | |||
| @property (nonatomic, assign) NSInteger HCHOMax; | |||
| //0x02:温度 | |||
| @property (nonatomic, assign) NSInteger temperatureScale; | |||
| @property (nonatomic, assign) NSInteger temperatureMin; | |||
| @property (nonatomic, assign) NSInteger temperatureMax; | |||
| //0x03:湿度 | |||
| @property (nonatomic, assign) NSInteger humidityScale; | |||
| @property (nonatomic, assign) NSInteger humidityMin; | |||
| @property (nonatomic, assign) NSInteger humidityMax; | |||
| //0x04:PM2.5 | |||
| @property (nonatomic, assign) NSInteger PM2_5Scale; | |||
| @property (nonatomic, assign) NSInteger PM2_5Min; | |||
| @property (nonatomic, assign) NSInteger PM2_5Max; | |||
| //0x05:PM1.0 | |||
| @property (nonatomic, assign) NSInteger PM1Scale; | |||
| @property (nonatomic, assign) NSInteger PM1Min; | |||
| @property (nonatomic, assign) NSInteger PM1Max; | |||
| //0x06:PM10 | |||
| @property (nonatomic, assign) NSInteger PM10Scale; | |||
| @property (nonatomic, assign) NSInteger PM10Min; | |||
| @property (nonatomic, assign) NSInteger PM10Max; | |||
| //0x07:VOC | |||
| @property (nonatomic, assign) NSInteger VOCScale; | |||
| @property (nonatomic, assign) NSInteger VOCMin; | |||
| @property (nonatomic, assign) NSInteger VOCMax; | |||
| //0x08:CO2 | |||
| @property (nonatomic, assign) NSInteger CO2Scale; | |||
| @property (nonatomic, assign) NSInteger CO2Min; | |||
| @property (nonatomic, assign) NSInteger CO2Max; | |||
| //0x09:AQI | |||
| @property (nonatomic, assign) NSInteger AQIScale; | |||
| @property (nonatomic, assign) NSInteger AQIMin; | |||
| @property (nonatomic, assign) NSInteger AQIMax; | |||
| //0x0A:报警功能 | |||
| @property (nonatomic, assign) BOOL alertSupport; | |||
| //0x0B:音量 | |||
| @property (nonatomic, assign) NSInteger volumeMax; | |||
| //0x0C:报警时长 | |||
| @property (nonatomic, assign) NSInteger alertDurationMax; | |||
| //0x0D:报警铃声 | |||
| @property (nonatomic, assign) NSInteger alertRingCount; | |||
| //0x0E:设备故障 | |||
| @property (nonatomic, assign) BOOL deviceErrorSupport; | |||
| //0x0F:设备自检 | |||
| @property (nonatomic, assign) BOOL deviceSelfTestSupport; | |||
| //0x10:TVOC | |||
| @property (nonatomic, assign) NSInteger TVOCScale; | |||
| @property (nonatomic, assign) NSInteger TVOCMin; | |||
| @property (nonatomic, assign) NSInteger TVOCMax; | |||
| //0x15:CO(一氧化碳) | |||
| @property (nonatomic, assign) NSInteger COScale; | |||
| @property (nonatomic, assign) NSInteger COMin; | |||
| @property (nonatomic, assign) NSInteger COMax; | |||
| //0x16:闹钟功能声明 | |||
| @property (nonatomic, assign) BOOL alarmAllSupport; | |||
| @property (nonatomic, assign) NSInteger alarmCount; | |||
| @property (nonatomic, assign) NSInteger alarmMode; | |||
| //0x17:恢复出厂设置声明 | |||
| @property (nonatomic, assign) BOOL restoreFactorySupport; | |||
| //0x18:参数校准声明 | |||
| @property (nonatomic, strong) NSArray<NSNumber *> *_Nullable calibrationSupportArray; | |||
| //0x19:时间格式声明 | |||
| @property (nonatomic, assign) BOOL timeFormat12HSupport; | |||
| @property (nonatomic, assign) BOOL timeFormat24HSupport; | |||
| //0x1A:设备亮度声明 | |||
| @property (nonatomic, assign) BOOL deviceBrightnessAuto; | |||
| @property (nonatomic, assign) BOOL deviceBrightnessManual; | |||
| @property (nonatomic, assign) BOOL deviceBrightnessGearMode; | |||
| @property (nonatomic, assign) BOOL deviceBrightnessGearMax; | |||
| //0x1B:按键音效声明 | |||
| @property (nonatomic, assign) BOOL keySoundSupport; | |||
| //0x1C:报警音效声明 | |||
| @property (nonatomic, assign) BOOL alertSoundSupport; | |||
| //0x1D:图标显示声明 | |||
| @property (nonatomic, assign) BOOL iconDisplaySupport; | |||
| //0x1E:监控显示数据声明 | |||
| @property (nonatomic, assign) BOOL monitoringDisplayDataSupport; | |||
| //0x1F:数据显示模式声明 | |||
| @property (nonatomic, assign) NSInteger dataDisplayModeCount; | |||
| @end | |||
| NS_ASSUME_NONNULL_END | |||
| @@ -1,63 +0,0 @@ | |||
| // | |||
| // ELAirDetectorBleHeader.h | |||
| // Pods | |||
| // | |||
| // Created by LarryZhang on 2022/12/13. | |||
| // | |||
| #ifndef ELAirDetectorBleHeader_h | |||
| #define ELAirDetectorBleHeader_h | |||
| typedef NS_ENUM(NSUInteger, ELAirDetectorBleCMD) { | |||
| ELAirDetectorBleCMD01 = 0x01, //CMD:获取设备支持的功能列表 | |||
| ELAirDetectorBleCMD02 = 0x02, //CMD:设备返回功能 | |||
| ELAirDetectorBleCMD03 = 0x03, //CMD:获取设备状态 | |||
| ELAirDetectorBleCMD04 = 0x04, //CMD:设备返回状态 | |||
| ELAirDetectorBleCMD05 = 0x05, //CMD:设置/获取参数功能 | |||
| ELAirDetectorBleCMD06 = 0x06, //CMD:MCU返回参数功能 | |||
| ELAirDetectorBleCMD07 = 0x07, //CMD:定时心跳包 | |||
| ELAirDetectorBleCMD08 = 0x08, //CMD:模块返回心跳包 | |||
| ELAirDetectorBleCMDF1 = 0xF1, //CMD:上发保存数据 | |||
| }; | |||
| typedef NS_ENUM(NSUInteger, ELAirDetectorTLVType) { | |||
| ELAirDetectorTLVTypeHCHO = 0x01, //甲醛 | |||
| ELAirDetectorTLVTypeTemperature = 0x02, //温度 | |||
| ELAirDetectorTLVTypeHumidity = 0x03, //湿度 | |||
| ELAirDetectorTLVTypePM2_5 = 0x04, //PM2.5 | |||
| ELAirDetectorTLVTypePM1 = 0x05, //PM1 | |||
| ELAirDetectorTLVTypePM10 = 0x06, //PM10 | |||
| ELAirDetectorTLVTypeVOC = 0x07, | |||
| ELAirDetectorTLVTypeCO2 = 0x08, | |||
| ELAirDetectorTLVTypeAQI = 0x09, | |||
| ELAirDetectorTLVTypeSettingAlert = 0x0A, //报警功能 | |||
| ELAirDetectorTLVTypeSettingVolume = 0x0B, //音量 | |||
| ELAirDetectorTLVTypeSettingAlertDuration = 0x0C, //报警时长 | |||
| ELAirDetectorTLVTypeSettingAlertRing = 0x0D, //报警铃声 | |||
| ELAirDetectorTLVTypeSettingDeviceError = 0x0E, //设备故障 | |||
| ELAirDetectorTLVTypeSettingDeviceSelfTest = 0x0F, //设备自检 | |||
| ELAirDetectorTLVTypeTVOC = 0x10, //TVOC | |||
| ELAirDetectorTLVTypeSwitchTemperatureUnit = 0x11, //单位切换 | |||
| ELAirDetectorTLVTypeBatteryState = 0x12, //电池状态 | |||
| ELAirDetectorTLVTypeBindDevice = 0x13, //设备绑定 | |||
| ELAirDetectorTLVTypeHeartbeat = 0x14, //心跳包(用以模块和APP通信) | |||
| ELAirDetectorTLVTypeCO = 0x15, //CO(一氧化碳) | |||
| ELAirDetectorTLVTypeAlarm = 0x16, //闹钟功能 | |||
| ELAirDetectorTLVTypeRestoreFactorySetting = 0x17, //恢复出厂设置 | |||
| ELAirDetectorTLVTypeCalibrationParameter = 0x18, //参数校准 | |||
| ELAirDetectorTLVTypeTimeFormat = 0x19, //时间格式 | |||
| ELAirDetectorTLVTypeDeviceBrightness = 0x1A, //设备亮度 | |||
| ELAirDetectorTLVTypeKeySound = 0x1B, //按键音效 | |||
| ELAirDetectorTLVTypeAlertSound = 0x1C, //报警音效 | |||
| ELAirDetectorTLVTypeIconDisplay = 0x1D, //图标显示 | |||
| ELAirDetectorTLVTypeMonitoringDisplayData = 0x1E, //监控显示数据 | |||
| ELAirDetectorTLVTypeDataDisplayMode = 0x1F, //数据显示模式 | |||
| }; | |||
| #endif /* ELAirDetectorBleHeader_h */ | |||
| @@ -1,32 +0,0 @@ | |||
| // | |||
| // ELAirDetectorBleParser.h | |||
| // AILinkBleSDK | |||
| // | |||
| // Created by LarryZhang on 2022/12/12. | |||
| // | |||
| #import <Foundation/Foundation.h> | |||
| #import "ELSDKHeader.h" | |||
| #import "ELAirDetectorBleHeader.h" | |||
| #import "ELAirDetectorBleFunctionModel.h" | |||
| #import "ELAirDetectorBleStatusModel.h" | |||
| #import "ELAirDetectorBleSettingModel.h" | |||
| NS_ASSUME_NONNULL_BEGIN | |||
| @interface ELAirDetectorBleParser : NSObject | |||
| typedef void(^airDetectorDidUpdateDataBlock)(ELAirDetectorBleCMD cmd, ELAirDetectorTLVType type); | |||
| @property (nonatomic, strong) ELAirDetectorBleFunctionModel *functionModel; | |||
| @property (nonatomic, strong) ELAirDetectorBleStatusModel *statusModel; | |||
| @property (nonatomic, strong) ELAirDetectorBleSettingModel *settingModel; | |||
| - (void)parseData:(NSData *)payload callback:(airDetectorDidUpdateDataBlock)calllback; | |||
| @end | |||
| NS_ASSUME_NONNULL_END | |||
| @@ -1,113 +0,0 @@ | |||
| // | |||
| // ELAirDetectorBleSettingModel.h | |||
| // AILinkBleSDK | |||
| // | |||
| // Created by LarryZhang on 2022/12/14. | |||
| // | |||
| #import <Foundation/Foundation.h> | |||
| NS_ASSUME_NONNULL_BEGIN | |||
| @interface ELAirDetectorBleSettingModel : NSObject | |||
| //0x01:甲醛 | |||
| @property (nonatomic, assign) BOOL HCHOAlertOn; | |||
| @property (nonatomic, assign) NSInteger HCHOAlertValue; | |||
| //0x02:温度 | |||
| @property (nonatomic, assign) NSInteger temperatureScale; | |||
| @property (nonatomic, assign) NSInteger temperatureUint; | |||
| @property (nonatomic, assign) NSInteger temperatureAlertMinValue; | |||
| @property (nonatomic, assign) NSInteger temperatureAlertMaxValue; | |||
| //0x03:湿度 | |||
| @property (nonatomic, assign) NSInteger humidityAlertMinValue; | |||
| @property (nonatomic, assign) NSInteger humidityAlertMaxValue; | |||
| //0x04:PM2.5 | |||
| @property (nonatomic, assign) BOOL PM2_5AlertOn; | |||
| @property (nonatomic, assign) NSInteger PM2_5AlertValue; | |||
| //0x05:PM1.0 | |||
| @property (nonatomic, assign) BOOL PM1AlertOn; | |||
| @property (nonatomic, assign) NSInteger PM1AlertValue; | |||
| //0x06:PM10 | |||
| @property (nonatomic, assign) BOOL PM10AlertOn; | |||
| @property (nonatomic, assign) NSInteger PM10AlertValue; | |||
| //0x07:VOC | |||
| @property (nonatomic, assign) BOOL VOCAlertOn; | |||
| @property (nonatomic, assign) NSInteger VOCAlertValue; | |||
| //0x08:CO2 | |||
| @property (nonatomic, assign) BOOL CO2AlertOn; | |||
| @property (nonatomic, assign) NSInteger CO2AlertValue; | |||
| //0x09:AQI | |||
| @property (nonatomic, assign) BOOL AQIAlertOn; | |||
| @property (nonatomic, assign) NSInteger AQIAlertValue; | |||
| //0x0B:音量状态 | |||
| @property (nonatomic, assign) BOOL volumeAlertOn; | |||
| @property (nonatomic, assign) NSInteger volumeValue; | |||
| //0x0C:报警时长 | |||
| @property (nonatomic, assign) NSInteger alertDurationValue; | |||
| //0x0D:报警铃声 | |||
| @property (nonatomic, assign) NSInteger alertRingValue; | |||
| //0x0F:设备自检 | |||
| @property (nonatomic, assign) BOOL deviceSelfTesting; | |||
| //0x10:TVOC | |||
| @property (nonatomic, assign) BOOL TVOCAlertOn; | |||
| @property (nonatomic, assign) NSInteger TVOCAlertValue; | |||
| //0x11:单位切换 | |||
| @property (nonatomic, assign) NSInteger switchTemperatureUint; | |||
| //0x13:设备绑定 | |||
| @property (nonatomic, assign) NSInteger bandState; | |||
| //0x15:CO | |||
| @property (nonatomic, assign) BOOL COAlertOn; | |||
| @property (nonatomic, assign) NSInteger COAlertValue; | |||
| //0x16:闹钟设置 //原始数据未解析 | |||
| @property (nonatomic, strong) NSData *alarmSettingData; | |||
| //0x17:恢复出厂设置 | |||
| @property (nonatomic, assign) NSInteger restoreFactoryState; | |||
| //0x18:参数校准设置 //原始数据未解析 | |||
| @property (nonatomic, strong) NSData *calibrationSettingData; | |||
| //0x19:时间格式设置 | |||
| @property (nonatomic, assign) NSInteger timeFormatValue; | |||
| //0x1A:设备亮度状态 | |||
| @property (nonatomic, assign) BOOL deviceBrightnessOn; | |||
| @property (nonatomic, assign) NSInteger deviceBrightnessValue; | |||
| //按键音效设置 | |||
| @property (nonatomic, assign) BOOL keySoundOn; | |||
| //0x1C:报警音效设置 | |||
| @property (nonatomic, assign) BOOL alertSoundOn; | |||
| //0x1D:图标显示设置 | |||
| @property (nonatomic, assign) BOOL iconDisplayOn; | |||
| //0x1E:监控显示数据 | |||
| @property (nonatomic, assign) BOOL monitoringDisplayDataOn; | |||
| //0x1F:数据显示模式设置 | |||
| @property (nonatomic, assign) NSInteger dataDisplayModeValue; | |||
| @end | |||
| NS_ASSUME_NONNULL_END | |||
| @@ -1,117 +0,0 @@ | |||
| // | |||
| // ELAirDetectorBleStatusModel.h | |||
| // AILinkBleSDK | |||
| // | |||
| // Created by LarryZhang on 2022/12/13. | |||
| // | |||
| #import <Foundation/Foundation.h> | |||
| NS_ASSUME_NONNULL_BEGIN | |||
| @interface ELAirDetectorBleStatusModel : NSObject | |||
| //0x01:甲醛 | |||
| @property (nonatomic, assign) NSInteger HCHOValue; | |||
| //0x02:温度 | |||
| @property (nonatomic, assign) NSInteger temperatureScale; | |||
| @property (nonatomic, assign) NSInteger temperatureValue; | |||
| @property (nonatomic, assign) NSInteger temperatureUint; | |||
| //0x03:湿度 | |||
| @property (nonatomic, assign) NSInteger humidityValue; | |||
| //0x04:PM2.5 | |||
| @property (nonatomic, assign) NSInteger PM2_5Value; | |||
| //0x05:PM1.0 | |||
| @property (nonatomic, assign) NSInteger PM1Value; | |||
| //0x06:PM10 | |||
| @property (nonatomic, assign) NSInteger PM10Value; | |||
| //0x07:VOC | |||
| @property (nonatomic, assign) NSInteger VOCValue; | |||
| //0x08:CO2 | |||
| @property (nonatomic, assign) NSInteger CO2Value; | |||
| //0x09:AQI | |||
| @property (nonatomic, assign) NSInteger AQIValue; | |||
| //0x0A:报警状态 | |||
| @property (nonatomic, assign) BOOL alertOn; | |||
| @property (nonatomic, assign) BOOL alertHCHOHigh; | |||
| @property (nonatomic, assign) BOOL alertTemperatureLow; | |||
| @property (nonatomic, assign) BOOL alertTemperatureHigh; | |||
| @property (nonatomic, assign) BOOL alertHumidityLow; | |||
| @property (nonatomic, assign) BOOL alertHumidityHigh; | |||
| @property (nonatomic, assign) BOOL alertPM2_5; | |||
| @property (nonatomic, assign) BOOL alertPM1; | |||
| @property (nonatomic, assign) BOOL alertPM10; | |||
| @property (nonatomic, assign) BOOL alertVOC; | |||
| @property (nonatomic, assign) BOOL alertCO2; | |||
| @property (nonatomic, assign) BOOL alertAQI; | |||
| @property (nonatomic, assign) BOOL alertTVOC; | |||
| //0x0B:音量状态 | |||
| @property (nonatomic, assign) BOOL volumeOn; | |||
| @property (nonatomic, assign) NSInteger volumeValue; | |||
| //0x0C:报警时长 | |||
| @property (nonatomic, assign) NSInteger alertDurationValue; | |||
| //0x0D:报警铃声 | |||
| @property (nonatomic, assign) NSInteger alertRingValue; | |||
| //0x0E:设备故障 | |||
| @property (nonatomic, assign) BOOL deviceError; | |||
| //0x0F:设备自检 | |||
| @property (nonatomic, assign) BOOL deviceSelfTesting; | |||
| //0x10:TVOC | |||
| @property (nonatomic, assign) NSInteger TVOCValue; | |||
| //0x12:电池状态 | |||
| @property (nonatomic, assign) NSInteger batteryState; | |||
| @property (nonatomic, assign) NSInteger batteryPercentValue; | |||
| //0x15:CO | |||
| @property (nonatomic, assign) NSInteger COValue; | |||
| //0x16:闹钟状态 //原始数据未解析 | |||
| @property (nonatomic, strong) NSData *alarmStatusData; | |||
| //0x17:恢复出厂设置 | |||
| @property (nonatomic, assign) NSInteger restoreFactoryState; | |||
| //0x18:参数校准状态 //原始数据未解析 | |||
| @property (nonatomic, strong) NSData *calibrationStatusData; | |||
| //0x19:时间格式状态 | |||
| @property (nonatomic, assign) NSInteger timeFormatValue; | |||
| //0x1A:设备亮度状态 | |||
| @property (nonatomic, assign) BOOL deviceBrightnessOn; | |||
| @property (nonatomic, assign) NSInteger deviceBrightnessValue; | |||
| //0x1B:按键音效状态 | |||
| @property (nonatomic, assign) BOOL keySoundOn; | |||
| //0x1C:报警音效状态 | |||
| @property (nonatomic, assign) BOOL alertSoundOn; | |||
| //0x1D:图标显示状态 | |||
| @property (nonatomic, assign) BOOL iconDisplayOn; | |||
| //0x1E:监控显示数据状态 | |||
| @property (nonatomic, assign) BOOL monitoringDisplayDataOn; | |||
| //0x1F:数据显示模式 | |||
| @property (nonatomic, assign) NSInteger dataDisplayModeValue; | |||
| @end | |||
| NS_ASSUME_NONNULL_END | |||
| @@ -0,0 +1,49 @@ | |||
| // | |||
| // ELBfsOKOKDataModel.h | |||
| // Elink | |||
| // | |||
| #import <Foundation/Foundation.h> | |||
| #import "ELBroadcastScaleBleHeader.h" | |||
| NS_ASSUME_NONNULL_BEGIN | |||
| typedef NS_ENUM(NSInteger, OKOKDevType) { | |||
| /** 体重秤 */ | |||
| OKOKDevType_Weight = 0 , | |||
| /** 体脂秤 */ | |||
| OKOKDevType_Bfr , | |||
| }; | |||
| /** lea one 秤返回的数据对象模型 */ | |||
| @interface ELBfsOKOKDataModel : NSObject | |||
| /** 流水号 */ | |||
| @property (nonatomic, assign) NSInteger serialNumber; | |||
| /** 设备返回的原始体重 */ | |||
| @property (nonatomic, assign) NSInteger rawWeight; | |||
| /** 电阻 */ | |||
| @property (nonatomic, assign) NSInteger adc; | |||
| /** mac地址 */ | |||
| @property (nonatomic, copy) NSString *mac; | |||
| /** 设备类型 */ | |||
| @property (nonatomic, assign) OKOKDevType devType; | |||
| /** 单位 (仅支持 kg,斤,lb和st:lb) */ | |||
| @property (nonatomic, assign) ELDeviceWeightUnit unit; | |||
| /** 小数位 */ | |||
| @property (nonatomic, assign) NSInteger weightPoint; | |||
| /** 是否为锁定数据 */ | |||
| @property (nonatomic, assign) BOOL isLockData; | |||
| + (instancetype)initWithDevBleData:(NSData *)data; | |||
| @end | |||
| NS_ASSUME_NONNULL_END | |||
| @@ -73,6 +73,8 @@ NS_ASSUME_NONNULL_BEGIN | |||
| @return 结构体 | |||
| */ | |||
| +(struct ELMCUStateStruct)analysisBluetoothConnectState:(NSData *)data; | |||
| //重构 | |||
| + (ELWMStateStruct)analysisWMState:(NSData *)data; | |||
| /** | |||
| 解析模块通信模式 | |||
| @@ -72,6 +72,9 @@ NS_ASSUME_NONNULL_BEGIN | |||
| @param stateStrct 结构体 | |||
| */ | |||
| -(void)bluetoothManagerReceiveMCUConnectedState:(struct ELMCUStateStruct)stateStrct; | |||
| //重构 | |||
| -(void)bluetoothManagerReceiveWMState:(ELWMStateStruct)stateStrct; | |||
| -(void)bluetoothManagerReceiveWMStateFailCode:(WMWorkStateFailCode)failCode; | |||
| /** | |||
| Query the callback of the communication mode(查询通信模式的回调) | |||
| @@ -68,6 +68,7 @@ static NSString *GET_A7_DECRYPT_BLE_PAYLOAD_DATA_CONTENT = @"GET_A7_DECRYPT_BLE_ | |||
| //Start scanning(开始扫描)- 过滤 cid 列表 | |||
| -(void)startScanFilterCids:(NSArray<NSNumber *> *)cids; | |||
| -(void)startScanAllFilterCids:(NSArray<NSNumber *> *)cids; | |||
| //Start scanning all (开始扫描附近所有设备) | |||
| - (void)startScanAll; | |||
| @@ -41,6 +41,8 @@ NS_ASSUME_NONNULL_BEGIN | |||
| @property (nonatomic, assign) long long createTime; | |||
| @property (nonatomic, assign) BOOL weightNegative; | |||
| @property (nonatomic, assign) UInt16 weightValue; | |||
| @end | |||
| @@ -106,10 +106,16 @@ typedef NS_ENUM(NSUInteger, ELSupportDeviceType) { | |||
| ELSupportDeviceTypeBroadcastScale = (0xffff +0x01) , //655536 Broadcast body fat scale(AILink广播体脂秤) | |||
| ELSupportDeviceTypeBroadcastHeightGauge = (0xffff + 0x03) , //65538 广播身高仪 | |||
| ELSupportDeviceTypeBroadcastScale_Lingyang = (0xffff +0x16) , //65557 凌阳广播体脂秤 | |||
| ELSupportDeviceTypeBroadcastBodyScale = (0xFFFF + 0x07) , //Broadcast body scale AILink广播体重秤(无体脂) | |||
| ELSupportDeviceTypeBroadcastNutritionFoodScale = (0xffff + 0x04) , //65539 广播营养秤 | |||
| ELSupportDeviceTypeBroadcastHygrothermograph = (0xffff + 0x06) , //65541 广播温湿度计 | |||
| ELSupportDeviceTypeBroadcastScale_OKOK = (0xffff + 0x08) , //65543 OKOK广播体脂秤 | |||
| ELSupportDeviceTypeBroadcastScale_T6 = (0xffff + 0x09) , //65544 T6广播体脂秤 | |||
| }; | |||
| #endif /* ELExSupportDeviceType_h */ | |||
| @@ -37,6 +37,7 @@ typedef NS_ENUM(NSUInteger, ELInetGetCmdType) { | |||
| 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连接状态) | |||
| ELInetGetCmdTypeGetConnectStateFailCode = 0xAB, //- WiFi connection error 连接失败原因 | |||
| 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协议(具体见二级指令)) | |||
| @@ -195,6 +196,50 @@ struct ELMCUStateStruct { | |||
| BleWiFiConnectServerFaildState faildState; | |||
| }; | |||
| //重构 | |||
| //BLE状态 | |||
| typedef NS_ENUM(Byte, WMBleState) { | |||
| WMBleStateNoConnection = 0,//无连接 | |||
| WMBleStateConnected = 1,//已连接 | |||
| WMBleStatePaired = 2,//配对完成 | |||
| WMBleStateMax = 0xFF | |||
| }; | |||
| //wifi状态 | |||
| typedef NS_ENUM(Byte, WMWiFiState) { | |||
| WMWiFiStateNotSetAP = 0, //未配置AP | |||
| WMWiFiStateConnectAPFail = 1, //连接AP失败,连接时密码错误、AP信号不好、主动断开都会是这个状态 | |||
| WMWiFiStateConnectServerFail = 2, //与服务器通讯失败 | |||
| WMWiFiStateConnectedAP = 3, //成功连接上AP | |||
| WMWiFiStateConnectingAP = 4, //正在连接AP | |||
| WMWiFiStateMax = 0xFF | |||
| }; | |||
| //工作状态 | |||
| typedef NS_ENUM(Byte, WMWorkState) { | |||
| WMWorkStateWakeup = 0,//唤醒 | |||
| WMWorkStateSleep = 1,//进入休眠 | |||
| WMWorkStateReady = 2,//模块准备就绪 | |||
| WMWorkStateMax = 0xFF | |||
| }; | |||
| //WiFi连接失败原因 | |||
| typedef NS_ENUM(Byte, WMWorkStateFailCode) { | |||
| WMWorkStateFailCodeUnknow = 0,//未知原因 | |||
| WMWorkStateFailCodeAPSignalBad = 1,//AP信号差 | |||
| WMWorkStateFailCodeWrongPassword = 2,//密码错误 | |||
| WMWorkStateFailCodeNoIP = 3,//获取不到IP | |||
| WMWorkStateFailCodeMax = 0xFF | |||
| }; | |||
| typedef struct { | |||
| WMBleState bleState; | |||
| WMWiFiState wifiState; | |||
| WMWorkState workState; | |||
| WMWorkStateFailCode failCode; | |||
| } ELWMStateStruct, ELWMStateStruct; | |||
| #pragma mark - AiLink unit | |||
| /** Type key of unit string(单位字符串的type key) */ | |||
| @@ -120,6 +120,9 @@ NS_ASSUME_NONNULL_BEGIN | |||
| ///获取设备连接的wifi名称 | |||
| - (void)getBleLinkWifiName; | |||
| /** 设置设备的IP地址,端口号和访问路径 */ | |||
| - (void)setDevAccessIpAddress:(NSString *)address portNumber:(NSUInteger)portNum path:(NSString *)path; | |||
| @property (nonatomic,assign) ELBluetoothState bleWifiBloodStatus; | |||
| @@ -0,0 +1,17 @@ | |||
| // | |||
| // BroadcastHeightGuage.h | |||
| // AILinkBleSDK_Example | |||
| // | |||
| // Created by LarryZhang on 2023/6/26. | |||
| // Copyright © 2023 zhengzida. All rights reserved. | |||
| // | |||
| #import <UIKit/UIKit.h> | |||
| NS_ASSUME_NONNULL_BEGIN | |||
| @interface BroadcastHeightGuage : UIViewController | |||
| @end | |||
| NS_ASSUME_NONNULL_END | |||
| @@ -0,0 +1,127 @@ | |||
| // | |||
| // BroadcastHeightGuage.m | |||
| // AILinkBleSDK_Example | |||
| // | |||
| // Created by LarryZhang on 2023/6/26. | |||
| // Copyright © 2023 zhengzida. All rights reserved. | |||
| // | |||
| #import "BroadcastHeightGuage.h" | |||
| #import <AILinkBleSDK/ELBroadcastHeightGaugeBleManager.h> | |||
| @interface BroadcastHeightGuage () | |||
| @property (weak, nonatomic) IBOutlet UILabel *bleStatusLabel; | |||
| @property (weak, nonatomic) IBOutlet UITextView *logTextView; | |||
| @end | |||
| @interface BroadcastHeightGuage () <ELBroadcastHeightGaugeBleDelegate> | |||
| @end | |||
| @implementation BroadcastHeightGuage | |||
| - (void)viewDidLoad { | |||
| [super viewDidLoad]; | |||
| // Do any additional setup after loading the view from its nib. | |||
| [self initBle]; | |||
| [self scanBle]; | |||
| } | |||
| - (void)dealloc { | |||
| [self deinitBle]; | |||
| } | |||
| #pragma mark - Action | |||
| - (IBAction)clearAction:(id)sender { | |||
| self.logTextView.text = @""; | |||
| } | |||
| - (IBAction)shareLogAction:(id)sender { | |||
| } | |||
| #pragma mark - BLE | |||
| - (void)initBle { | |||
| [ELBroadcastHeightGaugeBleManager shareManager].heightGaugeDelegate = self; | |||
| } | |||
| - (void)scanBle { | |||
| [[ELBroadcastHeightGaugeBleManager shareManager] startScanAll]; | |||
| } | |||
| - (void)deinitBle { | |||
| [[ELBroadcastHeightGaugeBleManager shareManager] stopScan]; | |||
| [ELBroadcastHeightGaugeBleManager shareManager].heightGaugeDelegate = nil; | |||
| } | |||
| /**Callback Bluetooth status(回调蓝牙状态) */ | |||
| - (void)broadcastHeightGaugeUpdateState:(ELBluetoothState)state { | |||
| if (state == ELBluetoothStateAvailable) { | |||
| self.bleStatusLabel.text = @"Connecting"; | |||
| } else if (state == ELBluetoothStateUnavailable) { | |||
| self.bleStatusLabel.text = @"Bluetooth is disconnected"; | |||
| } | |||
| } | |||
| /** 回调身高数据 */ | |||
| - (void)broadcastHeightGaugeDeviceDataModel:(ELBroadcastHeightGaugeBleDataModel *)model { | |||
| static NSInteger serialNumber = 0; | |||
| if (serialNumber == model.serialNumber) { | |||
| return; | |||
| } | |||
| serialNumber = model.serialNumber; | |||
| switch (model.testState) { | |||
| case BroadcastHeightGuage_TestState_Measuring: { | |||
| self.bleStatusLabel.text = @"Measuring"; | |||
| break; | |||
| } | |||
| case BroadcastHeightGuage_TestState_Stable: { | |||
| self.bleStatusLabel.text = @"Stabl"; | |||
| break; | |||
| } | |||
| case BroadcastHeightGuage_TestState_Failed: { | |||
| self.bleStatusLabel.text = @"Failed"; | |||
| break; | |||
| } | |||
| } | |||
| NSString *log = [NSString stringWithFormat:@"MAC:%@ cid = %d--vid=%d--pid=%d\n Height = %@%@", model.mac, model.cid - 0xFFFF, model.vid, model.pid, @(model.height), AiLinkBleHeightUnitDic[@(model.heightUnit)]]; | |||
| [self addLog:log]; | |||
| } | |||
| #pragma mark - Log | |||
| - (void)addLog:(NSString *)log { | |||
| [self addLog:log newline:YES]; | |||
| } | |||
| - (void)addWithoutNewlineLog:(NSString *)log { | |||
| [self addLog:log newline:NO]; | |||
| } | |||
| - (void)addLog:(NSString *)log newline:(BOOL)newline { | |||
| NSDateFormatter *format = [[NSDateFormatter alloc] init]; | |||
| format.dateFormat = @"HH:mm:ss.SSS"; | |||
| NSString *time = [format stringFromDate:[NSDate date]]; | |||
| if (newline) { | |||
| self.logTextView.text = [self.logTextView.text stringByAppendingFormat:@"%@ %@\n", time, log]; | |||
| } else { | |||
| self.logTextView.text = [self.logTextView.text stringByAppendingFormat:@"%@ %@", time, log]; | |||
| } | |||
| [self.logTextView scrollRangeToVisible:NSMakeRange(self.logTextView.text.length, 1)]; | |||
| } | |||
| @end | |||
| @@ -0,0 +1,101 @@ | |||
| <?xml version="1.0" encoding="UTF-8"?> | |||
| <document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="21701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES"> | |||
| <device id="retina6_12" orientation="portrait" appearance="light"/> | |||
| <dependencies> | |||
| <deployment identifier="iOS"/> | |||
| <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="21679"/> | |||
| <capability name="Safe area layout guides" minToolsVersion="9.0"/> | |||
| <capability name="System colors in document resources" minToolsVersion="11.0"/> | |||
| <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> | |||
| </dependencies> | |||
| <objects> | |||
| <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="BroadcastHeightGuage"> | |||
| <connections> | |||
| <outlet property="bleStatusLabel" destination="0xz-aS-XmR" id="M4X-Dn-08b"/> | |||
| <outlet property="logTextView" destination="7mG-7x-9xa" id="8Vr-ji-Eql"/> | |||
| <outlet property="view" destination="Cra-or-dGB" id="NoP-us-drS"/> | |||
| </connections> | |||
| </placeholder> | |||
| <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/> | |||
| <view clearsContextBeforeDrawing="NO" contentMode="scaleToFill" id="Cra-or-dGB"> | |||
| <rect key="frame" x="0.0" y="0.0" width="393" height="852"/> | |||
| <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> | |||
| <subviews> | |||
| <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="y1w-g7-Gwh"> | |||
| <rect key="frame" x="16" y="346" width="31" height="30"/> | |||
| <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/> | |||
| <state key="normal" title="清空"/> | |||
| <connections> | |||
| <action selector="clearAction:" destination="-1" eventType="touchUpInside" id="k92-gw-3vb"/> | |||
| </connections> | |||
| </button> | |||
| <button hidden="YES" opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="PGm-jo-Ko3"> | |||
| <rect key="frame" x="346" y="346" width="31" height="30"/> | |||
| <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/> | |||
| <state key="normal" title="分享"/> | |||
| <connections> | |||
| <action selector="shareLogAction:" destination="-1" eventType="touchUpInside" id="jj3-ON-0lh"/> | |||
| </connections> | |||
| </button> | |||
| <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Stauts" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="0xz-aS-XmR"> | |||
| <rect key="frame" x="0.0" y="63" width="393" height="21"/> | |||
| <fontDescription key="fontDescription" type="system" pointSize="17"/> | |||
| <nil key="textColor"/> | |||
| <nil key="highlightedColor"/> | |||
| </label> | |||
| <view clipsSubviews="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="itb-kd-JGo"> | |||
| <rect key="frame" x="8" y="384" width="377" height="434"/> | |||
| <subviews> | |||
| <textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" showsHorizontalScrollIndicator="NO" indicatorStyle="white" editable="NO" selectable="NO" translatesAutoresizingMaskIntoConstraints="NO" id="7mG-7x-9xa"> | |||
| <rect key="frame" x="0.0" y="0.0" width="377" height="434"/> | |||
| <color key="backgroundColor" systemColor="labelColor"/> | |||
| <color key="textColor" systemColor="opaqueSeparatorColor"/> | |||
| <fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="10"/> | |||
| <textInputTraits key="textInputTraits" autocapitalizationType="sentences"/> | |||
| </textView> | |||
| </subviews> | |||
| <color key="backgroundColor" systemColor="systemBackgroundColor"/> | |||
| <constraints> | |||
| <constraint firstItem="7mG-7x-9xa" firstAttribute="leading" secondItem="itb-kd-JGo" secondAttribute="leading" id="0NM-af-zvv"/> | |||
| <constraint firstAttribute="trailing" secondItem="7mG-7x-9xa" secondAttribute="trailing" id="Q09-hB-QcZ"/> | |||
| <constraint firstItem="7mG-7x-9xa" firstAttribute="top" secondItem="itb-kd-JGo" secondAttribute="top" id="kkV-Sm-BVr"/> | |||
| <constraint firstAttribute="bottom" secondItem="7mG-7x-9xa" secondAttribute="bottom" id="nqD-ZR-BY0"/> | |||
| </constraints> | |||
| <userDefinedRuntimeAttributes> | |||
| <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius"> | |||
| <real key="value" value="8"/> | |||
| </userDefinedRuntimeAttribute> | |||
| </userDefinedRuntimeAttributes> | |||
| </view> | |||
| </subviews> | |||
| <viewLayoutGuide key="safeArea" id="k4u-s9-7Su"/> | |||
| <color key="backgroundColor" systemColor="systemBackgroundColor"/> | |||
| <constraints> | |||
| <constraint firstItem="k4u-s9-7Su" firstAttribute="bottom" secondItem="itb-kd-JGo" secondAttribute="bottom" id="031-Ze-0Uo"/> | |||
| <constraint firstItem="itb-kd-JGo" firstAttribute="top" secondItem="PGm-jo-Ko3" secondAttribute="bottom" constant="8" symbolic="YES" id="49Z-8f-jcF"/> | |||
| <constraint firstItem="itb-kd-JGo" firstAttribute="top" secondItem="0xz-aS-XmR" secondAttribute="bottom" constant="300" id="6aU-tq-ex8"/> | |||
| <constraint firstItem="itb-kd-JGo" firstAttribute="top" secondItem="y1w-g7-Gwh" secondAttribute="bottom" constant="8" symbolic="YES" id="MZu-VN-DtI"/> | |||
| <constraint firstItem="y1w-g7-Gwh" firstAttribute="leading" secondItem="k4u-s9-7Su" secondAttribute="leading" constant="16" id="O7j-eL-y7n"/> | |||
| <constraint firstItem="k4u-s9-7Su" firstAttribute="trailing" secondItem="itb-kd-JGo" secondAttribute="trailing" constant="8" id="Spc-n1-4dx"/> | |||
| <constraint firstItem="k4u-s9-7Su" firstAttribute="trailing" secondItem="0xz-aS-XmR" secondAttribute="trailing" id="bLk-Ca-9bf"/> | |||
| <constraint firstItem="k4u-s9-7Su" firstAttribute="trailing" secondItem="PGm-jo-Ko3" secondAttribute="trailing" constant="16" id="h1Q-kO-zCq"/> | |||
| <constraint firstItem="itb-kd-JGo" firstAttribute="leading" secondItem="k4u-s9-7Su" secondAttribute="leading" constant="8" id="mGb-E5-W9q"/> | |||
| <constraint firstItem="0xz-aS-XmR" firstAttribute="leading" secondItem="k4u-s9-7Su" secondAttribute="leading" id="qzH-Hp-bXE"/> | |||
| <constraint firstItem="0xz-aS-XmR" firstAttribute="top" secondItem="k4u-s9-7Su" secondAttribute="top" constant="4" id="sdm-yW-Wjg"/> | |||
| <constraint firstItem="0xz-aS-XmR" firstAttribute="centerX" secondItem="Cra-or-dGB" secondAttribute="centerX" id="zhi-rs-RXG"/> | |||
| </constraints> | |||
| <point key="canvasLocation" x="53" y="20"/> | |||
| </view> | |||
| </objects> | |||
| <resources> | |||
| <systemColor name="labelColor"> | |||
| <color red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> | |||
| </systemColor> | |||
| <systemColor name="opaqueSeparatorColor"> | |||
| <color red="0.77647058823529413" green="0.77647058823529413" blue="0.78431372549019607" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> | |||
| </systemColor> | |||
| <systemColor name="systemBackgroundColor"> | |||
| <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> | |||
| </systemColor> | |||
| </resources> | |||
| </document> | |||
| @@ -0,0 +1,21 @@ | |||
| // | |||
| // MeatProbeVC.h | |||
| // AILinkBleSDK_Example | |||
| // | |||
| // Created by LarryZhang on 2023/3/7. | |||
| // Copyright © 2023 zhengzida. All rights reserved. | |||
| // | |||
| #import <UIKit/UIKit.h> | |||
| NS_ASSUME_NONNULL_BEGIN | |||
| @class ELAILinkPeripheral; | |||
| @interface MeatProbeVC : UIViewController | |||
| @property (nonatomic, strong) ELAILinkPeripheral *per; | |||
| @end | |||
| NS_ASSUME_NONNULL_END | |||
| @@ -0,0 +1,261 @@ | |||
| // | |||
| // MeatProbeVC.m | |||
| // AILinkBleSDK_Example | |||
| // | |||
| // Created by LarryZhang on 2023/3/7. | |||
| // Copyright © 2023 zhengzida. All rights reserved. | |||
| // | |||
| #import "MeatProbeVC.h" | |||
| #import <AILinkBleSDK/ELAILinkBleManager+MeatProbe.h> | |||
| #import <AILinkBleSDK/ELMeatProbeBleTool.h> | |||
| #import "ELDemoButton.h" | |||
| @interface MeatProbeVC () <ELAILinkBleManagerDelegate> | |||
| @property (weak, nonatomic) IBOutlet UILabel *bleStatusLabel; | |||
| @property (weak, nonatomic) IBOutlet UITextView *logTextView; | |||
| @property (nonatomic, strong) ELAILinkBleManager *bleManager; | |||
| @end | |||
| @implementation MeatProbeVC | |||
| - (void)viewDidLoad { | |||
| [super viewDidLoad]; | |||
| // Do any additional setup after loading the view from its nib. | |||
| [self initBle]; | |||
| } | |||
| - (void)dealloc { | |||
| [self deinitBle]; | |||
| } | |||
| #pragma mark - Action | |||
| - (IBAction)customDataRequestAction:(id)sender { | |||
| NSData *payload = [self.bleManager meatProbeRequestCustomData]; | |||
| NSString *log = [NSString stringWithFormat:@"发: payload: %@", payload]; | |||
| [self addLog:log]; | |||
| } | |||
| - (IBAction)customDataSendAction:(id)sender { | |||
| NSData *payload = [self.bleManager meatProbeSendCustomData:[self coustumData]]; | |||
| NSString *log = [NSString stringWithFormat:@"发: payload: %@", payload]; | |||
| [self addLog:log]; | |||
| } | |||
| - (IBAction)customDataClearAction:(id)sender { | |||
| NSData *payload = [self.bleManager meatProbeSendCustomData:[NSData data]]; | |||
| NSString *log = [NSString stringWithFormat:@"发: payload: %@", payload]; | |||
| [self addLog:log]; | |||
| } | |||
| - (IBAction)switchUnitAction:(id)sender { | |||
| static BOOL flag = NO; | |||
| if (flag) { | |||
| NSData *payload = [self.bleManager meatProbeSwitchUint:0]; | |||
| NSString *log = [NSString stringWithFormat:@"发: payload: %@ -- 切换单位 to C", payload]; | |||
| [self addLog:log]; | |||
| } else { | |||
| NSData *payload = [self.bleManager meatProbeSwitchUint:1]; | |||
| NSString *log = [NSString stringWithFormat:@"发: payload: %@ -- 切换单位 to F", payload]; | |||
| [self addLog:log]; | |||
| } | |||
| flag = !flag; | |||
| } | |||
| - (IBAction)clearAction:(id)sender { | |||
| self.logTextView.text = @""; | |||
| } | |||
| - (IBAction)shareLogAction:(id)sender { | |||
| } | |||
| - (NSData *)coustumData { | |||
| //自定义数据 | |||
| //*******要验证设备必须支持128字节payload | |||
| Byte bytes[128]; | |||
| memset(bytes, 0, sizeof(bytes)); | |||
| for (int i=0; i<sizeof(bytes); i++) { | |||
| bytes[i] = 0x80 + i; | |||
| } | |||
| NSData *data = [NSData dataWithBytes:bytes length:sizeof(bytes)]; | |||
| NSLog(@"meatProbeAction() data:%@", data); | |||
| return data; | |||
| } | |||
| #pragma mark - ELAILinkBleManagerDelegate | |||
| - (void)initBle { | |||
| self.bleManager = [[ELAILinkBleManager alloc] init]; | |||
| self.bleManager.ailinkDelegate = self; | |||
| } | |||
| - (void)scanBle { | |||
| [self.bleManager scanFilterWithCidArray:@[@(self.per.cid)]]; | |||
| } | |||
| - (void)connect { | |||
| [self.bleManager connectAILinkPeripheral:self.per]; | |||
| [self updateBleStatusView:NELBleManagerConnectStateConnecting]; | |||
| } | |||
| - (void)deinitBle { | |||
| [self.bleManager stopScan]; | |||
| self.bleManager.ailinkDelegate = nil; | |||
| [self.bleManager disconnectPeripheral]; | |||
| } | |||
| - (void)updateBleStatusView:(NELBleManagerConnectState)state { | |||
| if (self.bleManager.central.state == CBManagerStatePoweredOff) { | |||
| self.bleStatusLabel.text = @"蓝牙关闭"; | |||
| return; | |||
| } | |||
| switch (state) { | |||
| case NELBleManagerConnectStateDisconnected: | |||
| self.bleStatusLabel.text = @"断开连接"; | |||
| break; | |||
| case NELBleManagerConnectStateFailed: | |||
| case NELBleManagerConnectStateFailedValidation: | |||
| self.bleStatusLabel.text = @"连接失败"; | |||
| break; | |||
| case NELBleManagerConnectStateConnecting: | |||
| self.bleStatusLabel.text = @"正在连接..."; | |||
| break; | |||
| case NELBleManagerConnectStatePassed: | |||
| self.bleStatusLabel.text = @"连接成功"; | |||
| //获取电量 | |||
| [self.bleManager getBluetoothInfoWithELInetGetCmdType:ELInetGetCmdTypeGetBatteryState]; | |||
| //获取 设置设备信息 | |||
| // [self requestDeviceData]; | |||
| break; | |||
| case NELBleManagerConnectStateCentralScanning: | |||
| self.bleStatusLabel.text = @"正在扫描..."; | |||
| break; | |||
| default: | |||
| break; | |||
| } | |||
| } | |||
| - (void)requestDeviceData { | |||
| dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 1.0), dispatch_get_main_queue(), ^{ | |||
| //获取 设置设备信息 | |||
| [self.bleManager meatProbeRequestCustomData]; | |||
| }); | |||
| } | |||
| // 设备状态变更 | |||
| - (void)managerDidUpdateState:(CBCentralManager *)central { | |||
| NSLog(@"%s state:%@", __func__, @(central.state)); | |||
| if (central.state == CBManagerStatePoweredOn) { | |||
| [self scanBle]; | |||
| } else if (central.state == CBManagerStatePoweredOff) { | |||
| [self updateBleStatusView:NELBleManagerConnectStateCentralPowerOff]; | |||
| } | |||
| } | |||
| - (void)managerScanState:(BOOL)scanning { | |||
| NSLog(@"%s scanning:%@", __func__, @(scanning)); | |||
| if (scanning) { | |||
| [self updateBleStatusView:NELBleManagerConnectStateCentralScanning]; | |||
| } | |||
| } | |||
| // 扫描到设备 | |||
| - (void)managerDidDiscoverPeripheral:(ELAILinkPeripheral *)peripheral { | |||
| NSLog(@"managerDidDiscoverPeripheral cid:%02x vid:%02x pid:%02x mac:%@", peripheral.cid, peripheral.vid, peripheral.pid, peripheral.macAddressString); | |||
| if ([peripheral.macAddressString isEqualToString:self.per.macAddressString]) { | |||
| [self.bleManager stopScan]; | |||
| [self.bleManager connectAILinkPeripheral:peripheral]; | |||
| } | |||
| } | |||
| - (void)managerDidUpdateConnect:(NELBleManagerConnectState)state { | |||
| NSLog(@"%s NELBleManagerConnectState:%@", __func__, @(state)); | |||
| [self updateBleStatusView:state]; | |||
| } | |||
| //A7数据 | |||
| - (void)aiLinkBleReceiveA7Data:(NSData *)payload { | |||
| NSLog(@"%s #### payload:%@", __func__, payload); | |||
| ELMeatProbeBleTemperatureStruct temperatureInfo = [ELMeatProbeBleTool parseTemperature:payload]; | |||
| if (temperatureInfo.createTime == 0) { | |||
| return; | |||
| } | |||
| NSString *log = [NSString stringWithFormat:@"internalTemprature:%@%@ (%@%@) ambientTemperature:%@%@ (%@%@)", @(temperatureInfo.internalTemperature_C), @"℃", @(temperatureInfo.internalTemperature_F), @"℉", @(temperatureInfo.ambientTemperature_C), @"℃", @(temperatureInfo.ambientTemperature_F), @"℉"]; | |||
| [self addLog:log]; | |||
| } | |||
| //A6数据 | |||
| - (void)aiLinkBleReceiveA6Data:(NSData *)packet { | |||
| NSLog(@"%s ##### packet:%@", __func__, packet); | |||
| Byte *bytes = (Byte *)packet.bytes; | |||
| Byte cmd = bytes[2]; | |||
| if (cmd == ELInetGetCmdTypeGetBatteryState) { | |||
| int power = self.bleManager.battery.power; | |||
| ELBatteryChargingState state = self.bleManager.battery.state; | |||
| NSLog(@"##### state: %lu power: %d", (unsigned long)state, power); | |||
| NSString *log = [NSString stringWithFormat:@"battery state:%@ power:%@", @(state), @(power)]; | |||
| [self addLog:log]; | |||
| return; | |||
| } | |||
| if (cmd == ELInetGetCmdTypeGetBMVersion) { | |||
| NSString *bmVersion = self.bleManager.bmVersion; | |||
| NSLog(@"##### bmVersion: %@", bmVersion); | |||
| return; | |||
| } | |||
| if (cmd == ELInetGetCmdTypeGetBMVersionPro) { | |||
| NSString *bmVersionPro = self.bleManager.bmVersionPro; | |||
| NSLog(@"##### bmVersionPro: %@", bmVersionPro); | |||
| return; | |||
| } | |||
| if (cmd == ELInetGetCmdTypeGetBasicInfoData) { | |||
| NSLog(@"##### ELInetGetCmdTypeGetBasicInfoData: %@", packet); | |||
| Byte state = bytes[3]; | |||
| if (state == 0x01) { | |||
| NSData *custom = [packet subdataWithRange:NSMakeRange(4, 128)]; | |||
| NSString *log = [NSString stringWithFormat:@"custom:%@", custom]; | |||
| [self addLog:log]; | |||
| } else { | |||
| NSString *log = [NSString stringWithFormat:@"custom:nil"]; | |||
| [self addLog:log]; | |||
| } | |||
| return; | |||
| } | |||
| } | |||
| #pragma mark - addLog | |||
| - (void)addLog:(NSString *)log { | |||
| [self addLog:log newline:YES]; | |||
| } | |||
| - (void)addWithoutNewlineLog:(NSString *)log { | |||
| [self addLog:log newline:NO]; | |||
| } | |||
| - (void)addLog:(NSString *)log newline:(BOOL)newline { | |||
| NSDateFormatter *format = [[NSDateFormatter alloc] init]; | |||
| format.dateFormat = @"HH:mm:ss.SSS"; | |||
| NSString *time = [format stringFromDate:[NSDate date]]; | |||
| if (newline) { | |||
| self.logTextView.text = [self.logTextView.text stringByAppendingFormat:@"%@ %@\n", time, log]; | |||
| } else { | |||
| self.logTextView.text = [self.logTextView.text stringByAppendingFormat:@"%@ %@", time, log]; | |||
| } | |||
| [self.logTextView scrollRangeToVisible:NSMakeRange(self.logTextView.text.length, 1)]; | |||
| } | |||
| @end | |||
| @@ -0,0 +1,145 @@ | |||
| <?xml version="1.0" encoding="UTF-8"?> | |||
| <document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="21701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES"> | |||
| <device id="retina6_12" orientation="portrait" appearance="light"/> | |||
| <dependencies> | |||
| <deployment identifier="iOS"/> | |||
| <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="21679"/> | |||
| <capability name="Safe area layout guides" minToolsVersion="9.0"/> | |||
| <capability name="System colors in document resources" minToolsVersion="11.0"/> | |||
| <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> | |||
| </dependencies> | |||
| <objects> | |||
| <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="MeatProbeVC"> | |||
| <connections> | |||
| <outlet property="bleStatusLabel" destination="7bY-Ib-xgF" id="obS-2C-ezt"/> | |||
| <outlet property="logTextView" destination="aWC-up-Yoe" id="Gad-hB-MrW"/> | |||
| <outlet property="view" destination="thx-ue-KPs" id="ozx-bW-w8j"/> | |||
| </connections> | |||
| </placeholder> | |||
| <view clearsContextBeforeDrawing="NO" contentMode="scaleToFill" id="thx-ue-KPs"> | |||
| <rect key="frame" x="0.0" y="0.0" width="393" height="852"/> | |||
| <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> | |||
| <subviews> | |||
| <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="LZQ-xA-pA3"> | |||
| <rect key="frame" x="16" y="346" width="31" height="30"/> | |||
| <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/> | |||
| <state key="normal" title="清空"/> | |||
| <connections> | |||
| <action selector="clearAction:" destination="-1" eventType="touchUpInside" id="P6P-KV-phg"/> | |||
| </connections> | |||
| </button> | |||
| <button hidden="YES" opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Wia-UQ-8Ld"> | |||
| <rect key="frame" x="346" y="346" width="31" height="30"/> | |||
| <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/> | |||
| <state key="normal" title="分享"/> | |||
| <connections> | |||
| <action selector="shareLogAction:" destination="-1" eventType="touchUpInside" id="e5W-ic-RSS"/> | |||
| </connections> | |||
| </button> | |||
| <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Stauts" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="7bY-Ib-xgF"> | |||
| <rect key="frame" x="0.0" y="63" width="393" height="21"/> | |||
| <fontDescription key="fontDescription" type="system" pointSize="17"/> | |||
| <nil key="textColor"/> | |||
| <nil key="highlightedColor"/> | |||
| </label> | |||
| <view clipsSubviews="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="2cp-J6-wNZ"> | |||
| <rect key="frame" x="8" y="384" width="377" height="434"/> | |||
| <subviews> | |||
| <textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" showsHorizontalScrollIndicator="NO" indicatorStyle="white" editable="NO" selectable="NO" translatesAutoresizingMaskIntoConstraints="NO" id="aWC-up-Yoe"> | |||
| <rect key="frame" x="0.0" y="0.0" width="377" height="434"/> | |||
| <color key="backgroundColor" systemColor="labelColor"/> | |||
| <color key="textColor" systemColor="opaqueSeparatorColor"/> | |||
| <fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="10"/> | |||
| <textInputTraits key="textInputTraits" autocapitalizationType="sentences"/> | |||
| </textView> | |||
| </subviews> | |||
| <color key="backgroundColor" systemColor="systemBackgroundColor"/> | |||
| <constraints> | |||
| <constraint firstItem="aWC-up-Yoe" firstAttribute="leading" secondItem="2cp-J6-wNZ" secondAttribute="leading" id="IA2-sg-ktX"/> | |||
| <constraint firstAttribute="bottom" secondItem="aWC-up-Yoe" secondAttribute="bottom" id="NbF-DQ-HWh"/> | |||
| <constraint firstItem="aWC-up-Yoe" firstAttribute="top" secondItem="2cp-J6-wNZ" secondAttribute="top" id="UvG-mE-0OI"/> | |||
| <constraint firstAttribute="trailing" secondItem="aWC-up-Yoe" secondAttribute="trailing" id="YF8-Au-gGR"/> | |||
| </constraints> | |||
| <userDefinedRuntimeAttributes> | |||
| <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius"> | |||
| <real key="value" value="8"/> | |||
| </userDefinedRuntimeAttribute> | |||
| </userDefinedRuntimeAttributes> | |||
| </view> | |||
| <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="RjY-Pb-1ZL"> | |||
| <rect key="frame" x="24" y="108" width="145.33333333333334" height="35"/> | |||
| <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/> | |||
| <state key="normal" title="Button"/> | |||
| <buttonConfiguration key="configuration" style="filled" title="请求自定义数据"/> | |||
| <connections> | |||
| <action selector="customDataRequestAction:" destination="-1" eventType="touchUpInside" id="4HT-gK-erD"/> | |||
| </connections> | |||
| </button> | |||
| <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="6wU-4y-kXJ"> | |||
| <rect key="frame" x="201.33333333333337" y="108" width="146" height="35"/> | |||
| <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/> | |||
| <state key="normal" title="Button"/> | |||
| <buttonConfiguration key="configuration" style="filled" title="发送自定义数据"/> | |||
| <connections> | |||
| <action selector="customDataSendAction:" destination="-1" eventType="touchUpInside" id="Tgn-0e-wxU"/> | |||
| </connections> | |||
| </button> | |||
| <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Vm8-VU-scN"> | |||
| <rect key="frame" x="202" y="159" width="93.333333333333314" height="35"/> | |||
| <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/> | |||
| <state key="normal" title="Button"/> | |||
| <buttonConfiguration key="configuration" style="filled" title="单位切换"/> | |||
| <connections> | |||
| <action selector="switchUnitAction:" destination="-1" eventType="touchUpInside" id="Gkc-6R-oeG"/> | |||
| </connections> | |||
| </button> | |||
| <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="ttt-Hs-Tk9"> | |||
| <rect key="frame" x="24" y="159" width="146" height="35"/> | |||
| <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/> | |||
| <state key="normal" title="Button"/> | |||
| <buttonConfiguration key="configuration" style="filled" title="清除自定义数据"/> | |||
| <connections> | |||
| <action selector="customDataClearAction:" destination="-1" eventType="touchUpInside" id="VKf-Yq-l4b"/> | |||
| </connections> | |||
| </button> | |||
| </subviews> | |||
| <viewLayoutGuide key="safeArea" id="5ya-cg-e71"/> | |||
| <color key="backgroundColor" systemColor="systemBackgroundColor"/> | |||
| <constraints> | |||
| <constraint firstItem="Vm8-VU-scN" firstAttribute="top" secondItem="RjY-Pb-1ZL" secondAttribute="bottom" constant="16" id="3fa-3k-CsR"/> | |||
| <constraint firstItem="7bY-Ib-xgF" firstAttribute="leading" secondItem="5ya-cg-e71" secondAttribute="leading" id="5iU-uI-ukE"/> | |||
| <constraint firstItem="5ya-cg-e71" firstAttribute="trailing" secondItem="Wia-UQ-8Ld" secondAttribute="trailing" constant="16" id="GYI-zv-QJU"/> | |||
| <constraint firstItem="7bY-Ib-xgF" firstAttribute="top" secondItem="5ya-cg-e71" secondAttribute="top" constant="4" id="KNZ-xZ-Kvy"/> | |||
| <constraint firstItem="ttt-Hs-Tk9" firstAttribute="top" secondItem="RjY-Pb-1ZL" secondAttribute="bottom" constant="16" id="Lji-qd-u0z"/> | |||
| <constraint firstItem="6wU-4y-kXJ" firstAttribute="leading" secondItem="RjY-Pb-1ZL" secondAttribute="trailing" constant="32" id="M6a-6u-DWR"/> | |||
| <constraint firstItem="RjY-Pb-1ZL" firstAttribute="leading" secondItem="5ya-cg-e71" secondAttribute="leading" constant="24" id="NYf-r3-SxK"/> | |||
| <constraint firstItem="2cp-J6-wNZ" firstAttribute="top" secondItem="7bY-Ib-xgF" secondAttribute="bottom" constant="300" id="P0n-PG-LvG"/> | |||
| <constraint firstItem="2cp-J6-wNZ" firstAttribute="top" secondItem="Wia-UQ-8Ld" secondAttribute="bottom" constant="8" symbolic="YES" id="SWO-jj-7Mh"/> | |||
| <constraint firstItem="RjY-Pb-1ZL" firstAttribute="top" secondItem="7bY-Ib-xgF" secondAttribute="bottom" constant="24" id="TRo-Mu-UVA"/> | |||
| <constraint firstItem="6wU-4y-kXJ" firstAttribute="top" secondItem="7bY-Ib-xgF" secondAttribute="bottom" constant="24" id="Uqf-4D-Cl0"/> | |||
| <constraint firstItem="2cp-J6-wNZ" firstAttribute="leading" secondItem="5ya-cg-e71" secondAttribute="leading" constant="8" id="Z3M-US-a9v"/> | |||
| <constraint firstItem="5ya-cg-e71" firstAttribute="trailing" secondItem="2cp-J6-wNZ" secondAttribute="trailing" constant="8" id="ZSu-l2-kID"/> | |||
| <constraint firstItem="Vm8-VU-scN" firstAttribute="leading" secondItem="ttt-Hs-Tk9" secondAttribute="trailing" constant="32" id="gT6-xc-gTY"/> | |||
| <constraint firstItem="ttt-Hs-Tk9" firstAttribute="leading" secondItem="5ya-cg-e71" secondAttribute="leading" constant="24" id="hNT-dX-rsK"/> | |||
| <constraint firstItem="LZQ-xA-pA3" firstAttribute="leading" secondItem="5ya-cg-e71" secondAttribute="leading" constant="16" id="kW2-mg-yKj"/> | |||
| <constraint firstItem="5ya-cg-e71" firstAttribute="bottom" secondItem="2cp-J6-wNZ" secondAttribute="bottom" id="ms3-vm-VMQ"/> | |||
| <constraint firstItem="5ya-cg-e71" firstAttribute="trailing" secondItem="7bY-Ib-xgF" secondAttribute="trailing" id="qVb-2b-hVU"/> | |||
| <constraint firstItem="2cp-J6-wNZ" firstAttribute="top" secondItem="LZQ-xA-pA3" secondAttribute="bottom" constant="8" symbolic="YES" id="tY0-Fc-dAj"/> | |||
| <constraint firstItem="7bY-Ib-xgF" firstAttribute="centerX" secondItem="thx-ue-KPs" secondAttribute="centerX" id="yRU-ks-IeE"/> | |||
| </constraints> | |||
| <point key="canvasLocation" x="53" y="20"/> | |||
| </view> | |||
| <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/> | |||
| </objects> | |||
| <resources> | |||
| <systemColor name="labelColor"> | |||
| <color red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> | |||
| </systemColor> | |||
| <systemColor name="opaqueSeparatorColor"> | |||
| <color red="0.77647058823529413" green="0.77647058823529413" blue="0.78431372549019607" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> | |||
| </systemColor> | |||
| <systemColor name="systemBackgroundColor"> | |||
| <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> | |||
| </systemColor> | |||
| </resources> | |||
| </document> | |||
| @@ -0,0 +1,27 @@ | |||
| // | |||
| // ELAILinkBleManager+MeatProbeBox.h | |||
| // AILinkBleSDK | |||
| // | |||
| // Created by LarryZhang on 2023/2/16. | |||
| // | |||
| #import <AILinkBleSDK/ELAILinkBleManager.h> | |||
| NS_ASSUME_NONNULL_BEGIN | |||
| @interface ELAILinkBleManager (MeatProbeBox) | |||
| //APP 获取设备状态数据(Type:01) | |||
| - (NSData *)meatProbeBoxGetStatus; | |||
| //设置、获取设备参数数据(Type:03) | |||
| - (NSData *)meatProbeBoxSendCustomData:(NSData *)customData withMac:(NSData *)macData; | |||
| - (NSData *)meatProbeBoxRequestCustomDataWithMac:(NSData *)macData; | |||
| - (NSData *)meatProbeBoxClearCustomDataWithMac:(NSData *)macData; | |||
| //切换单位(Type:04) | |||
| - (NSData *)meatProbeBoxSwitchUint:(ELDeviceTemperatureUnit)unit; | |||
| @end | |||
| NS_ASSUME_NONNULL_END | |||
| @@ -0,0 +1,55 @@ | |||
| // | |||
| // ELAILinkBleManager+MeatProbeBox.m | |||
| // AILinkBleSDK | |||
| // | |||
| // Created by LarryZhang on 2023/2/16. | |||
| // | |||
| #import "ELAILinkBleManager+MeatProbeBox.h" | |||
| #import "ELMeatProbeBoxBleHeader.h" | |||
| @implementation ELAILinkBleManager (MeatProbeBox) | |||
| //APP 获取设备状态数据(Type:01) | |||
| - (NSData *)meatProbeBoxGetStatus { | |||
| Byte bytes[] = { ELMeatProbeBoxCMDAppGetStatus_Type01, 0x01 }; | |||
| NSData *payload = [[NSData alloc] initWithBytes:bytes length:sizeof(bytes)]; | |||
| [self sendA7PayloadNoEncryption:payload]; | |||
| return payload; | |||
| } | |||
| //设置、获取设备参数数据(Type:03) | |||
| - (NSData *)meatProbeBoxSendCustomData:(NSData *)customData withMac:(NSData *)macData { | |||
| Byte bytes[] = { ELMeatProbeBoxCMDCustomData_Type03, 0x01 }; | |||
| NSMutableData *payload = [[NSMutableData alloc] initWithBytes:bytes length:sizeof(bytes)]; | |||
| [payload appendData:macData]; | |||
| [payload appendData:customData]; | |||
| [self sendA7PayloadNoEncryption:payload.copy]; | |||
| return payload.copy; | |||
| } | |||
| - (NSData *)meatProbeBoxRequestCustomDataWithMac:(NSData *)macData { | |||
| Byte bytes[] = { ELMeatProbeBoxCMDCustomData_Type03, 0x02 }; | |||
| NSMutableData *payload = [[NSMutableData alloc] initWithBytes:bytes length:sizeof(bytes)]; | |||
| [payload appendData:macData]; | |||
| [self sendA7PayloadNoEncryption:payload.copy]; | |||
| return payload.copy; | |||
| } | |||
| - (NSData *)meatProbeBoxClearCustomDataWithMac:(NSData *)macData { | |||
| Byte bytes[] = { ELMeatProbeBoxCMDCustomData_Type03, 0x00 }; | |||
| NSMutableData *payload = [[NSMutableData alloc] initWithBytes:bytes length:sizeof(bytes)]; | |||
| [payload appendData:macData]; | |||
| [self sendA7PayloadNoEncryption:payload.copy]; | |||
| return payload.copy; | |||
| } | |||
| //切换单位(Type:04) | |||
| - (NSData *)meatProbeBoxSwitchUint:(ELDeviceTemperatureUnit)unit { | |||
| Byte bytes[] = { ELMeatProbeBoxCMDAppSwitchUnit_Type04, unit }; | |||
| NSData *payload = [[NSData alloc] initWithBytes:bytes length:sizeof(bytes)]; | |||
| [self sendA7PayloadNoEncryption:payload]; | |||
| return payload; | |||
| } | |||
| @end | |||
| @@ -0,0 +1,23 @@ | |||
| // | |||
| // ELMeatProbeBoxBleHeader.h | |||
| // Pods | |||
| // | |||
| // Created by LarryZhang on 2023/3/30. | |||
| // | |||
| #ifndef ELMeatProbeBoxBleHeader_h | |||
| #define ELMeatProbeBoxBleHeader_h | |||
| typedef NS_ENUM(UInt8, ELMeatProbeBoxCMD) { | |||
| ELMeatProbeBoxCMDAppGetStatus_Type01 = 0x01, //0x01:Type:APP 获取设备状态 | |||
| ELMeatProbeBoxCMDMcuUploadStatus_Type02 = 0x02, //0x02:Type:设备上报设备数据 | |||
| ELMeatProbeBoxCMDCustomData_Type03 = 0x03, //0x03:Type:APP 设置、获取设备相关信息 | |||
| ELMeatProbeBoxCMDAppSwitchUnit_Type04 = 0x04, //0x04:Type:切换单位 | |||
| }; | |||
| #endif /* ELMeatProbeBoxBleHeader_h */ | |||
| @@ -0,0 +1,102 @@ | |||
| // | |||
| // ELMeatProbeBoxBleParser.h | |||
| // AILinkBleSDK | |||
| // | |||
| // Created by LarryZhang on 2023/2/16. | |||
| // | |||
| #import <Foundation/Foundation.h> | |||
| #import <AILinkBleSDK/ELSDKHeader.h> | |||
| NS_ASSUME_NONNULL_BEGIN | |||
| @class ELMeatProbeBoxBleBoxStatusModel, ELMeatProbeBoxBleProbeStatusModel; | |||
| @protocol ELMeatProbeBoxBleParserDelegate; | |||
| @interface ELMeatProbeBoxBleParser : NSObject | |||
| @property (nonatomic, copy) NSString *mac; | |||
| @property (nonatomic, weak) id<ELMeatProbeBoxBleParserDelegate> delegate; | |||
| - (void)parseA7Payload:(NSData *)payloadData; | |||
| @end | |||
| @protocol ELMeatProbeBoxBleParserDelegate <NSObject> | |||
| @optional | |||
| //MCU 上报设备状态数据(Type:02) | |||
| - (void)meatProbeBoxBleParser:(ELMeatProbeBoxBleParser *)bleParser boxStatus:(ELMeatProbeBoxBleBoxStatusModel *)boxStatus probeStatus:(ELMeatProbeBoxBleProbeStatusModel *)probeStatus offline:(BOOL)offline; | |||
| //设置、获取设备参数数据(Type:03) | |||
| - (void)meatProbeBoxBleParser:(ELMeatProbeBoxBleParser *)bleParser state:(BOOL)state mac:(NSString *)mac customData:(NSData *)customData; | |||
| //切换单位(Type:04) | |||
| - (void)meatProbeBoxBleParser:(ELMeatProbeBoxBleParser *)bleParser unit:(ELDeviceTemperatureUnit)unit; | |||
| @end | |||
| @interface ELMeatProbeBoxBleBoxStatusModel : NSObject | |||
| //设备状态数据协议版本:0x01 | |||
| @property (nonatomic, assign) UInt8 version; | |||
| //支持的探针数量 M | |||
| @property (nonatomic, assign) UInt8 probeMaxCount; | |||
| //当前连接的探针数量 N | |||
| @property (nonatomic, assign) UInt8 probeCount; | |||
| //充电盒电池状态 | |||
| @property (nonatomic, assign) UInt8 batteryStatus; | |||
| @property (nonatomic, assign) UInt8 batteryPercent; | |||
| //温度单位 | |||
| @property (nonatomic, assign) ELDeviceTemperatureUnit unit; | |||
| //生成时间 | |||
| @property (nonatomic, assign) double timestamp; | |||
| @end | |||
| @interface ELMeatProbeBoxBleProbeStatusModel : NSObject | |||
| //探针编号(1-M) 无法确定可连 接探针的编号,上报 0xFF | |||
| @property (nonatomic, assign) UInt8 index; | |||
| @property (nonatomic, assign) UInt8 dataIndex; | |||
| //探针 mac 地址 | |||
| @property (nonatomic, strong) NSData *macData; | |||
| @property (nonatomic, copy) NSString *macString; | |||
| //食物温度 | |||
| @property (nonatomic, assign) NSInteger internalTemperature; | |||
| @property (nonatomic, assign) ELDeviceTemperatureUnit internalTemperatureUnit; | |||
| @property (nonatomic, assign) UInt16 internalTemperatureRaw; | |||
| //环境温度 | |||
| @property (nonatomic, assign) NSInteger ambientTemperature; | |||
| @property (nonatomic, assign) ELDeviceTemperatureUnit ambientTemperatureUnit; | |||
| @property (nonatomic, assign) UInt16 ambientTemperatureRaw; | |||
| //探针电池状态 | |||
| @property (nonatomic, assign) UInt8 batteryStatus; | |||
| @property (nonatomic, assign) UInt8 batteryPercent; | |||
| @property (nonatomic, assign) UInt8 batteryRaw; | |||
| //探针插入食物状态 | |||
| @property (nonatomic, assign) UInt8 insertStatusRaw; | |||
| //生成时间 | |||
| @property (nonatomic, assign) double timestamp; | |||
| //数据无效 | |||
| - (void)makeInvalid; | |||
| @end | |||
| NS_ASSUME_NONNULL_END | |||
| @@ -0,0 +1,228 @@ | |||
| // | |||
| // ELMeatProbeBoxBleParser.m | |||
| // AILinkBleSDK | |||
| // | |||
| // Created by LarryZhang on 2023/2/16. | |||
| // | |||
| #import "ELMeatProbeBoxBleParser.h" | |||
| #import "ELMeatProbeBoxBleHeader.h" | |||
| #import <objc/runtime.h> | |||
| @interface ELMeatProbeBoxBleParser () | |||
| @property (nonatomic, strong) ELMeatProbeBoxBleBoxStatusModel *boxStatusModel; | |||
| @property (nonatomic, strong) ELMeatProbeBoxBleProbeStatusModel *probeStatusModel; | |||
| @end | |||
| @implementation ELMeatProbeBoxBleParser | |||
| - (instancetype)init { | |||
| if (self = [super init]) { | |||
| _boxStatusModel = [[ELMeatProbeBoxBleBoxStatusModel alloc] init]; | |||
| _probeStatusModel = [[ELMeatProbeBoxBleProbeStatusModel alloc] init]; | |||
| } | |||
| return self; | |||
| } | |||
| #pragma mark - 解析包 | |||
| - (void)parseA7Payload:(NSData *)payloadData { | |||
| UInt8 *bytes = (Byte *)payloadData.bytes; | |||
| // UInt8 len = payloadData.length; | |||
| UInt8 cmd = bytes[0]; | |||
| switch (cmd) { | |||
| case ELMeatProbeBoxCMDMcuUploadStatus_Type02: | |||
| [self handelMcuUploadStatus:payloadData]; | |||
| break; | |||
| case ELMeatProbeBoxCMDCustomData_Type03: | |||
| [self handelCustomData:payloadData]; | |||
| break; | |||
| case ELMeatProbeBoxCMDAppSwitchUnit_Type04: | |||
| [self handelSwitchUnit:payloadData]; | |||
| break; | |||
| default: | |||
| break; | |||
| } | |||
| } | |||
| - (void)handelCustomData:(NSData *)payloadData { | |||
| UInt8 *bytes = (Byte *)payloadData.bytes; | |||
| UInt8 len = payloadData.length; | |||
| BOOL state = bytes[1]; | |||
| NSData *mac = [payloadData subdataWithRange:NSMakeRange(2, 6)]; | |||
| Byte *bytesMac = (Byte *)mac.bytes; | |||
| NSString *macString = [NSString stringWithFormat:@"%02X:%02X:%02X:%02X:%02X:%02X", bytesMac[5], bytesMac[4], bytesMac[3], bytesMac[2], bytesMac[1], bytesMac[0]]; | |||
| NSData *customData = [payloadData subdataWithRange:NSMakeRange(8, len - 8)]; | |||
| if (self.delegate && [self.delegate respondsToSelector:@selector(meatProbeBoxBleParser:state:mac:customData:)]) { | |||
| [self.delegate meatProbeBoxBleParser:self state:state mac:macString customData:customData]; | |||
| } | |||
| } | |||
| - (void)handelSwitchUnit:(NSData *)payloadData { | |||
| UInt8 *bytes = (Byte *)payloadData.bytes; | |||
| //UInt8 len = payloadData.length; | |||
| ELDeviceTemperatureUnit unit = bytes[1]; | |||
| if (self.delegate && [self.delegate respondsToSelector:@selector(meatProbeBoxBleParser:unit:)]) { | |||
| [self.delegate meatProbeBoxBleParser:self unit:unit]; | |||
| } | |||
| } | |||
| - (void)handelMcuUploadStatus:(NSData *)payloadData { | |||
| UInt8 *bytes = (Byte *)payloadData.bytes; | |||
| UInt8 len = payloadData.length; | |||
| _boxStatusModel.version = bytes[1]; | |||
| UInt8 probeMaxCount = bytes[2]; | |||
| if (probeMaxCount < 1) { | |||
| return;//探针数排错 | |||
| } | |||
| _boxStatusModel.probeMaxCount = probeMaxCount; | |||
| UInt8 probeCount = bytes[3]; | |||
| if (probeCount > probeMaxCount) { | |||
| return;//探针数排错 | |||
| } | |||
| if (len < 1 + 8 + 16 * probeCount) { | |||
| return;//数据长度排错 | |||
| } | |||
| _boxStatusModel.probeCount = probeCount; | |||
| _boxStatusModel.batteryStatus = bytes[4] >> 7; | |||
| _boxStatusModel.batteryPercent = bytes[4] & 0x7F; | |||
| _boxStatusModel.unit = bytes[5]; | |||
| UInt8 reserved = bytes[6]; | |||
| reserved = bytes[7]; | |||
| reserved = bytes[8]; | |||
| double timestamp = [[NSDate date] timeIntervalSince1970]; | |||
| _boxStatusModel.timestamp = timestamp; | |||
| // for (int i=0, j=9+16*i; i<probeCount; i++) { | |||
| for (int i=0, j=9+16*i; i<probeMaxCount; i++) { | |||
| _probeStatusModel.index = bytes[j+0]; | |||
| _probeStatusModel.dataIndex = i; | |||
| _probeStatusModel.macData = [payloadData subdataWithRange:NSMakeRange(j+1, 6)]; | |||
| _probeStatusModel.macString = [NSString stringWithFormat:@"%02X:%02X:%02X:%02X:%02X:%02X", bytes[j+6], bytes[j+5], bytes[j+4], bytes[j+3], bytes[j+2], bytes[j+1]]; | |||
| if ([_probeStatusModel.macString isEqualToString:@"00:00:00:00:00:00"] || [_probeStatusModel.macString isEqualToString:@"FF:FF:FF:FF:FF:FF"]) { | |||
| continue; | |||
| } | |||
| if (i >= probeCount) { | |||
| [_probeStatusModel makeInvalid]; | |||
| _probeStatusModel.timestamp = timestamp; | |||
| if (self.delegate && [self.delegate respondsToSelector:@selector(meatProbeBoxBleParser:boxStatus:probeStatus:offline:)]) { | |||
| [self.delegate meatProbeBoxBleParser:self boxStatus:_boxStatusModel probeStatus:_probeStatusModel offline:YES]; | |||
| } | |||
| continue; | |||
| } | |||
| UInt16 temp = (bytes[j+7] << 8) | bytes[j+8]; | |||
| _probeStatusModel.internalTemperatureRaw = temp; | |||
| _probeStatusModel.internalTemperatureUnit = (temp & 0x8000) ? ELDeviceTemperatureUnit_F : ELDeviceTemperatureUnit_C; | |||
| _probeStatusModel.internalTemperature = (temp & 0x4000) ? -(temp & 0x3FFF) : (temp & 0x3FFF); | |||
| temp = (bytes[j+9] << 8) | bytes[j+10]; | |||
| _probeStatusModel.ambientTemperatureRaw = temp; | |||
| _probeStatusModel.ambientTemperatureUnit = (temp & 0x8000) ? ELDeviceTemperatureUnit_F : ELDeviceTemperatureUnit_C; | |||
| _probeStatusModel.ambientTemperature = (temp & 0x4000) ? -(temp & 0x3FFF) : (temp & 0x3FFF); | |||
| #if DEBUG | |||
| // _probeStatusModel.ambientTemperature += 40; | |||
| #endif | |||
| UInt8 battery = bytes[j+11]; | |||
| _probeStatusModel.batteryRaw = battery; | |||
| _probeStatusModel.batteryStatus = battery >> 7; | |||
| _probeStatusModel.batteryPercent = battery & 0x7F; | |||
| _probeStatusModel.insertStatusRaw = bytes[j+12]; | |||
| _probeStatusModel.timestamp = timestamp; | |||
| if (self.delegate && [self.delegate respondsToSelector:@selector(meatProbeBoxBleParser:boxStatus:probeStatus:offline:)]) { | |||
| [self.delegate meatProbeBoxBleParser:self boxStatus:_boxStatusModel probeStatus:_probeStatusModel offline:NO]; | |||
| } | |||
| } | |||
| } | |||
| @end | |||
| @implementation ELMeatProbeBoxBleBoxStatusModel | |||
| #pragma mark ---- description | |||
| - (NSString *)description { | |||
| NSMutableString *desc = [NSStringFromClass([self class]) stringByAppendingString:@": {\n"].mutableCopy; | |||
| unsigned int count; | |||
| Ivar *ivar = class_copyIvarList([self class], &count); | |||
| for (int i = 0 ; i < count ; i++) { | |||
| Ivar iv = ivar[i]; | |||
| const char *name = ivar_getName(iv); | |||
| NSString *strName = [NSString stringWithUTF8String:name]; | |||
| //利用KVC取值 | |||
| id value = [self valueForKey:strName]; | |||
| [desc appendString:[NSString stringWithFormat:@" %@: %@,\n", strName, value]]; | |||
| } | |||
| free(ivar); | |||
| [desc appendString:@"}"]; | |||
| return desc; | |||
| } | |||
| - (NSString *)debugDescription { | |||
| return [self description]; | |||
| } | |||
| @end | |||
| @implementation ELMeatProbeBoxBleProbeStatusModel | |||
| //数据无效 | |||
| - (void)makeInvalid { | |||
| self.internalTemperatureRaw = 0xFFFF; | |||
| self.internalTemperatureUnit = 0; | |||
| self.internalTemperature = 0; | |||
| self.ambientTemperatureRaw = 0xFFFF; | |||
| self.ambientTemperatureUnit = 0; | |||
| self.ambientTemperature = 0; | |||
| self.batteryRaw = 0xFF; | |||
| self.batteryStatus = 0; | |||
| self.batteryPercent = 0; | |||
| self.insertStatusRaw = 0; | |||
| } | |||
| #pragma mark ---- description | |||
| - (NSString *)description { | |||
| NSMutableString *desc = [NSStringFromClass([self class]) stringByAppendingString:@": {\n"].mutableCopy; | |||
| unsigned int count; | |||
| Ivar *ivar = class_copyIvarList([self class], &count); | |||
| for (int i = 0 ; i < count ; i++) { | |||
| Ivar iv = ivar[i]; | |||
| const char *name = ivar_getName(iv); | |||
| NSString *strName = [NSString stringWithUTF8String:name]; | |||
| //利用KVC取值 | |||
| id value = [self valueForKey:strName]; | |||
| [desc appendString:[NSString stringWithFormat:@" %@: %@,\n", strName, value]]; | |||
| } | |||
| free(ivar); | |||
| [desc appendString:@"}"]; | |||
| return desc; | |||
| } | |||
| - (NSString *)debugDescription { | |||
| return [self description]; | |||
| } | |||
| @end | |||
| @@ -0,0 +1,21 @@ | |||
| // | |||
| // MeatProbeBoxVC.h | |||
| // AILinkBleSDK_Example | |||
| // | |||
| // Created by LarryZhang on 2023/3/7. | |||
| // Copyright © 2023 zhengzida. All rights reserved. | |||
| // | |||
| #import <UIKit/UIKit.h> | |||
| NS_ASSUME_NONNULL_BEGIN | |||
| @class ELAILinkPeripheral; | |||
| @interface MeatProbeBoxVC : UIViewController | |||
| @property (nonatomic, strong) ELAILinkPeripheral *per; | |||
| @end | |||
| NS_ASSUME_NONNULL_END | |||
| @@ -0,0 +1,292 @@ | |||
| // | |||
| // MeatProbeBoxVC.m | |||
| // AILinkBleSDK_Example | |||
| // | |||
| // Created by LarryZhang on 2023/3/7. | |||
| // Copyright © 2023 zhengzida. All rights reserved. | |||
| // | |||
| #import "MeatProbeBoxVC.h" | |||
| #import <AILinkBleSDK/ELAILinkBleManager.h> | |||
| #import <AILinkBleSDK/NSData+AILinkBle.h> | |||
| #import "ELAILinkBleManager+MeatProbeBox.h" | |||
| #import "ELMeatProbeBoxBleParser.h" | |||
| @interface MeatProbeBoxVC () <ELAILinkBleManagerDelegate, ELMeatProbeBoxBleParserDelegate> | |||
| @property (weak, nonatomic) IBOutlet UILabel *bleStatusLabel; | |||
| @property (weak, nonatomic) IBOutlet UITextView *logTextView; | |||
| @property (nonatomic, strong) ELAILinkBleManager *bleManager; | |||
| @property (nonatomic, assign) NELBleManagerConnectState bleConnectState; | |||
| @property (nonatomic, strong) ELMeatProbeBoxBleParser *bleParser; | |||
| @property (nonatomic, strong) NSMutableSet *probeList; | |||
| @property (nonatomic, strong) ELMeatProbeBoxBleBoxStatusModel *boxStatus; | |||
| @end | |||
| @implementation MeatProbeBoxVC | |||
| - (void)viewDidLoad { | |||
| [super viewDidLoad]; | |||
| // Do any additional setup after loading the view from its nib. | |||
| self.probeList = [NSMutableSet set]; | |||
| [self initBle]; | |||
| } | |||
| - (void)dealloc { | |||
| [self deinitBle]; | |||
| } | |||
| #pragma mark - Action | |||
| - (IBAction)customDataRequestAction:(id)sender { | |||
| for (NSData *mac in self.probeList) { | |||
| NSData *payload = [self.bleManager meatProbeBoxRequestCustomDataWithMac:mac]; | |||
| NSString *log = [NSString stringWithFormat:@"发: payload: %@", payload]; | |||
| [self addLog:log]; | |||
| } | |||
| } | |||
| - (IBAction)customDataSendAction:(id)sender { | |||
| for (NSData *mac in self.probeList) { | |||
| NSData *payload = [self.bleManager meatProbeBoxSendCustomData:[self coustumData] withMac:mac]; | |||
| NSString *log = [NSString stringWithFormat:@"发: payload: %@", payload]; | |||
| [self addLog:log]; | |||
| } | |||
| } | |||
| - (IBAction)customDataClearAction:(id)sender { | |||
| for (NSData *mac in self.probeList) { | |||
| NSData *payload = [self.bleManager meatProbeBoxClearCustomDataWithMac:mac]; | |||
| NSString *log = [NSString stringWithFormat:@"发: payload: %@", payload]; | |||
| [self addLog:log]; | |||
| } | |||
| } | |||
| - (IBAction)switchUnitAction:(id)sender { | |||
| if (self.boxStatus.unit == 1) { | |||
| NSData *payload = [self.bleManager meatProbeBoxSwitchUint:0]; | |||
| NSString *log = [NSString stringWithFormat:@"发: payload: %@ -- 切换单位 to C", payload]; | |||
| [self addLog:log]; | |||
| } else { | |||
| NSData *payload = [self.bleManager meatProbeBoxSwitchUint:1]; | |||
| NSString *log = [NSString stringWithFormat:@"发: payload: %@ -- 切换单位 to F", payload]; | |||
| [self addLog:log]; | |||
| } | |||
| } | |||
| - (IBAction)clearAction:(id)sender { | |||
| self.logTextView.text = @""; | |||
| } | |||
| - (IBAction)shareLogAction:(id)sender { | |||
| } | |||
| - (NSData *)coustumData { | |||
| //自定义数据 | |||
| //*******要验证设备必须支持128字节payload | |||
| Byte bytes[128]; | |||
| memset(bytes, 0, sizeof(bytes)); | |||
| for (int i=0; i<sizeof(bytes); i++) { | |||
| bytes[i] = 0x80 + i; | |||
| } | |||
| NSData *data = [NSData dataWithBytes:bytes length:sizeof(bytes)]; | |||
| NSLog(@"meatProbeAction() data:%@", data); | |||
| return data; | |||
| } | |||
| #pragma mark - ELAILinkBleManagerDelegate | |||
| - (void)initBle { | |||
| self.bleManager = [[ELAILinkBleManager alloc] init]; | |||
| self.bleManager.ailinkDelegate = self; | |||
| self.bleParser = [ELMeatProbeBoxBleParser new]; | |||
| self.bleParser.delegate = self; | |||
| } | |||
| - (void)scanBle { | |||
| [self.bleManager scanFilterWithCidArray:@[@(self.per.cid)]]; | |||
| } | |||
| - (void)connect:(ELAILinkPeripheral *)peripheral { | |||
| [self.bleManager connectAILinkPeripheral:peripheral]; | |||
| [self updateBleStatusView:NELBleManagerConnectStateConnecting]; | |||
| } | |||
| - (void)deinitBle { | |||
| [self.bleManager stopScan]; | |||
| self.bleManager.ailinkDelegate = nil; | |||
| [self.bleManager disconnectPeripheral]; | |||
| } | |||
| - (void)updateBleStatusView:(NELBleManagerConnectState)state { | |||
| if (self.bleManager.central.state == CBManagerStatePoweredOff) { | |||
| self.bleStatusLabel.text = @"蓝牙关闭"; | |||
| [self addLog:self.bleStatusLabel.text]; | |||
| return; | |||
| } | |||
| switch (state) { | |||
| case NELBleManagerConnectStateDisconnected: | |||
| self.bleStatusLabel.text = @"断开连接"; | |||
| break; | |||
| case NELBleManagerConnectStateFailed: | |||
| case NELBleManagerConnectStateFailedValidation: | |||
| self.bleStatusLabel.text = @"连接失败"; | |||
| break; | |||
| case NELBleManagerConnectStateConnecting: | |||
| self.bleStatusLabel.text = @"正在连接..."; | |||
| break; | |||
| case NELBleManagerConnectStatePassed: | |||
| self.bleStatusLabel.text = @"连接成功"; | |||
| [self requestDeviceData]; | |||
| break; | |||
| case NELBleManagerConnectStateCentralScanning: | |||
| self.bleStatusLabel.text = @"正在扫描..."; | |||
| break; | |||
| default: | |||
| break; | |||
| } | |||
| [self addLog:self.bleStatusLabel.text]; | |||
| } | |||
| - (void)requestDeviceData { | |||
| dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 1.0), dispatch_get_main_queue(), ^{ | |||
| // //APP获取设备功能列表 | |||
| // [self.bleManager airDetectorRequestDeviceFunctions]; | |||
| // //APP获取设备状态 //0x03 CMD:获取设备状态 | |||
| // [self.bleManager airDetectorRequestDeviceStatus]; | |||
| }); | |||
| } | |||
| // 设备状态变更 | |||
| - (void)managerDidUpdateState:(CBCentralManager *)central { | |||
| NSLog(@"%s state:%@", __func__, @(central.state)); | |||
| if (central.state == CBManagerStatePoweredOn) { | |||
| [self scanBle]; | |||
| } else if (central.state == CBManagerStatePoweredOff) { | |||
| self.bleConnectState = NELBleManagerConnectStateCentralPowerOff; | |||
| [self updateBleStatusView:NELBleManagerConnectStateCentralPowerOff]; | |||
| } | |||
| } | |||
| - (void)managerScanState:(BOOL)scanning { | |||
| NSLog(@"%s scanning:%@", __func__, @(scanning)); | |||
| if (scanning) { | |||
| [self updateBleStatusView:NELBleManagerConnectStateCentralScanning]; | |||
| } | |||
| } | |||
| // 扫描到设备 | |||
| - (void)managerDidDiscoverPeripheral:(ELAILinkPeripheral *)peripheral { | |||
| NSLog(@"managerDidDiscoverPeripheral cid:%02x vid:%02x pid:%02x mac:%@", peripheral.cid, peripheral.vid, peripheral.pid, peripheral.macAddressString); | |||
| if ([peripheral.macAddressString isEqualToString:self.per.macAddressString]) { | |||
| [self.bleManager stopScan]; | |||
| [self connect:peripheral]; | |||
| } | |||
| } | |||
| - (void)managerDidUpdateConnect:(NELBleManagerConnectState)state { | |||
| NSLog(@"%s NELBleManagerConnectState:%@", __func__, @(state)); | |||
| [self updateBleStatusView:state]; | |||
| } | |||
| //A7数据 | |||
| - (void)aiLinkBleReceiveA7Data:(NSData *)payload { | |||
| NSLog(@"%s #### payload:%@", __func__, payload.elHexString); | |||
| NSString *log = [NSString stringWithFormat:@"收: payload: %@", payload.elHexString]; | |||
| [self addLog:log]; | |||
| [self.bleParser parseA7Payload:payload]; | |||
| } | |||
| //A6数据 | |||
| - (void)aiLinkBleReceiveA6Data:(NSData *)packet { | |||
| NSLog(@"%s ##### packet:%@", __func__, packet.elHexString); | |||
| Byte *bytes = (Byte *)packet.bytes; | |||
| Byte cmd = bytes[2]; | |||
| if (cmd == ELInetGetCmdTypeGetBatteryState) { | |||
| int power = self.bleManager.battery.power; | |||
| ELBatteryChargingState state = self.bleManager.battery.state; | |||
| NSLog(@"##### state: %lu power: %d", (unsigned long)state, power); | |||
| } | |||
| if (cmd == ELInetGetCmdTypeGetBMVersion) { | |||
| NSString *bmVersion = self.bleManager.bmVersion; | |||
| NSLog(@"##### bmVersion: %@", bmVersion); | |||
| } | |||
| if (cmd == ELInetGetCmdTypeGetBMVersionPro) { | |||
| NSString *bmVersionPro = self.bleManager.bmVersionPro; | |||
| NSLog(@"##### bmVersionPro: %@", bmVersionPro); | |||
| } | |||
| } | |||
| #pragma mark - ELMeatProbeBoxBleParserDelegate | |||
| //MCU 上报设备状态数据(Type:02) | |||
| - (void)meatProbeBoxBleParser:(ELMeatProbeBoxBleParser *)bleParser boxStatus:(ELMeatProbeBoxBleBoxStatusModel *)boxStatus probeStatus:(ELMeatProbeBoxBleProbeStatusModel *)probeStatus offline:(BOOL)offline { | |||
| NSLog(@"##### boxStatus(): %@ probeStatus(): %@", boxStatus, probeStatus); | |||
| self.boxStatus = boxStatus; | |||
| NSString *log = [NSString stringWithFormat:@"boxStatus: { probeMaxCount:%hhu, probeCount:%hhu, batteryStatus:%hhu batteryPercent:%hhu, unit:%ld }", boxStatus.probeMaxCount, boxStatus.probeCount, boxStatus.batteryStatus, boxStatus.batteryPercent, boxStatus.unit]; | |||
| [self addLog:log]; | |||
| NSString *log2 = [NSString stringWithFormat:@"probeStatus: { index:%hhu, macString:%@, internalTemperature:%ld, ambientTemperature:%ld, batteryPercent:%hhu }", probeStatus.index, probeStatus.macString, probeStatus.internalTemperature, probeStatus.ambientTemperature, probeStatus.batteryPercent]; | |||
| [self addLog:log2]; | |||
| if (![self.probeList containsObject:probeStatus.macData]) { | |||
| [self.probeList addObject:probeStatus.macData]; | |||
| NSData *payload = [self.bleManager meatProbeBoxRequestCustomDataWithMac:probeStatus.macData]; | |||
| NSString *log = [NSString stringWithFormat:@"发: payload: %@", payload]; | |||
| [self addLog:log]; | |||
| } | |||
| } | |||
| //设置、获取设备参数数据(Type:03) | |||
| - (void)meatProbeBoxBleParser:(ELMeatProbeBoxBleParser *)bleParser state:(BOOL)state mac:(NSData *)mac customData:(NSData *)customData { | |||
| NSLog(@"##### state:%d mac:%@ customData():%@", state, mac, customData); | |||
| NSLog(@""); | |||
| } | |||
| //切换单位(Type:04) | |||
| - (void)meatProbeBoxBleParser:(ELMeatProbeBoxBleParser *)bleParser unit:(ELDeviceTemperatureUnit)unit { | |||
| NSLog(@"##### unit(): %@", @(unit)); | |||
| NSLog(@""); | |||
| } | |||
| #pragma mark - addLog | |||
| - (void)addLog:(NSString *)log { | |||
| [self addLog:log newline:YES]; | |||
| } | |||
| - (void)addWithoutNewlineLog:(NSString *)log { | |||
| [self addLog:log newline:NO]; | |||
| } | |||
| - (void)addLog:(NSString *)log newline:(BOOL)newline { | |||
| NSDateFormatter *format = [[NSDateFormatter alloc] init]; | |||
| format.dateFormat = @"HH:mm:ss.SSS"; | |||
| NSString *time = [format stringFromDate:[NSDate date]]; | |||
| if (newline) { | |||
| self.logTextView.text = [self.logTextView.text stringByAppendingFormat:@"%@ %@\n", time, log]; | |||
| } else { | |||
| self.logTextView.text = [self.logTextView.text stringByAppendingFormat:@"%@ %@", time, log]; | |||
| } | |||
| [self.logTextView scrollRangeToVisible:NSMakeRange(self.logTextView.text.length, 1)]; | |||
| } | |||
| @end | |||
| @@ -0,0 +1,145 @@ | |||
| <?xml version="1.0" encoding="UTF-8"?> | |||
| <document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="21507" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES"> | |||
| <device id="retina6_12" orientation="portrait" appearance="light"/> | |||
| <dependencies> | |||
| <deployment identifier="iOS"/> | |||
| <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="21505"/> | |||
| <capability name="Safe area layout guides" minToolsVersion="9.0"/> | |||
| <capability name="System colors in document resources" minToolsVersion="11.0"/> | |||
| <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> | |||
| </dependencies> | |||
| <objects> | |||
| <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="MeatProbeBoxVC"> | |||
| <connections> | |||
| <outlet property="bleStatusLabel" destination="Rgz-Ge-utp" id="h2s-vl-sLn"/> | |||
| <outlet property="logTextView" destination="Txf-5E-hsN" id="Azk-gu-Gls"/> | |||
| <outlet property="view" destination="i5M-Pr-FkT" id="sfx-zR-JGt"/> | |||
| </connections> | |||
| </placeholder> | |||
| <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/> | |||
| <view clearsContextBeforeDrawing="NO" contentMode="scaleToFill" id="i5M-Pr-FkT"> | |||
| <rect key="frame" x="0.0" y="0.0" width="393" height="852"/> | |||
| <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> | |||
| <subviews> | |||
| <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="K5I-eH-HGA"> | |||
| <rect key="frame" x="16" y="346" width="31" height="30"/> | |||
| <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/> | |||
| <state key="normal" title="清空"/> | |||
| <connections> | |||
| <action selector="clearAction:" destination="-1" eventType="touchUpInside" id="o2p-MO-8pL"/> | |||
| </connections> | |||
| </button> | |||
| <button hidden="YES" opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="lwE-Xr-Dac"> | |||
| <rect key="frame" x="346" y="346" width="31" height="30"/> | |||
| <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/> | |||
| <state key="normal" title="分享"/> | |||
| <connections> | |||
| <action selector="shareLogAction:" destination="-1" eventType="touchUpInside" id="aLe-00-nz6"/> | |||
| </connections> | |||
| </button> | |||
| <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Stauts" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Rgz-Ge-utp"> | |||
| <rect key="frame" x="0.0" y="63" width="393" height="21"/> | |||
| <fontDescription key="fontDescription" type="system" pointSize="17"/> | |||
| <nil key="textColor"/> | |||
| <nil key="highlightedColor"/> | |||
| </label> | |||
| <view clipsSubviews="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="I1h-EM-UuI"> | |||
| <rect key="frame" x="8" y="384" width="377" height="434"/> | |||
| <subviews> | |||
| <textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" showsHorizontalScrollIndicator="NO" indicatorStyle="white" editable="NO" selectable="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Txf-5E-hsN"> | |||
| <rect key="frame" x="0.0" y="0.0" width="377" height="434"/> | |||
| <color key="backgroundColor" systemColor="labelColor"/> | |||
| <color key="textColor" systemColor="opaqueSeparatorColor"/> | |||
| <fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="10"/> | |||
| <textInputTraits key="textInputTraits" autocapitalizationType="sentences"/> | |||
| </textView> | |||
| </subviews> | |||
| <color key="backgroundColor" systemColor="systemBackgroundColor"/> | |||
| <constraints> | |||
| <constraint firstAttribute="bottom" secondItem="Txf-5E-hsN" secondAttribute="bottom" id="CLf-PD-bjv"/> | |||
| <constraint firstItem="Txf-5E-hsN" firstAttribute="top" secondItem="I1h-EM-UuI" secondAttribute="top" id="RHZ-uy-ZqR"/> | |||
| <constraint firstItem="Txf-5E-hsN" firstAttribute="leading" secondItem="I1h-EM-UuI" secondAttribute="leading" id="vQ7-WS-tPk"/> | |||
| <constraint firstAttribute="trailing" secondItem="Txf-5E-hsN" secondAttribute="trailing" id="wsr-Tq-aYp"/> | |||
| </constraints> | |||
| <userDefinedRuntimeAttributes> | |||
| <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius"> | |||
| <real key="value" value="8"/> | |||
| </userDefinedRuntimeAttribute> | |||
| </userDefinedRuntimeAttributes> | |||
| </view> | |||
| <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="U2W-tX-U1Z"> | |||
| <rect key="frame" x="24" y="108" width="145.33333333333334" height="35"/> | |||
| <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/> | |||
| <state key="normal" title="Button"/> | |||
| <buttonConfiguration key="configuration" style="filled" title="请求自定义数据"/> | |||
| <connections> | |||
| <action selector="customDataRequestAction:" destination="-1" eventType="touchUpInside" id="EbK-Xt-NEO"/> | |||
| </connections> | |||
| </button> | |||
| <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="MNm-EU-G2q"> | |||
| <rect key="frame" x="201.33333333333337" y="108" width="146" height="35"/> | |||
| <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/> | |||
| <state key="normal" title="Button"/> | |||
| <buttonConfiguration key="configuration" style="filled" title="发送自定义数据"/> | |||
| <connections> | |||
| <action selector="customDataSendAction:" destination="-1" eventType="touchUpInside" id="Bgd-AX-0sf"/> | |||
| </connections> | |||
| </button> | |||
| <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="AXK-mu-b6T"> | |||
| <rect key="frame" x="202" y="159" width="93.333333333333314" height="35"/> | |||
| <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/> | |||
| <state key="normal" title="Button"/> | |||
| <buttonConfiguration key="configuration" style="filled" title="单位切换"/> | |||
| <connections> | |||
| <action selector="switchUnitAction:" destination="-1" eventType="touchUpInside" id="qmW-aP-fla"/> | |||
| </connections> | |||
| </button> | |||
| <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="7tV-LN-Ahy"> | |||
| <rect key="frame" x="24" y="159" width="146" height="35"/> | |||
| <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/> | |||
| <state key="normal" title="Button"/> | |||
| <buttonConfiguration key="configuration" style="filled" title="清除自定义数据"/> | |||
| <connections> | |||
| <action selector="customDataClearAction:" destination="-1" eventType="touchUpInside" id="ZWX-NO-7e6"/> | |||
| </connections> | |||
| </button> | |||
| </subviews> | |||
| <viewLayoutGuide key="safeArea" id="Q5M-cg-NOt"/> | |||
| <color key="backgroundColor" systemColor="systemBackgroundColor"/> | |||
| <constraints> | |||
| <constraint firstItem="Rgz-Ge-utp" firstAttribute="leading" secondItem="Q5M-cg-NOt" secondAttribute="leading" id="26n-ac-URx"/> | |||
| <constraint firstItem="K5I-eH-HGA" firstAttribute="leading" secondItem="Q5M-cg-NOt" secondAttribute="leading" constant="16" id="43e-FM-L00"/> | |||
| <constraint firstItem="U2W-tX-U1Z" firstAttribute="top" secondItem="Rgz-Ge-utp" secondAttribute="bottom" constant="24" id="76S-le-4CY"/> | |||
| <constraint firstItem="Rgz-Ge-utp" firstAttribute="centerX" secondItem="i5M-Pr-FkT" secondAttribute="centerX" id="Cuz-sL-8PR"/> | |||
| <constraint firstItem="7tV-LN-Ahy" firstAttribute="leading" secondItem="Q5M-cg-NOt" secondAttribute="leading" constant="24" id="DGY-hw-cQW"/> | |||
| <constraint firstItem="Q5M-cg-NOt" firstAttribute="bottom" secondItem="I1h-EM-UuI" secondAttribute="bottom" id="Dfj-32-bLS"/> | |||
| <constraint firstItem="I1h-EM-UuI" firstAttribute="top" secondItem="K5I-eH-HGA" secondAttribute="bottom" constant="8" symbolic="YES" id="EN4-TU-LIY"/> | |||
| <constraint firstItem="Rgz-Ge-utp" firstAttribute="top" secondItem="Q5M-cg-NOt" secondAttribute="top" constant="4" id="NV7-q2-a68"/> | |||
| <constraint firstItem="AXK-mu-b6T" firstAttribute="top" secondItem="U2W-tX-U1Z" secondAttribute="bottom" constant="16" id="Nnq-dz-fTJ"/> | |||
| <constraint firstItem="7tV-LN-Ahy" firstAttribute="top" secondItem="U2W-tX-U1Z" secondAttribute="bottom" constant="16" id="RA0-gL-Ljv"/> | |||
| <constraint firstItem="AXK-mu-b6T" firstAttribute="leading" secondItem="7tV-LN-Ahy" secondAttribute="trailing" constant="32" id="RAL-eu-lGT"/> | |||
| <constraint firstItem="MNm-EU-G2q" firstAttribute="leading" secondItem="U2W-tX-U1Z" secondAttribute="trailing" constant="32" id="Su5-Ls-bvw"/> | |||
| <constraint firstItem="Q5M-cg-NOt" firstAttribute="trailing" secondItem="I1h-EM-UuI" secondAttribute="trailing" constant="8" id="Ulp-Zv-w68"/> | |||
| <constraint firstItem="Q5M-cg-NOt" firstAttribute="trailing" secondItem="lwE-Xr-Dac" secondAttribute="trailing" constant="16" id="aZt-4V-Vkm"/> | |||
| <constraint firstItem="I1h-EM-UuI" firstAttribute="top" secondItem="Rgz-Ge-utp" secondAttribute="bottom" constant="300" id="gWj-B6-gld"/> | |||
| <constraint firstItem="I1h-EM-UuI" firstAttribute="leading" secondItem="Q5M-cg-NOt" secondAttribute="leading" constant="8" id="mGL-Xz-QuQ"/> | |||
| <constraint firstItem="Q5M-cg-NOt" firstAttribute="trailing" secondItem="Rgz-Ge-utp" secondAttribute="trailing" id="myT-ol-sQQ"/> | |||
| <constraint firstItem="U2W-tX-U1Z" firstAttribute="leading" secondItem="Q5M-cg-NOt" secondAttribute="leading" constant="24" id="onE-X9-raT"/> | |||
| <constraint firstItem="MNm-EU-G2q" firstAttribute="top" secondItem="Rgz-Ge-utp" secondAttribute="bottom" constant="24" id="vx8-hV-lTa"/> | |||
| <constraint firstItem="I1h-EM-UuI" firstAttribute="top" secondItem="lwE-Xr-Dac" secondAttribute="bottom" constant="8" symbolic="YES" id="zvN-yN-K2g"/> | |||
| </constraints> | |||
| <point key="canvasLocation" x="53" y="20"/> | |||
| </view> | |||
| </objects> | |||
| <resources> | |||
| <systemColor name="labelColor"> | |||
| <color red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> | |||
| </systemColor> | |||
| <systemColor name="opaqueSeparatorColor"> | |||
| <color red="0.77647058823529413" green="0.77647058823529413" blue="0.78431372549019607" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> | |||
| </systemColor> | |||
| <systemColor name="systemBackgroundColor"> | |||
| <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> | |||
| </systemColor> | |||
| </resources> | |||
| </document> | |||
| @@ -20,6 +20,7 @@ | |||
| #import "BabyScaleViewController.h" | |||
| #import "BloodScanViewController.h" | |||
| #import "HeightGuageScanViewController.h" | |||
| #import "BroadcastHeightGuage.h" | |||
| #import "RemoteControlScanViewController.h" | |||
| #import "ForeheadScanViewController.h" | |||
| #import "ThermometerScanViewController.h" | |||
| @@ -42,6 +43,8 @@ | |||
| #import "HeightBodyFatScaleVC.h" | |||
| #import "MeatProbeVC.h" | |||
| #import "MeatProbeBoxVC.h" | |||
| @@ -69,6 +72,9 @@ | |||
| [ELDemoDeviceModel modelWithIndex:@"04" imageName:@"type_baby_scale_ic" title:@"Baby Scale" subtitle:@"婴儿秤" entryVCName:NSStringFromClass(BabyScaleViewController.class)], | |||
| [ELDemoDeviceModel modelWithIndex:@"05" imageName:@"type_sphygmomanometer_ic" title:@"Sphygmomanometer" subtitle:@"血压计" entryVCName:NSStringFromClass(BloodScanViewController.class)], | |||
| [ELDemoDeviceModel modelWithIndex:@"06" imageName:@"type_height_measuring_instrument" title:@"Height Guage" subtitle:@"身高仪" entryVCName:NSStringFromClass(HeightGuageScanViewController.class)], | |||
| [ELDemoDeviceModel modelWithIndex:@"06B" imageName:@"type_height_measuring_instrument" title:@"Broadcast Height Guage" subtitle:@"广播身高仪" entryVCName:NSStringFromClass(BroadcastHeightGuage.class)], | |||
| [ELDemoDeviceModel modelWithIndex:@"07" imageName:@"type_control_vision_ic" title:@"Remote Control" subtitle:@"遥控器" entryVCName:NSStringFromClass(RemoteControlScanViewController.class)], | |||
| [ELDemoDeviceModel modelWithIndex:@"08" imageName:@"type_temperature_gun_ic" title:@"Forehead thermometer" subtitle:@"额温枪" entryVCName:NSStringFromClass(ForeheadScanViewController.class)], | |||
| [ELDemoDeviceModel modelWithIndex:@"09" imageName:@"type_thermometer_ic" title:@"Digital thermometer" subtitle:@"温度计" entryVCName:NSStringFromClass(ThermometerScanViewController.class)], | |||
| @@ -93,6 +99,9 @@ | |||
| [ELDemoDeviceModel modelWithIndex:@"25" imageName:@"height_body_fat_scale_type_ic" title:@"HeightBodyFatScale" subtitle:@"身高体脂秤" entryVCName:NSStringFromClass(HeightBodyFatScaleVC.class) cids:@[@(ELSupportDeviceTypeHeightBodyFatScale)]], | |||
| [ELDemoDeviceModel modelWithIndex:@"26" imageName:@"meat_probe_type_ic" title:@"MeatProbe" subtitle:@"食物探针" entryVCName:NSStringFromClass(MeatProbeVC.class) cids:@[@(ELSupportDeviceTypeMeatProbe)]], | |||
| [ELDemoDeviceModel modelWithIndex:@"27" imageName:@"ailink_cid85_type_ic" title:@"MeatProbeBox" subtitle:@"食物探针盒子" entryVCName:NSStringFromClass(MeatProbeBoxVC.class) cids:@[@(ELSupportDeviceTypeMeatProbeBox)]], | |||
| ]; | |||
| } | |||
| @@ -10,4 +10,5 @@ | |||
| | 1.5.9| 20230206 | larry | 增加 身高体脂秤,优化 Demo UI | | |||
| | 1.5.11 | 20230327 | larry | 增加 蓝牙体重秤 | | |||
| | 1.5.15 | 20230427 | larry | 修改 增加 蓝牙牙刷防飞溅 | | |||
| | 1.6.1 | 20230626 | larry | 修改 增加 广播身高仪 食物探针 食物探针盒子 支持 | | |||