- UID
- 864567
|
这是发表在电子产品世界2009精选实用电子设计100例上的文章,论述了蓝牙技术的兼容性问题出现的原因以及解决方法。
引言
蓝牙技术问世10余年,得到了广泛应用,其中部分原因在于蓝牙SIG组织为各种应用以profile的形式定义了应用协议,这样蓝牙设备之间的互操作便有章可循,但即使如此,蓝牙设备之间的互操作性又称兼容性问题仍存在于几乎所有蓝牙应用中。笔者历时两年时间为某合资汽车厂商开发了一款蓝牙车载产品,实现了免提通话、双重呼叫管理、电话本自动下载与手动下载、流媒体音乐播放及远程控制功能,期间测试了近100部手机和音乐播放器,遇到并解决了各种兼容性问题。结合产品开发过程中测试并解决兼容性问题的经验,本文对兼容性问题出现的原因进行了分析,大致有以下三个方面的原因:具体应用本身定义不严格、应用上下文差异、引入协议带来的兼容性。以下就这三个方面进行详细分析并结合具体实例,说明其解决方法。
应用定义不严格
蓝牙SIG组织定义了Profile,对各种功能的实现方式做了规范,并且定义了必选功能和可选功能,设备厂商可以对可选项有选择得实现,这样便会造成一定的差异。而且Profile并没有对应用本身做严格定义,只是定义了功能,而应用是功能的集合体,Profile并没有定义怎么由多个功能组合实现某个应用,这样蓝牙设备厂商在实现某一应用时便有了差异性。双重呼叫是车载设备免提通话应用中兼容性最多的一种应用,下面分析下该应用出现兼容性问题的原因并举例剖析其解决方法。
对于免提通话而言,比较重要的几个功能是呼叫建立提示CALL_SETUP、呼叫保持CALL_HELD、呼叫结果CALL、呼叫信息CLCC,手机在呼叫状态产生变化时实时向免提设备端传送这些提示消息,免提设备端便可以与手机的呼叫状态保持一致,在免提设备端控制呼叫才符合预期。其中CALL_SETUP和CALL是必选功能,但对于双重呼叫而言非常重要的CALL_HELD和CLCC却是可选功能,双重呼叫在免提剖面HFP(Hands-Free Profile)中定义为Three way calling,这也是一个可选功能。这样在支持双重呼叫时,各种手机便以自己的方式来支持或者部分支持,这样便来了双重呼叫的兼容性问题。下面以第二个呼叫为呼出为例剖析下解决方法。
当拨打第二个电话时,手机会发送CALL_SETUP=2消息,表示正在呼出,结果有对方拒接、对方接听、未拨通这么几种情况。显然判断出呼出结果是至关重要的,我们通过对手机进行测试然后根据其表现特性进行分类,将手机分为如下几类:A-支持CALL_HELD不支持CLCC、B-支持CALL_HELD和CLCC、C-支持CLCC不支持CALL_HELD而且手机在Three way calling下不支持CALL、D-支持CLCC不支持CALL_HELD但手机在Three way calling下支持CALL、E-不支持CALL_HELD也不支持CLCC但手机在Three way calling下支持CALL、F-不支持CALL_HELD也不支持CLCC而且手机Three way calling下不支持CALL。
对于支持CALL_HELD消息的AB类手机而言,我们可以通过CALL_HELD来判断呼出结果,CALL_HELD=1表示对方接听,CALL_HELD=0则表示对方拒接或未拨通;对于支持CLCC的CD类手机而言,如果手机在Three way calling下支持CALL,CALL=1则表示对方接听,如果没有CALL消息说明对方拒接或未拨通,这时需要在CALL_SETUP=0时读取手机当前的呼叫信息,然后根据该呼叫信息更新免提设备端的呼叫状态;对于不支持CLCC和CALL_HELD的EF类手机而言,如果手机在Three way calling下支持CALL,CALL=1则表示对方接听,否则在CALL_SETUP=0时默认将呼叫结果处理为对方拒接,即这个时候无法判断呼出结果。
应用上下文差异
蓝牙是个对时间特性要求很严格的应用,每种蓝牙行为及其每个阶段必须在相应时间内完成,否则可能造成失败或者长时间无法响应。应用的上下文是指在某个蓝牙行为完成后,下面将要进行什么样的蓝牙行为,它是由蓝牙设备的应用决定的,同类产品在应用上的差异便会带来应用上下文上的差异,这样便可能会带来兼容性问题。比如在蓝牙车载设备与蓝牙手机互操作完成配对后,当车载设备实现配对后的自动连接时,便由于手机在配对完成后的处理有所不同而遇到了兼容性问题。车载设备实现了配对后的自动连接功能,在配对完成后车载设备读取外部设备的SDP进行服务查询以判断外部设备类型(包括免提、音频流、免提+音频流三种类型)然后自动连接其免提或音频流服务,结果造成部分手机读取SDP失败、部分手机自动连接失败、部分手机处于长时间无法响应的状态。
对于这种兼容性问题,需要对手机在不同应用上下文的表现特性进行分析,并根据其差异进行分类。通过对手机在配对完成后的处理进行分析,有的手机配对完成后马上自动连接,有的需要用户确认再手动连接,有的会通过SDP读取车载设备的服务列表然后针对车载设备提供的服务自动连接(车载设备提供免提服务、SPP服务、SyncML服务、流媒体音乐播放服务),而有的不会自动连接,这样分类后,根据手机特性的不同设计实现配对后的自动连接如下:
蓝牙车载设备在配对完成后的4秒内无操作,配对后马上自动连接的手机(如nokia 6500c)和大部分读取SDP后自动连接的手机(如三星SGH-U608、SGH-E208),可以迅速连接上车载设备。配对完成四秒后蓝牙车载设备通过SDP判断配对设备的类型(包括免提、音频流、免提+音频流三种类型),如果类型为免提+音频流,则在连接免提成功后等待10秒再去连接音频流,之所以10秒后再去连接音频流是因为免提连接成功后,需要连接PBAP或SyncML或SPP去下载电话本,如果同时进行A2DP的连接去连接配对设备的流媒体服务,会造成链路丢失,免提连接及音频流连接断开。如果连接免提失败,则不再连接其音频流服务,因为有的手机如多普达D600的PDA手机,配对完成后读取SDP然后自动连接,有时会造成免提连接不成功,如果去连接其音频流,连接成功,但之后从车载设备端连接手机无法连接成功。断开流媒体后,连接免提一直失败,必须重新配对才行。
对于用户确认手动连接的手机和部分读取SDP然后自动连接车载设备的手机,在车载设备自动连接手机期间,可能会收到手机的连接请求,如果连接请求的手机与自动连接的手机为同一设备(蓝牙地址相同),则接收该连接请求,否则会造成自动连接失败。同时由于车载设备支持SPP的dev A,PDA手机的dev A可能会在配对后自动连接车载设备的SPP dev A,这时要拒绝该连接,如果不对该连接请求进行处理,会造成PDA手机处于长时间无法响应的状态。
引入协议带来的兼容性
蓝牙技术是个开放性的协议,它借鉴了很多成熟的已经得到广泛应用的协议,比如Syncml,封装在蓝牙OBEX协议上可以实现个人信息的同步更新,比如vCard,它和PBAP、OPP协议结合,用来进行电话本条目和呼叫日志的封装、下载和解析,这些协议本身便存在一定的兼容性问题,需要深入研究引入的协议,并尽量多得测试更多手机以尽量完善应用程序。下面以vCard的解析为例来说明该兼容性问题的解决方法。
vCard是电子名片规范,定义了个人信息数据的存储格式及访问接口的规范,现在广泛应用的是v2.1版本和3.0版本,对于电话本条目和呼叫日志而言,关键信息为姓名、电话号码及呼叫时间。含有多个电话号码的电话本条目,我们将之定义为VCARD,其电话号码包含家庭电话、工作电话、手机、车载电话四种属性。
vCard样例如下:
BEGIN:VCARD
VERSION:2.1
N;CHARSET=UTF-8;ENCODING=QUOTED-PRINTABLE;:=9A=6C=5E=FA=8F=89
TEL;CELL:13475909642
TEL;WORK:053182605413
END:VCARD
以上的vCard样例中,人名字段提取为“马建辉”的UTF-8字符0x9A6C 0x5EFA 0x8F89,这部分的兼容性在于不同手机在封装电话本条目的人名字段时所使用的字符集和编码方式不一致,字符集有ASCII和UTF-8,编码方式有8BIT、QUOTED-PRINTABLEPRINTABLE、BASE64这么几种方式,需要对这几种方式分别处理,比如以上vCard人名字段的处理需要把=9A=6C=5E=FA=8F=89转换为0x9A6C 0x5EFA 0x8F89,处理代码如下所示,temp_name数组为未处理的人名字符串,处理好的人名放在NAME数组中:
if(temp_name=='=')
{
if((temp_name[i+1]>=0x41)&&(temp_name[i+1]<=0x46))
temp1=temp_name[i+1]-0x37;
else if((temp_name[i+1]>=0x30)&&(temp_name[i+1]<=0x39))
temp1=temp_name[i+1]-0x30;
if((temp_name[i+2]>=0x41)&&(temp_name[i+2]<=0x46))
temp2=temp_name[i+2]-0x37;
else if((temp_name[i+2]>=0x30)&&(temp_name[i+2]<=0x39))
temp2=temp_name[i+2]-0x30;
NAME[name_len]=(temp1<<4)+temp2;
name_len++;
i+=3;
}
另外还需要考虑一些特殊情况,如Sony Erricson 手机电话本条目的人名字段有时会把空格处理为0xE38080,所以如果提取出0xE38080,需要把该特殊字符以空格0x20代替,否则会处理为乱码。
对于号码字段的提取,关键字不仅是HOME、WORK、CELL、CAR,还要把PREF、VOICE作为可以被识别的关键字,而且有手机不带关键字,把不带关键字的处理为CELL即手机属性即可。
呼叫时间,其字段以X-IRMC-CALL-DATETIME表示,其标准格式举例如下:20080112T1212,年四个字节,月和日分别两个字节,但对于部分手机,其月和日没有严格遵循该规范,月+日字段共两个字节或共三个字节,这就需要根据月和日的特性进行特殊处理了。处理代码如下,月日字节数为temp_month_date_length,存放在temp_month_date数组中,
if(temp_month_date_length==2)
{
temp_month=temp_month_date[0]-0x30;
temp_date=temp_month_date[1]-0x30;
}
else if(temp_month_date_length==3)
{
if(temp_month_date[0]>0x31)//then the character must be month
{
//214-2 14
temp_month=temp_month_date[0]-0x30;
temp_date=(unsigned char)((temp_month_date[1]-0x30)*10+(temp_month_date[2]-0x30));
}
else if(temp_month_date[1]>0x32)
{
//130-1 30
temp_month=temp_month_date[0]-0x30;
temp_date=(unsigned char)((temp_month_date[1]-0x30)*10+(temp_month_date[2]-0x30));
}
else
{
//114 to month=11 date=4
temp_month=(unsigned char)((temp_month_date[0]-0x30)*10+(temp_month_date[1]-0x30));
temp_date=temp_month_date[2]-0x30;
if(temp_month>=11)
{
temp_month=0;
temp_date=0;
}
}
}
结语
兼容性是蓝牙产品开发中的难点问题,本文分析了兼容性问题出现的原因,并结合具体实例分析其解决方法,有很好的借鉴意义。 |
|