2017-05-29 148 views
0

我已經提出了連接到BLE(Arduino uno上的HM-10)的ios的應用程序。有溫度,光線和溼度傳感器連接到Arduino。問題在於,iPhone顯示的數據與顯示Arduino串行顯示屏上的數據相同。而當我點擊一個「溫度按鈕」時,我想讓溫度傳感器的數據顯示出來,而每個其他傳感器的數據都是一樣的。其他的事情我不知道是我想要的通知,如果應用程序沒有在案件溫度運行。一定程度下降。我該怎麼做Swift 3 arduino Uno HM-10 Ble - iPhone上的通知

請幫忙!!

這裏是Arduino的代碼(是有可能在同一行打印數據,而不是它在新的一行連連打印)

int sensePin = A1; //This is the Arduino Pin that will control Relay #1 
int sensorValue = 0; //The variable we will use to store the sensor input 
//int sensePin = A0; //This is the Arduino Pin that will control Relay #1 
int sensorInput; //The variable we will use to store the sensor input 
double temp; 


void setup() { 
    // put your setup code here, to run once: 
    Serial.begin(9600); //Start the Serial Port at 9600 baud (default) 

} 
void loop() { 
    // put your main code here, to run repeatedly: 
    sensorValue = analogRead(A1); //read the analog sensor and store it 

    sensorInput = analogRead(A0); //read the analog sensor and store it 
    temp = (double)sensorInput/1024;  //find percentage of input reading 
    temp = temp * 5;     //multiply by 5V to get voltage 
    temp = temp - 0.5;    //Subtract the offset 
    temp = temp * 100;    //Convert to degrees 


    if (temp > 28) { 
    Serial.print("Current Temp is hot i.e.: "); 
    Serial.println(temp); 
    } 

    else if (temp < 28) { 
    Serial.print("Current Temp is cold i.e.: "); 
    Serial.println(temp); 
    } 
    else{ 
    Serial.print("Current Temp: "); 
    Serial.println(temp); 
    } 

if (sensorValue > 70) { 
    Serial.print("Current Light is high i.e.: "); 
    Serial.println(sensorValue); 
    } 

    else if (sensorValue < 60) { 
    Serial.print("Current Light is low i.e.: "); 
    Serial.println(sensorValue); 
    } 
    else{ 
    Serial.print("Light seems good: "); 
    Serial.println(sensorValue); 
    } 


    //Serial.print("Current Temp: "); 

    //Serial.println(temp); 

    //Serial.print("Current Light: "); 
    //Serial.println(sensorValue); 

    //Serial.end(); 
    delay(10000); 
} 

這裏是IPHONE代碼

import UIKit 
import CoreBluetooth 
import QuartzCore 

/// The option to add a \n or \r or \r\n to the end of the send message 
enum MessageOption: Int { 
    case noLineEnding, 
     newline, 
     carriageReturn, 
     carriageReturnAndNewline 
} 

/// The option to add a \n to the end of the received message (to make it more readable) 
enum ReceivedMessageOption: Int { 
    case none, 
     newline 
} 

final class SerialViewController: UIViewController, UITextFieldDelegate, BluetoothSerialDelegate { 

//MARK: IBOutlets 

    @IBOutlet weak var mainTextView: UITextView! 

    @IBOutlet weak var messageField: UITextField! 
    @IBOutlet weak var bottomView: UIView! 
    @IBOutlet weak var bottomConstraint: NSLayoutConstraint! // used to move the textField up when the keyboard is present 
    @IBOutlet weak var barButton: UIBarButtonItem! 
    @IBOutlet weak var navItem: UINavigationItem! 




//MARK: Functions 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     // init serial 
     serial = BluetoothSerial(delegate: self) 

     // UI 
     mainTextView.text = "" 
     reloadView() 

     NotificationCenter.default.addObserver(self, selector: #selector(SerialViewController.reloadView), name: NSNotification.Name(rawValue: "reloadStartViewController"), object: nil) 

     // we want to be notified when the keyboard is shown (so we can move the textField up) 
     NotificationCenter.default.addObserver(self, selector: #selector(SerialViewController.keyboardWillShow(_:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil) 
     NotificationCenter.default.addObserver(self, selector: #selector(SerialViewController.keyboardWillHide(_:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil) 

     // to dismiss the keyboard if the user taps outside the textField while editing 
     let tap = UITapGestureRecognizer(target: self, action: #selector(SerialViewController.dismissKeyboard)) 
     tap.cancelsTouchesInView = false 
     view.addGestureRecognizer(tap) 

     // style the bottom UIView 
     bottomView.layer.masksToBounds = false 
     bottomView.layer.shadowOffset = CGSize(width: 0, height: -1) 
     bottomView.layer.shadowRadius = 0 
     bottomView.layer.shadowOpacity = 0.5 
     bottomView.layer.shadowColor = UIColor.gray.cgColor 


    } 

    deinit { 
     NotificationCenter.default.removeObserver(self) 
    } 

    func keyboardWillShow(_ notification: Notification) { 
     // animate the text field to stay above the keyboard 
     var info = (notification as NSNotification).userInfo! 
     let value = info[UIKeyboardFrameEndUserInfoKey] as! NSValue 
     let keyboardFrame = value.cgRectValue 

     //TODO: Not animating properly 
     UIView.animate(withDuration: 1, delay: 0, options: UIViewAnimationOptions(), animations: {() -> Void in 
      self.bottomConstraint.constant = keyboardFrame.size.height 
      }, completion: { Bool -> Void in 
      self.textViewScrollToBottom() 
     }) 
    } 

    func keyboardWillHide(_ notification: Notification) { 
     // bring the text field back down.. 
     UIView.animate(withDuration: 1, delay: 0, options: UIViewAnimationOptions(), animations: {() -> Void in 
      self.bottomConstraint.constant = 0 
     }, completion: nil) 

    } 

    func reloadView() { 
     // in case we're the visible view again 
     serial.delegate = self 

     if serial.isReady { 
      navItem.title = serial.connectedPeripheral!.name 
      barButton.title = "Disconnect" 
      barButton.tintColor = UIColor.red 
      barButton.isEnabled = true 
     } else if serial.centralManager.state == .poweredOn { 
      navItem.title = "Bluetooth Serial" 
      barButton.title = "Connect" 
      barButton.tintColor = view.tintColor 
      barButton.isEnabled = true 
     } else { 
      navItem.title = "Bluetooth Serial" 
      barButton.title = "Connect" 
      barButton.tintColor = view.tintColor 
      barButton.isEnabled = false 
     } 
    } 

    func textViewScrollToBottom() { 
     let range = NSMakeRange(NSString(string: mainTextView.text).length - 1, 1) 
     mainTextView.scrollRangeToVisible(range) 
     //mainTextView.text = ""; 
    } 


//MARK: BluetoothSerialDelegate 

    func serialDidReceiveString(_ message: String) { 
     // add the received text to the textView, optionally with a line break at the end 
     mainTextView.text! += message 
     let pref = UserDefaults.standard.integer(forKey: ReceivedMessageOptionKey) 
     if pref == ReceivedMessageOption.newline.rawValue { mainTextView.text! += "\n" } 
     textViewScrollToBottom() 

    } 

    func serialDidDisconnect(_ peripheral: CBPeripheral, error: NSError?) { 
     reloadView() 
     dismissKeyboard() 
     let hud = MBProgressHUD.showAdded(to: view, animated: true) 
     hud?.mode = MBProgressHUDMode.text 
     hud?.labelText = "Disconnected" 
     hud?.hide(true, afterDelay: 1.0) 
    } 

    func serialDidChangeState() { 
     reloadView() 
     if serial.centralManager.state != .poweredOn { 
      dismissKeyboard() 
      let hud = MBProgressHUD.showAdded(to: view, animated: true) 
      hud?.mode = MBProgressHUDMode.text 
      hud?.labelText = "Bluetooth turned off" 
      hud?.hide(true, afterDelay: 1.0) 
     } 
    } 


//MARK: UITextFieldDelegate 

    func textFieldShouldReturn(_ textField: UITextField) -> Bool { 
     if !serial.isReady { 
      let alert = UIAlertController(title: "Not connected", message: "What am I supposed to send this to?", preferredStyle: .alert) 
      alert.addAction(UIAlertAction(title: "Dismiss", style: UIAlertActionStyle.default, handler: { action -> Void in self.dismiss(animated: true, completion: nil) })) 
      present(alert, animated: true, completion: nil) 
      messageField.resignFirstResponder() 
      return true 
     } 

     // send the message to the bluetooth device 
     // but fist, add optionally a line break or carriage return (or both) to the message 
     let pref = UserDefaults.standard.integer(forKey: MessageOptionKey) 
     var msg = messageField.text! 
     switch pref { 
     case MessageOption.newline.rawValue: 
      msg += "\n" 
     case MessageOption.carriageReturn.rawValue: 
      msg += "\r" 
     case MessageOption.carriageReturnAndNewline.rawValue: 
      msg += "\r\n" 
     default: 
      msg += "" 
     } 

     // send the message and clear the textfield 
     serial.sendMessageToDevice(msg) 
     messageField.text = "" 
     return true 
    } 

    func dismissKeyboard() { 
     messageField.resignFirstResponder() 
    } 


//MARK: IBActions 

    @IBAction func barButtonPressed(_ sender: AnyObject) { 
     if serial.connectedPeripheral == nil { 
      performSegue(withIdentifier: "ShowScanner", sender: self) 
     } else { 
      serial.disconnect() 
      reloadView() 
     } 
    } 
} 

CoreBluetooth碼。

import UIKit 
import CoreBluetooth 
var serial: BluetoothSerial! // Global serial handler, don't forget to initialize it with init(delgate:) 
// Delegate functions 
protocol BluetoothSerialDelegate { 
// ** Required ** 

/// Called when de state of the CBCentralManager changes (e.g. when bluetooth is turned on/off) 
func serialDidChangeState() 

/// Called when a peripheral disconnected 
func serialDidDisconnect(_ peripheral: CBPeripheral, error: NSError?) 

// ** Optionals ** 

/// Called when a message is received 
func serialDidReceiveString(_ message: String) 

/// Called when a message is received 
func serialDidReceiveBytes(_ bytes: [UInt8]) 

/// Called when a message is received 
func serialDidReceiveData(_ data: Data) 

/// Called when the RSSI of the connected peripheral is read 
func serialDidReadRSSI(_ rssi: NSNumber) 

/// Called when a new peripheral is discovered while scanning. Also gives the RSSI (signal strength) 
func serialDidDiscoverPeripheral(_ peripheral: CBPeripheral, RSSI: NSNumber?) 

/// Called when a peripheral is connected (but not yet ready for cummunication) 
func serialDidConnect(_ peripheral: CBPeripheral) 

/// Called when a pending connection failed 
func serialDidFailToConnect(_ peripheral: CBPeripheral, error: NSError?) 

/// Called when a peripheral is ready for communication 
func serialIsReady(_ peripheral: CBPeripheral) 

}

// Make some of the delegate functions optional extension BluetoothSerialDelegate { 
func serialDidReceiveString(_ message: String) {} 
func serialDidReceiveBytes(_ bytes: [UInt8]) {} 
func serialDidReceiveData(_ data: Data) {} 
func serialDidReadRSSI(_ rssi: NSNumber) {} 
func serialDidDiscoverPeripheral(_ peripheral: CBPeripheral, RSSI: NSNumber?) {} 
func serialDidConnect(_ peripheral: CBPeripheral) {} 
func serialDidFailToConnect(_ peripheral: CBPeripheral, error: NSError?) {} 
func serialIsReady(_ peripheral: CBPeripheral) {} 
} 

final class BluetoothSerial: NSObject,CBCentralManagerDelegate,CBPeripheralDelegate { 

// MARK: Variables 

/// The delegate object the BluetoothDelegate methods will be called upon 
var delegate: BluetoothSerialDelegate! 

/// The CBCentralManager this bluetooth serial handler uses for... well, everything really 
var centralManager: CBCentralManager! 

/// The peripheral we're trying to connect to (nil if none) 
var pendingPeripheral: CBPeripheral? 

/// The connected peripheral (nil if none is connected) 
var connectedPeripheral: CBPeripheral? 

/// The characteristic 0xFFE1 we need to write to, of the connectedPeripheral 
weak var writeCharacteristic: CBCharacteristic? 

/// Whether this serial is ready to send and receive data 
var isReady: Bool { 
    get { 
     return centralManager.state == .poweredOn && 
       connectedPeripheral != nil && 
       writeCharacteristic != nil 
    } 
} 

/// Whether this serial is looking for advertising peripherals 
var isScanning: Bool { 
    return centralManager.isScanning 
} 

/// Whether the state of the centralManager is .poweredOn 
var isPoweredOn: Bool { 
    return centralManager.state == .poweredOn 
} 

/// UUID of the service to look for. 
var serviceUUID = CBUUID(string: "FFE0") 

/// UUID of the characteristic to look for. 
var characteristicUUID = CBUUID(string: "FFE1") 

/// Whether to write to the HM10 with or without response. Set automatically. 
/// Legit HM10 modules (from JNHuaMao) require 'Write without Response', 
/// while fake modules (e.g. from Bolutek) require 'Write with Response'. 
private var writeType: CBCharacteristicWriteType = .withoutResponse 


// MARK: functions 

/// Always use this to initialize an instance 
init(delegate: BluetoothSerialDelegate) { 
    super.init() 
    self.delegate = delegate 
    centralManager = CBCentralManager(delegate: self, queue: nil) 
} 

/// Start scanning for peripherals 
func startScan() { 
    guard centralManager.state == .poweredOn else { return } 

    // start scanning for peripherals with correct service UUID 
    centralManager.scanForPeripherals(withServices: [serviceUUID], options: nil) 

    // retrieve peripherals that are already connected 
    // see this stackoverflow question http://stackoverflow.com/questions/13286487 
    let peripherals = centralManager.retrieveConnectedPeripherals(withServices: [serviceUUID]) 
    for peripheral in peripherals { 
     delegate.serialDidDiscoverPeripheral(peripheral, RSSI: nil) 
    } 
} 

/// Stop scanning for peripherals 
func stopScan() { 
    centralManager.stopScan() 
} 

/// Try to connect to the given peripheral 
func connectToPeripheral(_ peripheral: CBPeripheral) { 
    pendingPeripheral = peripheral 
    centralManager.connect(peripheral, options: nil) 
} 

/// Disconnect from the connected peripheral or stop connecting to it 
func disconnect() { 
    if let p = connectedPeripheral { 
     centralManager.cancelPeripheralConnection(p) 
    } else if let p = pendingPeripheral { 
     centralManager.cancelPeripheralConnection(p) //TODO: Test whether its neccesary to set p to nil 
    } 
} 

/// The didReadRSSI delegate function will be called after calling this function 
func readRSSI() { 
    guard isReady else { return } 
    connectedPeripheral!.readRSSI() 
} 

/// Send a string to the device 
func sendMessageToDevice(_ message: String) { 
    guard isReady else { return } 

    if let data = message.data(using: String.Encoding.utf8) { 
     connectedPeripheral!.writeValue(data, for: writeCharacteristic!, type: writeType) 
    } 
} 

/// Send an array of bytes to the device 
func sendBytesToDevice(_ bytes: [UInt8]) { 
    guard isReady else { return } 

    let data = Data(bytes: UnsafePointer<UInt8>(bytes), count: bytes.count) 
    connectedPeripheral!.writeValue(data, for: writeCharacteristic!, type: writeType) 
} 

/// Send data to the device 
func sendDataToDevice(_ data: Data) { 
    guard isReady else { return } 

    connectedPeripheral!.writeValue(data, for: writeCharacteristic!, type: writeType) 
} 


// MARK: CBCentralManagerDelegate functions 

func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) { 
    // just send it to the delegate 
    delegate.serialDidDiscoverPeripheral(peripheral, RSSI: RSSI) 
} 

func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) { 
    // set some stuff right 
    peripheral.delegate = self 
    pendingPeripheral = nil 
    connectedPeripheral = peripheral 

    // send it to the delegate 
    delegate.serialDidConnect(peripheral) 

    // Okay, the peripheral is connected but we're not ready yet! 
    // First get the 0xFFE0 service 
    // Then get the 0xFFE1 characteristic of this service 
    // Subscribe to it & create a weak reference to it (for writing later on), 
    // and find out the writeType by looking at characteristic.properties. 
    // Only then we're ready for communication 

    peripheral.discoverServices([serviceUUID]) 
} 

func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?) { 
    connectedPeripheral = nil 
    pendingPeripheral = nil 

    // send it to the delegate 
    delegate.serialDidDisconnect(peripheral, error: error as NSError?) 
} 

func centralManager(_ central: CBCentralManager, didFailToConnect peripheral: CBPeripheral, error: Error?) { 
    pendingPeripheral = nil 

    // just send it to the delegate 
    delegate.serialDidFailToConnect(peripheral, error: error as NSError?) 
} 

func centralManagerDidUpdateState(_ central: CBCentralManager) { 
    // note that "didDisconnectPeripheral" won't be called if BLE is turned off while connected 
    connectedPeripheral = nil 
    pendingPeripheral = nil 

    // send it to the delegate 
    delegate.serialDidChangeState() 
} 


// MARK: CBPeripheralDelegate functions 

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([characteristicUUID], 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 
    for characteristic in service.characteristics! { 
     if characteristic.uuid == characteristicUUID { 
      // subscribe to this value (so we'll get notified when there is serial data for us..) 
      peripheral.setNotifyValue(true, for: characteristic) 

      // keep a reference to this characteristic so we can write to it 
      writeCharacteristic = characteristic 

      // find out writeType 
      writeType = characteristic.properties.contains(.write) ? .withResponse : .withoutResponse 

      // notify the delegate we're ready for communication 
      delegate.serialIsReady(peripheral) 
     } 
    } 
} 

func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) { 
    // notify the delegate in different ways 
    // if you don't use one of these, just comment it (for optimum efficiency :]) 
    let data = characteristic.value 
    guard data != nil else { return } 

    // first the data 
    delegate.serialDidReceiveData(data!) 

    // then the string 
    if let str = String(data: data!, encoding: String.Encoding.utf8) { 
     delegate.serialDidReceiveString(str) 
    } else { 
     //print("Received an invalid string!") uncomment for debugging 
    } 

    // now the bytes array 
    var bytes = [UInt8](repeating: 0, count: data!.count/MemoryLayout<UInt8>.size) 
    (data! as NSData).getBytes(&bytes, length: data!.count) 
    delegate.serialDidReceiveBytes(bytes) 
} 

func peripheral(_ peripheral: CBPeripheral, didReadRSSI RSSI: NSNumber, error: Error?) { 
    delegate.serialDidReadRSSI(RSSI) 
} 

}

這裏是整個代碼:https://github.com/vari217/aw

+0

在後臺使用藍牙的核心藍牙編程指南中有一章。您將需要您的應用程序實施後臺模式,並在收到相應數據時發佈本地通知 – Paulw11

+0

以及如何在單行中打印數據/更新數據? –

+0

你的意思是在一條線上?你的意思是一個單一的印刷聲明?爲什麼不簡單地發送由逗號分隔的兩個傳感器值,並將其留給應用程序做出閾值判斷? – Paulw11

回答

0

如果你想,當你在你的按鈕挖掘只得到了價值,你不得不防你的Arduino一旦從你的BT收到一面旗幟就會這麼做。

不要在主循環中使用這麼多的延遲,10秒太多。圖如何處理事件而不是持有循環,您可以讓其他任務處理。

我沒有看到你的整個代碼,但從你發佈的內容我會遵循這條路徑。

對於您的Arduino,請等待閱讀並假脫機,直到您從應用中獲得申請,如果不使用,請不要浪費CPU時間。 如果您想每隔XX秒緩衝一些值,請在每隔XX秒驗證傳感器的地方放置一個例程,並將其保存在您的ROM上(如果確實需要)。

如果不是這樣,我的建議是:

char val;   // variable to receive data from the serial port [BT] 
char buffer[50]; 
void setup() 
{ 

    Serial.begin(115200);  // start serial communication at 115200bps 

} 

void loop() { 

    if(Serial.available())  // if data is available to read 
    { 
    val = Serial.read();   // read it and store it in 'val' 
    } 

    if(val == 'T')    // if 'T' was received read temperature 
    { 
    sensorInput = analogRead(A0); //read the analog sensor and store it 
    temp = (double)sensorInput/1024;  //find percentage of input reading 
    temp = temp * 5;     //multiply by 5V to get voltage 
    temp = temp - 0.5;    //Subtract the offset 
    temp = temp * 100;    //Convert to degrees 


    if (temp > 28) { 

     sprintf(buffer, "Current Temp is hot i.e.: %d", temp); 
     Serial.println(buffer); 
    } 

    else if (temp < 28) { 
     sprintf(buffer, "Current Temp is cold i.e.: %d", temp); 
     Serial.println(buffer); 
    } 
    else { 
     sprintf(buffer, "Current Temp %d", temp); 
     Serial.println(buffer); 
    } 
    } 

    if(val == 'L')    // if 'L' was received read light 
    { 
    sensorValue = analogRead(A1); //read the analog sensor and store it 
    if (sensorValue > 70) { 
     sprintf(buffer, "Current Light is high i.e.: %d", sensorValue); 
     Serial.println(buffer); 
    } 
    else if (sensorValue < 60) { 
     sprintf(buffer, "Current Light is low i.e.: %d", sensorValue); 
     Serial.println(buffer); 
    } 
    else { 
     sprintf(buffer, "Light seems good: %d", sensorValue); 
     Serial.println(buffer);  
    } 
    } 
    val = ''; 
} 

併爲您的SWIFT代碼,這樣的事情:

@IBAction func getTemperature(sender: AnyObject) 
{ 
    var str:NSString = "T" 
    data = str.dataUsingEncoding(NSUTF8StringEncoding)! 
    peripheral.writeValue(data, forCharacteristic: arrCharacteristics!.objectAtIndex(1) as CBCharacteristic , type: CBCharacteristicWriteType.WithoutResponse) 
} 

@IBAction func getLight(sender: AnyObject) 
{ 
    var str:NSString = "L" 
    data = str.dataUsingEncoding(NSUTF8StringEncoding)! 
    peripheral.writeValue(data, forCharacteristic: arrCharacteristics!.objectAtIndex(1) as CBCharacteristic , type: CBCharacteristicWriteType.WithoutResponse) 
} 

爲了您的有關通知的問題,我會關注@ Paulw11的建議,也有iOS背景中的一些陷阱和遵循教程是您必須實現它的最佳方式。

對於您關於單行打印的問題,請查看我的代碼中使用的sprintf函數。

+0

謝謝你讓我多花點時間。我會盡力做你在工作之後所說的話,並讓你知道。再次感謝。 –

+0

很高興幫助。如果我的答案幫助你,只是不要忘記接受它作爲你接受的答案。謝謝 – GIJOW

+0

謝謝,你的Arduino答案確實幫了我很大的忙,它很直接,很簡單。再次感謝。我還沒有拿到iPhone。請你稍微解釋一下,我是ios的新手。 ----我已經改變了你的代碼,像下面我不知道它是否正確,在代碼中,如果我是對的,我怎麼才能從數組 –