Android端末(Xamarin.FormsとBLE Plugin)とEsp32(PlatformIO)でのBLEのやりとり


Android端末とEsp32でBLEのデータ送受信をしようと思っているのですが  
Android側から送信し、ESP32で受信することは成功したのですが  
ESP32からAndroidへのデータ送信が上手くいきません  
まるで受信したデータを受け取っていないようなのですが・・・  
何が間違っているのかわかりますでしょうか

切り分けがまるで出来ていなくて、ESP32から送信出来ていないのか  
Android側で受信していないのかもわからないのですが  
Android側から送信出来ているからには、サービスUUIDやCHARACTERISTIC UUIDは間違っていないとは思うのですが・・

Android側のソース

[code]

            /// <summary>
            /// コンストラクタ
            /// </summary>
            public BLEControlBase()
            {
                _BluetoothLe = Plugin.BLE.CrossBluetoothLE.Current;     //BLEの検索する
                _adapter = _BluetoothLe.Adapter;                        //アダプターの準備
                _adapter.ScanTimeout = 5000;                            //検索タイムアウト
                _adapter.DeviceDiscovered += BLE_DeviceDiscoverd;       //検索時の発見イベント
                _adapter.ScanTimeoutElapsed += BLE_ScanTimeoutElapsed;  //検索タイムアウトイベント
    
            }
    
            /// <summary>
            /// 検索発見イベント
            /// </summary>
            /// <param name="sender">送信元</param>
            /// <param name="e">イベント内容</param>
            private void BLE_DeviceDiscoverd(object sender, Plugin.BLE.Abstractions.EventArgs.DeviceEventArgs e)
            {
                IDevice device = e.Device;
    
                if (device.Name == _bleconInfo.TerminalName)    //指定したデバイス名ならば
                {
                    _adapter.StopScanningForDevicesAsync();
                    Connect(device);                            //接続
                }
    
                //throw new NotImplementedException();
            }
    
            async private void Connect(IDevice device)
            {
                try
                {
                    await _adapter.ConnectToDeviceAsync(device);
                    //  var services = await device.GetServicesAsync(); //発見したサービスを片っ端から捕まえる
                    //  var service = await device.GetServiceAsync(Guid.Parse("00001101-0000-1000-8000-00805f9b34fb")); //指定したサービスを捕まえる
                    _device = device;
                    var service = await device.GetServiceAsync(Guid.Parse(_bleconInfo.UUService)); //指定したサービスを捕まえる
                    if (service != null)
                    {
                        _service = service;
                        _IsRecieve = true;
                        startRecieve();//接続成功したので電文受信出来るようにイベントハンドラ作成
                    }
                }
                catch (DeviceConnectionException e)
                {
                    // ... could not connect to device
                }
            }
    
            //受信開始　★この中で受信イベントが結びついているはず・・・
            async private void startRecieve()
            {
                var characteristicread = await _service.GetCharacteristicAsync(Guid.Parse(_bleconInfo.UUCharacteristic));
                if (characteristicread.CanRead == true)
                {
                    characteristicread.ValueUpdated += Characteristicread_ValueUpdated;
                }           
            }
    
            private void Characteristicread_ValueUpdated(object sender, Plugin.BLE.Abstractions.EventArgs.CharacteristicUpdatedEventArgs e)
            {
                byte[] b = e.Characteristic.Value;//受信電文が来るはず・・・★全然来ない
            }
    
            /// <summary>
            /// データ送信
            /// </summary>
            /// <param name="bdata">接続先にデータを送信する</param>
            /// <exception cref=""></exception>
            async public void Write(byte[] bdata)
            {
                try
                {
                    if (_service == null)   //サービスが確保されていなかったら
                    {
                        return;             //終了
                    }               
                    var characteristic = await _service.GetCharacteristicAsync(Guid.Parse(_bleconInfo.UUCharacteristic));
                    if (characteristic.CanWrite == true)
                    {
                        await characteristic.WriteAsync(bdata);
                    }
    
                }catch(Exception e)
                {
                    throw new Exception(e.Message);
                }
            }
    
    
    
[/code]

ESP32側のソース

[code]

    #include <Arduino.h>
    #include <BLEDevice.h>
    #include <BLEUtils.h>
    #include <BLEServer.h>
    
    BLECharacteristic *p;
    
    void setup() {
      Serial.begin(115200);
    
      Serial.println("1- Download and install an BLE scanner app in your phone");
      Serial.println("2- Scan for BLE devices in the app");
      Serial.println("3- Connect to MyESP32");
      Serial.println("4- Go to CUSTOM CHARACTERISTIC in CUSTOM SERVICE and write something");
      Serial.println("5- See the magic =)");
    
      BLEDevice::init("MyESP32");
      static BLEServer *pServer = BLEDevice::createServer();
    
      static BLEService *pService = pServer->createService(SERVICE_UUID);
    
      static BLECharacteristic *pCharacteristic = pService->createCharacteristic(
                                             CHARACTERISTIC_UUID,
                                             BLECharacteristic::PROPERTY_READ |
                                             BLECharacteristic::PROPERTY_WRITE
                                           );
    
      pCharacteristic->setCallbacks(new MyCallbacks());
    
      pCharacteristic->setValue("Hello World");
      pService->start();
    
      p = pCharacteristic;
      BLEAdvertising *pAdvertising = pServer->getAdvertising();
      pAdvertising->start();
    }
    
    int i=0;
    char c[100];
    void loop() {
      // put your main code here, to run repeatedly:
    
    
      sprintf(c,"test %d",i);
      Serial.println(c);
      p->setValue(c);  //★このデータを端末側で受信して欲しい
      //p->setValue("test");
    
      delay(2000);
      i++;
    }
    
[/code]




お騒がせしました  
解決しました(さっきのReadAsyncでも良さそうですが)  
ValueUpdateでイベントを受信するためにはペリフェラルのESP32側の操作可能なプロパティに(BLECharacteristic::PROPERTY_NOTIFY)を以下のように追加し、

[code]

    static BLECharacteristic *pCharacteristic = pService->createCharacteristic(
                                             CHARACTERISTIC_UUID,
                                             BLECharacteristic::PROPERTY_READ |
                                             BLECharacteristic::PROPERTY_WRITE                                                                                 );
    
[/code]

を

[code]

      static BLECharacteristic *pCharacteristic = pService->createCharacteristic(
                                             CHARACTERISTIC_UUID,
                                             BLECharacteristic::PROPERTY_READ |
                                             BLECharacteristic::PROPERTY_WRITE |
                                             BLECharacteristic::PROPERTY_NOTIFY //★通知を操作可能にする
                                                                                    );
    
[/code]

に変更

受信側の  
startRecieve()関数にawait characteristicread.StartUpdatesAsync();を追加したら

[code]

    async private void startRecieve()
            {
                var characteristicread = await _service.GetCharacteristicAsync(Guid.Parse(_bleconInfo.UUCharacteristic));
                if (characteristicread.CanRead == true)
                {
                    characteristicread.ValueUpdated += Characteristicread_ValueUpdated;
                    await characteristicread.StartUpdatesAsync();               //★これを追加しないとイベントを受信しない
                }
                return;
            }
    
[/code]

Characteristicread_ValueUpdated(s,e)イベントでデータを受信することが出来ました  
独り相撲でお騒がせしました・・・




Android向けのBlutoothターミナルソフトがいくつか出てますんで、まずはそれで送受信の確認されてはどうでしょうか。  
少なくともそれで、どちら側に問題があるのか切り分けができます

