Commit 211744a9b91fa58963fc94d39326ab902d28c10c

Authored by jason
1 parent b867ff0e

feat:ota import

HDFwear.xcodeproj/project.pbxproj
... ... @@ -280,6 +280,7 @@
280 280 6CFEEBC02773353700621863 /* BOReferenceVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CFEEBBF2773353700621863 /* BOReferenceVC.swift */; };
281 281 6CFEEBC22773354500621863 /* HRReferenceVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CFEEBC12773354500621863 /* HRReferenceVC.swift */; };
282 282 6CFEEBC42773355700621863 /* SleepReferenceVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CFEEBC32773355700621863 /* SleepReferenceVC.swift */; };
  283 + 84067DB52B5E67DC0030E30E /* OTA in Resources */ = {isa = PBXBuildFile; fileRef = 84067DB42B5E67DC0030E30E /* OTA */; };
283 284 844959782B48EF900029E2E0 /* BluetoothManager+Deprecated.swift in Sources */ = {isa = PBXBuildFile; fileRef = 844959772B48EF900029E2E0 /* BluetoothManager+Deprecated.swift */; };
284 285 845ADEA12B551C8E00C3AD73 /* NewStepModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 845ADEA02B551C8E00C3AD73 /* NewStepModel.swift */; };
285 286 8473FB622B4BF1A200409148 /* TaskManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8473FB612B4BF1A200409148 /* TaskManager.swift */; };
... ... @@ -662,6 +663,7 @@
662 663 6CFEEBBF2773353700621863 /* BOReferenceVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BOReferenceVC.swift; sourceTree = "<group>"; };
663 664 6CFEEBC12773354500621863 /* HRReferenceVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HRReferenceVC.swift; sourceTree = "<group>"; };
664 665 6CFEEBC32773355700621863 /* SleepReferenceVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SleepReferenceVC.swift; sourceTree = "<group>"; };
  666 + 84067DB42B5E67DC0030E30E /* OTA */ = {isa = PBXFileReference; lastKnownFileType = folder; path = OTA; sourceTree = "<group>"; };
665 667 844959772B48EF900029E2E0 /* BluetoothManager+Deprecated.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "BluetoothManager+Deprecated.swift"; sourceTree = "<group>"; };
666 668 845ADE9F2B5507FA00C3AD73 /* 20240126ReadMe.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = 20240126ReadMe.md; sourceTree = "<group>"; };
667 669 845ADEA02B551C8E00C3AD73 /* NewStepModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewStepModel.swift; sourceTree = "<group>"; };
... ... @@ -1125,6 +1127,7 @@
1125 1127 6C6F405E27434B8D00F9473C /* Tools */ = {
1126 1128 isa = PBXGroup;
1127 1129 children = (
  1130 + 84067DB42B5E67DC0030E30E /* OTA */,
1128 1131 6C411EDE275DE737009B2E02 /* BluetoothManager.swift */,
1129 1132 844959772B48EF900029E2E0 /* BluetoothManager+Deprecated.swift */,
1130 1133 6C1F987E279BF0AA00C0C3BA /* BluetoothManager+Set.swift */,
... ... @@ -1464,6 +1467,7 @@
1464 1467 6C34958827A12DB000F792AA /* DailCell.xib in Resources */,
1465 1468 6CE7E3E62782AA8300D6B374 /* Localizable.strings in Resources */,
1466 1469 6C228BB3279261340078B22E /* ContactCell.xib in Resources */,
  1470 + 84067DB52B5E67DC0030E30E /* OTA in Resources */,
1467 1471 6C9CAC3A278C2A4D00787CA6 /* Motion.storyboard in Resources */,
1468 1472 6CC6E57727716BA9006C01A7 /* CustomProgress.xib in Resources */,
1469 1473 6C1B7E9927B794B300DB9D1C /* NFCCell.xib in Resources */,
... ...
HDFwear/HDFwear-Bridging-Header.h
... ... @@ -16,3 +16,4 @@
16 16 #import <ShareSDKExtension/ShareSDK+Extension.h>
17 17 //#import "MASmoothPathTool.h"
18 18 //#import "LxxPlaySound.h"
  19 +#import "Tools/OTA/OTAManager.h"
... ...
HDFwear/Tools/OTA/LETransceiver.h 0 → 100644
  1 +//
  2 +// LETransceiver.h
  3 +// ActsBluetoothSpeed
  4 +//
  5 +// Created by inidhu on 2019/3/15.
  6 +// Copyright © 2019 Actions. All rights reserved.
  7 +//
  8 +
  9 +#import <Foundation/Foundation.h>
  10 +#import <CoreBluetooth/CoreBluetooth.h>
  11 +
  12 +NS_ASSUME_NONNULL_BEGIN
  13 +
  14 +#define KeyWriteServiceUUID @"kWriteServiceUUID"
  15 +#define KeyIndicateServiceUUID @"kIndicateServiceUUID"
  16 +#define KeyWriteCharacteristicUUID @"kWriteCharacteristicUUID"
  17 +#define KeyIndicateCharacteristicUUID @"kIndicateCharacteristicUUID"
  18 +
  19 +@protocol LEConnctionDelegate <NSObject>
  20 +
  21 +@required
  22 +- (void)onFoundPeripheral:(CBPeripheral *) peripheral advertisementData:(NSDictionary *) advertisementData;
  23 +
  24 +@optional
  25 +- (void)onConnectedPeripheral:(CBPeripheral *) peripheral;
  26 +- (void)onDisconnectedPeripheral:(CBPeripheral *) peripheral;
  27 +
  28 +@end
  29 +
  30 +@protocol LEDataDelegate <NSObject>
  31 +
  32 +@optional
  33 +
  34 +- (void)onDataReceive:(NSData *) data;
  35 +
  36 +@end
  37 +
  38 +@interface LETransceiver : NSObject<CBPeripheralDelegate, CBCentralManagerDelegate>
  39 +
  40 +@property (weak, nonatomic) id<LEConnctionDelegate> connectionDelegate;
  41 +@property (weak, nonatomic) id<LEDataDelegate> dataDelegate;
  42 +
  43 +- (void)setUUIDs:(NSDictionary *) uuids;
  44 +
  45 +- (void)scanStart;
  46 +- (void)scanStop;
  47 +
  48 +- (void)connect:(CBPeripheral *)peripheral;
  49 +- (void)disconnect:(CBPeripheral *)peripheral;
  50 +
  51 +- (void)write:(NSData *) data;
  52 +- (void)write:(NSData *) data index:(int) i;
  53 +
  54 +@end
  55 +
  56 +NS_ASSUME_NONNULL_END
... ...
HDFwear/Tools/OTA/LETransceiver.m 0 → 100644
  1 +//
  2 +// LETransceiver.m
  3 +// ActsBluetoothSpeed
  4 +//
  5 +// Created by inidhu on 2019/3/15.
  6 +// Copyright © 2019 Actions. All rights reserved.
  7 +//
  8 +
  9 +#import "LETransceiver.h"
  10 +#import <UIKit/UIKit.h>
  11 +
  12 +
  13 +@implementation LETransceiver {
  14 + NSString *writeServiceUUID;
  15 + NSString *writeCharacteristicUUID;
  16 + NSString *indicateServiceUUID;
  17 + NSString *indicateCharacteristicUUID;
  18 +
  19 + CBCharacteristicWriteType writeType;
  20 + CBCentralManager *centralManager;
  21 +
  22 + CBPeripheral *connectedPeripheral;
  23 + CBCharacteristic *characteristicWrite;
  24 + CBCharacteristic *characteristicIndicate;
  25 +
  26 + NSTimer *connectTimer;
  27 + BOOL isReadyToSendWrite;
  28 +
  29 +
  30 +}
  31 +
  32 +- (id) init {
  33 + self = [super init];
  34 +
  35 + writeType = CBCharacteristicWriteWithoutResponse;
  36 +
  37 + centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
  38 +
  39 + return self;
  40 +}
  41 +
  42 +- (void)setUUIDs:(NSDictionary *) uuids {
  43 + NSArray *keys = [uuids allKeys];
  44 + for (NSString *key in keys) {
  45 + if ([key isEqualToString:KeyWriteServiceUUID]) {
  46 + writeServiceUUID = [[uuids objectForKey:KeyWriteServiceUUID] uppercaseString];
  47 + } else if ([key isEqualToString:KeyIndicateServiceUUID]) {
  48 + indicateServiceUUID = [[uuids objectForKey:KeyIndicateServiceUUID] uppercaseString];
  49 + } else if ([key isEqualToString:KeyWriteCharacteristicUUID]) {
  50 + writeCharacteristicUUID = [[uuids objectForKey:KeyWriteCharacteristicUUID] uppercaseString];
  51 + } else if ([key isEqualToString:KeyIndicateCharacteristicUUID]) {
  52 + indicateCharacteristicUUID = [[uuids objectForKey:KeyIndicateCharacteristicUUID] uppercaseString];
  53 + }
  54 + }
  55 +}
  56 +
  57 +- (void)scanStart {
  58 + NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:NO], CBCentralManagerScanOptionAllowDuplicatesKey, nil];
  59 + /*
  60 + NSMutableArray *servicesUUID = [[NSMutableArray alloc] init];
  61 + if (writeServiceUUID)
  62 + [servicesUUID addObject:writeServiceUUID];
  63 + if (indicateServiceUUID)
  64 + [servicesUUID addObject:indicateServiceUUID];
  65 + */
  66 + [centralManager scanForPeripheralsWithServices:nil options:options];
  67 +}
  68 +
  69 +- (void)scanStop {
  70 + [centralManager stopScan];
  71 +}
  72 +
  73 +- (void)connect:(CBPeripheral *)peripheral {
  74 + [self scanStop];
  75 +
  76 + [centralManager connectPeripheral:peripheral options:@{CBConnectPeripheralOptionNotifyOnConnectionKey:@YES}];
  77 +
  78 + if (connectTimer) {
  79 + [connectTimer invalidate];
  80 + }
  81 + connectTimer = [NSTimer scheduledTimerWithTimeInterval:20.0 target:self selector:@selector(connectTimeout:) userInfo:peripheral repeats:NO];
  82 +}
  83 +
  84 +- (void)disconnect:(CBPeripheral *)peripheral {
  85 + if (![self isPeripheralConnected:peripheral]) {
  86 + return;
  87 + }
  88 +
  89 + NSLog(@"disconnect %@", peripheral.name);
  90 + [centralManager cancelPeripheralConnection:peripheral];
  91 +}
  92 +
  93 +- (BOOL) isPeripheralConnected:(CBPeripheral *) peripheral {
  94 + if (IOS_VERSION >= 7.0) {
  95 + if (peripheral.state == CBPeripheralStateConnected) {
  96 + return YES;
  97 + }
  98 + } else {
  99 +#ifndef __IPHONE_7_0
  100 + if (peripheral.isConnected) {
  101 + return YES;
  102 + }
  103 +#endif
  104 + }
  105 + return NO;
  106 +}
  107 +
  108 +- (NSUInteger) getMtuForType:(CBCharacteristicWriteType) type {
  109 + return [connectedPeripheral maximumWriteValueLengthForType:type];
  110 +}
  111 +
  112 +- (void)write:(NSData *) data {
  113 + if (characteristicWrite) {
  114 + NSUInteger mtu = [self getMtuForType:CBCharacteristicWriteWithoutResponse];
  115 + NSLog(@"writeData mtu: %ld, %@", mtu, data);
  116 + for (NSUInteger index = 0; index < data.length; index += mtu) {
  117 + NSUInteger len = (data.length - index) > mtu ? mtu : (data.length - index);
  118 + NSData *value = [data subdataWithRange:NSMakeRange(index, len)];
  119 + [connectedPeripheral writeValue:value forCharacteristic:characteristicWrite type:CBCharacteristicWriteWithoutResponse];
  120 + NSLog(@"writeValue: %@", value);
  121 + }
  122 + }
  123 +}
  124 +
  125 +- (void)write:(NSData *) data index:(int) i {
  126 + if (characteristicWrite) {
  127 + NSUInteger mtu = [self getMtuForType:CBCharacteristicWriteWithoutResponse];
  128 + NSLog(@"i writeData mtu: %ld, %@", mtu, data);
  129 +
  130 + for (NSUInteger index = 0; index < data.length; index += mtu) {
  131 + NSUInteger len = (data.length - index) > mtu ? mtu : (data.length - index);
  132 + NSData *value = [data subdataWithRange:NSMakeRange(index, len)];
  133 + if(i != 0 && i % 62 == 0) {
  134 + NSData *value2 = [value subdataWithRange:NSMakeRange(0, 1)];
  135 + NSData *value3 = [value subdataWithRange:NSMakeRange(1, value.length - 1)];
  136 + [connectedPeripheral writeValue:value2 forCharacteristic:characteristicWrite type:CBCharacteristicWriteWithResponse];
  137 + [connectedPeripheral writeValue:value3 forCharacteristic:characteristicWrite type:CBCharacteristicWriteWithoutResponse];
  138 + } else {
  139 + [connectedPeripheral writeValue:value forCharacteristic:characteristicWrite type:CBCharacteristicWriteWithoutResponse];
  140 + }
  141 + NSLog(@"writeValue: %@", value);
  142 + }
  143 + }
  144 +}
  145 +
  146 +- (void)connectTimeout:(NSTimer *)timer {
  147 + CBPeripheral *peripheral = (CBPeripheral *)[timer userInfo];
  148 + [self disconnect:peripheral];
  149 +}
  150 +
  151 +#pragma mark -- CBCentralManagerDelegate
  152 +- (void)centralManagerDidUpdateState:(CBCentralManager *)central {
  153 + NSString *messtoshow;
  154 + switch (central.state) {
  155 + case CBManagerStatePoweredOn:{
  156 + messtoshow=[NSString stringWithFormat:@"CBCentralManagerStatePoweredOn"];
  157 + [self scanStart];
  158 + break;
  159 + }
  160 + case CBManagerStateUnknown:
  161 + {
  162 + messtoshow=[NSString stringWithFormat:@"State unknown, update imminent"];
  163 + break;
  164 + }
  165 + case CBManagerStateResetting:
  166 + {
  167 + messtoshow=[NSString stringWithFormat:@"The connection with the system service was momentarily lost, update imminent."];
  168 + break;
  169 + }
  170 + case CBManagerStateUnsupported:
  171 + {
  172 + messtoshow=[NSString stringWithFormat:@"The platform doesn't support Bluetooth Low Energy"];
  173 + break;
  174 + }
  175 + case CBManagerStateUnauthorized:
  176 + {
  177 + messtoshow=[NSString stringWithFormat:@"The app is not authorized to use Bluetooth Low Energy"];
  178 + break;
  179 + }
  180 + case CBManagerStatePoweredOff:
  181 + {
  182 + [self disconnect:connectedPeripheral];
  183 +
  184 + messtoshow=[NSString stringWithFormat:@"Bluetooth is currently powered off"];
  185 + break;
  186 + }
  187 + default:
  188 + break;
  189 + }
  190 + NSLog(@"%@",messtoshow);
  191 +}
  192 +
  193 +- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI{
  194 +// NSLog(@"didDiscoverPeripheral: %@", peripheral);
  195 +
  196 + if(_connectionDelegate && [_connectionDelegate respondsToSelector:@selector(onFoundPeripheral:advertisementData:)]) {
  197 + [_connectionDelegate onFoundPeripheral:peripheral advertisementData:advertisementData];
  198 + }
  199 +}
  200 +
  201 +- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral{
  202 + NSLog(@"didConnectPeripheral: %@", peripheral.name);
  203 +
  204 + peripheral.delegate = self;
  205 + [peripheral discoverServices:nil];
  206 +}
  207 +
  208 +- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error{
  209 + NSLog(@"Fail to connect: %@", peripheral.name);
  210 +}
  211 +
  212 +- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error{
  213 + NSLog(@"didDisconnectPeripheral %@, error: %@",peripheral, error);
  214 +
  215 + connectedPeripheral = nil;
  216 + characteristicWrite = nil;
  217 + characteristicIndicate = nil;
  218 + if(_connectionDelegate && [_connectionDelegate respondsToSelector:@selector(onDisconnectedPeripheral:)]) {
  219 + [_connectionDelegate onDisconnectedPeripheral:peripheral];
  220 + }
  221 +}
  222 +
  223 +#pragma mark -- CBPeripheralDelegate
  224 +- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error{
  225 + NSLog(@"didDiscoverServices: %@", peripheral.name);
  226 + if (error) {
  227 + NSLog(@"Error discovering service:%@", [error localizedDescription]);
  228 + return;
  229 + }
  230 +
  231 + for (CBService *service in peripheral.services) {
  232 +
  233 + NSLog(@"service: %@", service);
  234 + [peripheral discoverCharacteristics:nil forService:service];
  235 + }
  236 +
  237 +}
  238 +
  239 +- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error{
  240 + NSLog(@"didDiscoverCharacteristicsForService: %@, %@", peripheral.name, service.UUID.UUIDString);
  241 + if (error) {
  242 + NSLog(@"Error didDiscoverCharacteristicsForService:%@",[error localizedDescription]);
  243 + return;
  244 + }
  245 +
  246 + NSLog(@"UUID: %@, %@, %@", service.UUID.UUIDString, writeServiceUUID, indicateServiceUUID);
  247 + if ([service.UUID.UUIDString isEqualToString:writeServiceUUID]) {
  248 + for (CBCharacteristic *characteristic in service.characteristics) {
  249 + NSLog(@"DiscoverCharacteristics: %@", characteristic.UUID);
  250 +
  251 + if ([characteristic.UUID.UUIDString isEqualToString:writeCharacteristicUUID])
  252 + characteristicWrite = characteristic;
  253 + }
  254 + }
  255 +
  256 + if ([service.UUID.UUIDString isEqualToString:indicateServiceUUID]) {
  257 + for (CBCharacteristic *characteristic in service.characteristics) {
  258 + NSLog(@"DiscoverCharacteristics: %@", characteristic.UUID);
  259 +
  260 + if ([characteristic.UUID.UUIDString isEqualToString:indicateCharacteristicUUID]) {
  261 + [peripheral setNotifyValue:YES forCharacteristic:characteristic];
  262 + characteristicIndicate = characteristic;
  263 + }
  264 + }
  265 + }
  266 +
  267 +
  268 + if (characteristicWrite && characteristicIndicate) {
  269 + connectedPeripheral = peripheral;
  270 + [connectTimer invalidate];
  271 +
  272 + if(_connectionDelegate && [_connectionDelegate respondsToSelector:@selector(onConnectedPeripheral:)]) {
  273 + [_connectionDelegate onConnectedPeripheral:peripheral];
  274 + }
  275 + }
  276 +}
  277 +
  278 +- (void)peripheral:(CBPeripheral *)peripheral didReadRSSI:(NSNumber *)RSSI error:(nullable NSError *)error {
  279 +
  280 +}
  281 +
  282 +- (void)peripheral:(CBPeripheral *)peripheral didWriteValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error {
  283 +
  284 + if (error) {
  285 + NSLog(@"%@,%@,Error didWriteValueForCharacteristic:%@",characteristic.UUID,[characteristic value], [error localizedDescription]);
  286 + return;
  287 + }
  288 +
  289 +}
  290 +
  291 +- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error {
  292 + if (error) {
  293 + NSLog(@"Error didUpdateValueForCharacteristic:%@", [error localizedDescription]);
  294 + return;
  295 + }
  296 + NSLog(@"didUpdateValueForCharacteristic: %@ %@", characteristic.UUID, characteristic.value);
  297 +
  298 + if (_dataDelegate && [_dataDelegate respondsToSelector:@selector(onDataReceive:)]) {
  299 + [_dataDelegate onDataReceive:[characteristic value]];
  300 + }
  301 +}
  302 +
  303 +@end
... ...
HDFwear/Tools/OTA/OTAManager.h 0 → 100644
  1 +//
  2 +// OTAManager.h
  3 +// ActsBluetoothOTA
  4 +//
  5 +// Created by inidhu on 2019/5/20.
  6 +// Copyright © 2019 Actions. All rights reserved.
  7 +//
  8 +
  9 +#import <Foundation/Foundation.h>
  10 +#import "RemoteStatus.h"
  11 +
  12 +NS_ASSUME_NONNULL_BEGIN
  13 +
  14 +typedef enum{
  15 + STATE_UNKNOWN = 0,
  16 + STATE_IDLE = 1,
  17 + STATE_PREPARING = 2,
  18 + STATE_PREPARED = 3,
  19 + STATE_TRANSFERRING = 4,
  20 + STATE_TRANSFERRED = 5,
  21 +} OTAStatus;
  22 +
  23 +
  24 +@protocol OTAManagerDelegate <NSObject>
  25 +
  26 +@optional
  27 +
  28 +- (void)sendData:(NSData *) data;
  29 +- (void)sendData:(NSData *)data index:(int) i;
  30 +- (void)audioDataReceive:(NSData *) data;
  31 +- (void)receiveAudioPSN:(NSInteger) psn data:(NSData *) data;
  32 +- (void)receiveSpeed:(NSInteger) speed;
  33 +- (void)receiveRemoteStatus:(RemoteStatus *) status;
  34 +- (void)onStatus:(OTAStatus) state;
  35 +- (void)onError:(NSInteger) errCode;
  36 +
  37 +@end
  38 +
  39 +@interface OTAManager : NSObject
  40 +
  41 +@property (weak, nonatomic) id<OTAManagerDelegate> delegate;
  42 +
  43 +- (BOOL)setOTAFile:(NSString *) path;
  44 +- (NSString *)getOTAVersion;
  45 +- (void)prepare;
  46 +- (void)upgrade;
  47 +- (void)confirmUpdateAndReboot;
  48 +- (void)setMaxMtu:(NSInteger)maxMtu;
  49 +
  50 +- (BOOL)receiveData:(NSData *) data;
  51 +
  52 +
  53 +@end
  54 +
  55 +NS_ASSUME_NONNULL_END
... ...
HDFwear/Tools/OTA/OTAManager.m 0 → 100644
  1 +//
  2 +// OTAManager.m
  3 +// ActsBluetoothOTA
  4 +//
  5 +// Created by inidhu on 2019/5/20.
  6 +// Copyright © 2019 Actions. All rights reserved.
  7 +//
  8 +
  9 +#import "OTAManager.h"
  10 +#import "Utils.h"
  11 +
  12 +@implementation OTAManager {
  13 + NSMutableData *receiveBuffer;
  14 +
  15 + NSInteger waitTimeout;
  16 + NSInteger restartTimeout;
  17 + NSInteger otaUnit;
  18 + NSInteger interval;
  19 + NSInteger ackEnable;
  20 +
  21 + NSString *fwVersion;
  22 + NSData *vRAM;
  23 + NSInteger otaMode;
  24 + NSInteger batteryThreshold;
  25 +
  26 + OTAStatus curState;
  27 +
  28 + NSData *otaFileData;
  29 +
  30 + NSTimer *timeoutTimer;
  31 +
  32 + BOOL remoteCrcSupport;
  33 +
  34 + NSInteger mWriteBytes;
  35 +
  36 + NSInteger maxMtu;
  37 +}
  38 +
  39 +- (id)init {
  40 + self = [super init];
  41 +
  42 + fwVersion = @"1.01";
  43 + otaMode = 0;
  44 + batteryThreshold = 30;
  45 + remoteCrcSupport = NO;
  46 +
  47 + return self;
  48 +}
  49 +
  50 +- (BOOL)setOTAFile:(NSString *) path {
  51 + if (path.length <= 0)
  52 + return NO;
  53 +
  54 + NSFileHandle *handle = [NSFileHandle fileHandleForReadingAtPath:path];
  55 + otaFileData = [handle readDataToEndOfFile];
  56 +
  57 + return YES;
  58 +}
  59 +
  60 +- (NSString *)getOTAVersion {
  61 + NSData *data = [otaFileData subdataWithRange:NSMakeRange(0, 4)];
  62 + NSString *magic = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
  63 + if ([magic isEqualToString:@"AOTA"]) {
  64 + data = [otaFileData subdataWithRange:NSMakeRange(64, 32)];
  65 + return [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
  66 + } else {
  67 + data = [otaFileData subdataWithRange:NSMakeRange(12, 4)];
  68 + return [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
  69 + }
  70 +}
  71 +
  72 +- (void)scheduleTimeoutTimer {
  73 + [self removeTimeoutTimer];
  74 +
  75 + timeoutTimer = [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(timeoutReport) userInfo:nil repeats:NO];
  76 +}
  77 +
  78 +- (void)removeTimeoutTimer {
  79 + if (timeoutTimer) {
  80 + [timeoutTimer invalidate];
  81 + }
  82 +}
  83 +
  84 +- (void)timeoutReport {
  85 + [self notifyStatus:STATE_UNKNOWN];
  86 +}
  87 +
  88 +- (void)readOTAHeader {
  89 + NSData *data = [otaFileData subdataWithRange:NSMakeRange(0, 4)];
  90 + NSString *magic = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
  91 + if ([magic isEqualToString:@"AOTA"]) {
  92 + data = [otaFileData subdataWithRange:NSMakeRange(64, 32)];
  93 + fwVersion = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
  94 + Byte placeholder[16] = {0x00};
  95 + vRAM = [NSData dataWithBytes:placeholder length:16];
  96 + } else {
  97 + data = [otaFileData subdataWithRange:NSMakeRange(12, 4)];
  98 + fwVersion = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
  99 + vRAM = [otaFileData subdataWithRange:NSMakeRange(56, 16)];
  100 + }
  101 +}
  102 +
  103 +- (void)checkRemoteStatus {
  104 + NSMutableArray *tlvs = [[NSMutableArray alloc] init];
  105 +
  106 + // package version
  107 + NSData *tlv = [self assembleType:0x01 length:fwVersion.length value:[fwVersion dataUsingEncoding:NSUTF8StringEncoding]];
  108 + [tlvs addObject:tlv];
  109 +
  110 + // component size
  111 + Byte valueSize[2] = {0x00, 0x00};
  112 + tlv = [self assembleType:0x02 length:2 value:[NSData dataWithBytes:valueSize length:2]];
  113 + [tlvs addObject:tlv];
  114 +
  115 + // VRAM
  116 + tlv = [self assembleType:0x03 length:vRAM.length value:vRAM];
  117 + [tlvs addObject:tlv];
  118 +
  119 + // ota work mode
  120 + Byte valueMode[1] = {(Byte)otaMode};
  121 + tlv = [self assembleType:0x04 length:1 value:[NSData dataWithBytes:valueMode length:1]];
  122 + [tlvs addObject:tlv];
  123 +
  124 + // feature support: Support CRC32 Checksum
  125 + Byte valueFeature[1] = {(Byte)0x1};
  126 + tlv = [self assembleType:0x09 length:1 value:[NSData dataWithBytes:valueFeature length:1]];
  127 + [tlvs addObject:tlv];
  128 +
  129 + NSData *command = [self assembleCommand:0x01 withTLVs:tlvs];
  130 + [self sendData:command];
  131 +}
  132 +
  133 +- (void)prepare{
  134 + [self notifyStatus:STATE_PREPARING];
  135 + [self readOTAHeader];
  136 + [self checkRemoteStatus];
  137 + [self scheduleTimeoutTimer];
  138 +}
  139 +
  140 +- (void)setMaxMtu:(NSInteger)maxMtu; {
  141 + self -> maxMtu = maxMtu;
  142 +}
  143 +
  144 +- (void)upgrade {
  145 +/* [self notifyStatus:STATE_PREPARING];
  146 +
  147 + [self readOTAHeader];
  148 + [self checkRemoteStatus];
  149 + [self scheduleTimeoutTimer];
  150 + */
  151 +
  152 + [self requestRemoteParameters];
  153 + [self scheduleTimeoutTimer];
  154 + mWriteBytes = 0;
  155 +}
  156 +
  157 +- (void)confirmUpdateAndReboot {
  158 + NSLog(@"confirmUpdateAndReboot");
  159 + NSData *buffer = [self assembleCommand:0x06 withTLVs:nil];
  160 + [self sendData:buffer];
  161 +}
  162 +
  163 +/* TLV结构组装 */
  164 +- (NSData *)assembleType:(NSInteger) type length:(NSInteger) length value:(NSData *) value {
  165 + NSInteger len = 3;
  166 + Byte *buffer = (Byte *)malloc(len);
  167 +
  168 + NSInteger index = 0;
  169 +
  170 + // Type
  171 + buffer[index++] = (Byte) (type & 0xFF);
  172 +
  173 + // Length
  174 + buffer[index++] = (Byte) (length & 0xFF);
  175 + buffer[index++] = (Byte) ((length >> 8) & 0xFF);
  176 +
  177 + // Value
  178 + NSMutableData *data = [NSMutableData dataWithBytes:buffer length:len];
  179 + [data appendData:value];
  180 +
  181 + free(buffer);
  182 +
  183 + return data;
  184 +}
  185 +
  186 +/* 命令组装 */
  187 +- (NSData *)assembleCommand:(NSInteger) cmdId withTLVs:(NSArray *) subTLVs {
  188 + NSInteger subTLVsLen = 0;
  189 + if (subTLVs && subTLVs.count > 0) {
  190 + for (NSData *tlv in subTLVs)
  191 + subTLVsLen += tlv.length;
  192 + }
  193 +
  194 + // Header
  195 + Byte *buffer = (Byte *)malloc(2);
  196 + // Server ID
  197 + buffer[0] = (Byte) 0x09;
  198 + // Command ID
  199 + buffer[1] = (Byte) (cmdId & 0xFF);
  200 + NSData *header = [NSData dataWithBytes:buffer length:2];
  201 + free(buffer);
  202 +
  203 + // Super TLV
  204 + NSData *superTLV = [self assembleType:0x80 length:subTLVsLen value:nil];
  205 +
  206 + NSMutableData *cmdData = [NSMutableData dataWithData:header];
  207 + [cmdData appendData:superTLV];
  208 + for (NSData *tlv in subTLVs) {
  209 + [cmdData appendData:tlv];
  210 + }
  211 +
  212 + return cmdData;
  213 +}
  214 +
  215 +- (void)notifyStatus:(OTAStatus) state {
  216 + if (curState == state)
  217 + return;
  218 +
  219 + curState = state;
  220 + if(_delegate && [_delegate respondsToSelector:@selector(onStatus:)]) {
  221 + [_delegate onStatus:curState];
  222 + }
  223 +}
  224 +
  225 +- (NSArray *)readOTADataFrom:(NSInteger) offset withLength:(NSInteger) length byBitmap:(NSData *) bitmap groupNum:(int) groupNum {
  226 + NSLog(@"groupNum:%d", groupNum);
  227 + NSArray *pkgIdx = [Utils getZeroBitIndexMap:bitmap groupNum:groupNum];
  228 + NSInteger pkgNum = pkgIdx.count;
  229 + NSLog(@"pkgNum:%d", pkgNum);
  230 +
  231 + NSMutableArray *packages = [[NSMutableArray alloc] init];
  232 + for (NSInteger i = 0; i < pkgNum; i++) {
  233 + NSInteger index = [pkgIdx[i] integerValue];
  234 + NSInteger odd = length - index * otaUnit;
  235 + if (odd <= 0)
  236 + break;
  237 +
  238 + NSInteger o = offset + index * otaUnit;
  239 + NSInteger len = odd > otaUnit ? otaUnit : odd;
  240 +
  241 + NSData *pkg = [otaFileData subdataWithRange:NSMakeRange(o, len)];
  242 + NSLog(@"i: %ld o: %ld pkgIdx: %ld pkgNum: %ld count: %ld", i, o, index, pkgNum, pkg.length);
  243 + if (pkg.length <= 0)
  244 + break;
  245 +
  246 + [packages addObject:pkg];
  247 + }
  248 +
  249 + return packages;
  250 +}
  251 +
  252 +- (void)sendData:(NSData *) data {
  253 + if(_delegate && [_delegate respondsToSelector:@selector(sendData:)]) {
  254 + [_delegate sendData:data];
  255 + }
  256 +}
  257 +
  258 +- (void)sendData:(NSData *) data index:(int) i{
  259 + if(_delegate && [_delegate respondsToSelector:@selector(sendData:index:)]) {
  260 + [_delegate sendData:data index:i];
  261 + }
  262 +}
  263 +
  264 +- (void)requestRemoteParameters {
  265 + NSData *data = [self assembleCommand:0x02 withTLVs:nil];
  266 + [self sendData:data];
  267 +}
  268 +
  269 +- (void)notifyRemoteAppReady:(NSInteger) state {
  270 + // ota status
  271 + Byte bytes[1] = {(Byte)(state & 0xFF)};
  272 + NSData *value = [NSData dataWithBytes:bytes length:1];
  273 + NSData *tlv = [self assembleType:0x01 length:0x01 value:value];
  274 +
  275 + NSArray *tlvs = [NSArray arrayWithObject:tlv];
  276 +
  277 + NSData *data = [self assembleCommand:0x09 withTLVs:tlvs];
  278 + [self sendData:data];
  279 +}
  280 +
  281 +/* 去除开始位置无效数据 */
  282 +- (NSData *)abandonInvalidHeaderData:(NSData *) data {
  283 + Byte *bytes = (Byte *)[data bytes];
  284 + NSInteger length = data.length;
  285 +
  286 + NSInteger index = 0;
  287 + for (index = 0; index < length; index++) {
  288 + if (bytes[index] == 0x09)
  289 + break;
  290 + }
  291 +
  292 + return [data subdataWithRange:NSMakeRange(index, length - index)];
  293 +}
  294 +
  295 +- (BOOL)receiveData:(NSData *) data {
  296 + if (!receiveBuffer) {
  297 + receiveBuffer = [[NSMutableData alloc] init];
  298 + }
  299 +
  300 + [receiveBuffer appendData:data];
  301 +
  302 + data = [self abandonInvalidHeaderData:receiveBuffer];
  303 + receiveBuffer = [NSMutableData dataWithData:data];
  304 +
  305 + /* 数据长度不足,等待下一次数据包 */
  306 + if (data.length <= 5) {
  307 + return NO;
  308 + }
  309 +
  310 + Byte *bytes = (Byte *)[data bytes];
  311 + NSInteger length = data.length;
  312 + NSInteger index = 0;
  313 +
  314 + Byte serviceId = bytes[index++];
  315 + Byte commandId = bytes[index++];
  316 +
  317 + Byte superTLV[3] = {0};
  318 + superTLV[0] = bytes[index++];
  319 + superTLV[1] = bytes[index++];
  320 + superTLV[2] = bytes[index++];
  321 + NSInteger subTLVsLen = superTLV[1] + (superTLV[2] << 8);
  322 +
  323 + /* 数据长度不足,等待下一次数据包 */
  324 + if (length - index < subTLVsLen) {
  325 + return NO;
  326 + }
  327 +
  328 + NSData *tmp = [data subdataWithRange:NSMakeRange(index + subTLVsLen, length - index - subTLVsLen)];
  329 + receiveBuffer = [NSMutableData dataWithData:tmp];
  330 +
  331 + NSData *tlvs = [data subdataWithRange:NSMakeRange(index, subTLVsLen)];
  332 + bytes = (Byte *)[tlvs bytes];
  333 + length = tlvs.length;
  334 + index = 0;
  335 +
  336 + switch (commandId) {
  337 + case 0x01: {
  338 + if (bytes[index] != 0x7F) {
  339 + return NO;
  340 + }
  341 +
  342 + index += 3;
  343 + // index++;
  344 + // int length = bytes[index];
  345 + // index++;
  346 + // length += (((int)bytes[index]) << 8);
  347 + // index++;
  348 + NSLog(@"length: %ld", length);
  349 + NSInteger errCode = [Utils bytes2UInt32:bytes index:index];
  350 + index += 4;
  351 +
  352 + NSLog(@"error code: %ld", errCode);
  353 + [self removeTimeoutTimer];
  354 +
  355 + NSData *data;
  356 + RemoteStatus *status = [[RemoteStatus alloc] init];
  357 +
  358 + for ( ; index < length; ) {
  359 + int type = bytes[index++];
  360 + int len = bytes[index++];
  361 + len += (((int)bytes[index]) << 8);
  362 + index++;
  363 + NSLog(@"index: %ld, type: %d, len: %d", index, type, len);
  364 + switch (type) {
  365 + case 0x04: // battery threshold
  366 + status.batteryThreshold = bytes[index++];
  367 + break;
  368 + case 0x05: // version name
  369 + data = [NSData dataWithBytes:&bytes[index] length:len];
  370 + index += len;
  371 + status.versionName = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
  372 + break;
  373 + case 0x06: // board name
  374 + data = [NSData dataWithBytes:&bytes[index] length:len];
  375 + index += len;
  376 + status.boardName = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
  377 + break;
  378 + case 0x07: // hardware rev
  379 + data = [NSData dataWithBytes:&bytes[index] length:len];
  380 + index += len;
  381 + status.hardwareRev = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
  382 + break;
  383 + case 0x08: // version code
  384 + status.versionCode = [Utils bytes2UInt32:bytes index:index];
  385 + index += 4;
  386 + break;
  387 + case 0x09: // feature support
  388 + status.featureSupport = bytes[index++];
  389 + remoteCrcSupport = status.featureSupport & 0x01;
  390 + break;
  391 + default:
  392 + index += len;
  393 + break;
  394 + }
  395 + }
  396 +
  397 + if (errCode == 100000) {
  398 + // [self requestRemoteParameters];
  399 + // [self scheduleTimeoutTimer];
  400 + if(_delegate && [_delegate respondsToSelector:@selector(receiveRemoteStatus:)]) {
  401 + [_delegate receiveRemoteStatus:status];
  402 + }
  403 +
  404 + [self notifyStatus:STATE_PREPARED];
  405 + } else {
  406 + curState = STATE_UNKNOWN;
  407 + if(_delegate && [_delegate respondsToSelector:@selector(onError:)]) {
  408 + [_delegate onError:errCode];
  409 + }
  410 + }
  411 + break;
  412 + }
  413 + case 0x02:{
  414 + // app wait timeout
  415 + index += 3;
  416 + waitTimeout = [Utils bytes2Short:bytes index:index];
  417 + index += 2;
  418 +
  419 + // device restart timeout
  420 + index += 3;
  421 + restartTimeout = [Utils bytes2Short:bytes index:index];
  422 + index += 2;
  423 +
  424 + // ota unit size
  425 + index += 3;
  426 + otaUnit = [Utils bytes2Short:bytes index:index];
  427 + NSLog(@"otaUnit:%ld", otaUnit);
  428 + if (maxMtu != 0) {
  429 + if ((maxMtu - 10) >= otaUnit) {
  430 +
  431 + } else {
  432 + otaUnit = maxMtu - 10; //根据最大mtu定制化设置单包最大数据量
  433 + }
  434 + } else {
  435 + otaUnit = 172;
  436 + }
  437 +
  438 + index += 2;
  439 +
  440 + // interval
  441 + index += 3;
  442 + interval = [Utils bytes2Short:bytes index:index];
  443 + index += 2;
  444 +
  445 + // ack enable
  446 + index += 3;
  447 + ackEnable = bytes[index] & 0xFF;
  448 + index++;
  449 +
  450 + [self removeTimeoutTimer];
  451 + [self notifyRemoteAppReady:1];
  452 +
  453 + // [self notifyStatus:STATE_PREPARED];
  454 + break;
  455 + }
  456 + case 0x03:{
  457 + [self notifyStatus:STATE_TRANSFERRING];
  458 +
  459 + if (ackEnable == 1) {
  460 + NSArray *array = [NSArray arrayWithObject:tlvs];
  461 + NSData *buf = [self assembleCommand:0x03 withTLVs:array];
  462 + [self sendData:buf];
  463 + }
  464 +
  465 + // file offset
  466 + int index = 3;
  467 + int offset = [Utils bytes2UInt32:bytes index:index];
  468 + index += 4;
  469 +
  470 + // file length
  471 + index += 3;
  472 + int length = [Utils bytes2UInt32:bytes index:index];
  473 + index += 4;
  474 +
  475 + // file apply bitmap
  476 + if (tlvs.length > 17) {
  477 + index ++;
  478 + int len = [Utils bytes2Short:bytes index:index];
  479 + index += 2;
  480 + if (tlvs.length >= 17 + len) {
  481 + Byte *bitmap = (Byte *)malloc(len);
  482 + for (int i = 0; i < len; i++) {
  483 + bitmap[i] = bytes[index++];
  484 + NSLog(@"bitmap[%d]: %x", i, bitmap[i]);
  485 + }
  486 +
  487 + NSData *bitmapData = [NSData dataWithBytes:bitmap length:len];
  488 + free(bitmap);
  489 +
  490 + // 计算组数
  491 + int groupNum = length / otaUnit + 1;
  492 +
  493 + NSArray *frames = [self readOTADataFrom:offset withLength:length byBitmap:bitmapData groupNum:groupNum];
  494 +// for (NSInteger i = 0; i < frames.count; i++) {
  495 + for (int i = 0; i < frames.count; i++) {
  496 + Byte b[1] = {(Byte)(i % 256)};
  497 + NSMutableData *pkg = [NSMutableData dataWithBytes:b length:1];
  498 +
  499 + NSInteger command = 0x04;
  500 + if (remoteCrcSupport) {
  501 + command = 0x0B;
  502 + int32_t checksum = [Utils crc32:frames[i]];
  503 + [pkg appendData: [NSData dataWithBytes: &checksum length: 4]];
  504 + }
  505 +
  506 + [pkg appendData:frames[i]];
  507 + NSArray *array = [NSArray arrayWithObject:pkg];
  508 + NSData *data = [self assembleCommand:command withTLVs:array];
  509 +
  510 + [self sendData:data index:i];
  511 +// NSLog(@"nick_data:%@", data);
  512 + mWriteBytes += data.length;
  513 + [_delegate receiveSpeed:mWriteBytes];
  514 + }
  515 + }
  516 + }
  517 + break;
  518 + }
  519 + case 0x05:{
  520 + // package valid size
  521 + index += 3;
  522 + int pkgValidSize = [Utils bytes2UInt32:bytes index:index];
  523 + index += 4;
  524 +
  525 + // received file size
  526 + index += 3;
  527 + int receivedSize = [Utils bytes2UInt32:bytes index:index];
  528 + index += 4;
  529 +
  530 + NSLog(@"receive 0x0905 pkgValidSize: %d, receivedSize: %d", pkgValidSize, receivedSize);
  531 + break;
  532 + }
  533 + case 0x06:{
  534 + index += 3;
  535 + int valid = bytes[index] & 0xFF;
  536 + index++;
  537 +
  538 + // NSData *buffer = [self assembleCommand:0x06 withTLVs:nil];
  539 + // [self sendData:buffer];
  540 + NSLog(@"receive 0x0906 valid: %d", valid);
  541 +
  542 + if (_delegate && [_delegate respondsToSelector:@selector(onStatus:)]) {
  543 + if (valid == 1) {
  544 + [_delegate onStatus:STATE_TRANSFERRED];
  545 + } else {
  546 + [_delegate onStatus:STATE_UNKNOWN];
  547 + }
  548 + }
  549 +
  550 + break;
  551 + }
  552 + case 0x07:{
  553 + if (bytes[index++] == 0x7F) {
  554 + index += 2;
  555 + int errCode = [Utils bytes2UInt32:bytes index:index];
  556 + index += 4;
  557 + if (errCode != 100000
  558 + && _delegate
  559 + && [_delegate respondsToSelector:@selector(onError:)]) {
  560 + NSLog(@"0x0907 Error: %d", errCode);
  561 +
  562 + [_delegate onError:errCode];
  563 + }
  564 + }
  565 +
  566 + break;
  567 + }
  568 + case 0x7D:{
  569 + int type = bytes[index] & 0xFF;
  570 + index++;
  571 + int len = [Utils bytes2Short:bytes index:index];
  572 + index += 2;
  573 + int psn = bytes[index] & 0xFF;
  574 + index++;
  575 + NSLog(@"0x097D, : %d, len: %d", psn, len);
  576 +
  577 + type = bytes[index] & 0xFF;
  578 + index++;
  579 + len = [Utils bytes2Short:bytes index:index];
  580 + index += 2;
  581 +
  582 + NSData *buffer = [tlvs subdataWithRange:NSMakeRange(index, len)];
  583 + NSLog(@"Receive 0x097D, data size: %d, %@", len, buffer);
  584 +
  585 + if (_delegate && [_delegate respondsToSelector:@selector(receiveAudioPSN:data:)]) {
  586 + [_delegate receiveAudioPSN:psn data:buffer];
  587 + }
  588 +
  589 + break;
  590 + }
  591 + default:
  592 + break;
  593 + }
  594 +
  595 + // 如果还有剩余数据,则继续处理
  596 + if (receiveBuffer.length > 0) {
  597 + [self receiveData:nil];
  598 + }
  599 +
  600 + return YES;
  601 +}
  602 +
  603 +@end
... ...
HDFwear/Tools/OTA/RemoteStatus.h 0 → 100644
  1 +//
  2 +// RemoteStatus.h
  3 +// ActsBluetoothOTA
  4 +//
  5 +// Created by inidhu on 2019/9/12.
  6 +// Copyright © 2019 Actions. All rights reserved.
  7 +//
  8 +
  9 +#import <Foundation/Foundation.h>
  10 +
  11 +NS_ASSUME_NONNULL_BEGIN
  12 +
  13 +@interface RemoteStatus : NSObject
  14 +
  15 +@property (nonatomic, strong, nullable) NSString *versionName;
  16 +@property (nonatomic, strong, nullable) NSString *boardName;
  17 +@property (nonatomic, strong, nullable) NSString *hardwareRev;
  18 +@property (nonatomic, readwrite) NSInteger batteryThreshold;
  19 +@property (nonatomic, readwrite) NSInteger versionCode;
  20 +@property (nonatomic, readwrite) NSInteger featureSupport;
  21 +
  22 +@end
  23 +
  24 +NS_ASSUME_NONNULL_END
... ...
HDFwear/Tools/OTA/RemoteStatus.m 0 → 100644
  1 +//
  2 +// RemoteStatus.m
  3 +// ActsBluetoothOTA
  4 +//
  5 +// Created by inidhu on 2019/9/12.
  6 +// Copyright © 2019 Actions. All rights reserved.
  7 +//
  8 +
  9 +#import "RemoteStatus.h"
  10 +
  11 +@implementation RemoteStatus
  12 +
  13 +- (id)init
  14 +{
  15 + if (self = [super init]) {
  16 +
  17 + self.batteryThreshold = 30;
  18 + self.versionName = nil;
  19 + self.boardName = nil;
  20 + self.hardwareRev = nil;
  21 + self.versionCode = 0;
  22 + self.featureSupport = 0x00;
  23 + }
  24 +
  25 + return self;
  26 +}
  27 +
  28 +@end
... ...
HDFwear/Tools/OTA/Utils.h 0 → 100644
  1 +//
  2 +// Utils.h
  3 +// ActsBluetoothOTA
  4 +//
  5 +// Created by inidhu on 2019/5/22.
  6 +// Copyright © 2019 Actions. All rights reserved.
  7 +//
  8 +
  9 +#import <Foundation/Foundation.h>
  10 +
  11 +NS_ASSUME_NONNULL_BEGIN
  12 +
  13 +@interface Utils : NSObject
  14 +
  15 ++ (UInt32)bytes2UInt32:(Byte*) bytes index:(NSInteger) index;
  16 ++ (UInt16)bytes2Short:(Byte*) bytes index:(NSInteger) index;
  17 +
  18 ++ (NSArray *)getZeroBitIndexMap:(NSData *) bitmap groupNum:(int) group;
  19 +
  20 ++ (int32_t)crc32:(NSData *)data;
  21 +
  22 +@end
  23 +
  24 +NS_ASSUME_NONNULL_END
... ...
HDFwear/Tools/OTA/Utils.m 0 → 100644
  1 +//
  2 +// Utils.m
  3 +// ActsBluetoothOTA
  4 +//
  5 +// Created by inidhu on 2019/5/22.
  6 +// Copyright © 2019 Actions. All rights reserved.
  7 +//
  8 +
  9 +#import "Utils.h"
  10 +
  11 +@implementation Utils
  12 +
  13 +
  14 ++ (UInt32)bytes2UInt32:(Byte*)bytes index:(NSInteger)index {
  15 + return (((bytes[index + 3] & 0xFF) << 24) + ((bytes[index + 2] & 0xFF) << 16)) + ((bytes[index + 1] & 0xFF) << 8) + (bytes[index] & 0xFF);
  16 +}
  17 +
  18 ++ (UInt16)bytes2Short:(Byte*)bytes index:(NSInteger)index {
  19 + return ((bytes[index + 1] & 0xFF) << 8) + (bytes[index] & 0xFF);
  20 +}
  21 +
  22 +/* 计算0比特位的个数 */
  23 ++ (NSInteger)countZeroBit:(NSData *) bitmap {
  24 + NSInteger count = 0;
  25 +
  26 + Byte *bytes = (Byte *)[bitmap bytes];
  27 + NSInteger length = bitmap.length;
  28 +
  29 + for (int i = 0; i < length; i++ ) {
  30 + Byte x = bytes[i];
  31 + while ((x + 1) != 0) {
  32 + x |= (x + 1);
  33 + count++;
  34 + }
  35 + }
  36 +
  37 + return count;
  38 +}
  39 +
  40 +/* 从bitmap获取相应0bit位的索引 */
  41 ++ (NSArray *)getZeroBitIndexMap:(NSData *) bitmap groupNum:(int) groupNum{
  42 + NSMutableArray *indexMap = [[NSMutableArray alloc] init];
  43 +
  44 + NSInteger count = 0;
  45 + NSInteger index = 0;
  46 + Byte *bytes = (Byte *)[bitmap bytes];
  47 + for (NSInteger i = 0; i < bitmap.length; i++) {
  48 + Byte b = bytes[i];
  49 + for (NSInteger j = 0; j < groupNum; j++) {
  50 + int offset = (index % groupNum);
  51 +
  52 + if ((b & (0x1 << offset)) == 0x0) {
  53 + [indexMap addObject:[NSNumber numberWithInteger:index]];
  54 + count++;
  55 + }
  56 +
  57 + index++;
  58 + }
  59 + }
  60 +
  61 + return indexMap;
  62 +}
  63 +
  64 ++ (int32_t)crc32:(NSData *)data {
  65 + uint32_t *table = malloc(sizeof(uint32_t) * 256);
  66 + uint32_t crc = 0xffffffff;
  67 + uint8_t *bytes = (uint8_t *)[data bytes];
  68 +
  69 + for (uint32_t i=0; i<256; i++) {
  70 + table[i] = i;
  71 + for (int j=0; j<8; j++) {
  72 + if (table[i] & 1) {
  73 + table[i] = (table[i] >>= 1) ^ 0xedb88320;
  74 + } else {
  75 + table[i] >>= 1;
  76 + }
  77 + }
  78 + }
  79 +
  80 + for (int i=0; i<data.length; i++) {
  81 + crc = (crc >> 8) ^ table[crc & 0xff ^ bytes[i]];
  82 + }
  83 + crc ^= 0xffffffff;
  84 +
  85 + free(table);
  86 + return crc;
  87 +}
  88 +
  89 +@end
... ...