From 60a29b2cbd4dd2a794268d5b8cea3da93a5d6a54 Mon Sep 17 00:00:00 2001 From: jason Date: Thu, 25 Jan 2024 15:46:41 +0800 Subject: [PATCH] feat:ota viewcontroller --- HDFwear.xcodeproj/project.pbxproj | 14 ++++++++++++++ HDFwear/HDFwear-Bridging-Header.h | 2 +- HDFwear/Mine/MineViewController.swift | 5 +++++ HDFwear/OTA/OTAManager.h | 8 ++++++++ HDFwear/OTA/OTAUpdateViewController.h | 13 ++++++++++++- HDFwear/OTA/OTAUpdateViewController.m | 219 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------- HDFwear/OTA/OTAUpdateViewController.xib | 95 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----- 7 files changed, 339 insertions(+), 17 deletions(-) diff --git a/HDFwear.xcodeproj/project.pbxproj b/HDFwear.xcodeproj/project.pbxproj index abb2cee..d09c0d2 100644 --- a/HDFwear.xcodeproj/project.pbxproj +++ b/HDFwear.xcodeproj/project.pbxproj @@ -291,8 +291,11 @@ 84792A232B5FACAC00851211 /* Utils.m in Sources */ = {isa = PBXBuildFile; fileRef = 84792A202B5FACAB00851211 /* Utils.m */; }; 84792A242B5FACAC00851211 /* RemoteStatus.m in Sources */ = {isa = PBXBuildFile; fileRef = 84792A1D2B5FACAB00851211 /* RemoteStatus.m */; }; 84792A252B5FACAC00851211 /* OTAManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 84792A1B2B5FACAB00851211 /* OTAManager.m */; }; + 84792A292B5FB05F00851211 /* BluetoothManager+OTA.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84792A282B5FB05F00851211 /* BluetoothManager+OTA.swift */; }; 847AF36E2B4CF35F00E3456E /* NewSleepModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 847AF36D2B4CF35F00E3456E /* NewSleepModel.swift */; }; 847B88EF2B5780CA00851EE7 /* NewIntensiveTimeModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 847B88EE2B5780CA00851EE7 /* NewIntensiveTimeModel.swift */; }; + 847CA80F2B6147680051AEAF /* OTAUpdateViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 847CA80D2B6147680051AEAF /* OTAUpdateViewController.m */; }; + 847CA8102B6147680051AEAF /* OTAUpdateViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 847CA80E2B6147680051AEAF /* OTAUpdateViewController.xib */; }; 84DA399D2B4D3A5B008D34A9 /* NewGpsModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84DA399C2B4D3A5B008D34A9 /* NewGpsModel.swift */; }; B212F1FD2A14CE0400781D59 /* LaunchSetting.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B212F1FF2A14CE0400781D59 /* LaunchSetting.storyboard */; }; B212F2052A14D28E00781D59 /* LaunchMyBodySettingVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = B212F2042A14D28E00781D59 /* LaunchMyBodySettingVC.swift */; }; @@ -682,8 +685,12 @@ 84792A202B5FACAB00851211 /* Utils.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Utils.m; sourceTree = ""; }; 84792A212B5FACAC00851211 /* RemoteStatus.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RemoteStatus.h; sourceTree = ""; }; 84792A272B5FADE500851211 /* LETransceiver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LETransceiver.h; sourceTree = ""; }; + 84792A282B5FB05F00851211 /* BluetoothManager+OTA.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "BluetoothManager+OTA.swift"; sourceTree = ""; }; 847AF36D2B4CF35F00E3456E /* NewSleepModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewSleepModel.swift; sourceTree = ""; }; 847B88EE2B5780CA00851EE7 /* NewIntensiveTimeModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewIntensiveTimeModel.swift; sourceTree = ""; }; + 847CA80C2B6147680051AEAF /* OTAUpdateViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OTAUpdateViewController.h; sourceTree = ""; }; + 847CA80D2B6147680051AEAF /* OTAUpdateViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OTAUpdateViewController.m; sourceTree = ""; }; + 847CA80E2B6147680051AEAF /* OTAUpdateViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = OTAUpdateViewController.xib; sourceTree = ""; }; 847D1C4A2B009FAC0097A96E /* 20231111ReadMe.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = 20231111ReadMe.md; sourceTree = ""; }; 847D2DE42B3D575F001BA7EF /* 20240110ReadMe.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = 20240110ReadMe.md; sourceTree = ""; }; 84DA399C2B4D3A5B008D34A9 /* NewGpsModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewGpsModel.swift; sourceTree = ""; }; @@ -1142,6 +1149,7 @@ 844959772B48EF900029E2E0 /* BluetoothManager+Deprecated.swift */, 6C1F987E279BF0AA00C0C3BA /* BluetoothManager+Set.swift */, B279A3792A4AC2F800A7C7B6 /* BluetoothManager+Function.swift */, + 84792A282B5FB05F00851211 /* BluetoothManager+OTA.swift */, 8473FB612B4BF1A200409148 /* TaskManager.swift */, 6C411EE4275DFF37009B2E02 /* Bluetooth+Types.swift */, 6C6051B92760843F00286B37 /* BleMessage.swift */, @@ -1332,6 +1340,9 @@ 84792A1D2B5FACAB00851211 /* RemoteStatus.m */, 84792A1C2B5FACAB00851211 /* Utils.h */, 84792A202B5FACAB00851211 /* Utils.m */, + 847CA80C2B6147680051AEAF /* OTAUpdateViewController.h */, + 847CA80D2B6147680051AEAF /* OTAUpdateViewController.m */, + 847CA80E2B6147680051AEAF /* OTAUpdateViewController.xib */, ); path = OTA; sourceTree = ""; @@ -1499,6 +1510,7 @@ 6CFEEBAF2772F18400621863 /* SettingCell2.xib in Resources */, 6C5972C227D0B2780096FD04 /* Sound1.wav in Resources */, 6C28F55A27901CF900E74EA5 /* HRReportCell.xib in Resources */, + 847CA8102B6147680051AEAF /* OTAUpdateViewController.xib in Resources */, 6C85FB69278D56DA007D309A /* BloodOxygenCell.xib in Resources */, 6CEA284727EB033E006A44AB /* MedalCell.xib in Resources */, 6C28F53E279017B200E74EA5 /* Mine.storyboard in Resources */, @@ -1656,6 +1668,7 @@ 6CFE53F6277ADAA300520B00 /* ModifyNicknameVC.swift in Sources */, 6C0D9B962776BA8300E8C880 /* HealthRemindVC.swift in Sources */, 6CBB0CAA27B7B6FA009B27C1 /* GenerateBlankVC.swift in Sources */, + 84792A292B5FB05F00851211 /* BluetoothManager+OTA.swift in Sources */, 6C2EE979277FF7120051413A /* HealthReportVC.swift in Sources */, 6CEA284D27EB1359006A44AB /* MedalDetailVC.swift in Sources */, B279A37A2A4AC2F800A7C7B6 /* BluetoothManager+Function.swift in Sources */, @@ -1782,6 +1795,7 @@ 6C0D9BA8277726EB00E8C880 /* FirmwareUpdateVC.swift in Sources */, 6C6F407D274382D900F9473C /* HeartRateCell.swift in Sources */, 6C1B7EAA27B7977000DB9D1C /* NFCBlankVC.swift in Sources */, + 847CA80F2B6147680051AEAF /* OTAUpdateViewController.m in Sources */, 6CCB7FF8276C6C06009EF617 /* RecordHeaderView.swift in Sources */, 6C8F74EA2779B98700B8A1A7 /* UserInfoSettingVC.swift in Sources */, B262F7C72A1BB71600B4DFD2 /* ZCStringPickerView.swift in Sources */, diff --git a/HDFwear/HDFwear-Bridging-Header.h b/HDFwear/HDFwear-Bridging-Header.h index c4addec..d927d9b 100644 --- a/HDFwear/HDFwear-Bridging-Header.h +++ b/HDFwear/HDFwear-Bridging-Header.h @@ -1,8 +1,8 @@ // // Use this file to import your target's public headers that you would like to expose to Swift. -// #import "OTAManager.h" #import "LETransceiver.h" +#import "OTAUpdateViewController.h" #import "MTKBleManager.h" #import "FmpGattClient.h" #import "test.h" diff --git a/HDFwear/Mine/MineViewController.swift b/HDFwear/Mine/MineViewController.swift index 73b2a7a..92ce494 100644 --- a/HDFwear/Mine/MineViewController.swift +++ b/HDFwear/Mine/MineViewController.swift @@ -429,6 +429,10 @@ extension MineViewController: UITableViewDataSource, UITableViewDelegate { } } + let archiveAction29 = UIAlertAction(title: "ota update", style: .default) { action in + BluetoothManager.shared.startOtaUpdate() + } + alert.addAction(archiveAction0) alert.addAction(archiveAction1) alert.addAction(archiveAction2) @@ -456,6 +460,7 @@ extension MineViewController: UITableViewDataSource, UITableViewDelegate { alert.addAction(archiveAction28a) alert.addAction(archiveAction28b) alert.addAction(archiveAction28c) + alert.addAction(archiveAction29) alert.addAction(UIAlertAction(title: "取消", style: .destructive, handler: nil)) present(alert, animated: true, completion: nil) diff --git a/HDFwear/OTA/OTAManager.h b/HDFwear/OTA/OTAManager.h index 4864db2..465888d 100644 --- a/HDFwear/OTA/OTAManager.h +++ b/HDFwear/OTA/OTAManager.h @@ -11,6 +11,14 @@ NS_ASSUME_NONNULL_BEGIN +#define kMsgPeripheralFound @"msgPeripheralFound" +#define kMsgPeripheralConnected @"msgPeripheralConnected" +#define kMsgPeripheralDisconnected @"msgPeripheralDisconnected" +#define kMsgOTAStatus @"msgOTAStatus" +#define kMsgAudioPackageRecevied @"msgAudioPackageRecevied" +#define kMsgAudioSpeedRecevied @"msgAudioSpeedRecevied" +#define kMsgRemoteStatusRecevied @"msgRemoteStatusRecevied" + typedef enum{ STATE_UNKNOWN = 0, STATE_IDLE = 1, diff --git a/HDFwear/OTA/OTAUpdateViewController.h b/HDFwear/OTA/OTAUpdateViewController.h index 1920d3c..6cd850a 100644 --- a/HDFwear/OTA/OTAUpdateViewController.h +++ b/HDFwear/OTA/OTAUpdateViewController.h @@ -8,8 +8,19 @@ #import NS_ASSUME_NONNULL_BEGIN - +typedef void(^CloseBlock)(void); @interface OTAUpdateViewController : UIViewController +@property (weak, nonatomic) IBOutlet UILabel *labelBluetoothState; +@property (weak, nonatomic) IBOutlet UIButton *buttonPrepare; +@property (weak, nonatomic) IBOutlet UIButton *buttonStart; +@property (weak, nonatomic) IBOutlet UILabel *labelOTAVersion; + +@property (weak, nonatomic) CBPeripheral *currentPeripheral; +@property (weak, nonatomic) OTAManager *otaManager; +@property (strong, nonatomic) NSString *path; +@property (copy, nonatomic) CloseBlock closeBlock; +- (IBAction)didButtonStartClicked:(UIButton *)sender; +- (IBAction)didButtonPrepareClicked:(UIButton *)sender; @end diff --git a/HDFwear/OTA/OTAUpdateViewController.m b/HDFwear/OTA/OTAUpdateViewController.m index 9a1aae6..e28177b 100644 --- a/HDFwear/OTA/OTAUpdateViewController.m +++ b/HDFwear/OTA/OTAUpdateViewController.m @@ -5,27 +5,226 @@ // Created by admin on 2024/1/24. // +#import "HDFwear-Bridging-Header.h" #import "OTAUpdateViewController.h" +#import "OTAManager.h" +#import "MBProgressHUD.h" @interface OTAUpdateViewController () @end -@implementation OTAUpdateViewController - +@implementation OTAUpdateViewController{ + NSDate *beginTime; + + BOOL isUpgrading; +} - (void)viewDidLoad { [super viewDidLoad]; - // Do any additional setup after loading the view from its nib. + // Do any additional setup after loading the view, typically from a nib. + + isUpgrading = NO; + + _buttonStart.layer.borderWidth = 1.0f; + _buttonStart.layer.cornerRadius = 4.0f; + _buttonStart.layer.masksToBounds = YES; + _buttonPrepare.layer.borderWidth = 1.0f; + _buttonPrepare.layer.cornerRadius = 4.0f; + _buttonPrepare.layer.masksToBounds = YES; + + + if (self.currentPeripheral) { + _labelBluetoothState.text = @"已连接"; + [_buttonPrepare setEnabled:YES]; + } else { + _labelBluetoothState.text = @"N/A"; + [_buttonPrepare setEnabled:NO]; + [_buttonStart setEnabled:NO]; + } + + NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; + [nc addObserver:self + selector:@selector(handleGlobalMessage:) + name:kMsgPeripheralConnected + object:nil]; + [nc addObserver:self + selector:@selector(handleGlobalMessage:) + name:kMsgPeripheralDisconnected + object:nil]; + [nc addObserver:self + selector:@selector(handleGlobalMessage:) + name:kMsgOTAStatus + object:nil]; + [nc addObserver:self + selector:@selector(handleGlobalMessage:) + name:kMsgAudioPackageRecevied + object:nil]; + [nc addObserver:self + selector:@selector(handleGlobalMessage:) + name:kMsgAudioSpeedRecevied + object:nil]; + [nc addObserver:self + selector:@selector(handleGlobalMessage:) + name:kMsgRemoteStatusRecevied + object:nil]; + +} + +- (void)viewWillDisappear:(BOOL)animated { + [super viewWillDisappear:animated]; + if (self.closeBlock) { + self.closeBlock(); + } +} + +- (void)handleGlobalMessage:(NSNotification *)note{ + NSString* name = note.name; + NSLog(@"nick_name:%@", name); + NSDictionary* dict = note.userInfo; + + if ([name isEqualToString:kMsgPeripheralConnected]){ + if (self.currentPeripheral) { + _labelBluetoothState.text = @"已连接"; + [_buttonPrepare setEnabled:YES]; + NSInteger mtu = [self.currentPeripheral maximumWriteValueLengthForType:CBCharacteristicWriteWithoutResponse]; + NSLog(@"mtu view:%d", mtu); + [self.otaManager setMaxMtu:mtu]; + } + } else if ([name isEqualToString:kMsgPeripheralDisconnected]){ + _labelBluetoothState.text = @"N/A"; + isUpgrading = NO; + [_buttonPrepare setEnabled:NO]; + [_buttonStart setEnabled:NO]; + [_buttonStart setTitle:@"START" forState:UIControlStateNormal]; + } else if ([name isEqualToString:kMsgOTAStatus]){ + NSInteger state = ((NSNumber *)[dict objectForKey:@"status"]).integerValue; + + NSString *msg = @"UNKNOWN"; + switch (state) { + case STATE_IDLE: + msg = @"IDLE"; + break; + + case STATE_PREPARING: + msg = @"PREPARING"; + break; + + case STATE_PREPARED: + msg = @"PREPARED"; + break; + + case STATE_TRANSFERRING: + msg = @"TRANSFERRING"; + beginTime = [NSDate date]; + NSLog(@"nick_time:%@", beginTime); + break; + + case STATE_TRANSFERRED: + msg = @"TRANSFERRED"; + isUpgrading = NO; + [_buttonStart setEnabled:YES]; + [_buttonStart setTitle:@"START" forState:UIControlStateNormal]; + + [self.otaManager confirmUpdateAndReboot]; + break; + + default: + msg = @"UNKNOWN"; + isUpgrading = NO; + [_buttonStart setEnabled:YES]; + [_buttonStart setTitle:@"START" forState:UIControlStateNormal]; + break; + } + + NSLog(@"onStatus: %ld %@", state, msg); + _labelBluetoothState.text = msg; + } else if ([name isEqualToString:kMsgAudioPackageRecevied]) { + NSInteger psn = ((NSNumber *)[dict objectForKey:@"psn"]).integerValue; + NSData *data = [dict objectForKey:@"data"]; + NSLog(@"nick_speed"); + + } else if ([name isEqualToString:kMsgRemoteStatusRecevied]) { + RemoteStatus *status = [dict objectForKey:@"status"]; + + [_buttonStart setEnabled:YES]; + } else if ([name isEqualToString:kMsgAudioSpeedRecevied]) { + NSInteger writeByte = ((NSNumber *)[dict objectForKey:@"speed"]).integerValue; + NSDate *now = [[NSDate alloc] init]; + now = [NSDate date]; + NSDateComponents *compt = [[NSCalendar currentCalendar] components:NSCalendarUnitMinute| NSCalendarUnitSecond fromDate:beginTime toDate:now options:0]; + int min = compt.minute; + int sec = compt.second; + int time = min * 60 + sec; + double speed = writeByte / time / 1000; + NSLog(@"nick_now:%d", sec); + } +} + +- (NSString *)convertDataToHexStr:(NSData *)data { + if (!data || [data length] == 0) { + return @""; + } + + NSMutableString *string = [[NSMutableString alloc] initWithCapacity:[data length]]; + [data enumerateByteRangesUsingBlock:^(const void *bytes, NSRange byteRange, BOOL *stop) { + unsigned char *dataBytes = (unsigned char*)bytes; + for (NSInteger i = 0; i < byteRange.length; i++) { + NSString *hexStr = [NSString stringWithFormat:@"%x", (dataBytes[i]) & 0xff]; + if ([hexStr length] == 2) { + [string appendString:hexStr]; + } else { + [string appendFormat:@"0%@", hexStr]; + } + } + }]; + + return string; } -/* -#pragma mark - Navigation +- (void)showTextHUD:(NSString *) text { + dispatch_async(dispatch_get_main_queue(), ^{ + // 快速显示一个提示信息 + MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES]; + hud.label.text = text; + + hud.label.textColor = [UIColor whiteColor]; + hud.label.font = [UIFont systemFontOfSize:17.0]; + hud.userInteractionEnabled = NO; + + hud.mode = MBProgressHUDModeCustomView; + hud.removeFromSuperViewOnHide = YES; + [hud hideAnimated:YES afterDelay:1.5]; + }); +} + +- (IBAction)didButtonStartClicked:(UIButton *)sender { + if (isUpgrading) { + [self showTextHUD:@"正在升级中,请稍候!"]; + return; + } + [self.otaManager upgrade]; + isUpgrading = YES; + [_buttonStart setEnabled:NO]; + [_buttonStart setTitle:@"UPGRADING" forState:UIControlStateNormal]; +} -// In a storyboard-based application, you will often want to do a little preparation before navigation -- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { - // Get the new view controller using [segue destinationViewController]. - // Pass the selected object to the new view controller. +- (IBAction)didButtonPrepareClicked:(UIButton *)sender { + if (isUpgrading) { + [self showTextHUD:@"正在升级中,请稍候!"]; + return; + } + + + NSLog(@"OTA path: %@", self.path); + + isUpgrading = NO; + [self.otaManager setOTAFile:self.path]; + + NSString *version = [self.otaManager getOTAVersion]; + [_labelOTAVersion setText:version]; + + [self.otaManager prepare]; } -*/ + @end diff --git a/HDFwear/OTA/OTAUpdateViewController.xib b/HDFwear/OTA/OTAUpdateViewController.xib index da8e6fe..eaf47bc 100644 --- a/HDFwear/OTA/OTAUpdateViewController.xib +++ b/HDFwear/OTA/OTAUpdateViewController.xib @@ -1,22 +1,107 @@ - - + + + - + + + + + + + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- libgit2 0.21.4