// // MultipleMeatProbeBoxVC.m // AILinkBleSDK_Example // // Created by LarryZhang on 2024/9/7. // Copyright © 2024 zhengzida. All rights reserved. // #import "MultipleMeatProbeBoxVC.h" #import #import #import "ELMeatProbeBoxMultipleBleParser.h" #import "ELMeatProbeBoxMultipleBleCmdTool.h" #import "ELMeatProbeBoxMultipleBleBBQParamModel.h" @interface MultipleMeatProbeBoxVC () @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) ELMeatProbeBoxMultipleBleParser *bleParser; @property (nonatomic, strong) ELMeatProbeBoxMultipleStatusModel *boxStatus; @property (nonatomic, strong) NSMutableDictionary *paramDic; @end @implementation MultipleMeatProbeBoxVC - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view from its nib. self.paramDic = [NSMutableDictionary dictionary]; [self initBle]; } - (void)dealloc { [self deinitBle]; } #pragma mark - Action - (IBAction)requestParamsAction:(id)sender { NSData *payload = [ELMeatProbeBoxMultipleBleCmdTool requestParams:self.bleManager]; NSString *log = [NSString stringWithFormat:@"发: payload: %@", payload]; [self addLog:log]; } - (IBAction)setupParamsAction:(id)sender { if (self.boxStatus == nil) { return; } if (self.boxStatus.probeStatusArray == nil || self.boxStatus.probeStatusArray.count != 2) { return; } ELMeatProbeBoxMultipleProbeStatusModel *status = self.boxStatus.probeStatusArray.firstObject; if (status == nil) { return; } ELMeatProbeBoxMultipleBleBBQParamModel *param = self.paramDic[status.macString]; if (param == nil) { return; } param.foodType = 1; param.targetTemperatureRaw_C = 70; param.targetTemperatureRaw_F = 212; param.foodRawness = 1; param.alarmTemperaturePercent = 0.95; param.cookingId = [NSDate date].timeIntervalSince1970; NSData *payload = [ELMeatProbeBoxMultipleBleCmdTool setupParam:param supportProbe:1 manager:self.bleManager]; NSString *log = [NSString stringWithFormat:@"发: payload: %@", payload]; [self addLog:log]; } - (IBAction)switchUnitAction:(id)sender { if (self.boxStatus.unit == 1) { NSData *payload = [ELMeatProbeBoxMultipleBleCmdTool switchUnit:0 manager:self.bleManager]; NSString *log = [NSString stringWithFormat:@"发: payload: %@ -- 切换单位 to ℃", payload]; [self addLog:log]; } else { NSData *payload = [ELMeatProbeBoxMultipleBleCmdTool switchUnit:1 manager:self.bleManager]; NSString *log = [NSString stringWithFormat:@"发: payload: %@ -- 切换单位 to ℉", payload]; [self addLog:log]; } } - (IBAction)clearAction:(id)sender { self.logTextView.text = @""; } - (IBAction)shareLogAction:(id)sender { } #pragma mark - ELAILinkBleManagerDelegate - (void)initBle { self.bleManager = [[ELAILinkBleManager alloc] init]; self.bleManager.ailinkDelegate = self; self.bleParser = [[ELMeatProbeBoxMultipleBleParser alloc] init]; self.bleParser.delegate = self; self.bleParser.mac = self.per.macAddressString; } - (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]; // read RSSI // [self readRSSI]; 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(), ^{ }); } // 设备状态变更 - (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 == ELInetGetCmdTypeGetBMVersion) { NSString *bmVersion = self.bleManager.bmVersion; NSLog(@"##### bmVersion: %@", bmVersion); } if (cmd == ELInetGetCmdTypeGetBMVersionPro) { NSString *bmVersionPro = self.bleManager.bmVersionPro; NSLog(@"##### bmVersionPro: %@", bmVersionPro); } } #pragma mark - ELMeatProbeBoxMultipleBleParserDelegate //MCU 上报设备状态数据(Type:02) - (void)meatProbeBoxMultipleBleParser:(ELMeatProbeBoxMultipleBleParser *)parser boxStatus:(ELMeatProbeBoxMultipleStatusModel *)boxStatus { NSLog(@"##### boxStatus(): %@ ", boxStatus.debugDescription); self.boxStatus = boxStatus; NSString *log = [NSString stringWithFormat:@"boxStatus: { mac:%@, probeMaxCount:%hhu, probeCount:%hhu, batteryStatus:%hhu batteryPercent:%hhu, unit:%ld }", parser.mac, boxStatus.probeMaxCount, boxStatus.probeCount, boxStatus.batteryStatus, boxStatus.batteryPercent, boxStatus.unit]; [self addLog:log]; ELMeatProbeBoxMultipleProbeStatusModel *probeStatus = boxStatus.probeStatusArray.firstObject; NSString *log2 = [NSString stringWithFormat:@"probeStatus: { connectState:%@ macString:%hhu, internalTemperature_C:%ld ℃, ambientTemperature_C:%ld ℃ batteryStatus:%hhu batteryPercent:%hhu }", probeStatus.macString, probeStatus.connectState, probeStatus.internalTemperature_C, probeStatus.ambientTemperature_C, probeStatus.batteryStatus, probeStatus.batteryPercent]; [self addLog:log2]; } //切换单位(Type:04) - (void)meatProbeBoxMultipleBleParser:(ELMeatProbeBoxMultipleBleParser *)parser unit:(ELDeviceTemperatureUnit)unit { NSLog(@"##### unit(): %@", @(unit)); NSString *log = [NSString stringWithFormat:@"unit(): %@", unit == 0 ? @"℃" : @"°F"]; [self addLog:log]; } //报警状态数据(Type:06)//state: bit0:食物目标温度到达时置1 - (void)meatProbeBoxMultipleBleParser:(ELMeatProbeBoxMultipleBleParser *)parser startAlarmWithState:(Byte)state macData:(NSData *)macData mac:(NSString *)mac { NSLog(@"##### box:%@ startAlarmWithState(): probe:%@ state:%@", parser.mac, mac, @(state)); NSString *log = [NSString stringWithFormat:@"box:%@ startAlarmWithState(): probe:%@ state:%@", parser.mac, mac, @(state)]; [self addLog:log]; } //取消报警(Type:08) - (void)meatProbeBoxMultipleBleParser:(ELMeatProbeBoxMultipleBleParser *)parser stopAlarmWithMacData:(NSData *)macData mac:(NSString *)mac { NSLog(@"##### box:%@ stopAlarmWithMacData(): probe:%@ ", parser.mac, mac); NSString *log = [NSString stringWithFormat:@"box:%@ stopAlarmWithMacData(): probe:%@ ", parser.mac, mac]; [self addLog:log]; } //烧烤任务参数(Type:0A)//Op:0x00:设置任务参数(设置时需要一个针一个针设定任务) 0x01:获取任务参数(返回所有的针任务,如果包长度超MTU时,会分包发) 0x02:结束烧烤任务 - (void)meatProbeBoxMultipleBleParser:(ELMeatProbeBoxMultipleBleParser *)parser option:(UInt8)option supportProbe:(UInt8)supportProbe param:(ELMeatProbeBoxMultipleBleBBQParamModel *)param { NSLog(@"##### box:%@ meatProbeScreenBoxBleParser(): option:%@ supportProbe:%@ ", parser.mac, @(option), @(supportProbe)); NSLog(@"##### param:%@ state:%@ foodType:%@", param.macString, @(param.state), @(param.foodType)); self.paramDic[param.macString] = param; NSString *log = [NSString stringWithFormat:@"box:%@ meatProbeScreenBoxBleParser(): option:%@ supportProbe:%@ ", parser.mac, @(option), @(supportProbe)]; NSString *log2 = [NSString stringWithFormat:@"param:%@ state:%@ foodType:%@", param.macString, @(param.state), @(param.foodType)]; [self addLog:log]; [self addLog:log2]; } //color info - (void)meatProbeBoxMultipleBleParser:(ELMeatProbeBoxMultipleBleParser *)parser colorInfos:(NSArray *)colorInfos { NSLog(@"##### colorInfos(): %@", colorInfos); if (colorInfos == nil || colorInfos.count == 0) { return; } ELMeatProbeBoxMultipleColorInfoModel *colorInfo = colorInfos.firstObject; NSString *log = [NSString stringWithFormat:@"colorInfos(): count:%@ probeIndex:%@ colorIndex:%@", @(colorInfos.count), @(colorInfo.probeIndex), @(colorInfo.colorIndex)]; [self addLog:log]; } - (void)peripheralDidReadRSSI:(nonnull NSNumber *)RSSI { NSLog(@"%s peripheralDidReadRSSI: %@", __FUNCTION__, RSSI); // main thread dispatch_async(dispatch_get_main_queue(), ^{ [self addLog:[NSString stringWithFormat:@"peripheralDidReadRSSI: %@", RSSI]]; }); [self readRSSI]; } - (void)readRSSI { // delay dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(4.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ // Read RSSI [self.bleManager readRSSI]; }); } #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