You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

454 lines
16 KiB

//
// JL_RunSDK.m
// JL_OTA_InnerBle
//
// Created by 凌煊峰 on 2021/10/9.
//
#import "JL_RunSDK.h"
#import "BluetoothFireBoltt.h"
#import <SVProgressHUD/SVProgressHUD.h>
@interface JL_RunSDK() <JL_ManagerMDelegate>
@property (strong, nonatomic) NSString *selectedOtaFilePath;
/// 手表表盘资源文件
@property (nonatomic ,strong) NSArray *mWatchList;
/// 是否正在升级
@property (nonatomic ,assign) BOOL isOtaUpdate;
/// <#arguments#>
@property (nonatomic ,strong) NSString *mOtaPath;
@property (nonatomic ,strong) NSString *otaString;
@property (nonatomic ,strong) JL_Timer *mTimer;
@end
@implementation JL_RunSDK
static JL_RunSDK *singleton = nil;
+ (instancetype)sharedInstance {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
singleton = [[self alloc] init];
});
return singleton;
}
- (instancetype)init
{
self = [super init];
if (self) {
self.bt_ble = [[BluetoothFireBoltt alloc] init];
self.mTimer = [[JL_Timer alloc] init];
}
return self;
}
+(BOOL)isConnectDevice
{
JL_RunSDK *bleSDK = [JL_RunSDK sharedInstance];
BluetoothFireBoltt *bt_ble = bleSDK.bt_ble;
/*--- 判断是否已连接设备 ---*/
if (bt_ble.currenModel == nil) {
[SVProgressHUD showErrorWithStatus:@"请先连设备!"];
// UIWindow *win = [DFUITools getWindow];
// [DFUITools showText: onView:win delay:1.0];
return NO;
}
return YES;
}
+(BOOL)isNeedUpdateResource{
/*--- 设备信息 ---*/
JL_ManagerM *mCmdManager = singleton.bt_ble.mAssist.mCmdManager;
JLModel_Device *model = [mCmdManager outputDeviceModel];
/*--- BLE是否需要更新资源 ---*/
if (model.otaWatch == JL_OtaWatchYES) {
[SVProgressHUD showErrorWithStatus:@"需要升级手表!"];
// UIWindow *win = [DFUITools getWindow];
// [DFUITools showText:@"需要升级手表!" onView:win delay:1.0];
return YES;
}
return NO;
}
+(BOOL)isNeedUpdateResource_1{
/*--- 设备信息 ---*/
JL_ManagerM *mCmdManager = singleton.bt_ble.mAssist.mCmdManager;
JLModel_Device *model = [mCmdManager outputDeviceModel];
/*--- BLE是否需要更新资源 ---*/
if (model.otaWatch == JL_OtaWatchYES) {
return YES;
}
return NO;
}
+(BOOL)isNeedUpdateOTA{
/*--- 设备信息 ---*/
JL_ManagerM *mCmdManager = singleton.bt_ble.mAssist.mCmdManager;
JLModel_Device *model = [mCmdManager outputDeviceModel];
/*--- BLE是否需要OTA升级 ---*/
if (model.otaStatus == JL_OtaStatusForce) {
// UIWindow *win = [DFUITools getWindow];
// [DFUITools showText:@"需要升级手表!" onView:win delay:1.0];
[SVProgressHUD showErrorWithStatus:@"需要升级手表!"];
return YES;
}
return NO;
}
+(BOOL)isNeedUpdateOTA_1{
/*--- 设备信息 ---*/
JL_ManagerM *mCmdManager = singleton.bt_ble.mAssist.mCmdManager;
JLModel_Device *model = [mCmdManager outputDeviceModel];
/*--- BLE是否需要OTA升级 ---*/
if (model.otaStatus == JL_OtaStatusForce) {
return YES;
}
return NO;
}
- (void)otaFuncWithFilePath:(NSString *)otaFilePath
{
[[NSUserDefaults standardUserDefaults] setObject:otaFilePath forKey:@"OTAPATH"];
self.mOtaPath = otaFilePath;
NSString *lastZip = [[self.mOtaPath lastPathComponent] stringByReplacingOccurrencesOfString:@".zip" withString:@""];
NSString *lastPath = [JL_Tools listPath:NSDocumentDirectory MiddlePath:lastZip File:@""];
[JL_Tools removePath:lastPath];
// [self.mTimer threadContinue];
NSArray *zipArr = [FatfsObject unzipFileAtPath:self.mOtaPath toDestination:lastPath];
if (zipArr.count == 0) {
[SVProgressHUD showErrorWithStatus:@"文件解压出错"];
return;
}
if (zipArr.count > 1)
{
[DialManager listFile:^(DialOperateType type, NSArray * _Nullable array) {
if (type == DialOperateTypeSuccess && array.count > 0)
{
self.mWatchList = array;
[JL_Tools subTask:^{
[self onUpdateResource:^{
[self onUpdateOTA];
}];
}];
}
}];
}
else
{
/*--- 只需要【OTA升级】 ---*/
[JL_Tools mainTask:^{
[self onUpdateOTA];
}];
}
}
- (void)onUpdateOTA
{
NSData *otaData = [self outputDataOfOtaPath:self.mOtaPath];
__weak typeof(self) weakSelf = self;
[self.bt_ble.mAssist.mCmdManager.mOTAManager cmdOTAData:otaData Result:^(JL_OTAResult result, float progress) {
if (result == JL_OTAResultUpgrading || result == JL_OTAResultPreparing) {
NSString *txt = [NSString stringWithFormat:@"%.1f%%",progress*100.0f];
if (result == JL_OTAResultPreparing) NSLog(@"校验文件中 %@",txt);
if (result == JL_OTAResultUpgrading) NSLog(@"正在升级 %@",txt);
[self otaTimeCheck];//增加超时检测
} else if (result == JL_OTAResultPrepared) {
NSLog(@"---> 检验文件【完成】");
[self otaTimeCheck];//增加超时检测
} else if (result == JL_OTAResultReconnect) {
NSLog(@"---> OTA正在回连设备... ");
[self otaTimeCheck];//关闭超时检测
} else if (result == JL_OTAResultReconnectWithMacAddr) {
NSLog(@"---> OTA正在通过Mac Addr方式回连设备... ");
[self otaTimeCheck];//关闭超时检测
} else if (result == JL_OTAResultSuccess) {
NSLog(@"--->升级成功.");
} else if (result == JL_OTAResultReboot) {
NSLog(@"--->设备重启.");
[self otaTimeClose];//关闭超时检测
} else if (result == JL_OTAResultFail) {
[self otaTimeClose];
NSLog(@"--->升级失败");
}else {
// 其余错误码详细 Command+点击JL_OTAResult 查看说明
NSLog(@"ota update result: %d", result);
}
if ([weakSelf.delegate respondsToSelector:@selector(otaProgressWithOtaResult:withProgress:)]) {
[weakSelf.delegate otaProgressWithOtaResult:result withProgress:progress];
}
}];
}
- (NSData*)outputDataOfOtaPath:(NSString*)path
{
NSString *folderName = [[path lastPathComponent] stringByReplacingOccurrencesOfString:@".zip" withString:@""];
NSString *zipPath = [JL_Tools listPath:NSDocumentDirectory MiddlePath:folderName File:@""];
[FatfsObject unzipFileAtPath:path toDestination:zipPath];
NSArray *zipArray = [JL_Tools subPaths:zipPath];
for (NSString *name in zipArray)
{
if ([name hasSuffix:@".ufw"])
{
NSString *otaPath = [JL_Tools listPath:NSDocumentDirectory MiddlePath:folderName File:name];
NSLog(@"---->Start OTA:%@ ",otaPath);
NSData *otaData = [[NSData alloc] initWithContentsOfFile:otaPath];
return otaData;
}
else
{
}
}
return nil;
}
typedef void(^OTA_VIEW_BK)(void);
-(void)onUpdateResource:(OTA_VIEW_BK __nullable)result
{
self.isOtaUpdate = YES;
JL_ManagerM *mCmdManager = BluetoothFireBoltt.shareInstance.mAssist.mCmdManager;
/*--- 更新资源标志 ---*/
[mCmdManager.mFlashManager cmdWatchUpdateResource];
/*--- 展示手表更新资源UI ---*/
NSLog(@"--->Fats Update UI.(OTA)");
__block uint8_t m_flag = 0;
[mCmdManager.mFlashManager cmdUpdateResourceFlashFlag:JL_FlashOperateFlagStart
Result:^(uint8_t flag) {
m_flag = flag;
}];
if (m_flag != 0) {
[JL_Tools mainTask:^{
//[DFUITools showText:@"升级请求失败!" onView:self.view delay:1.0];
[SVProgressHUD showErrorWithStatus:NSLocalizedString(@"升级请求失败!", nil)];
}];
self.isOtaUpdate = NO;
return;
}
[DialManager updateResourcePath:self.mOtaPath List:self.mWatchList
Result:^(DialUpdateResult updateResult,
NSArray * _Nullable array,
NSInteger index, float progress){
[JL_Tools mainTask:^{
if (updateResult == DialUpdateResultReplace) {
[self otaTimeCheck];//增加超时检测
NSString *fileName = array[index];
[SVProgressHUD showWithStatus:[NSString stringWithFormat:@"正在更新表盘:%@(%d/%lu)\n%.1f%%",
fileName,(int)index+1,(unsigned long)array.count,progress*100.0]];
return;
}
if (updateResult == DialUpdateResultAdd)
{
[self otaTimeCheck];//增加超时检测
NSString *fileName = array[index];
[SVProgressHUD showWithStatus:[NSString stringWithFormat:@"正在传输新表盘%@(%d/%lu)\n%.1f%%",
fileName,(int)index+1,(unsigned long)array.count,progress*100.0]];
return;
}
if (updateResult == DialUpdateResultFinished) self.otaString = @"资源更新完成";
if (updateResult == DialUpdateResultNewest) self.otaString = @"资源已是最新";
if (updateResult == DialUpdateResultInvalid) self.otaString = @"无效资源文件";
if (updateResult == DialUpdateResultEmpty) self.otaString = @"资源文件为空";
if (updateResult == DialUpdateResultNoSpace) self.otaString = @"资源升级空间不足";
if (updateResult == DialUpdateResultZipError) self.otaString = @"ZIP资源文件错误";
[SVProgressHUD showErrorWithStatus:self.otaString];
// [JL_Tools delay:1.0 Task:^{
// [SVProgressHUD showErrorWithStatus:NSLocalizedString(self.otaString, nil)];
// if (result) result();
// }];
}];
}];
}
-(void)transportFile:(NSString*)path fileName:(NSString *)fileName Result:(void(^_Nullable)(JL_BigFileResult result, float progress))callback
{
JL_ManagerM *mCmdManager = BluetoothFireBoltt.shareInstance.mAssist.mCmdManager;
///设置需要Unicode命名⻓⽂件名
[mCmdManager.mFileManager setIsOtherEncode:true];
///设置编码格式
[mCmdManager.mFileManager setEncodeType:NSUTF16LittleEndianStringEncoding];
JLModel_Device *deviceModel = [mCmdManager outputDeviceModel];
if (deviceModel.audioFileType == JL_AudioFileTypeYES)
{
}
[JL_Tools mainTask:^{
[mCmdManager.mFileManager setCurrentFileHandleType:[self getMusicTargetDev:deviceModel]];
//设置设备的环境变量
[mCmdManager.mFileManager cmdPreEnvironment:0x00 Result:^(JL_CMDStatus status, uint8_t sn, NSData * _Nullable data) {
if (status == JL_CMDStatusSuccess)
{
//大文件传输API
[mCmdManager.mFileManager cmdBigFileData:path WithFileName:fileName Result:^(JL_BigFileResult result,float progress) {
callback(result,progress);
if (result == JL_BigFileTransferEnd)
{
NSLog(@"传输完成,清除播放列表缓存");
[mCmdManager.mFileManager cmdCleanCacheType:[self getCardTypeDev:deviceModel]];
// [self loadRootFiles];
}
}];
}
}];
// [JL_Tools delay:2.0 Task:^{
// [self stopTransport];
// }];
}];
}
- (void)stopTransport
{
JL_ManagerM *mCmdManager = BluetoothFireBoltt.shareInstance.mAssist.mCmdManager;
[mCmdManager.mFileManager cmdStopBigFileData];
}
static NSTimer *otaTimer = nil;
static int otaTimeout= 0;
-(void)otaTimeCheck{
otaTimeout = 0;
if (otaTimer == nil) {
otaTimer = [JL_Tools timingStart:@selector(otaTimeAdd)
target:self Time:1.0];
}
}
-(void)otaTimeClose{
[JL_Tools timingStop:otaTimer];
otaTimeout = 0;
otaTimer = nil;
}
-(void)otaTimeAdd{
otaTimeout++;
if (otaTimeout == 20) {
self.isOtaUpdate = NO;
[self otaTimeClose];
[SVProgressHUD showErrorWithStatus:NSLocalizedString(@"OTA升级超时", nil)];
NSLog(@"OTA ---> 超时了!!!");
// [self removeOTAzip];
}
}
/**
* 获取音乐文件传输句柄
*/
- (JL_FileHandleType)getMusicTargetDev:(JLModel_Device*)deviceModel {
if ([deviceModel.cardArray containsObject:@(JL_CardTypeSD_1)]) {
return JL_FileHandleTypeSD_1;
} else if ([deviceModel.cardArray containsObject:@(JL_CardTypeSD_0)] && [deviceModel.cardArray containsObject:@(JL_CardTypeSD_1)]) {
return JL_FileHandleTypeSD_1;
} else if ([deviceModel.cardArray containsObject:@(JL_CardTypeSD_0)]) {
return JL_FileHandleTypeSD_0;
} else if ([deviceModel.cardArray containsObject:@(JL_CardTypeUSB)]) {
return JL_FileHandleTypeUSB;
}
return JL_FileHandleTypeSD_1;
}
/**
* 获取音乐文件传输句柄
*/
- (JL_CardType)getCardTypeDev:(JLModel_Device*)deviceModel {
if ([deviceModel.cardArray containsObject:@(JL_CardTypeSD_1)]) {
return JL_CardTypeSD_1;
} else if ([deviceModel.cardArray containsObject:@(JL_CardTypeSD_0)] && [deviceModel.cardArray containsObject:@(JL_CardTypeSD_1)]) {
return JL_CardTypeSD_1;
} else if ([deviceModel.cardArray containsObject:@(JL_CardTypeSD_0)]) {
return JL_CardTypeSD_0;
} else if ([deviceModel.cardArray containsObject:@(JL_CardTypeUSB)]) {
return JL_CardTypeUSB;
}
return JL_CardTypeSD_1;
}
-(void)loadRootFiles
{
JL_ManagerM *mCmdManager = BluetoothFireBoltt.shareInstance.mAssist.mCmdManager;
// JLModel_Device *deviceModel = [mCmdManager outputDeviceModel];
//
// JLModel_File *fileModel = [JLModel_File new];
// fileModel.fileType = JL_BrowseTypeFolder;
// fileModel.cardType = JL_CardTypeSD_1;
// fileModel.fileHandle = deviceModel.handleSD_1;
// fileModel.fileName = @"SD Card";
// fileModel.folderName = @"SD Card";
// fileModel.fileClus = 0;
//
// //读取目录
// [mCmdManager.mFileManager cmdBrowseModel:fileModel Number:10 Result:nil];
[mCmdManager cmdGetSystemInfo:JL_FunctionCodeCOMMON
SelectionBit:0x04
Result:nil];
[mCmdManager.mFileManager cmdBrowseMonitorResult:^(NSArray * _Nullable array, JL_BrowseReason reason) {
switch (reason) {
case JL_BrowseReasonReading:{
NSLog(@"---> 正在读取:%@",array);
}break;
case JL_BrowseReasonCommandEnd:{
NSLog(@"读取命令结束:%lu",(unsigned long)array.count);
}break;
case JL_BrowseReasonFolderEnd:{
NSLog(@"---> 目录读取结束:%lu",(unsigned long)array.count);
}break;
case JL_BrowseReasonBusy:{
NSLog(@"设备在忙");
}break;
case JL_BrowseReasonDataFail:{
NSLog(@"数据读取失败");
}break;
case JL_BrowseReasonPlaySuccess:{
NSLog(@"---> 播放成功");
}break;
case JL_BrowseReasonUnknown:{
NSLog(@"未知错误");
}
default:
break;
}
}];
}
@end