我正在尝试弄清楚如何使用 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/
我正在尝试使用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请求没有正确的命名空间。任何人都可以建议我
我想安装一个带有一些身份验证的私有(private)Rubygem服务器。我希望能够使用公共(public)Ubuntu服务器托管内部gem。我读到了http://docs.rubygems.org/read/chapter/18.但是那个没有身份验证-如我所见。然后我读到了https://github.com/cwninja/geminabox.但是当我使用基本身份验证(他们在他们的Wiki中有)时,它会提示从我的服务器获取源。所以。如何制作带有身份验证的私有(private)Rubygem服务器?这是不可能的吗?谢谢。编辑:Geminabox问题。我尝试“捆绑”以安装新的gem..
我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚
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
最近,当我启动我的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
我正在尝试修改当前依赖于定义为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之间的所有版本,你可以这
在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
我有一个这样的哈希数组:[{: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
我试图在索引页中创建一个超链接,但它没有显示,也没有给出任何错误。这是我的index.html.erb代码。ListingarticlesTitleTextssss我检查了我的路线,我认为它们也没有问题。PrefixVerbURIPatternController#Actionwelcome_indexGET/welcome/index(.:format)welcome#indexarticlesGET/articles(.:format)articles#indexPOST/articles(.:format)articles#createnew_articleGET/article
我刚刚被困在这个问题上一段时间了。以这个基地为例:moduleTopclassTestendmoduleFooendend稍后,我可以通过这样做在Foo中定义扩展Test的类:moduleTopmoduleFooclassSomeTest但是,如果我尝试通过使用::指定模块来最小化缩进:moduleTop::FooclassFailure这失败了:NameError:uninitializedconstantTop::Foo::Test这是一个错误,还是仅仅是Ruby解析变量名的方式的逻辑结果? 最佳答案 Isthisabug,or