2017-05-29 16 views
0

私は、BLE(Arduino unoのHM-10)に接続するiosのアプリケーションを作成しました。 Arduinoには、温度、光、湿度センサーが接続されています。問題は、iPhoneがArduinoシリアルディスプレイのデータを表示するのと同じデータを表示することです。一方、「温度ボタン」をクリックすると、他のすべてのセンサーで同じように、温度センサーのデータを表示する必要があります。私が把握できない他の事は、アプリがケース・テンポで実行されていない場合に通知を欲しいということです。ある点まで下がる。どうすればいいですか?Swift 3 arduino Uno HM-10 Ble - iphoneでのお知らせ

助けてください!

ここArduinoのコードがある(むしろ、それは新しい行に何度も印刷するよりも1行のデータを印刷することが可能である)

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でありますコード。 HERE

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) 
} 

}

WHOLEコードです:https://github.com/vari217/aw

+0

バックグラウンドでBluetoothを使用している場合は、Core Bluetoothプログラミングガイドの章全体があります。バックグラウンドモードを実装し、適切なデータが受信されたときにローカル通知を投稿するにはアプリが必要です – Paulw11

+0

とデータの印刷方法/データを1行で更新する方法は? –

+0

1行で何を意味していますか? 1つのプリントステートメントで意味しますか?ちょうど2つのセンサーの値をコンマで区切って送信し、しきい値判断をするためにアプリに任せてみませんか? – 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を手に入れていません。あなたは少し説明してください、私は新しいです。 ----私はあなたのコードを以下のように変更しました。正しいかどうかわからないのですが、もしコードが正しいとすれば、配列から正しい文字を知る方法は? –