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

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

Android側のソース

```

            /// <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);
                }
            }
    
    
    
```

ESP32側のソース

```

    #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++;
    }
    
```
CC BY-SA 4.0
2020-05-10T12:25:16.693
66489
2020-05-12T08:05:53.143
15047
question
c# bluetooth xamarin esp32 bluetooth-lowenergy
Android端末(Xamarin.FormsとBLE Plugin)とEsp32(PlatformIO)でのBLEのやりとり
Android向けのBlutoothターミナルソフトがいくつか出てますんで、まずはそれで送受信の確認されてはどうでしょうか。  
少なくともそれで、どちら側に問題があるのか切り分けができます
CC BY-SA 4.0
2020-05-11T00:36:34.447
66496
2020-05-11T00:36:34.447
27481
66489
answer
質問者です  
受信開始のためのstartRecieveを  
以下のように書き換えてタイマーを起動し、  
データの受信をイベントではなく  
characteristic.ReadAsync()  
関数を使用してリードするようにしたらデータを取れるようになりました

ただ、リードデータを取得すると、ライブラリのバッファ内に前回のデータが残っているらしく  
characteristic.ReadAsync()  
が延々と前回のデータを取得し続けてしまうので前回との差分を取ってから取得完了にする必要はありそうですが・・

とりあえず別タスクかスレッドでcharacteristic.ReadAsync()を実行し続けるようにするかして解決することにしました(面倒なのでこのままタイマーでもいいかもとは思っていますが)

ただ、それだと  
ValueUpdated イベントハンドラは一体何に使うのかという謎は残るのですが(ヘルプの見方を間違ったのかもしれないですが)

```

            private System.Timers.Timer _tim;
    
            private bool _rec = true;
            async private void startRecieve()
            {
                //100mタイマースタート
                _tim = new System.Timers.Timer();
                _tim.Interval = 100;
                _tim.Elapsed += _tim_Elapsed;
                _tim.Start();
    
            }
    
            //タイマーイベント
            private void _tim_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
            {
                if (_rec == true)
                {
                    _rec = false;
                    Read();
                }
            }
    
            //データリード
            /// <summary>
            /// 
            /// </summary>
            async private void Read()
            {
                if(_service == null)
                {
                    _IsRecieve = false;
                    return;
                }
                var characteristic = await _service.GetCharacteristicAsync(Guid.Parse(_bleconInfo.UUCharacteristic));
                var bytes = await characteristic.ReadAsync();   //データリード
                if (bytes.Length != 0)
                {
                    e.bdata = bytes;            //★前回のデータが残っている
                }
                _rec = true;
            }
    
```
CC BY-SA 4.0
2020-05-12T07:42:43.493
66534
2020-05-12T07:42:43.493
15047
66489
answer
お騒がせしました  
解決しました(さっきのReadAsyncでも良さそうですが)  
ValueUpdateでイベントを受信するためにはペリフェラルのESP32側の操作可能なプロパティに(BLECharacteristic::PROPERTY_NOTIFY)を以下のように追加し、

```

    static BLECharacteristic *pCharacteristic = pService->createCharacteristic(
                                             CHARACTERISTIC_UUID,
                                             BLECharacteristic::PROPERTY_READ |
                                             BLECharacteristic::PROPERTY_WRITE                                                                                 );
    
```

を

```

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

に変更

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

```

    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;
            }
    
```

Characteristicread_ValueUpdated(s,e)イベントでデータを受信することが出来ました  
独り相撲でお騒がせしました・・・
CC BY-SA 4.0
2020-05-12T08:05:53.143
66535
2020-05-12T08:05:53.143
15047
66489
answer