1. 程式人生 > >基於SPP協議,通過iphone藍芽與經過蘋果MFI授權認證的硬體通訊,傳輸圖片

基於SPP協議,通過iphone藍芽與經過蘋果MFI授權認證的硬體通訊,傳輸圖片

因為公司產品需要,要寫一個demo,演示iphone與硬體通過藍芽通訊,傳輸資料包,折騰好久,終於折騰了出來了。分享一下實現的過程。

      首先,要拿到蘋果公司的MFI認證,然後要定義至少一種命令協議,讓配件支援,Apple 並不負責提供協議的註冊機制,製造商必須自己決定支援哪些協議,為了防止命名衝

突,協議的名字是反向的 DNS 字串,類似com.apple.myProtocol

      定義好協議後,要在工程中宣告協議,在Info.plist的UISupportedExternalAccessoryProtocols鍵中宣告。

      工程裡要新增ExternalAccessory 框架。

      通過EAAccessoryManager獲取配件列表,通過EAAccessory與配件建立連線,就可以建立一個EASession回話,與配件進行通訊

      詳細程式碼參照官方EADemo例項,裡面實現的很清楚。

      我的任務是將圖片讀進去,提取它的raw資料,但由於圖片是96x96畫素,就是說raw資料大小有96x96x4個bit,大約40k,輸出到配件後要進行寫入,速度太慢,所以將raw數

據經過處理,去掉透明度,RGB分別取5位,6位,5位,這樣大約剩20k,即使這樣也要將每個資料包分段傳送,每段256個位元組,傳送資料前,加上一個檔案頭,每一段加上一個

段頭,每一段傳送之後等待硬體響應,響應之後才能傳送下一段,1s之內沒有接受響應則終止傳送。部分程式碼如下:

  1.     UIImage *img=[UIImage imageNamed:myFilePath];//myFilePath點陣圖片路徑  
  2.     CGImageRef cgimage=img.CGImage;  
  3.     CFDataRef dataref=CGDataProviderCopyData(CGImageGetDataProvider(cgimage));//獲取圖片cfdata資料  
  4.     int cgdatalength=CFDataGetLength(dataref);  
  5.     UInt8 *pixelByteData=(UInt8 *)malloc(cgdatalength);  
  6.     CFDataGetBytes(dataref, CFRangeMake(0,cgdatalength),pixelByteData);  
  7.     int eachgroupnum=256;//每一段資料大小為256bit  
  8.     int groumpcount=cgdatalength/(eachgroupnum*2);//分段總數  
  9.     NSMutableData *data1 = [NSMutableData data];  
  10.     const char *buf = [self.ID UTF8String];//將命令頭處理為位元組流  
  11.     if (buf)  
  12.     {  
  13.         uint32_t len = strlen(buf);  
  14.         char singleNumberString[3] = {'\0', '\0', '\0'};  
  15.         uint32_t singleNumber = 0;  
  16.         for(uint32_t i = 0 ; i <len; i+=2)  
  17.         {  
  18.             if ( ((i+1) <len) && isxdigit(buf[i]) && (isxdigit(buf[i+1])) )  
  19.             {  
  20.                 singleNumberString[0] = buf[i];  
  21.                 singleNumberString[1] = buf[i + 1];  
  22.                 sscanf(singleNumberString, "%x", &singleNumber);  
  23.                 uint8_t tmp = (uint8_t)(singleNumber & 0x000000FF);  
  24.                 [data1 appendBytes:(void *)(&tmp) length:1];  
  25.             }  
  26.             else  
  27.             {  
  28.                 break;  
  29.             }  
  30.         }  
  31.     }  
  32.     [data1 appendBytes:(void *)(&groumpcount) length:1];//將分段總數新增到位元組流中  
  33.     [[EADSessionController sharedController] writeData:data1];//傳送檔案頭  
  34.     //將圖片位元組流資料分成groumpcount分,每個畫素點去掉透明體,3位元組RGB處理成2位元組,讀入位元組流緩衝區  
  35.     NSMutableData *datas = [NSMutableData data];  
  36.     UInt16 temp=0;  
  37.     for(int i=0;i<groumpcount;i++)  
  38.     {  
  39.        [datas appendBytes:(void *)(&i) length:1];//段首編號部分  
  40.        [datas appendBytes:(void *)(&groumpcount) length:1];//段首編號分段總數部分  
  41.         for(int j=eachgroupnum*i*2;j<eachgroupnum*(i+1)*2;j=j+4)  
  42.         {  
  43.            temp=pixelByteData[j+2];  
  44.            temp+=pixelByteData[j+1]*32;  
  45.            temp+=pixelByteData[j]*2048;  
  46.            uint8_t tmp1 = (uint8_t)(temp & 0x0000FF00);  
  47.            uint8_t tmp2 = (uint8_t)(temp & 0x000000FF);  
  48.            [datas appendBytes:(void *)(&tmp1) length:1];  
  49.            [datas appendBytes:(void *)(&tmp2) length:1];  
  50.          }  
  51.         if (i==0) {  
  52.             [[EADSessionController sharedController] writeData:datas];//第一段資料直接傳送  
  53.         }  
  54.         else{  
  55.             if(readdatabuf==0xff0000){//readdatabuf為硬體響應發回的資料,當以一段資料成功接受後,給應用發回0xff0000,且readdatabuf值儲存最後 一次硬體響應  
  56.                 [[EADSessionController sharedController] writeData:datas];//傳送下一段資料  
  57.                 readdatabuf=0;//清空上一次接受的資料  
  58.                 [datas setData:nil];//清空上一次傳送的資料  
  59.                 continue;//結束本次迴圈  
  60.             }  
  61.             [self performSelector:@selector(laterwritedata:) withObject:datas afterDelay:1];  
  62.             if(temp==NO)  
  63.             {  
  64.                 break;//1s之內沒有收到硬體的響應,跳出迴圈,終止傳送  
  65.             }  
  66.         }  
  67.         readdatabuf=0;//清空上一次接受的資料  
  68.         [datas setData:nil];//清空上一次傳送的資料  
  69.     }  
  70. -(void) laterwritedata:(NSMutableData *)data  
  71. {  
  72.     if(readdatabuf==0xff0000){  
  73.         temps=YES;//temp位YES,表示已得到響應,可以進行下一段的傳送  
  74.         [[EADSessionController sharedController] writeData:data];  
  75.         }  
  76.         else  
  77.         {  
  78.             temps=NO;  
  79.         }  
  80. }