// Update is called once per frame void Update() { if (_timeout > 0f) { _timeout -= Time.deltaTime; if (_timeout <= 0f) { _timeout = 0f; switch (_state) { case States.None: break; case States.Scan: StatusMessage = "Scanning for " + DeviceName; BluetoothLEHardwareInterface.ScanForPeripheralsWithServices(null, (address, name) => { // if your device does not advertise the rssi and manufacturer specific data // then you must use this callback because the next callback only gets called // if you have manufacturer specific data if (!_rssiOnly) { if (name.Contains(DeviceName)) { StatusMessage = "Found " + name; BluetoothLEHardwareInterface.StopScan(); // found a device with the name we want // this example does not deal with finding more than one _deviceAddress = address; SetState(States.Connect, 0.5f); } } }, (address, name, rssi, bytes) => { // use this one if the device responses with manufacturer specific data and the rssi if (name.Contains(DeviceName)) { StatusMessage = "Found " + name; if (_rssiOnly) { _rssi = rssi; } else { BluetoothLEHardwareInterface.StopScan(); // found a device with the name we want // this example does not deal with finding more than one _deviceAddress = address; SetState(States.Connect, 0.5f); } } }, _rssiOnly); // this last setting allows RFduino to send RSSI without having manufacturer data if (_rssiOnly) { SetState(States.ScanRSSI, 0.5f); } break; case States.ScanRSSI: break; case States.Connect: StatusMessage = "Connecting..."; // set these flags _foundButtonUUID = false; _foundLedUUID = false; // note that the first parameter is the address, not the name. I have not fixed this because // of backwards compatiblity. // also note that I am note using the first 2 callbacks. If you are not looking for specific characteristics you can use one of // the first 2, but keep in mind that the device will enumerate everything and so you will want to have a timeout // large enough that it will be finished enumerating before you try to subscribe or do any other operations. BluetoothLEHardwareInterface.ConnectToPeripheral(_deviceAddress, null, null, (address, serviceUUID, characteristicUUID) => { StatusMessage = "Connected..."; if (IsEqual(serviceUUID, ServiceUUID)) { StatusMessage = "Found Service UUID"; _foundButtonUUID = _foundButtonUUID || IsEqual(characteristicUUID, ButtonUUID); _foundLedUUID = _foundLedUUID || IsEqual(characteristicUUID, LedUUID); // if we have found both characteristics that we are waiting for // set the state. make sure there is enough timeout that if the // device is still enumerating other characteristics it finishes // before we try to subscribe if (_foundButtonUUID && _foundLedUUID) { _connected = true; SetState(States.RequestMTU, 2f); } } }); break; case States.RequestMTU: StatusMessage = "Requesting MTU"; BluetoothLEHardwareInterface.RequestMtu(_deviceAddress, 185, (address, newMTU) => { StatusMessage = "MTU set to " + newMTU.ToString(); SetState(States.Subscribe, 0.1f); }); break; case States.Subscribe: StatusMessage = "Subscribing to characteristics..."; BluetoothLEHardwareInterface.SubscribeCharacteristicWithDeviceAddress(_deviceAddress, ServiceUUID, ButtonUUID, (notifyAddress, notifyCharacteristic) => { StatusMessage = "Waiting for user action (1)..."; _state = States.None; // read the initial state of the button BluetoothLEHardwareInterface.ReadCharacteristic(_deviceAddress, ServiceUUID, ButtonUUID, (characteristic, bytes) => { ProcessButton(bytes); }); }, (address, characteristicUUID, bytes) => { if (_state != States.None) { // some devices do not properly send the notification state change which calls // the lambda just above this one so in those cases we don't have a great way to // set the state other than waiting until we actually got some data back. // The esp32 sends the notification above, but if yuor device doesn't you would have // to send data like pressing the button on the esp32 as the sketch for this demo // would then send data to trigger this. StatusMessage = "Waiting for user action (2)..."; _state = States.None; } // we received some data from the device ProcessButton(bytes); }); break; case States.Unsubscribe: BluetoothLEHardwareInterface.UnSubscribeCharacteristic(_deviceAddress, ServiceUUID, ButtonUUID, null); SetState(States.Disconnect, 4f); break; case States.Disconnect: StatusMessage = "Commanded disconnect."; if (_connected) { BluetoothLEHardwareInterface.DisconnectPeripheral(_deviceAddress, (address) => { StatusMessage = "Device disconnected"; BluetoothLEHardwareInterface.DeInitialize(() => { _connected = false; _state = States.None; }); }); } else { BluetoothLEHardwareInterface.DeInitialize(() => { _state = States.None; }); } break; } } } }