1.iOS 蓝牙数据BCC(异或校验)
2.ãIOSãBLE-èç空ä¸å级(OAD)
3.ios设å¤appä½ä¸ºèçå¤è®¾ç«¯
4.iOS èç
iOS 蓝牙数据BCC(异或校验)
深入解析iOS蓝牙数据传输中的蓝蓝牙BCC(异或校验)实现 在iOS开发中,蓝牙数据传输的牙源源码安全性和准确性至关重要。其中,下载BCC(异或校验)是蓝蓝牙入户登记源码一种常见的数据验证机制,用于确保数据在传输过程中没有被篡改。牙源源码下面,下载让我们来详细解读这段关键的蓝蓝牙函数HSMCheckBCCWithHex,它在蓝牙数据包中扮演着守护者的牙源源码角色。 首先,下载函数接收一个以十六进制表示的蓝蓝牙字符串(hexstring),其核心逻辑在于对每个字符进行异或运算。牙源源码happytime源码我们看到,下载cheack变量初始化为0,蓝蓝牙这将用来累积每个字符的牙源源码校验值。 对于输入的下载每个十六进制字符,函数会将其转换为十进制数值。requestapi源码在循环中,如果needAddStr为空,就直接存储当前字符;否则,将其与当前字符拼接,并通过HSMTOOL工具进行转换。dynamodb源码转换后的十进制数,与cheack进行异或运算,以累积校验值。异或操作的特性在于,相同的thinkphpcrm源码输入结果为0,不同则为1,这有助于检测数据传输过程中是否发生位错误。 在每个字符处理完成后,cheack会被清零,为下一次计算做准备。当循环结束后,累积的校验值会被转换回十六进制并返回,通过这个值,接收方可以验证发送方的数据完整性和正确性。 总结:在iOS蓝牙数据传输中,HSMCheckBCCWithHex函数是实现数据安全传输的重要步骤。通过异或校验,它确保了数据的完整性和准确性,为开发者提供了强有力的保障。对于蓝牙应用开发者来说,理解并熟练运用这样的校验方法,是提升应用程序稳定性和用户体验不可或缺的一部分。ãIOSãBLE-èç空ä¸å级(OAD)
èç为CC ioså级èçåºä»¶;
1.头æ件
å级è¦ç¨å°çID
2.è·åèçå表,éæ©éè¦å级çèç
3.è·åææçç¹å¾å¼,æ¾å°æ们éè¦çéé,设置ééç模å¼ä¸ºçæµééåå
ä¼ è¿å»æéçåæ°
4.æå®èçç代çå代çæ¹æ³
5.éæ©è¦å级çæ件(è¿éæ¯æ¬å°)
6.å¼å§è¿è¡èçå级:
(1)åéä¸ä¸ªåèæ°æ®æ¥è·åèç设å¤çå½å设å¤ä¿¡æ¯
(2)å¨ä»£çå¤æ¥æ¶è¿åæ°æ®
(3)å¤çæ¥æ¶çæ°æ®,å¦æçæ¬ä¸ç¸å,å°±ææ¬å°æ件çåºä»¶ä¿¡æ¯éè¿ éé1 åéè¿å»;
åºä»¶ä¿¡æ¯å å«çä¿¡æ¯æï¼åºä»¶çæ¬ãåºä»¶é¿åº¦ãåºä»¶ç±»å
(4)å¨ä»£çå¤æ¥æ¶è¿åæ°æ®(å¦ææåä¼éè¿ éé2 è¿åæ°æ®)
(5)å¤çæ°æ®,å¼å§åéæ¬å°æ件;æ¶å°çæ°æ®æ¯éè¦åéæ°æ®çåºå·(-FFFF,é«ä½å¨å;,,...FF,,...)
æ¤æ¶æ两ç§æ¹æ³:
第ä¸ç§æ¯æ¯æ¬¡é½éè¿æ¥æ¶å°çåºå·æ¥åéæ°æ®,å°±ä¸éè¦æ¹åèççåéåæ¥æ¶æ¨¡å¼;
第äºç§æ¯ç´æ¥æç §ä¸å®çé´éå»åéæ°æ®;åªè¦å硬件è§å®å¥½æ¶é´å°±å¯ä»¥åºæ¬ä¿è¯æå;
ç±äºç¬¬ä¸ç§æ¹æ³çé度å¾æ ¢,æ以æéæ©ç第äºç§æ¹å¼;
(6)设置å®æ¶å¨,é´éæ¶é´ms;ç±äºæ¯ç´æ¥åéä¸éè¦è¿åæ以éæ© CBCharacteristicWriteWithoutResponse çæ¹å¼;
(7)ä¼ è¾ç»æå,硬件设å¤ä¼èªå¯,èçä¼æå¼;
demo没æ´ç è§è°
/huasali/blueToothDemo
ios设å¤appä½ä¸ºèçå¤è®¾ç«¯
è¹æææºå¯ä»¥ä½ä¸ºèçå¤è®¾ç«¯ï¼è¢«èçä¸å¤®ç«¯æ¥æ«æè¿æ¥äº¤äºæ°æ®ï¼å®ç°æ¨¡æèçå¤è®¾ç¡¬ä»¶ãéè¿é 读CoreBluetoothåºï¼å¯ä»¥æ¾å°ä¸ä¸ªCBPeripheralManagerçç±»ï¼è¯¥ç±»ä¸»è¦çä½ç¨å°±æ¯å è®¸ä½ æ¥ç®¡çåå¸servicesï¼æè¿äºservices广åç»å ¶ä»ç设å¤ãå¦ææ³è¯¦ç»äºè§£è¯¥ç±»çå±æ§åæ¹æ³ï¼å»ºè®®å»ççCoreBluetooth/CBPeripheralManager.hãä¸é¢æ¥æ¨¡æä¸ä¸ªç®åçèçå¤è®¾ç«¯ã
ä¸é¢ä¸ï¼serviceUUID为ç»å¤è®¾é ç½®çæå¡çUUIDï¼å¯ä»¥æå¤ä¸ªï¼characteristicUUID为ç»serviceæ·»å çç¹å¾çUUIDï¼ä¹å¯ä»¥æå¤ä¸ªï¼å¯èªå®ä¹å¯è¯»å¯åççå±æ§.characteristicValue为characteristicçå¼,localNameåserviceUUIDsåå«ä¸ºé®CBAdvertisementDataLocalNameKeyåCBAdvertisementDataServiceUUIDsKey对åºçvalueãç±äºä½ä¸ºå¤è®¾ç«¯æ¶åé广æå ï¼å¹¿æå ä¸æä¾å å«ç两个é®å¼å¯¹ï¼å¦ææå¦å¤çé®å¼å¯¹æ³è¦åéï¼ä¾å¦CBAdvertisementDataServiceDataKeyï¼ä¼åºç°é误ã
é¦å è¦å¯¼å ¥èçåº
#import <CoreBluetooth/CoreBluetooth.h>
éµå®åè®®
å建peripheralManager对象
å建äºperipheralManager对象åä¼èªå¨è°ç¨åè°æ¹æ³didUpdateState
- (void)peripheralManagerDidUpdateState:(CBPeripheralManager *)peripheral {
if (peripheral.state != CBPeripheralManagerStatePowerOn) {
return;
}
}
ç»å¤è®¾é ç½®æå¡åç¹å¾
- (void)configServiceAndCharacteristicForPeripheral {
CBMutableCharacteristic *writeReadCharacteristic = [[CBMutableCharacteristic alloc] initWithType:characteristicUUID properties:CBCharacteristicPropertyWrite | CBCharacteristicPropertyRead value:nil permissions:CBAttributePermissionsReadEncryptionRequired | CBAttributePermissionsWriteEncryptionRequired];
CBMutableService *service = [[CBMutableService alloc] initWithType:serviceUUID primary:YES];
[service setCharacteristics:@[writeReadCharacteristic]];
[self.peripheralManager addService:service];
}
è°ç¨ä¸é¢çæ¹æ³æ¶ï¼ä¼çå¬didAddService:
- (void)peripheralManager:(CBPeripheralManager *)peripheral didAddService:(CBService *)service error:(NSError *)error {
}
å¼å§å¹¿æ
è°ç¨ä¸ é¢æ¹æ³æ¶ï¼ä¼çå¬DidStartAdvertising:
- (void)peripheralManagerDidStartAdvertising:(CBPeripheralManager *)peripheral error:(NSError *)error {
}
å½ä¸å¤®ç«¯è¿æ¥ä¸äºæ¤è®¾å¤å¹¶è®¢é äºç¹å¾æ¶ä¼åè° didSubscribeToCharacteristic:
- (void)peripheralManager:(CBPeripheralManager *)peripheral central:(CBCentral *)central didSubscribeToCharacteristic:(CBCharacteristic *)characteristic {
[self.peripheralManager updateValue:characteristicValue forCharacteristic:characteristic onSubscribedCentrals:nil];
}
å½ä¸å¤®ç«¯åæ¶è®¢é æ¶ä¼è°ç¨didUnsubscribeFromCharacteristic:
- (void)peripheralManager:(CBPeripheralManager *)peripheral central:(CBCentral *)central didUnsubscribeFromCharacteristic:(CBCharacteristic *)characteristic {
}
å½æ¥æ¶å°ä¸å¤®ç«¯è¯»ç请æ±æ¶ä¼è°ç¨didReceiveReadRequest:
- (void)peripheralManager:(CBPeripheralManager *)peripheral didReceiveReadRequest:(CBATTRequest *)request {
if (request.characteristic.properties & CBCharacteristicPropertyRead) {
NSData *data = request.characteristic.value;
[request setValue:data];
[self.peripheralManager respondToRequest:request withResult:CBATTErrorSuccess];
} else {
[self.peripheralManager respondToRequest:request withResult:CBATTErrorReadNotPermitted];
}
}
å½æ¥æ¶å°ä¸å¤®ç«¯åç请æ±æ¶ä¼è°ç¨didReceiveWriteRequest:
- (void)peripheralManager:(CBPeripheralManager *)peripheral didReceiveWriteRequests:(NSArray<CBATTRequest *> *)requests {
CBATTRequest *request = requests[0];
if (request.characteristic.properties & CBCharacteristicPropertyWrite) {
CBMutableCharacteristic *c = (CBMutableCharacteristic *)request.characteristic;
c.value = request.value;
[self.peripheralManager respondToRequest:request withResult:CBATTErrorSuccess];
} else {
[self.peripheralManager respondToRequest:request withResult:CBATTErrorWriteNotPermitted];
}
}
ææºappå¯ä»¥ä½ä¸ºä¸ä¸ªèçå¤è®¾ç«¯æ¥æ¨¡æå¤è®¾ç¡¬ä»¶ï¼ä½å¹¿æå éçæ°æ®åªè½å å«localNameåserviceUUIDï¼ç¸å¯¹äºå¤è®¾ç¡¬ä»¶æ¥è¯´è¿æ¯æä¸äºä¸è¶³ä¹å¤ã
iOS èç
1. iOSä¸å¼åèç常ç¨çç³»ç»åºæ¯<CoreBluetooth/CoreBluetooth.h>ã
2.èçå¤è®¾å¿ é为4.0å以ä¸(2.0éè¦MFI认è¯)ï¼å¦åæ æ³è¿è¡å¼åï¼èç4.0设æ½ç±äºä½èçµï¼æ以ä¹å«åBLEã
3. CoreBluetoothæ¡æ¶çæ ¸å¿å ¶å®æ¯ä¿©ä¸è¥¿
3.1 Peripheral
3.2 Central
4. æå¡åç¹å¾(service characteristic)ï¼ç®èè¨ä¹ï¼å¤é¨èçä¸å®æè¥å¹²ä¸ªæå¡serviceï¼æå¡ä½ è½äºè§£ä¸ºèçææ¥æçå¯ä»¥åï¼ï¼èæ¯ä¸ªæå¡serviceä¸æ¥æè¥å¹²ä¸ªç¹å¾characteristicï¼ç¹å¾ä½ è½äºè§£ä¸ºè§£éè¿ä¸ªæå¡çå±æ§ï¼ã
5. Descriptorï¼å½¢å®¹ï¼ä½¿ç¨æ¥å½¢å®¹characteristicåéçå±æ§ãä¾å¦ï¼ä¸ä¸ªdescriptorè½è§å®ä¸ä¸ªå¯è¯»ç形容ï¼æè è ä¸ä¸ªcharacteristicåéå¯æ¥åçèå´ï¼æè è ä¸ä¸ªcharacteristicåéç¹å®çåä½ã
3.1 å建ä¸ä¸ªCBCentralManagerå®ä¾æ¥è¿è¡èç管çï¼
3.2 æç´¢æ«æå¤å´è®¾å¤ï¼
3.3 è¿æ¥å¤å´è®¾å¤ï¼
3.4 è·å¾å¤å´è®¾å¤çæå¡ï¼
3.5 è·å¾æå¡çç¹å¾ï¼
3.6 ä»å¤å´è®¾å¤è¯»åæ°æ®ï¼
3.7 ç»å¤å´è®¾å¤åéï¼åå ¥ï¼æ°æ®ã
4.1 åå§å
dispatch_queue_t centralQueue = dispatch_queue_create(âcentralQueue",DISPATCH_QUEUE_SERIAL);
NSDictionary *dic = @{ CBCentralManagerOptionRestoreIdentifierKey : restoreIdentifier};
self.centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:centralQueue options:dic];
CBCentralManagerOptionRestoreIdentifierKey对åºçæ¯ä¸ä¸ªå¯ä¸æ è¯çå符串ï¼ç¨äºèçè¿ç¨è¢«æææ¢å¤è¿æ¥æ¶ä½¿ç¨
4.2 æ«æ
/
**æ«æ设å¤
*/
- ( void )scanForDevices:(NSError**)error
{
if (CBCentralManagerStatePoweredOn == self .centralManager.state) {
//ååå·²è¿æ¥çservice设å¤
NSArray* retrievedPeripherals = [ self .centralManagerretrieveConnectedPeripheralsWithServices:@[ self .serviceUUID]];
for (CBPeripheral* peripheral in retrievedPeripherals){
//NSLog(@"retrieved peripheral:%@", peripheral);
[ self .delegateclient: self didDiscoverDevice:peripheral.identifier];
}
//å¯å¨æ«æ
if ( self .advertisementUUID) {
[ self .centralManager scanForPeripheralsWithServices:@[ self .advertisementUUID ] options:@{ CBCentralManagerScanOptionAllowDuplicatesKey:@YES }];
} else {
[ self .centralManager scanForPeripheralsWithServices: nil options:@{ CBCentralManagerScanOptionAllowDuplicatesKey:@YES }];
// [self.centralManager scanForPeripheralsWithServices:nil options:nil];
}
} else {
if (error != NULL ) {
*error = [NSErrorerrorWithDomain:HCErrorDomaincode:(SRVClientErrorUnknown+ self .centralManager.state)userInfo: nil ];
NSLog(@"[NSError errorWithDomain:HCErrorDomain code:(SRVClientErrorUnknown + self.centralManager.state) userInfo:nil];");
}
}
}
4.3 åç°å¤å´è®¾å¤
- ( void )centralManager:(CBCentralManager*)centraldidDiscoverPeripheral:(CBPeripheral*)peripheraladvertisementData:(NSDictionary*)advertisementDataRSSI:(NSNumber*)RSSI {
NSString*peripheralName = peripheral.name;
if (peripheralName == nil || peripheralName.length==0) {
return ;
}
if ([peripheralNameisEqualToString:SRV_CLIENT_DEV_NAME] || [peripheralNameisEqualToString:SRV_CLIENT_DFU_NAME]) {
}
}
4.4 è¿æ¥å¤å´è®¾å¤
//èçè¿æ¥æååè°
- ( void )centralManager:(CBCentralManager*)centraldidConnectPeripheral:(CBPeripheral*)peripheral {
[ self .centralManager stopScan];
peripheral.delegate= self ;
self .commandNo=0;
NSLog(@"[D] CentralManager Discover services.");
NSLog(@"%@", self .peripheral);
self .peripheral.delegate= self ;
[ self .peripheral discoverServices:@[ self .serviceUUID]];
NSLog(@"%@", self .serviceUUID);
//å®æ¶è·åRSSI
if ( self .needReadRSSI) {
[ self readPeripheralRSSI];
if (! self .rssiTimer) {
self .rssiTimer = [NSTimer scheduledTimerWithTimeInterval:5.0
target: self
selector: @selector (readPeripheralRSSI)
userInfo: nil
repeats: YES ];
}
}
}
#pragma mark è¿æ¥å¤è®¾ââ失败
- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error{
NSLog(@"%@", error);
}
#pragma mark åæ¶ä¸å¤è®¾çè¿æ¥åè°
- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error{
NSLog(@"%@", peripheral);
}
4.5 è·å¾å¤å´è®¾å¤çæå¡
//åç°æå¡çåè°
- ( void )peripheral:(CBPeripheral*)peripheraldidDiscoverServices:(NSError*)error
{
NSLog(@"%@---didDiscoverServices",peripheral);
if (error){
NSLog(@"[E] peripheral didDiscoverServices error: %@", error.localizedDescription);
[ self cancelConnection];
return ;
}
for (CBService* service in peripheral.services){
NSLog(@"[D] Discover characteristics. For service = %@", service);
[peripheraldiscoverCharacteristics: nil forService:service];
}
}
//åç°ç¹å¾çåè°
- ( void )peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error
{
if (error){
NSLog(@"[E] peripheral didDiscoverCharacteristicsForService error: %@", error.localizedDescription);
[ self cancelConnection];
return ;
}
NSLog(@"[D] peripheral DiscoverCharacteristics = %@", service.characteristics);
//订é ç¹å¾
for (CBCharacteristic*characteristic in service.characteristics){
if (characteristic.properties & (CBCharacteristicPropertyNotify|CBCharacteristicPropertyIndicate)){
if (!characteristic.isNotifying) {
if ([ self .ignoreCharacteristicUUIDscontainsObject:characteristic.UUID]) {
continue ;
}
NSLog(@"[D] Enable notify value. For characteristic = %@", characteristic);
//d订é ç¹æ§å½æ°æ®é¢ç¹æ¹åæ¶ç¨ setNotifyValue ä¸é¢ç¹æ¶ç¨readValueForCharacteristic
[peripheralsetNotifyValue: YES forCharacteristic:characteristic];
}
}
}
}
// 订é åçcallback
- ( void )peripheral:(CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
{
if (error){
NSLog(@"[E] peripheral didUpdateNotificationStateForCharacteristic error: %@", error.localizedDescription);
[ self cancelConnection];
return ;
}
if ([ self isAllCharacteristicNotificationEnabled]){
NSLog(@"订é æå");
//authorizeRequest ææ认è¯
[ self .delegate clientDidPrepareForOperation: self ];
}
// [self.delegate clientDidPrepareForOperation:self];
}
4.6 ä»å¤å´è®¾å¤è¯»åæ°æ®
// peripheral主å¨åæ°æ®ï¼å æ¬åå½ä»¤å主å¨è¿åçç¶æ 读æ°æ®çåè°
- ( void )peripheral:(CBPeripheral*)peripheraldidUpdateValueForCharacteristic:(CBCharacteristic*)characteristicerror:(NSError*)error
{
if (error) {
NSLog(@"[E] peripheral didUpdateValueForCharacteristic error: %@ %@", error.localizedDescription,characteristic);
[ self cancelConnection];
[ self cleanupOperationUnexpectedly];
return ;
}
NSLog(@"%@",peripheral);
NSLog(@"%@",characteristic);
[ self .delegate client: self didUpdateValueForCharacteristic:characteristic.UUID value:characteristic.value];
if ([characteristic.UUIDisEqual: self .ctrlptUUID]) {
if (CTRLPTProgressWaitResp == self .ctrlptProgress) {
}
}
}
4.7 ç»å¤å´è®¾å¤åéï¼åå ¥ï¼æ°æ®
- ( BOOL )performOperationSegment:(CBCharacteristic*)characteristic
{
BOOL isLastSegment;
uint8_tsegment[];
uint_tindex =0;
uint_tsegLength;
NSIntegerforwardLength = self .forwardFlow.length;
if ((forwardLength - self .forwardOffset) > (- index)) {
isLastSegment = NO ;
segLength = (- index);
} else {
isLastSegment = YES ;
segLength = (forwardLength - self .forwardOffset);
}
memcpy(&segment[index], & self .forwardFlow.bytes[ self .forwardOffset], segLength);
self .forwardOffset+= segLength;
index += segLength;
NSData*writeData = [NSDatadataWithBytes:segmentlength:index];
NSLog(@"[D] Write value = %@. For characteristic = %@", writeData, characteristic);
[ self .peripheral writeValue:writeData forCharacteristic:characteristic type:CBCharacteristicWriteWithResponse];//对äºææ§ç±»èçï¼æ°æ®åå ¥è¦æ±é常快ï¼å ¶ä¸writeWithSponceåå ¥æ¶èçæ¶é´æ¯writeWithoutSponceç2.3åï¼å æ¤å°½éæ¹åæwriteWithoutSponceæ¥æååå ¥éç
return isLastSegment;
}
//æ¯å¦åå ¥æåçåè°
- ( void )peripheral:(CBPeripheral*)peripheraldidWriteValueForCharacteristic:(CBCharacteristic*)characteristicerror:(NSError*)error
{
if (error) {
NSLog(@"[E] peripheral didWriteValueForCharacteristic error: %@", error);
[ self cancelConnection];
[ self cleanupOperationUnexpectedly];
return ;
}
NSLog(@"åå ¥æå----%@",characteristic);
if ([characteristic.UUIDisEqual: self .ctrlptUUID]) {
if (CTRLPTProgressWritting == self .ctrlptProgress) {
if ([ self performOperationSegment:characteristic]) {
self .ctrlptProgress = CTRLPTProgressWaitResp;
self .backwardFlow.length=0;
self .backwardOffset=0;
}
}
}
}
4.8 å¦ä½è§£æèçæ°æ®
//å¤ææ¯å¦ç¬¬ä¸ä¸ªå ï¼è¥æ¯ï¼ååºå é¿åº¦
if (0== self .backwardOffset&& length >=2) {
uint_tcommandLength;
[characteristicDatagetBytes:&commandLengthlength: sizeof (commandLength)];
offset += sizeof (commandLength);
self .backwardLength= commandLength;
[ self .backwardFlowappendData:[characteristicDatasubdataWithRange:NSMakeRange(offset, length - offset)]];
} else {
[ self .backwardFlowappendData:characteristicData];
}