草庐IT

swift - 在 swift 中收听事件舞会蓝牙外围设备

coder 2023-09-09 原文

我有一个适用于低功耗蓝牙的 Dash 按钮。我可以扫描并找到它,连接到它并发现它的服务。

现在我想听听它的按钮是否被按下。但是我的这部分似乎有一些严重的问题。我是 Swift 的新手,所以如果你能帮我解决这个问题,我真的很感激。

这是我的快速代码:

import CoreBluetooth
import UIKit

struct DisplayPeripheral{
    var peripheral: CBPeripheral?
    var lastRSSI: NSNumber?
    var isConnectable: Bool?
}

class PeripheralViewController: UIViewController {

    @IBOutlet weak var statusLabel: UILabel!
    @IBOutlet weak var bluetoothIcon: UIImageView!
    @IBOutlet weak var scanningButton: ScanButton!

    var centralManager: CBCentralManager?
    var peripherals: [DisplayPeripheral] = []
    var viewReloadTimer: Timer?
    let BEAN_NAME = "Security Tag"
    let BEAN_SCRATCH_UUID = CBUUID(string: "90946c81-e466-4a43-9974-949e465d35a1")
    let BEAN_SERVICE_UUID = CBUUID(string: "00001c00-d102-11e1-9b23-000efb0000a7")

    var selectedPeripheral: CBPeripheral?

    @IBOutlet weak var tableView: UITableView!

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)

        //Initialise CoreBluetooth Central Manager
        centralManager = CBCentralManager(delegate: self, queue: DispatchQueue.main)
    }

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

        viewReloadTimer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(PeripheralViewController.refreshScanView), userInfo: nil, repeats: true)
    }

    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)

        viewReloadTimer?.invalidate()
    }

    func updateViewForScanning(){
        statusLabel.text = "Scanning BLE Devices..."
        bluetoothIcon.pulseAnimation()
        bluetoothIcon.isHidden = false
        scanningButton.buttonColorScheme(true)
    }

    func updateViewForStopScanning(){
        let plural = peripherals.count > 1 ? "s" : ""
        statusLabel.text = "\(peripherals.count) Device\(plural) Found"
        bluetoothIcon.layer.removeAllAnimations()
        bluetoothIcon.isHidden = true
        scanningButton.buttonColorScheme(false)
    }

    @IBAction func scanningButtonPressed(_ sender: AnyObject){
        if centralManager!.isScanning{
            centralManager?.stopScan()
            updateViewForStopScanning()
        }else{
            startScanning()
        }
    }

    func startScanning(){
        peripherals = []
        self.centralManager?.scanForPeripherals(withServices: nil, options: [CBCentralManagerScanOptionAllowDuplicatesKey: true])
        updateViewForScanning()
        let triggerTime = (Int64(NSEC_PER_SEC) * 10)
        DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + Double(triggerTime) / Double(NSEC_PER_SEC), execute: { () -> Void in
            if self.centralManager!.isScanning{
                self.centralManager?.stopScan()
                self.updateViewForStopScanning()
            }
        })
    }

    func refreshScanView()
    {
        if peripherals.count > 1 && centralManager!.isScanning{
            tableView.reloadData()
        }
    }

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if let destinationViewController = segue.destination as? PeripheralConnectedViewController{
            destinationViewController.peripheral = selectedPeripheral
        }
    }
}

extension PeripheralViewController: CBCentralManagerDelegate{
    func centralManagerDidUpdateState(_ central: CBCentralManager){
        //if (central.state == CBCentralManagerState.poweredOn){
            startScanning()
        //}else{
            // do something like alert the user that ble is not on
        //}
    }

    func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber){

        for (index, foundPeripheral) in peripherals.enumerated(){
            if foundPeripheral.peripheral?.identifier == peripheral.identifier{
                peripherals[index].lastRSSI = RSSI
                return
            }
        }

        let isConnectable = advertisementData["kCBAdvDataIsConnectable"] as! Bool
        if(peripheral.name == BEAN_NAME)
        {
            print(peripheral.name)
            print(peripheral.identifier)
            print("is?",isConnectable)
            let displayPeripheral = DisplayPeripheral(peripheral: peripheral, lastRSSI: RSSI, isConnectable: isConnectable)
            peripherals.append(displayPeripheral)
        }

        tableView.reloadData()
    }


}

extension PeripheralViewController: CBPeripheralDelegate {
    func centralManager(_ central: CBCentralManager, didFailToConnect peripheral: CBPeripheral, error: Error?) {
        print("Error connecting peripheral: \(error?.localizedDescription)")
    }

    func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral)
    {
        print("Peripheral connected")
        performSegue(withIdentifier: "PeripheralConnectedSegue", sender: self)
        peripheral.discoverServices(nil)

    }
    func peripheral(peripheral: CBPeripheral, didDiscoverServices error: NSError?)
    {
        print("jdbsud")

        for service in peripheral.services!
        {
            let thisService = service as CBService

            if service.uuid == BEAN_SERVICE_UUID {
                peripheral.discoverCharacteristics(nil,for: thisService)
            }
        }
    }


}

extension PeripheralViewController: UITableViewDataSource {
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{

        let cell = self.tableView.dequeueReusableCell(withIdentifier: "cell")! as! DeviceTableViewCell
        cell.displayPeripheral = peripherals[indexPath.row]
        cell.delegate = self
        return cell
    }

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

extension PeripheralViewController: DeviceCellDelegate{
    func connectPressed(_ peripheral: CBPeripheral) {
        if peripheral.state != .connected {
            selectedPeripheral = peripheral
            peripheral.delegate = self
            centralManager?.connect(peripheral, options: nil)
            //you can listen to the commands here


        }
    }

    }

我在 func peripheral(peripheral: CBPeripheral, didDiscoverServices error: NSError?) 中打印了一些东西来检查我是否进入那里,显然我没有输入那部分代码。

最佳答案

经过努力,我自己解决了这个问题。

在找到服务后,我应该将这两个函数添加到代码中,它的效果非常好:

  func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
    debugPrint("Enabling ...")

    for characteristic in service.characteristics! {
        let thisCharacteristic = characteristic as CBCharacteristic

        debugPrint("Characteristic: ", thisCharacteristic.uuid)

        if thisCharacteristic.uuid == BEAN_SCRATCH_UUID {
            debugPrint("Set to notify: ", thisCharacteristic.uuid)

            // Prepare to show data

            self.peripheral.setNotifyValue(true, for: thisCharacteristic)
       }
    }
}

func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
    if characteristic.uuid == BEAN_SCRATCH_UUID {
        let content = String(data: characteristic.value!, encoding: String.Encoding.utf8)

        debugPrint("Notified.")
    }
}

关于swift - 在 swift 中收听事件舞会蓝牙外围设备,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42052519/

有关swift - 在 swift 中收听事件舞会蓝牙外围设备的更多相关文章

  1. ruby-on-rails - 事件管理员日期过滤器日期格式自定义 - 2

    是否有简单的方法来更改默认ISO格式(yyyy-mm-dd)的ActiveAdmin日期过滤器显示格式? 最佳答案 您可以像这样为日期选择器提供额外的选项,而不是覆盖js:=f.input:my_date,as::datepicker,datepicker_options:{dateFormat:"mm/dd/yy"} 关于ruby-on-rails-事件管理员日期过滤器日期格式自定义,我们在StackOverflow上找到一个类似的问题: https://s

  2. 【鸿蒙应用开发系列】- 获取系统设备信息以及版本API兼容调用方式 - 2

    在应用开发中,有时候我们需要获取系统的设备信息,用于数据上报和行为分析。那在鸿蒙系统中,我们应该怎么去获取设备的系统信息呢,比如说获取手机的系统版本号、手机的制造商、手机型号等数据。1、获取方式这里分为两种情况,一种是设备信息的获取,一种是系统信息的获取。1.1、获取设备信息获取设备信息,鸿蒙的SDK包为我们提供了DeviceInfo类,通过该类的一些静态方法,可以获取设备信息,DeviceInfo类的包路径为:ohos.system.DeviceInfo.具体的方法如下:ModifierandTypeMethodDescriptionstatic StringgetAbiList​()Obt

  3. ruby-on-rails - 事件记录 : Select max of limit - 2

    我正在尝试将以下SQL查询转换为ActiveRecord,它正在融化我的大脑。deletefromtablewhereid有什么想法吗?我想做的是限制表中的行数。所以,我想删除少于最近10个条目的所有内容。编辑:通过结合以下几个答案找到了解决方案。Temperature.where('id这给我留下了最新的10个条目。 最佳答案 从您的SQL来看,您似乎想要从表中删除前10条记录。我相信到目前为止的大多数答案都会如此。这里有两个额外的选择:基于MurifoX的版本:Table.where(:id=>Table.order(:id).

  4. ruby-on-rails - 禁用设备的 :confirmable on-the-fly to batch-generate users - 2

    Devise是一个Ruby库,它为我提供了这个User类:classUser当写入:confirmable时,注册时会发送一封确认邮件。上周我不得不批量创建300个用户,所以我在恢复之前注释掉了:confirmable几分钟。现在我正在为用户批量创建创建一个UI,因此我需要即时添加/删除:confirmable。(我也可以直接修改Devise的源码,但我宁愿不去调和它)问题:如何即时添加/删除:confirmable? 最佳答案 WayneConrad的解决方案:user=User.newuser.skip_confirmation

  5. ruby-on-rails - 事件管理员和自定义方法 - 2

    这是我在ActiveAdmin中的自定义页面ActiveAdmin.register_page"Settings"doaction_itemdolink_to('Importprojects','settings/importprojects')endcontentdopara"Text"endcontrollerdodefimportprojectssystem"rakedataspider:import_projects_ninja"para"OK"endendend我想做的是,当我单击“导入项目”按钮时,我想在Controller中执行rake任务。但是我无法访问该方法。可能是什

  6. ruby-on-rails - 在不重新查询数据库的情况下重新排序 Rails 中的事件记录? - 2

    例如,假设我有一个名为Products的模型,并且在ProductsController中,我有以下代码用于product_listView以显示已排序的产品。@products=Product.order(params[:order_by])让我们想象一下,在product_listView中,用户可以使用下拉菜单按价格、评级、重量等进行排序。数据库中的产品不会经常更改。我很难理解的是,每次用户选择新的order_by过滤器时,rails是否必须查询,或者rails是否能够以某种方式缓存事件记录以在服务器端重新排序?有没有一种方法可以编写它,以便在用户排序时rails不会重新查询结果

  7. ruby-on-rails - Ruby 长时间运行的进程对队列事件使用react - 2

    我有一个将某些事件写入队列的Rails3应用。现在我想在服务器上创建一个服务,每x秒轮询一次队列,并按计划执行其他任务。除了创建ruby​​脚本并通过cron作业运行它之外,还有其他稳定的替代方案吗? 最佳答案 尽管启动基于Rails的持久任务是一种选择,但您可能希望查看更有序的系统,例如delayed_job或Starling管理您的工作量。我建议不要在cron中运行某些东西,因为启动整个Rails堆栈的开销可能很大。每隔几秒运行一次它是不切实际的,因为Rails上的启动时间通常为5-15秒,具体取决于您的硬件。不过,每天这样做几

  8. ruby-on-rails - 使用 Rails 事件记录获取二级模型 - 2

    我有一个帖子属于城市的关系,城市又属于一个州,例如:classPost现在我想找到所有帖子及其所属的城市和州。我编写了以下查询来获取带有城市的帖子,但不知道如何在同一查找器中获取带有城市的相应州:@post=Post.find:all,:include=>[:city]感谢任何帮助。谢谢。 最佳答案 Post.all(:include=>{:city=>:state}) 关于ruby-on-rails-使用Rails事件记录获取二级模型,我们在StackOverflow上找到一个类似的问

  9. ruby - 在没有数据库的情况下伪造一个事件记录模型 - 2

    我觉得我错过了什么。我正在编写一个ruby​​gem,它允许与事件记录进行交互,作为其主要功能的附加功能。在为其编写测试用例时,我需要能够指定虚拟事件记录模型来测试此功能。如果我可以获得一个事件记录模型的实例,它不需要与数据库的任何连接,可以有关系,所有这些东西,但不需要我在数据库中设置表,那就太棒了。我对测试还很陌生,在Rails测试之外我也很陌生,但似乎我应该能够相当轻松地完成类似的事情,但我什么也没找到。谁能告诉我我错过了什么?我看过工厂、制造商、固定装置,所有这些似乎都想达到目标。人们如何在您只需要AR对象进行测试的地方测试gem? 最佳答案

  10. ruby-on-rails - 在事件记录库中添加某些方法的首选方法是什么? - 2

    我想创建一个模块,为从事件记录库继承的类提供一些通用方法。以下是我们可以实现的两种方式。1)moduleCommentabledefself.extended(base)base.class_evaldoincludeInstanceMethodsextendClassMethodsendendmoduleClassMethodsdeftest_commentable_classmethodputs'testclassmethod'endendmoduleInstanceMethodsdeftest_commentable_instance_methodputs'testinstanc

随机推荐