Hello,
I am writing an app that connects to an Arduino Nano with BLE. I would like the app to read data sent from the Arduino (the peripheral). My code connects to the Arduino using a specific UUID, but I think it is failing to detect a service from the Arduino. Here is my BluetoothViewController:
//
// BluetoothViewController.swift
import UIKit
import CoreBluetooth
//local central device object
class BluetoothViewController: UIViewController, CBPeripheralDelegate, CBCentralManagerDelegate {
//properties
private var centralManager: CBCentralManager!
private var peripheral: CBPeripheral!
var feedbackAmt = String() // from session setup view controller
//label to display stage of gait cycle
@IBOutlet weak var StateLabel: UILabel!
//characteristics
private var StateVar: CBCharacteristic?
override func viewDidLoad() {
super.viewDidLoad()
centralManager = CBCentralManager(delegate: self, queue: nil)
}
//func tells the delegate the central manager's state updated (required)
func centralManagerDidUpdateState(_ central: CBCentralManager) {
if central.state == .poweredOn {
//can start scanning peripherals
centralManager.scanForPeripherals(withServices: [ArduinoPeripheral.ArduinoServiceUUID], options: nil)
StateLabel.text = "Scanning for devices..."
}
}
//result of scan - call to this method reflects a detected advertisement packet of a BLE peripheral in range
func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
//found peripheral so stop scanning
self.centralManager.stopScan()
//copy the peripheral instance
self.peripheral = peripheral
self.peripheral.delegate = self
//connect to peripheral
self.centralManager.connect(self.peripheral, options: nil)
}
//if successfully connected
func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
//check if this is the desired peripheral
if peripheral == self.peripheral {
//start service discovery for desired service
peripheral.discoverServices([ArduinoPeripheral.ArduinoServiceUUID])
StateLabel.text = "Connected!"
}
}
//handle service discovery event
func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
//cycle through available services
if let services = peripheral.services {
for service in services {
//find the service from arduino
if service.uuid == ArduinoPeripheral.ArduinoServiceUUID {
//start discovery of the service's characteristics
peripheral.discoverCharacteristics([ArduinoPeripheral.ArduinoCharacteristicUUID], for: service)
StateLabel.text = "Service found"
return
}
}
}
}
//handle discovery of characteristics
func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
if let characteristics = service.characteristics {
for characteristic in characteristics {
if characteristic.uuid == ArduinoPeripheral.ArduinoCharacteristicUUID {
StateVar = characteristic
StateLabel.text = "Characteristic found"
}
}
}
}
//subscribe to characteristic for value change / notification
func subscribeToNotifications(peripheral: CBPeripheral, characteristic: CBCharacteristic) {
peripheral.setNotifyValue(true, for: characteristic)
StateLabel.text = "Subscribed"
}
//notification update
func peripheral(_ peripheral: CBPeripheral, didUpdateNotificationStateFor characteristic: CBCharacteristic, error: Error?) {
if let error = error {
// Handle error
print(error)
return
}
// Successfully subscribed to or unsubscribed from notifications/indications on a characteristic
}
//read value
func readValue(characteristic: CBCharacteristic) {
self.peripheral.readValue(for: characteristic)
}
//value returned from readValue
func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
if let error = error {
// Handle error
print(error)
return
}
StateLabel.text = "Value updated"
}
}
Where the Arduino characteristic UUUID and service UUID are defined in another swift file. I know it is connecting to the Arduino because the label says "Connected" when debugging, but it seems to get stuck on the line: "for service in services" and I am not sure why.
Thank you for the help!
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
Hello,
I am reading the value of a characteristic sent from an Arduino (peripheral) via Bluetooth. However, when attempting to print the value, it only prints an empty string. I cannot even compare the value to another variable (integer or string) because it cannot be converted from type Data. I have tried turning it into a UTF8 (string), ascii string, etc. but nothing seems to be working.
Here is my code and some things I've tried:
import UIKit
import CoreBluetooth
//local central device object
class BluetoothViewController: UIViewController, CBPeripheralDelegate, CBCentralManagerDelegate {
//properties
private var centralManager: CBCentralManager!
private var peripheral: CBPeripheral!
//label to display stage of gait cycle
@IBOutlet weak var StateLabel: UILabel!
//characteristics
private var StateVar: CBCharacteristic?
override func viewDidLoad() {
super.viewDidLoad()
centralManager = CBCentralManager(delegate: self, queue: nil)
}
//a bunch of core bluetooth functions connecting to peripheral and finding the Arduino's serivce...
//handle discovery of characteristics... subscribe to notifications...
//notification update
func peripheral(_ peripheral: CBPeripheral, didUpdateNotificationStateFor characteristic: CBCharacteristic, error: Error?) {
if let error = error {
// Handle error
print(error)
return
}
// Successfully subscribed to or unsubscribed from notifications/indications on a characteristic
}
//read value
func readValue(characteristic: CBCharacteristic) {
self.peripheral.readValue(for: characteristic)
}
//value returned from readValue
func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
if let error = error {
// Handle error
print(error)
return
}
//var charASCIIval = NSString()
//guard let StateVar = characteristic.value else { return }
guard let StateVar = characteristic.value,
let stringFromData = String(data: StateVar, encoding: .utf8) else { return }
//let stringVal = String(decoding: StateVar, as: UTF8.self)
//let stringVal = "\u{StateVar}"
//let stringVal = String(UnicodeScalar(StateVar))
//let StateVar = string.StateVar(using: .utf8)
print(stringFromData)
StateLabel.text = stringFromData
//if([readCBUUIDs containsObject: [ArduinoPeripheral.ArduinoCharacteristicUUID]])
//let ASCIIstring = NSString(data: StateVar, encoding: String.Encoding.utf8.rawValue) //else { return }
//charASCIIval = ASCIIstring
//guard let StateVarInt = StateVar as? UInt8 else { return }
//StateLabel.text = String(data: StateVar, encoding: String.Encoding.ascii)!
//StateLabel.text = "Value updated"
//let StateVar = StateVar as! UInt8
//State machine
if StateVar == 0 {
StateLabel.text = "Leg Hold"
}
else if StateVar == 1 {
StateLabel.text = "Swing"
}
else if StateVar == 2 {
StateLabel.text = "Heel Step"
}
else if StateVar == 3 {
StateLabel.text = "Drag Heel"
}
else if StateVar == 4 {
StateLabel.text = "Toe Off"
}
else if StateVar == 5 {
StateLabel.text = "Drag Toe"
}
else if StateVar == 6 {
StateLabel.text = "Stance"
}
else if StateVar == 7 {
StateLabel.text = "Drag All"
}
else if StateVar == 8 {
StateLabel.text = "Leg Moving Backwards"
}
}
// initT (_ source T) where T: BinaryInteger
// init init(clamping:)
}
I would like to compare the value of the characteristic to a number (0-8) so I can output the correct stage of the gait cycle but I get the error:
Referencing operator function '==' on 'BinaryInteger' requires that 'Data' conform to 'BinaryInteger'
Please help!! Thank you!
Hello,
My app has a settings page where the user can toggle buttons etc and I would like those values to carry over to the next screen / view controller file so that I can display different things depending on what the user inputted. I have tried everything from state and binding variables to cocoa touch class with a segue that can modify the variables of the destination view controller, but I always get errors. I'm not sure if it's because I'm using a more recent version of swift? But here is my code and some of the things I've tried:
Settings page:
import UIKit
class SessionSetupViewController: UIViewController, UIPickerViewDataSource, UIPickerViewDelegate {
//@State var visualBool = true
//var feedbackAmt: String = "String"
//var feedbackAmt = String()
@IBAction func VisualToggle(_ sender: Any) {
}
@IBAction func AuditoryToggle(_ sender: Any) {
}
@IBOutlet weak var PickerLabel: UILabel!
@IBOutlet weak var FeedbkAmtPicker: UIPickerView!
let amounts = ["Low", "Medium", "High"]
func numberOfComponents(in pickerView: UIPickerView) - Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) - String? {
return amounts[row]
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) - Int {
return amounts.count
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
PickerLabel.text = amounts[row]
//feedbackAmt = amounts[row]
//let feedbackAmt = amounts[row]
}
@IBAction func BeginButtonPressed(_ sender: Any) {
self.performSegue(withIdentifier: "BeginSegue", sender: self)
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
// override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// if segue.identifier == "BeginSegue" {
// let destinationController = segue.destination as! BluetoothViewController
// destinationController.feedbackAmt = PickerLabel.text!
// }
// }
}
And then the destination view controller:
import UIKit
import CoreBluetooth
//local central device object
class BluetoothViewController: UIViewController, CBPeripheralDelegate, CBCentralManagerDelegate {
//properties
private var centralManager: CBCentralManager!
private var peripheral: CBPeripheral!
var feedbackAmt = String() // from session setup view controller
//var sessionSetupViewController: SessionSetupViewController?
//let bluetoothViewController = BluetoothViewController()
//let sessionSetupViewController = SessionSetupViewController()
//bluetoothViewController.sessionSetupViewController = sessionSetupViewController
//sessionSetupViewControler?.feedbackAmt
//label to display stage of gait cycle
@IBOutlet weak var StateLabel: UILabel!
//characteristics
private var StateVar: CBCharacteristic?
override func viewDidLoad() {
super.viewDidLoad()
centralManager = CBCentralManager(delegate: self, queue: nil)
//StateLabel.text = "\(ArduinoPeripheral.ArduinoCharacteristicUUID)"
//StateLabel.text = "\(SessionSetupViewController.feedbackAmt)"
//StateLabel.text = feedbackAmt
}
// core bluetooth functions...
Please let me know if there is another way I can pass those values/settings to the next view controller. Thanks!
Hello,
I am trying to play sound in my app but I'm having trouble adding the AVFoundation framework to my app by going to the general tab in xcode project properties... but I don't have "project properties" anywhere in my xcode (it should be the newest version). How do I add this framework? Is there any way to bypass this? Can I import AVFoundation without the framework?
Thanks!