草庐IT

iOS 蓝牙开发 Mac地址问题

斌雅iOS 2023-10-06 原文

在蓝牙开发中,经常会遇到蓝牙Mac地址(物理地址-->唯一标记)链接的问题:
对于安卓来说,可以通过Mac地址来链接,因为他们可以获取到外设的Mac地址。
对于苹果而言,是不可以通过Mac地址链接的,因为我们无法获取外设的Mac地址。

虽然苹果给我们提供了一个外设的UUID,但是这个UUID是通过外设的Mac地址和手机的Mac地址进行加密计算得来的。

换言之,不同手机链接同一外设这个值是不同的,所以这个值并不能取代Mac地址作为唯一标记,况且安卓是没有这个UUID的。

peripheral.identifier.UUIDString;
*!
 *  @property identifier
 *
 *  @discussion The unique, persistent identifier associated with the peer.
 */
@property(readonly, nonatomic) NSUUID *identifier NS_AVAILABLE(10_13, 7_0);
/* Return a string description of the UUID, such as "E621E1F8-C36C-495A-93FC-0C247A3E6E5F" */
@property (readonly, copy) NSString *UUIDString;

那iOS如何获取Mac地址呢?

方案A:硬件工程师将Mac地址写到厂商数据中,然后我们获取(扫描阶段就可以获取到)

方案B:(本质就是读取固定指令获取)读取外设的180A服务里的2A23特征值,再去进行剪切和拼接来获取(必须先链接上外设)
详情参考:https://www.jianshu.com/p/1d6a8fc8134f
但这个方案有大弊端:
1、就是我必须先链接上然后再去获取这个Mac地址,太消耗成本,且效率不高。
假如有很多设备的话,我必须一一验证,不是再断开,远没有在扫描阶段(扫描的过程是很快的,可以在短短几秒钟内就可以找到周围的上百台设备),确认是再链接高效。
2、这样会有莫名其妙的问题。
3、从链接的角度来讲有点本末倒置,本来我是用Mac地址来链接的,但现在变成了,先链接再获取Mac地址,验证是否正确。
4、仅限某些设备,如果你的蓝牙设备不支持这样获取,你需要跟硬件工程师沟通,说白了并不通用

那iOS如何链接呢?
一般我们可以通过名称、厂商数据来链接。
当手机蓝牙(此地将手机蓝牙作为中心设备)扫描到外设(譬如手环之类的)后,会进入这个方法

/*!
 *  @method centralManager:didDiscoverPeripheral:advertisementData:RSSI:
 *
 *  @param central              The central manager providing this update.
 *  @param peripheral           A <code>CBPeripheral</code> object.
 *  @param advertisementData    A dictionary containing any advertisement and scan response data.
 *  @param RSSI                 The current RSSI of <i>peripheral</i>, in dBm. A value of <code>127</code> is reserved and indicates the RSSI
 *                                was not available.
 *
 *  @discussion                 This method is invoked while scanning, upon the discovery of <i>peripheral</i> by <i>central</i>. A discovered peripheral must
 *                              be retained in order to use it; otherwise, it is assumed to not be of interest and will be cleaned up by the central manager. For
 *                              a list of <i>advertisementData</i> keys, see {@link CBAdvertisementDataLocalNameKey} and other similar constants.
 *
 *  @seealso                    CBAdvertisementData.h
 *
 */
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary<NSString *, id> *)advertisementData RSSI:(NSNumber *)RSSI;

名称、厂商数据可以从advertisementData(广告数据)中读取

/*!
 *  @constant CBAdvertisementDataLocalNameKey
 *
 *  @discussion A <code>NSString</code> containing the local name of a peripheral.
 *
 */
CB_EXTERN NSString * const CBAdvertisementDataLocalNameKey;
/*!
 *  @constant CBAdvertisementDataManufacturerDataKey
 *
 *  @discussion A <code>NSData</code> object containing the manufacturer data of a peripheral.
 *
 */
CB_EXTERN NSString * const CBAdvertisementDataManufacturerDataKey;
//advertisementData中可以发送的数据有约定 如下
17 /*
18 对应设置NSString类型的广播名
19 NSString *const CBAdvertisementDataLocalNameKey;
20 外设制造商的NSData数据
21 NSString *const CBAdvertisementDataManufacturerDataKey;
22 外设制造商的CBUUID数据
23 NSString *const CBAdvertisementDataServiceDataKey;
24 服务的UUID与其对应的服务数据字典数组
25 NSString *const CBAdvertisementDataServiceUUIDsKey;
26 附加服务的UUID数组
27 NSString *const CBAdvertisementDataOverflowServiceUUIDsKey;
28 外设的发送功率 NSNumber类型
29 NSString *const CBAdvertisementDataTxPowerLevelKey;
30 外设是否可以连接
31 NSString *const CBAdvertisementDataIsConnectable;
32 服务的UUID数组
33 NSString *const CBAdvertisementDataSolicitedServiceUUIDsKey;
34 */

具体如何保证唯一性,这个就需要和蓝牙硬件工程师约定了。
1、如果名称是唯一的,我们就可以用名称来约定唯一性。
2、如果名称相同,又要确定唯一性,那我们就需要通过厂商数据来约定了。

具体这个规则要怎么来约定唯一性,就靠彼此约定了,这个规则随意,只要彼此双方约定好就可以。

综上:
比较好的链接方案就是,苹果、安卓、硬件大家约定好一个规则,不论是通过名称或者厂商数据都可以确定唯一性通用性。

来源:http://t.zoukankan.com/lijianyi-p-14761020.html

有关iOS 蓝牙开发 Mac地址问题的更多相关文章

  1. ruby - 在 64 位 Snow Leopard 上使用 rvm、postgres 9.0、ruby 1.9.2-p136 安装 pg gem 时出现问题 - 2

    我想为Heroku构建一个Rails3应用程序。他们使用Postgres作为他们的数据库,所以我通过MacPorts安装了postgres9.0。现在我需要一个postgresgem并且共识是出于性能原因你想要pggem。但是我对我得到的错误感到非常困惑当我尝试在rvm下通过geminstall安装pg时。我已经非常明确地指定了所有postgres目录的位置可以找到但仍然无法完成安装:$envARCHFLAGS='-archx86_64'geminstallpg--\--with-pg-config=/opt/local/var/db/postgresql90/defaultdb/po

  2. ruby - 通过 rvm 升级 ruby​​gems 的问题 - 2

    尝试通过RVM将RubyGems升级到版本1.8.10并出现此错误:$rvmrubygemslatestRemovingoldRubygemsfiles...Installingrubygems-1.8.10forruby-1.9.2-p180...ERROR:Errorrunning'GEM_PATH="/Users/foo/.rvm/gems/ruby-1.9.2-p180:/Users/foo/.rvm/gems/ruby-1.9.2-p180@global:/Users/foo/.rvm/gems/ruby-1.9.2-p180:/Users/foo/.rvm/gems/rub

  3. ruby - 使用 C 扩展开发 ruby​​gem 时,如何使用 Rspec 在本地进行测试? - 2

    我正在编写一个包含C扩展的gem。通常当我写一个gem时,我会遵循TDD的过程,我会写一个失败的规范,然后处理代码直到它通过,等等......在“ext/mygem/mygem.c”中我的C扩展和在gemspec的“扩展”中配置的有效extconf.rb,如何运行我的规范并仍然加载我的C扩展?当我更改C代码时,我需要采取哪些步骤来重新编译代码?这可能是个愚蠢的问题,但是从我的gem的开发源代码树中输入“bundleinstall”不会构建任何native扩展。当我手动运行rubyext/mygem/extconf.rb时,我确实得到了一个Makefile(在整个项目的根目录中),然后当

  4. ruby - 通过 RVM (OSX Mountain Lion) 安装 Ruby 2.0.0-p247 时遇到问题 - 2

    我的最终目标是安装当前版本的RubyonRails。我在OSXMountainLion上运行。到目前为止,这是我的过程:已安装的RVM$\curl-Lhttps://get.rvm.io|bash-sstable检查已知(我假设已批准)安装$rvmlistknown我看到当前的稳定版本可用[ruby-]2.0.0[-p247]输入命令安装$rvminstall2.0.0-p247注意:我也试过这些安装命令$rvminstallruby-2.0.0-p247$rvminstallruby=2.0.0-p247我很快就无处可去了。结果:$rvminstall2.0.0-p247Search

  5. ruby - Fast-stemmer 安装问题 - 2

    由于fast-stemmer的问题,我很难安装我想要的任何ruby​​gem。我把我得到的错误放在下面。Buildingnativeextensions.Thiscouldtakeawhile...ERROR:Errorinstallingfast-stemmer:ERROR:Failedtobuildgemnativeextension./System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/bin/rubyextconf.rbcreatingMakefilemake"DESTDIR="cleanmake"DESTDIR=

  6. Ruby Sinatra 配置用于生产和开发 - 2

    我已经在Sinatra上创建了应用程序,它代表了一个简单的API。我想在生产和开发上进行部署。我想在部署时选择,是开发还是生产,一些方法的逻辑应该改变,这取决于部署类型。是否有任何想法,如何完成以及解决此问题的一些示例。例子:我有代码get'/api/test'doreturn"Itisdev"end但是在部署到生产环境之后我想在运行/api/test之后看到ItisPROD如何实现? 最佳答案 根据SinatraDocumentation:EnvironmentscanbesetthroughtheRACK_ENVenvironm

  7. ruby - 如何验证 IO.copy_stream 是否成功 - 2

    这里有一个很好的答案解释了如何在Ruby中下载文件而不将其加载到内存中:https://stackoverflow.com/a/29743394/4852737require'open-uri'download=open('http://example.com/image.png')IO.copy_stream(download,'~/image.png')我如何验证下载文件的IO.copy_stream调用是否真的成功——这意味着下载的文件与我打算下载的文件完全相同,而不是下载一半的损坏文件?documentation说IO.copy_stream返回它复制的字节数,但是当我还没有下

  8. ruby - 安装 Ruby 时遇到问题(无法下载资源 "readline--patch") - 2

    当我尝试安装Ruby时遇到此错误。我试过查看this和this但无济于事➜~brewinstallrubyWarning:YouareusingOSX10.12.Wedonotprovidesupportforthispre-releaseversion.Youmayencounterbuildfailuresorotherbreakages.Pleasecreatepull-requestsinsteadoffilingissues.==>Installingdependenciesforruby:readline,libyaml,makedepend==>Installingrub

  9. ruby - 从 Ruby 中的主机名获取 IP 地址 - 2

    我有一个存储主机名的Ruby数组server_names。如果我打印出来,它看起来像这样:["hostname.abc.com","hostname2.abc.com","hostname3.abc.com"]相当标准。我想要做的是获取这些服务器的IP(可能将它们存储在另一个变量中)。看起来IPSocket类可以做到这一点,但我不确定如何使用IPSocket类遍历它。如果它只是尝试像这样打印出IP:server_names.eachdo|name|IPSocket::getaddress(name)pnameend它提示我没有提供服务器名称。这是语法问题还是我没有正确使用类?输出:ge

  10. ruby - 是否可以覆盖 gemfile 进行本地开发? - 2

    我们的git存储库中目前有一个Gemfile。但是,有一个gem我只在我的环境中本地使用(我的团队不使用它)。为了使用它,我必须将它添加到我们的Gemfile中,但每次我checkout到我们的master/dev主分支时,由于与跟踪的gemfile冲突,我必须删除它。我想要的是类似Gemfile.local的东西,它将继承从Gemfile导入的gems,但也允许在那里导入新的gems以供使用只有我的机器。此文件将在.gitignore中被忽略。这可能吗? 最佳答案 设置BUNDLE_GEMFILE环境变量:BUNDLE_GEMFI

随机推荐