78DC4DF62990FB40006C6911 /* ELDeviceScanCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 78DC4DF02990FB40006C6911 /* ELDeviceScanCell.xib */; }; | 78DC4DF62990FB40006C6911 /* ELDeviceScanCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 78DC4DF02990FB40006C6911 /* ELDeviceScanCell.xib */; }; | ||||
78DC4DFB2990FC10006C6911 /* HeightBodyFatScaleVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 78DC4DF82990FC10006C6911 /* HeightBodyFatScaleVC.m */; }; | 78DC4DFB2990FC10006C6911 /* HeightBodyFatScaleVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 78DC4DF82990FC10006C6911 /* HeightBodyFatScaleVC.m */; }; | ||||
78DC4DFC2990FC10006C6911 /* HeightBodyFatScaleVC.xib in Resources */ = {isa = PBXBuildFile; fileRef = 78DC4DF92990FC10006C6911 /* HeightBodyFatScaleVC.xib */; }; | 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 */; }; | 952D19A1276DE80000ED3A0C /* AILinkBleSDK.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 952D19A0276DE80000ED3A0C /* AILinkBleSDK.framework */; }; | ||||
95565B792786EA3B000265EA /* SkipConnectionViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 95565B752786EA3B000265EA /* SkipConnectionViewController.m */; }; | 95565B792786EA3B000265EA /* SkipConnectionViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 95565B752786EA3B000265EA /* SkipConnectionViewController.m */; }; | ||||
95565B7A2786EA3B000265EA /* SkipScanViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 95565B782786EA3B000265EA /* SkipScanViewController.m */; }; | 95565B7A2786EA3B000265EA /* SkipScanViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 95565B782786EA3B000265EA /* SkipScanViewController.m */; }; | ||||
78DC4DF82990FC10006C6911 /* HeightBodyFatScaleVC.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HeightBodyFatScaleVC.m; sourceTree = "<group>"; }; | 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>"; }; | 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>"; }; | 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>"; }; | 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>"; }; | 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>"; }; | 95565B762786EA3B000265EA /* SkipScanViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SkipScanViewController.h; sourceTree = "<group>"; }; | ||||
955725E0276C38CC003BFBAC /* 04_BabyScale */, | 955725E0276C38CC003BFBAC /* 04_BabyScale */, | ||||
955725BA276C38CC003BFBAC /* 05_BloodPressure */, | 955725BA276C38CC003BFBAC /* 05_BloodPressure */, | ||||
955725E5276C38CC003BFBAC /* 06_HeightGuage */, | 955725E5276C38CC003BFBAC /* 06_HeightGuage */, | ||||
78E07B662A49663F00E68200 /* 06B_BroadcastHeightGuage */, | |||||
9557261E276C38CD003BFBAC /* 07_RemoteControl */, | 9557261E276C38CD003BFBAC /* 07_RemoteControl */, | ||||
95572614276C38CD003BFBAC /* 08_Forehead */, | 95572614276C38CD003BFBAC /* 08_Forehead */, | ||||
955725F9276C38CD003BFBAC /* 09_Thermometer */, | 955725F9276C38CD003BFBAC /* 09_Thermometer */, | ||||
955725F4276C38CD003BFBAC /* 23_FaceMask */, | 955725F4276C38CD003BFBAC /* 23_FaceMask */, | ||||
95565B742786EA3B000265EA /* 24_Skip */, | 95565B742786EA3B000265EA /* 24_Skip */, | ||||
78DC4DF72990FC10006C6911 /* 25_HeightBodyFatScale */, | 78DC4DF72990FC10006C6911 /* 25_HeightBodyFatScale */, | ||||
78E07B6C2A49664D00E68200 /* 26_MeatProbe */, | |||||
78E07B702A49664E00E68200 /* 27_MeatProbeBox */, | |||||
); | ); | ||||
path = DeviceDemo; | path = DeviceDemo; | ||||
sourceTree = "<group>"; | sourceTree = "<group>"; | ||||
path = AILinkBleSDKDemo/DeviceDemo/25_HeightBodyFatScale; | path = AILinkBleSDKDemo/DeviceDemo/25_HeightBodyFatScale; | ||||
sourceTree = SOURCE_ROOT; | 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 */ = { | 95565B742786EA3B000265EA /* 24_Skip */ = { | ||||
isa = PBXGroup; | isa = PBXGroup; | ||||
children = ( | children = ( | ||||
files = ( | files = ( | ||||
78DC4DF42990FB40006C6911 /* ELDeviceTypeCell.xib in Resources */, | 78DC4DF42990FB40006C6911 /* ELDeviceTypeCell.xib in Resources */, | ||||
E622E287243F1D41003C319D /* Main.storyboard in Resources */, | E622E287243F1D41003C319D /* Main.storyboard in Resources */, | ||||
78E07B7E2A49664E00E68200 /* MeatProbeBoxVC.xib in Resources */, | |||||
78DC4DE32990FB2E006C6911 /* ELDemoScanVC.xib in Resources */, | 78DC4DE32990FB2E006C6911 /* ELDemoScanVC.xib in Resources */, | ||||
E622E26E243F1CA6003C319D /* LaunchScreen.storyboard in Resources */, | E622E26E243F1CA6003C319D /* LaunchScreen.storyboard in Resources */, | ||||
E622E26B243F1CA6003C319D /* Assets.xcassets in Resources */, | E622E26B243F1CA6003C319D /* Assets.xcassets in Resources */, | ||||
78DC4DF62990FB40006C6911 /* ELDeviceScanCell.xib in Resources */, | 78DC4DF62990FB40006C6911 /* ELDeviceScanCell.xib in Resources */, | ||||
78E07B7B2A49664E00E68200 /* MeatProbeVC.xib in Resources */, | |||||
78350BBD29D28C1200456695 /* README.md in Resources */, | 78350BBD29D28C1200456695 /* README.md in Resources */, | ||||
78E07B6B2A49664000E68200 /* BroadcastHeightGuage.xib in Resources */, | |||||
78DC4DFC2990FC10006C6911 /* HeightBodyFatScaleVC.xib in Resources */, | 78DC4DFC2990FC10006C6911 /* HeightBodyFatScaleVC.xib in Resources */, | ||||
); | ); | ||||
runOnlyForDeploymentPostprocessing = 0; | runOnlyForDeploymentPostprocessing = 0; | ||||
95572641276C38CD003BFBAC /* ELEightScaleRecordModel.m in Sources */, | 95572641276C38CD003BFBAC /* ELEightScaleRecordModel.m in Sources */, | ||||
95572634276C38CD003BFBAC /* HeightGuageScanViewController.m in Sources */, | 95572634276C38CD003BFBAC /* HeightGuageScanViewController.m in Sources */, | ||||
958B4EA7263C08E800476BAE /* UIButton+WZAdd.m in Sources */, | 958B4EA7263C08E800476BAE /* UIButton+WZAdd.m in Sources */, | ||||
78E07B7C2A49664E00E68200 /* ELAILinkBleManager+MeatProbeBox.m in Sources */, | |||||
958B4EA9263C08E800476BAE /* ELSelectView.m in Sources */, | 958B4EA9263C08E800476BAE /* ELSelectView.m in Sources */, | ||||
95572635276C38CD003BFBAC /* HeightGuageConnectViewController.m in Sources */, | 95572635276C38CD003BFBAC /* HeightGuageConnectViewController.m in Sources */, | ||||
95572639276C38CD003BFBAC /* NutritionScaleConnectionViewController.m in Sources */, | 95572639276C38CD003BFBAC /* NutritionScaleConnectionViewController.m in Sources */, | ||||
95572647276C38CD003BFBAC /* ForeheadConnectViewController.m in Sources */, | 95572647276C38CD003BFBAC /* ForeheadConnectViewController.m in Sources */, | ||||
E622E271243F1CA6003C319D /* main.m in Sources */, | E622E271243F1CA6003C319D /* main.m in Sources */, | ||||
78E07B7F2A49664E00E68200 /* MeatProbeBoxVC.m in Sources */, | |||||
95572646276C38CD003BFBAC /* FoodThermometerConnectionViewController.m in Sources */, | 95572646276C38CD003BFBAC /* FoodThermometerConnectionViewController.m in Sources */, | ||||
958B4EB3263C08E800476BAE /* View+MASAdditions.m in Sources */, | 958B4EB3263C08E800476BAE /* View+MASAdditions.m in Sources */, | ||||
958B4EB1263C08E800476BAE /* MASLayoutConstraint.m in Sources */, | 958B4EB1263C08E800476BAE /* MASLayoutConstraint.m in Sources */, | ||||
9557263A276C38CD003BFBAC /* FaceMaskConnectionViewController.m in Sources */, | 9557263A276C38CD003BFBAC /* FaceMaskConnectionViewController.m in Sources */, | ||||
95572636276C38CD003BFBAC /* OximeterScanViewController.m in Sources */, | 95572636276C38CD003BFBAC /* OximeterScanViewController.m in Sources */, | ||||
78E07B7D2A49664E00E68200 /* ELMeatProbeBoxBleParser.m in Sources */, | |||||
958B4EA4263C08E800476BAE /* ELInputAlertView.m in Sources */, | 958B4EA4263C08E800476BAE /* ELInputAlertView.m in Sources */, | ||||
958B4EB6263C08E800476BAE /* MASViewAttribute.m in Sources */, | 958B4EB6263C08E800476BAE /* MASViewAttribute.m in Sources */, | ||||
958B4EBB263C08E800476BAE /* InheritConnectViewController.m in Sources */, | 958B4EBB263C08E800476BAE /* InheritConnectViewController.m in Sources */, | ||||
78DC4DF32990FB40006C6911 /* ELDemoButton.m in Sources */, | 78DC4DF32990FB40006C6911 /* ELDemoButton.m in Sources */, | ||||
958B4EA5263C08E800476BAE /* UILabel+WZAdd.m in Sources */, | 958B4EA5263C08E800476BAE /* UILabel+WZAdd.m in Sources */, | ||||
95572633276C38CD003BFBAC /* BabyScaleConnectViewController.m in Sources */, | 95572633276C38CD003BFBAC /* BabyScaleConnectViewController.m in Sources */, | ||||
78E07B7A2A49664E00E68200 /* MeatProbeVC.m in Sources */, | |||||
95572644276C38CD003BFBAC /* BodyFatScaleConnectViewController.m in Sources */, | 95572644276C38CD003BFBAC /* BodyFatScaleConnectViewController.m in Sources */, | ||||
958B4EBD263C08E800476BAE /* AppDelegate.m in Sources */, | 958B4EBD263C08E800476BAE /* AppDelegate.m in Sources */, | ||||
95565B792786EA3B000265EA /* SkipConnectionViewController.m in Sources */, | 95565B792786EA3B000265EA /* SkipConnectionViewController.m in Sources */, | ||||
95572645276C38CD003BFBAC /* FoodThermometerScanViewController.m in Sources */, | 95572645276C38CD003BFBAC /* FoodThermometerScanViewController.m in Sources */, | ||||
958B4EA6263C08E800476BAE /* UIView+Category.m in Sources */, | 958B4EA6263C08E800476BAE /* UIView+Category.m in Sources */, | ||||
9557262E276C38CD003BFBAC /* ELBfsWifiConnectVC.m in Sources */, | 9557262E276C38CD003BFBAC /* ELBfsWifiConnectVC.m in Sources */, | ||||
78E07B6A2A49664000E68200 /* BroadcastHeightGuage.m in Sources */, | |||||
95572637276C38CD003BFBAC /* OximeterConnectionViewController.m in Sources */, | 95572637276C38CD003BFBAC /* OximeterConnectionViewController.m in Sources */, | ||||
95572648276C38CD003BFBAC /* ForeheadScanViewController.m in Sources */, | 95572648276C38CD003BFBAC /* ForeheadScanViewController.m in Sources */, | ||||
78DC4DE42990FB2E006C6911 /* ELDemoDeviceModel.m in Sources */, | 78DC4DE42990FB2E006C6911 /* ELDemoDeviceModel.m in Sources */, | ||||
buildSettings = { | buildSettings = { | ||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; | ||||
CODE_SIGN_STYLE = Automatic; | CODE_SIGN_STYLE = Automatic; | ||||
CURRENT_PROJECT_VERSION = 20230427; | |||||
CURRENT_PROJECT_VERSION = 20230626; | |||||
DEVELOPMENT_TEAM = YEU77XR292; | DEVELOPMENT_TEAM = YEU77XR292; | ||||
FRAMEWORK_SEARCH_PATHS = ( | FRAMEWORK_SEARCH_PATHS = ( | ||||
"$(inherited)", | "$(inherited)", | ||||
"$(PROJECT_DIR)/AILinkBleSDKDemo/DeviceDemo/13_EightScale/HTBodyfat_SDK", | "$(PROJECT_DIR)/AILinkBleSDKDemo/DeviceDemo/13_EightScale/HTBodyfat_SDK", | ||||
"$(PROJECT_DIR)/AILinkBleSDKDemo/DeviceDemo/13_EightScale/BhBodyComposition120", | "$(PROJECT_DIR)/AILinkBleSDKDemo/DeviceDemo/13_EightScale/BhBodyComposition120", | ||||
); | ); | ||||
MARKETING_VERSION = 1.5.15; | |||||
MARKETING_VERSION = 1.6.1; | |||||
OTHER_LDFLAGS = "-ObjC"; | OTHER_LDFLAGS = "-ObjC"; | ||||
PRODUCT_BUNDLE_IDENTIFIER = com.pingwang.AILinkBleSDKDemo; | PRODUCT_BUNDLE_IDENTIFIER = com.pingwang.AILinkBleSDKDemo; | ||||
PRODUCT_NAME = "$(TARGET_NAME)"; | PRODUCT_NAME = "$(TARGET_NAME)"; | ||||
buildSettings = { | buildSettings = { | ||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; | ||||
CODE_SIGN_STYLE = Automatic; | CODE_SIGN_STYLE = Automatic; | ||||
CURRENT_PROJECT_VERSION = 20230427; | |||||
CURRENT_PROJECT_VERSION = 20230626; | |||||
DEVELOPMENT_TEAM = YEU77XR292; | DEVELOPMENT_TEAM = YEU77XR292; | ||||
FRAMEWORK_SEARCH_PATHS = ( | FRAMEWORK_SEARCH_PATHS = ( | ||||
"$(inherited)", | "$(inherited)", | ||||
"$(PROJECT_DIR)/AILinkBleSDKDemo/DeviceDemo/13_EightScale/HTBodyfat_SDK", | "$(PROJECT_DIR)/AILinkBleSDKDemo/DeviceDemo/13_EightScale/HTBodyfat_SDK", | ||||
"$(PROJECT_DIR)/AILinkBleSDKDemo/DeviceDemo/13_EightScale/BhBodyComposition120", | "$(PROJECT_DIR)/AILinkBleSDKDemo/DeviceDemo/13_EightScale/BhBodyComposition120", | ||||
); | ); | ||||
MARKETING_VERSION = 1.5.15; | |||||
MARKETING_VERSION = 1.6.1; | |||||
OTHER_LDFLAGS = "-ObjC"; | OTHER_LDFLAGS = "-ObjC"; | ||||
PRODUCT_BUNDLE_IDENTIFIER = com.pingwang.AILinkBleSDKDemo; | PRODUCT_BUNDLE_IDENTIFIER = com.pingwang.AILinkBleSDKDemo; | ||||
PRODUCT_NAME = "$(TARGET_NAME)"; | PRODUCT_NAME = "$(TARGET_NAME)"; |
#import "NELBleManagerHeader.h" | #import "NELBleManagerHeader.h" | ||||
#import "NELMacAddressModel.h" | #import "NELMacAddressModel.h" | ||||
#import "NSData+AILinkBle.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 "ELAILinkBleManager+MeatProbe.h" | ||||
#import "ELMeatProbeBleTool.h" | #import "ELMeatProbeBleTool.h" | ||||
#import "ELAILinkBleManager+NoiseMeter.h" | #import "ELAILinkBleManager+NoiseMeter.h" | ||||
#import "ELBroadcastNutritionFoodScaleBleManager.h" | #import "ELBroadcastNutritionFoodScaleBleManager.h" | ||||
#import "ELBroadcastNutritionFoodScaleDataModel.h" | #import "ELBroadcastNutritionFoodScaleDataModel.h" | ||||
#import "ELBfsLeaOneDataModel.h" | #import "ELBfsLeaOneDataModel.h" | ||||
#import "ELBfsOKOKDataModel.h" | |||||
#import "ELBroadcastScaleBleHeader.h" | #import "ELBroadcastScaleBleHeader.h" | ||||
#import "ELBroadcastScaleBleManager.h" | #import "ELBroadcastScaleBleManager.h" | ||||
#import "ELBroadcastScaleDataModel.h" | #import "ELBroadcastScaleDataModel.h" |
#define AILinkBleSDK_Version_h | #define AILinkBleSDK_Version_h | ||||
//版本号 SDK Version | //版本号 SDK Version | ||||
#define AiLinkBleSDKVersion @"1.5.15" //20230427 增加 蓝牙牙刷防飞溅 | |||||
#define AiLinkBleSDKVersion @"1.6.1" //20230626 增加 广播身高仪 食物探针 食物探针盒子 支持 | |||||
#endif /* AILinkBleSDK_Version_h */ | #endif /* AILinkBleSDK_Version_h */ |
// | |||||
// 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 | |||||
//MeatProbe 设置设备信息 0x35 | //MeatProbe 设置设备信息 0x35 | ||||
- (void)meatProbeSendCustomData:(NSData *_Nonnull)customData; | |||||
- (NSData *)meatProbeSendCustomData:(NSData *)customData; | |||||
//MeatProbe 设置设备信息 0x35 请求 | //MeatProbe 设置设备信息 0x35 请求 | ||||
- (void)meatProbeRequestCustomData; | |||||
- (NSData *)meatProbeRequestCustomData; | |||||
//切换温度单位 A7 | //切换温度单位 A7 | ||||
- (void)meatProbeSwitchUint:(ELDeviceTemperatureUnit)unit; | |||||
//关闭自动关机指令 A7 **调试阶段使用 | |||||
//- (void)meatProbeCloseAutoOff; | |||||
- (NSData *)meatProbeSwitchUint:(ELDeviceTemperatureUnit)unit; | |||||
@end | @end |
@interface ELAILinkBleManager (WIFI) | @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 设置命令) ============== | //============ Bluetooth WIFI calling method(蓝牙WIFI 设置命令) ============== | ||||
/** | /** |
- (NSString *)sdkVersion; | - (NSString *)sdkVersion; | ||||
+ (NSString *)sdkVersion; | + (NSString *)sdkVersion; | ||||
//扫描状态 | |||||
@property(nonatomic, assign, readonly, getter=isScanning) BOOL scanning; | @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"); | @property (nonatomic, weak) id<ELAILinkBleManagerDelegate> delegate DEPRECATED_MSG_ATTRIBUTE("use 'ailinkDelegate' only"); | ||||
@end | @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 | NS_ASSUME_NONNULL_END |
// | |||||
// 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 |
// | |||||
// 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 */ |
// | |||||
// 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 |
// | |||||
// 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 |
// | |||||
// 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 |
// | |||||
// 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 |
@return 结构体 | @return 结构体 | ||||
*/ | */ | ||||
+(struct ELMCUStateStruct)analysisBluetoothConnectState:(NSData *)data; | +(struct ELMCUStateStruct)analysisBluetoothConnectState:(NSData *)data; | ||||
//重构 | |||||
+ (ELWMStateStruct)analysisWMState:(NSData *)data; | |||||
/** | /** | ||||
解析模块通信模式 | 解析模块通信模式 |
@param stateStrct 结构体 | @param stateStrct 结构体 | ||||
*/ | */ | ||||
-(void)bluetoothManagerReceiveMCUConnectedState:(struct ELMCUStateStruct)stateStrct; | -(void)bluetoothManagerReceiveMCUConnectedState:(struct ELMCUStateStruct)stateStrct; | ||||
//重构 | |||||
-(void)bluetoothManagerReceiveWMState:(ELWMStateStruct)stateStrct; | |||||
-(void)bluetoothManagerReceiveWMStateFailCode:(WMWorkStateFailCode)failCode; | |||||
/** | /** | ||||
Query the callback of the communication mode(查询通信模式的回调) | Query the callback of the communication mode(查询通信模式的回调) |
//Start scanning(开始扫描)- 过滤 cid 列表 | //Start scanning(开始扫描)- 过滤 cid 列表 | ||||
-(void)startScanFilterCids:(NSArray<NSNumber *> *)cids; | -(void)startScanFilterCids:(NSArray<NSNumber *> *)cids; | ||||
-(void)startScanAllFilterCids:(NSArray<NSNumber *> *)cids; | |||||
//Start scanning all (开始扫描附近所有设备) | //Start scanning all (开始扫描附近所有设备) | ||||
- (void)startScanAll; | - (void)startScanAll; |
@property (nonatomic, assign) long long createTime; | @property (nonatomic, assign) long long createTime; | ||||
@property (nonatomic, assign) BOOL weightNegative; | |||||
@property (nonatomic, assign) UInt16 weightValue; | |||||
@end | @end | ||||
ELSupportDeviceTypeBroadcastScale = (0xffff +0x01) , //655536 Broadcast body fat scale(AILink广播体脂秤) | ELSupportDeviceTypeBroadcastScale = (0xffff +0x01) , //655536 Broadcast body fat scale(AILink广播体脂秤) | ||||
ELSupportDeviceTypeBroadcastHeightGauge = (0xffff + 0x03) , //65538 广播身高仪 | ELSupportDeviceTypeBroadcastHeightGauge = (0xffff + 0x03) , //65538 广播身高仪 | ||||
ELSupportDeviceTypeBroadcastScale_Lingyang = (0xffff +0x16) , //65557 凌阳广播体脂秤 | ELSupportDeviceTypeBroadcastScale_Lingyang = (0xffff +0x16) , //65557 凌阳广播体脂秤 | ||||
ELSupportDeviceTypeBroadcastBodyScale = (0xFFFF + 0x07) , //Broadcast body scale AILink广播体重秤(无体脂) | |||||
ELSupportDeviceTypeBroadcastNutritionFoodScale = (0xffff + 0x04) , //65539 广播营养秤 | ELSupportDeviceTypeBroadcastNutritionFoodScale = (0xffff + 0x04) , //65539 广播营养秤 | ||||
ELSupportDeviceTypeBroadcastHygrothermograph = (0xffff + 0x06) , //65541 广播温湿度计 | ELSupportDeviceTypeBroadcastHygrothermograph = (0xffff + 0x06) , //65541 广播温湿度计 | ||||
ELSupportDeviceTypeBroadcastScale_OKOK = (0xffff + 0x08) , //65543 OKOK广播体脂秤 | |||||
ELSupportDeviceTypeBroadcastScale_T6 = (0xffff + 0x09) , //65544 T6广播体脂秤 | |||||
}; | }; | ||||
#endif /* ELExSupportDeviceType_h */ | #endif /* ELExSupportDeviceType_h */ |
ELInetGetCmdTypeGetC_V_P_ID = 0x1E, //-Read CID, VID, PID(读取CID、VID、PID) | ELInetGetCmdTypeGetC_V_P_ID = 0x1E, //-Read CID, VID, PID(读取CID、VID、PID) | ||||
ELInetGetCmdTypeGetCommunicationMode = 0x20, //-Get module communication mode(获取模块通信模式) | ELInetGetCmdTypeGetCommunicationMode = 0x20, //-Get module communication mode(获取模块通信模式) | ||||
ELInetGetCmdTypeGetConnectState = 0x26, //-Get Bluetooth and WiFi connection status(获取蓝牙和WiFi连接状态) | ELInetGetCmdTypeGetConnectState = 0x26, //-Get Bluetooth and WiFi connection status(获取蓝牙和WiFi连接状态) | ||||
ELInetGetCmdTypeGetConnectStateFailCode = 0xAB, //- WiFi connection error 连接失败原因 | |||||
ELInetGetCmdTypeGetBatteryState = 0x28, //-Get MCU battery status(获取MCU电池状态) | ELInetGetCmdTypeGetBatteryState = 0x28, //-Get MCU battery status(获取MCU电池状态) | ||||
ELInetGetCmdTypeGetHandshake = 0x24, //-Encrypted handshake data returned by Bluetooth(蓝牙返回的加密的握手数据) | 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协议(具体见二级指令)) | ELInetGetCmdTypeGetBodyFatScaleA6Data = 0x2B, //-Body fat scale 0x2B stands for A6 protocol (see the second level instructions for details)(体脂秤0x2B代表A6协议(具体见二级指令)) | ||||
BleWiFiConnectServerFaildState faildState; | 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 | #pragma mark - AiLink unit | ||||
/** Type key of unit string(单位字符串的type key) */ | /** Type key of unit string(单位字符串的type key) */ |
///获取设备连接的wifi名称 | ///获取设备连接的wifi名称 | ||||
- (void)getBleLinkWifiName; | - (void)getBleLinkWifiName; | ||||
/** 设置设备的IP地址,端口号和访问路径 */ | |||||
- (void)setDevAccessIpAddress:(NSString *)address portNumber:(NSUInteger)portNum path:(NSString *)path; | |||||
@property (nonatomic,assign) ELBluetoothState bleWifiBloodStatus; | @property (nonatomic,assign) ELBluetoothState bleWifiBloodStatus; | ||||
// | |||||
// 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 |
// | |||||
// 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 |
<?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> |
// | |||||
// 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 |
// | |||||
// 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 |
<?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> |
// | |||||
// 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 |
// | |||||
// 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 |
// | |||||
// 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 */ |
// | |||||
// 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 |
// | |||||
// 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 | |||||
// | |||||
// 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 |
// | |||||
// 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 |
<?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> |
#import "BabyScaleViewController.h" | #import "BabyScaleViewController.h" | ||||
#import "BloodScanViewController.h" | #import "BloodScanViewController.h" | ||||
#import "HeightGuageScanViewController.h" | #import "HeightGuageScanViewController.h" | ||||
#import "BroadcastHeightGuage.h" | |||||
#import "RemoteControlScanViewController.h" | #import "RemoteControlScanViewController.h" | ||||
#import "ForeheadScanViewController.h" | #import "ForeheadScanViewController.h" | ||||
#import "ThermometerScanViewController.h" | #import "ThermometerScanViewController.h" | ||||
#import "HeightBodyFatScaleVC.h" | #import "HeightBodyFatScaleVC.h" | ||||
#import "MeatProbeVC.h" | |||||
#import "MeatProbeBoxVC.h" | |||||
[ELDemoDeviceModel modelWithIndex:@"04" imageName:@"type_baby_scale_ic" title:@"Baby Scale" subtitle:@"婴儿秤" entryVCName:NSStringFromClass(BabyScaleViewController.class)], | [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:@"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:@"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:@"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:@"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)], | [ELDemoDeviceModel modelWithIndex:@"09" imageName:@"type_thermometer_ic" title:@"Digital thermometer" subtitle:@"温度计" entryVCName:NSStringFromClass(ThermometerScanViewController.class)], | ||||
[ELDemoDeviceModel modelWithIndex:@"25" imageName:@"height_body_fat_scale_type_ic" title:@"HeightBodyFatScale" subtitle:@"身高体脂秤" entryVCName:NSStringFromClass(HeightBodyFatScaleVC.class) cids:@[@(ELSupportDeviceTypeHeightBodyFatScale)]], | [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)]], | |||||
]; | ]; | ||||
} | } | ||||
| 1.5.9| 20230206 | larry | 增加 身高体脂秤,优化 Demo UI | | | 1.5.9| 20230206 | larry | 增加 身高体脂秤,优化 Demo UI | | ||||
| 1.5.11 | 20230327 | larry | 增加 蓝牙体重秤 | | | 1.5.11 | 20230327 | larry | 增加 蓝牙体重秤 | | ||||
| 1.5.15 | 20230427 | larry | 修改 增加 蓝牙牙刷防飞溅 | | | 1.5.15 | 20230427 | larry | 修改 增加 蓝牙牙刷防飞溅 | | ||||
| 1.6.1 | 20230626 | larry | 修改 增加 广播身高仪 食物探针 食物探针盒子 支持 | | |||||