J'essaie d'envoyer des données de mon iPhone à un appareil Bluetooth qui est connecté à un Arduino. Je sais que le périphérique bluetooth fonctionne bien car j'ai utilisé l'application nRF connect et j'ai envoyé des données à partir de là vers le bluetooth que l'Arduino a lu.Les données Swift 3 ne sont pas envoyées vers l'appareil Bluetooth depuis l'application iPhone
Je pense que la façon dont mon application est organisée crée des problèmes. En l'état, il y a trois contrôleurs de vue.
Le premier contrôleur de vue est un écran de page d'accueil qui en contient peu. Vous pouvez connecter le deuxième et un troisième contrôleur de vue depuis la page d'accueil. Le second contrôleur de vue est un écran de connexion du Bluetooth Le contrôleur troisième vue est un écran d'action avec des boutons
Le second contrôleur de vue est une vue de table avec une option de numérisation pour rechercher les périphériques Bluetooth disponibles. J'utilise ce code:
import UIKit
import CoreBluetooth
class ViewController: UIViewController, CBCentralManagerDelegate, UITableViewDataSource, UITableViewDelegate
{
//MARK: Variables
//central manager
var manager: CBCentralManager?
//peripheral manager
var peripheral: CBPeripheral?
//HM-10 service code
let HMServiceCode = CBUUID(string: "0xFFE0")
//HM-10 characteristic code
let HMCharactersticCode = CBUUID(string: "0xFFE1")
//array to store the peripherals
var peripheralArray:[(peripheral: CBPeripheral, RSSI: Float)] = []
//for timing..obvs
var timer: Timer!
//MARK: IBOutlets
//if cancel is pressed go back to homepage
@IBAction func cancelButton(_ sender: Any)
{
performSegue(withIdentifier: "segueBackwards", sender: nil)
}
//this is for the tableview so that you can reference it
@IBOutlet var tableView: UITableView!
//allow for disabling the scanning button whilst scanning
@IBOutlet var scanningButton: UIBarButtonItem!
//loads the centralmanager delegate in here
override func viewDidLoad()
{
manager = CBCentralManager(delegate: self, queue: nil)
tableView.delegate = self
tableView.dataSource = self
super.viewDidLoad()
if(peripheral != nil)
{
disconnectPeripheral()
}
}
//nothing
override func didReceiveMemoryWarning()
{
super.didReceiveMemoryWarning()
}
//MARK: cancel any preexisting connection - this still needs to be done
func disconnectPeripheral()
{
manager?.cancelPeripheralConnection(peripheral!)
}
//MARK: Bluetooth central
//required centralmanager component. Text for what power state currently is
func centralManagerDidUpdateState(_ central: CBCentralManager)
{
var consoleMsg = ""
switch (central.state)
{
case.poweredOff:
consoleMsg = "BLE is Powered Off"
scanningButton.isEnabled = false
alert()
case.poweredOn:
consoleMsg = "BLE is Powered On"
scanningButton.isEnabled = true
case.resetting:
consoleMsg = "BLE is resetting"
case.unknown:
consoleMsg = "BLE is in an unknown state"
case.unsupported:
consoleMsg = "This device is not supported by BLE"
case.unauthorized:
consoleMsg = "BLE is not authorised"
}
print("\(consoleMsg)")
}
//MARK: Alert if Bluetooth is not turned on
func alert()
{
//main header
let title = "Bluetooth Power"
//the little debrief below the main title
let message = "Please turn on Bluetooth to use this app"
//text in the text box
let text = "OK"
//this says what the title and message is
let alert = UIAlertController(title: title, message: message , preferredStyle: UIAlertControllerStyle.alert)
//add button for the answer
let okayButton = UIAlertAction(title: text, style: UIAlertActionStyle.cancel, handler: nil)
alert.addAction(okayButton)
//show the alert
present(alert, animated: true, completion: nil)
print("said ok on button to turning on bluetooth")
}
//MARK: Connection to bluetooth
//once scanned this will say what has been discovered - add to peripheralArray
func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber)
{
for existing in peripheralArray
{
if existing.peripheral.identifier == peripheral.identifier {return}
}
//adding peripheral to the array
let theRSSI = RSSI.floatValue
peripheralArray.append(peripheral: peripheral, RSSI: theRSSI)
peripheralArray.sort { $0.RSSI < $1.RSSI }
print("discovered peripheral")
tableView.reloadData()
print("There are \(peripheralArray.count) peripherals in the array")
}
//create a link/connection to the peripheral
func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral)
{
peripheral.discoverServices(nil) //may need to remove this not sure it does much
print("connected to peripheral")
}
//disconnect from the peripheral
func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?)
{
print("disconnected from peripheral")
stopScanning()
}
//if it failed to connect to a peripheral will tell us (although not why)
func centralManager(_ central: CBCentralManager, didFailToConnect peripheral: CBPeripheral, error: Error?)
{
print("failed to connect to peripheral")
stopScanning()
}
//MARK: scanning
//press scan button to initiate scanning sequence
@IBAction func scanButton(_ sender: Any)
{
startTimer()
}
//start scanning for 5 seconds
func startTimer()
{
//after 5 seconds this goes to the stop scanning routine
timer = Timer.scheduledTimer(timeInterval: 5, target: self, selector: #selector(ViewController.stopScanning), userInfo: nil, repeats: true)
print("Start Scan")
manager?.scanForPeripherals(withServices: [HMServiceCode], options: nil)
scanningButton.isEnabled = false
}
//stop the scanning and re-enable the scan button so you can do it again
func stopScanning()
{
timer?.invalidate()
print("timer stopped")
manager?.stopScan()
print("Scan Stopped")
print("array items are: \(peripheralArray)")
print("peripheral items are: \(peripheral)")
print("manager items are: \(manager)")
scanningButton.isEnabled = true
}
//MARK: Table View
//number of sections the table will have
func numberOfSections(in tableView: UITableView) -> Int
{
return 1
}
//number of rows each section of the table will have
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return peripheralArray.count
}
//the way the data will be displayed in each row for the sections
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
let BluetoothNaming = peripheralArray[indexPath.row].peripheral.name
cell.textLabel?.text = BluetoothNaming
return cell
}
//what happens when we select an item from the bluetooth list
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
{
//tableView.deselectRow(at: indexPath, animated: true)
stopScanning()
peripheral = peripheralArray[(indexPath as NSIndexPath).row].peripheral
print ("connecting to peripheral called \(peripheral)")
//store the name of the connected peripeheral
let connectedPeripheral = peripheral
manager?.connect(connectedPeripheral!, options: nil)
performSegue(withIdentifier: "segueBackwards", sender: nil)
}
//MARK: change label name
override func prepare(for segue: UIStoryboardSegue, sender: Any?)
{
if segue.identifier == "segueBackwards"
{
if let indexPath = self.tableView.indexPathForSelectedRow
{
//storing the name of the peripheral and then saving to send to Homepage
let peripheral = peripheralArray[indexPath.row].peripheral.name
let vc = segue.destination as! HomepageViewController
vc.selectedName = peripheral
//this is to unselect the row in the table
tableView.deselectRow(at: indexPath, animated: true)
}
}
}
//MARK: end
}
Dans l'ensemble la deuxième page, je peux me connecter à un périphérique Bluetooth. Je retourne ensuite à l'écran d'accueil. De là, je vais ensuite au contrôleur troisième vue qui est de contrôler les actions pour mon application. Je l'ai réglé de sorte que vous cliquez sur un bouton, puis cela vous permet d'envoyer des données au bluetooth. Cependant, pour une raison quelconque, je ne peux pas envoyer de données. le clic sur le bouton fonctionne, mais les données ne sont pas envoyées.
Voici mon code pour le contrôleur troisième vue:
import UIKit
import CoreBluetooth
class SelectionViewController: UIViewController, CBPeripheralDelegate
{
//MARK: Variables
var mainPeripheral: CBPeripheral?
let UuidSerialService = "6E400001-B5A3-F393-E0A9-E50E24DCCA9E"
let UuidTx = "6E400002-B5A3-F393-E0A9-E50E24DCCA9E"
let UuidRx = "6E400003-B5A3-F393-E0A9-E50E24DCCA9E"
let txCharacteristicUUID = "0000ffe0-0000-1000-8000-00805f9b34fb"
let txServiceUUID = "0000ffe1-0000-1000-8000-00805f9b34fb"
/// Whether to write to the HM10 with or without response.
/// Legit HM10 modules (from JNHuaMao) require 'Write without Response',
/// while fake modules (e.g. from Bolutek) require 'Write with Response'.
var writeType: CBCharacteristicWriteType = .withoutResponse
var writeCharacteristic: CBCharacteristic?
//MARK: IBOutlets
@IBOutlet var whiteButtonControl: UIButton!
@IBAction func doneButton(_ sender: Any)
{
performSegue(withIdentifier: "segueControltoHome", sender: nil)
}
//MARK: preset buttons
@IBAction func whiteButton(_ sender: Any)
{
let value : UInt8 = 75
let data = Data([value])
mainPeripheral?.writeValue(data, for: writeCharacteristic!, type: writeType)
print("Button pressed")
}
//MARK: Peripheral Control
func peripheralManagerDidUpdateState(_ peripheral: CBPeripheralManager)
{
var consoleMsg = ""
switch (peripheral.state)
{
case.poweredOff:
consoleMsg = "Peripheral is Powered Off"
case.poweredOn:
consoleMsg = "Peripheral is Powered On"
case.resetting:
consoleMsg = "Peripheral is resetting"
case.unknown:
consoleMsg = "Peripheral is in an unknown state"
case.unsupported:
consoleMsg = "This device is not supported by Peripheral"
case.unauthorized:
consoleMsg = "Peripheral is not authorised"
}
print("\(consoleMsg)")
}
func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?)
{
// discover the 0xFFE1 characteristic for all services (though there should only be one)
for service in peripheral.services!
{
peripheral.discoverCharacteristics([CBUUID(string: "FFE1")], for: service)
}
}
func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?)
{
// check whether the characteristic we're looking for (0xFFE1) is present - just to be sure
print("reading this part")
for characteristic in service.characteristics!
{
if characteristic.uuid == CBUUID(string: "FFE1")
{
// subscribe to this value (so we'll get notified when there is serial data for us..)
peripheral.setNotifyValue(true, for: characteristic)
print ("subscribed to this value")
// keep a reference to this characteristic so we can write to it
writeCharacteristic = characteristic
print("characteristic is fine")
}
}
}
Je pense qu'une partie du problème est que le service périphérique et caractéristique ne se connectent pas au centre? Est-ce que ça sonne bien? Au moment où je cherche à envoyer la valeur 75 à la bluetooth que l'Arduino peut alors lire. Est-ce que j'ai fait quelque chose de mal avec le délégué périphérique? Que dois-je faire pour qu'il soit en mesure d'envoyer des données
grâce
Utilisez un Singleton pour gérer votre partie Bluetooth. Ensuite, tout ViewController y aura accès. – Larme
une chance que vous pourriez développer à ce sujet? –