基于SPP协议,通过iphone蓝⽛与经过苹果MFI授权认证的硬件通讯,传输图
因为公司产品需要,要写⼀个demo,演⽰iphone与硬件通过蓝⽛通讯,传输数据包,折腾好久,终于折腾了出来了。分享⼀下实现的过程。
⾸先,要拿到苹果公司的MFI认证,然后要定义⾄少⼀种命令协议,让配件⽀持,Apple 并不负责提供协议的注册机制,制造商必须⾃⼰决定⽀持哪些协议,为了防⽌命名冲突,协议的名字是反向的 DNS 字符串,类似Protocol。
定义好协议后,要在⼯程中声明协议,在Info.plist的UISupportedExternalAccessoryProtocols键中声明。
⼯程⾥要添加ExternalAccessory 框架。
通过EAAccessoryManager获取配件列表,通过EAAccessory与配件建⽴连接,就可以创建⼀个EASession回话,与配件进⾏通讯。
详细代码参照官⽅EADemo实例,⾥⾯实现的很清楚。
我的任务是将图⽚读进去,提取它的raw数据,但由于图⽚是96x96像素,就是说raw数据⼤⼩有96x96x4个bit,⼤约40k,输出到配件后要进⾏写⼊,速度太慢,所以将raw 数
据经过处理,去掉透明度,RGB分别取5位,6位,5位,这样⼤约剩20k,即使这样也要将每个数据包分段发送,每段256个字节,发送数据前,加上⼀个⽂件头,每⼀段加上⼀个
段头,每⼀段发送之后等待硬件响应,响应之后才能发送下⼀段,1s之内没有接受响应则终⽌发送。部分代码如下:
[html]
01.    UIImage *img=[UIImage imageNamed:myFilePath];//myFilePath位图⽚路径
02.    CGImageRef cgimage=img.CGImage;
03.    CFDataRef dataref=CGDataProviderCopyData(CGImageGetDataProvider(cgimage));//获取图⽚cfdata数据
04.    int cgdatalength=CFDataGetLength(dataref);
05.    UInt8 *pixelByteData=(UInt8 *)malloc(cgdatalength);
06.    CFDataGetBytes(dataref, CFRangeMake(0,cgdatalength),pixelByteData);
07.    int eachgroupnum=256;//每⼀段数据⼤⼩为256bit
08.    int groumpcount=cgdatalength/(eachgroupnum*2);//分段总数
09.    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++)
苹果apple id注册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.
71.
72. -(void) laterwritedata:(NSMutableData *)data
73. {
74.    if(readdatabuf==0xff0000){
75. temps=YES;//temp位YES,表⽰已得到响应,可以进⾏下⼀段的发送
76.        [[EADSessionController sharedController] writeData:data];
77.        }
78.        else
79.        {
80. temps=NO;
81.        }
82. }