jjzjj

ios - CoreBluetooth central 在指定服务时没有发现任何外围设备

coder 2024-01-17 原文

我正在尝试弄清楚如何使用 CoreBluetooth 来扫描外围设备,这些外围设备为预先知道的服务做广告。所以我有以下 View Controller ,它显示在 UITableViewController 中发现的外围设备:

import UIKit
import CoreBluetooth

class MasterViewController: UITableViewController {

    var discoveredPeripherals = [CBPeripheral]()
    var connectedPeripherals = [CBPeripheral]()
    var peripheralsSupportingDeviceInformation = [CBPeripheral]()

    private let scannedServices: [CBUUID]? = [CBUUID(string: "180A")]//nil

    private var scanning = false

    private var centralManager: CBCentralManager?

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        navigationItem.leftBarButtonItem = editButtonItem
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
    }

    // MARK: - Table View

    override func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return discoveredPeripherals.count
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)

        let peripheral = discoveredPeripherals[indexPath.row]
        cell.textLabel!.text = peripheral.identifier.uuidString
        cell.detailTextLabel!.text = peripheral.name ?? ""
        if self.peripheralsSupportingDeviceInformation.contains(peripheral) {
            cell.accessoryType = .checkmark
        } else {
            cell.accessoryType = .none
        }
        return cell
    }

    override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
        // Return false if you do not want the specified item to be editable.
        return true
    }

    @IBAction func scanTapped(_ sender: Any) {
        if !scanning {
            self.navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Stop", style: .plain, target: self, action: #selector(scanTapped(_:)))
            self.discoveredPeripherals.removeAll()
            self.connectedPeripherals.removeAll()
            self.peripheralsSupportingDeviceInformation.removeAll()
            self.centralManager = CBCentralManager(delegate: self, queue: nil)
        } else {
            self.navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Scan", style: .plain, target: self, action: #selector(scanTapped(_:)))
            self.centralManager?.stopScan()
            self.centralManager = nil
        }

    }
}

extension MasterViewController: CBCentralManagerDelegate {
    func centralManagerDidUpdateState(_ central: CBCentralManager) {
        if central.state == .poweredOn {
            central.scanForPeripherals(withServices: scannedServices, options: [CBCentralManagerScanOptionAllowDuplicatesKey: false])
        }
    }

    func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
        if discoveredPeripherals.contains(where: { periph -> Bool in
            periph.identifier.uuidString == peripheral.identifier.uuidString
        }) {
            return
        }
        self.discoveredPeripherals.append(peripheral)
        self.tableView.reloadData()
        central.connect(peripheral, options: nil)
    }

    func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
        self.connectedPeripherals.append(peripheral)
        peripheral.delegate = self
        peripheral.discoverServices(scannedServices)
    }
}

extension MasterViewController: CBPeripheralDelegate {
    func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
        if let error = error {
            print("Service discovery error: \(String(describing: error))")
        } else {
            if let services = peripheral.services, services.contains(where: { service -> Bool in
                service.uuid.uuidString == "180A"
            }) {
                self.peripheralsSupportingDeviceInformation.append(peripheral)
                self.tableView.reloadData()
            } else if let services = peripheral.services {
                let serviceList = services.map { service -> String in
                    return service.uuid.uuidString
                }
                print("Services supported by \(peripheral.description): \(serviceList.joined(separator: ", "))")
            }
        }
    }
}

它是最基本的,目前我的申请中没有任何其他内容。 现在,如果我将 scannedServices 设置为 nil,我会得到我周围的所有设备,其中大多数设备(例如我的 MacBook Pro、我的 Apple Watch 等)会显示一个复选标记,指示广告设备信息服务 (180A)。 然而,当我将 scannedServices 设置为 [CBUUID(string: "180A")] 以仅扫描宣传此服务的设备时(至少这是我从文档中了解到的内容),然后 centralManager (_:didDiscover:,advertisementData:,RSSI:) 委托(delegate)方法不再被调用,列表保持为空。

我是否忘记或误解了文档中的某些内容? 如果您想尝试一下,完整的项目是 there .

最佳答案

您的代码没问题。没有发现任何设备的原因是不同的......

尽管大多数蓝牙设备都实现了设备信息服务,但它们并没有公布它。当您的应用程序扫描设备时,过滤器会处理广告数据。所以没有找到设备。连接到设备后,所有已实现的服务都将可用。

因此您需要使用确实宣传过的不同蓝牙服务进行测试。 MacBook Pro 不会宣传任何服务,除非您运行的应用程序这样做。我不知道 Apple Watch。可能您需要另一台设备进行测试。

在 Android 或 iOS 设备上安装 Nordic Semiconductor 的 nRF Connect 应用程序。它可以扫描外围设备并显示广告服务。它甚至可以通过选择和广告服务将其配置为外围设备。

关于ios - CoreBluetooth central 在指定服务时没有发现任何外围设备,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57826377/

有关ios - CoreBluetooth central 在指定服务时没有发现任何外围设备的更多相关文章

  1. ruby - 使用 ruby​​ 和 savon 的 SOAP 服务 - 2

    我正在尝试使用ruby​​和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我

  2. ruby - 具有身份验证的私有(private) Ruby Gem 服务器 - 2

    我想安装一个带有一些身份验证的私有(private)Rubygem服务器。我希望能够使用公共(public)Ubuntu服务器托管内部gem。我读到了http://docs.rubygems.org/read/chapter/18.但是那个没有身份验证-如我所见。然后我读到了https://github.com/cwninja/geminabox.但是当我使用基本身份验证(他们在他们的Wiki中有)时,它会提示从我的服务器获取源。所以。如何制作带有身份验证的私有(private)Rubygem服务器?这是不可能的吗?谢谢。编辑:Geminabox问题。我尝试“捆绑”以安装新的gem..

  3. ruby - 如何将脚本文件的末尾读取为数据文件(Perl 或任何其他语言) - 2

    我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚

  4. ruby - 如何指定 Rack 处理程序 - 2

    Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack

  5. ruby-on-rails - 启动 Rails 服务器时 ImageMagick 的警告 - 2

    最近,当我启动我的Rails服务器时,我收到了一长串警告。虽然它不影响我的应用程序,但我想知道如何解决这些警告。我的估计是imagemagick以某种方式被调用了两次?当我在警告前后检查我的git日志时。我想知道如何解决这个问题。-bcrypt-ruby(3.1.2)-better_errors(1.0.1)+bcrypt(3.1.7)+bcrypt-ruby(3.1.5)-bcrypt(>=3.1.3)+better_errors(1.1.0)bcrypt和imagemagick有关系吗?/Users/rbchris/.rbenv/versions/2.0.0-p247/lib/ru

  6. ruby-on-rails - 在 ruby​​ .gemspec 文件中,如何指定依赖项的多个版本? - 2

    我正在尝试修改当前依赖于定义为activeresource的gem:s.add_dependency"activeresource","~>3.0"为了让gem与Rails4一起工作,我需要扩展依赖关系以与activeresource的版本3或4一起工作。我不想简单地添加以下内容,因为它可能会在以后引起问题:s.add_dependency"activeresource",">=3.0"有没有办法指定可接受版本的列表?~>3.0还是~>4.0? 最佳答案 根据thedocumentation,如果你想要3到4之间的所有版本,你可以这

  7. ruby-on-rails - s3_direct_upload 在生产服务器中不工作 - 2

    在Rails4.0.2中,我使用s3_direct_upload和aws-sdkgems直接为s3存储桶上传文件。在开发环境中它工作正常,但在生产环境中它会抛出如下错误,ActionView::Template::Error(noimplicitconversionofnilintoString)在View中,create_cv_url,:id=>"s3_uploader",:key=>"cv_uploads/{unique_id}/${filename}",:key_starts_with=>"cv_uploads/",:callback_param=>"cv[direct_uplo

  8. ruby - 如果指定键的值在数组中相同,如何合并哈希 - 2

    我有一个这样的哈希数组:[{:foo=>2,:date=>Sat,01Sep2014},{:foo2=>2,:date=>Sat,02Sep2014},{:foo3=>3,:date=>Sat,01Sep2014},{:foo4=>4,:date=>Sat,03Sep2014},{:foo5=>5,:date=>Sat,02Sep2014}]如果:date相同,我想合并哈希值。我对上面数组的期望是:[{:foo=>2,:foo3=>3,:date=>Sat,01Sep2014},{:foo2=>2,:foo5=>5:date=>Sat,02Sep2014},{:foo4=>4,:dat

  9. ruby-on-rails - link_to 不显示任何 rails - 2

    我试图在索引页中创建一个超链接,但它没有显示,也没有给出任何错误。这是我的index.html.erb代码。ListingarticlesTitleTextssss我检查了我的路线,我认为它们也没有问题。PrefixVerbURIPatternController#Actionwelcome_indexGET/welcome/index(.:format)welcome#indexarticlesGET/articles(.:format)articles#indexPOST/articles(.:format)articles#createnew_articleGET/article

  10. ruby - 当使用::指定模块时,为什么 Ruby 不在更高范围内查找类? - 2

    我刚刚被困在这个问题上一段时间了。以这个基地为例:moduleTopclassTestendmoduleFooendend稍后,我可以通过这样做在Foo中定义扩展Test的类:moduleTopmoduleFooclassSomeTest但是,如果我尝试通过使用::指定模块来最小化缩进:moduleTop::FooclassFailure这失败了:NameError:uninitializedconstantTop::Foo::Test这是一个错误,还是仅仅是Ruby解析变量名的方式的逻辑结果? 最佳答案 Isthisabug,or

随机推荐