自分のスマホが出力しているであろうCOCOAのBLEを見てみる

先日リリースされた接触確認アプリのCOCOA。
仕組みとしてはBLEを使っているはずなので、仕様さえわかれば受信してみることは可能なはず。

ということで、「自分のスマホが出力しているであろうCOCOAのBLEを見てみたい」ということを目標に試してみる


# 仕様

+ アップルが公開している仕様のあれこれ。
https://www.apple.com/covid19/contacttracing/

+ BLEの仕様
https://covid19-static.cdn-apple.com/applications/covid19/current/static/contact-tracing/pdf/ExposureNotification-BluetoothSpecificationv1.2.pdf


UUIDは[0xFD6F]
飛んでいるBLEを受信して、このID（10進だと64879）のものを拾えばいいはず。

なのだが、なんだか上手くいかない。。


## 似たようなことをやっている人を発見

そんな中[Facebookのグループで出てたスケッチ](https://gist.github.com/ksasao/0da6437d3eac9b2dbd675b6fee5d1117)をまねして作ってみたのが以下。
※サンプルにしたスケッチがM5ATOM用だったので、表示などをM5StickC用にしてます。

```
#include <M5StickC.h>
#include <BLEDevice.h>

int scanTime = 5; //In seconds
BLEScan* pBLEScan;

// Contact Tracing Bluetooth Specification (Apple/Google)
// https://blog.google/documents/58/Contact_Tracing_-_Bluetooth_Specification_v1.1_RYGZbKW.pdf
const char* uuid = "0000fd6f-0000-1000-8000-00805f9b34fb";
bool found = false;
int deviceNum = 0;
int nearDeviceNum = 0;

class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
    void onResult(BLEAdvertisedDevice advertisedDevice) {
        if(advertisedDevice.haveServiceUUID()){
            if(strncmp(advertisedDevice.getServiceUUID().toString().c_str(),uuid, 36) == 0){
                int rssi = advertisedDevice.getRSSI();
                Serial.print("  >> ADDR: ");
                Serial.print(advertisedDevice.getAddress().toString().c_str());
                Serial.print(" , ");
                Serial.print("RSSI: ");
                Serial.print(rssi);
                deviceNum++;
                if(rssi > -69){
                    found = true;
                    Serial.print(" >> Near! << ");
                    nearDeviceNum++;
                }
                Serial.println("");
            }
        }
    }
};

void setup() {
    M5.begin(true, false, true);
    M5.Lcd.setRotation( 1 );
    M5.Lcd.fillScreen(BLACK);
//    Serial.begin(115200);
    Serial.println("Scanning...");
    BLEDevice::init("");
    pBLEScan = BLEDevice::getScan(); //create new scan
    pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
    pBLEScan->setActiveScan(true); //active scan uses more power, but get results faster
    pBLEScan->setInterval(100);
    pBLEScan->setWindow(99); // less or equal setInterval value

    M5.Lcd.setTextSize(2);
}

void loop(){

    M5.update();

    Serial.println("Loop Start.");
    found = false;
    deviceNum = 0;
    nearDeviceNum = 0;
    BLEScanResults foundDevices = pBLEScan->start(scanTime, false); 

    M5.Lcd.fillScreen(BLACK);
    M5.Lcd.setTextColor(WHITE);
    M5.Lcd.setCursor(30, 20);
    
    M5.Lcd.print("Found : ");
    M5.Lcd.println(deviceNum);
    Serial.print(" - FoundDevice : ");
    Serial.println(deviceNum);

    if(nearDeviceNum > 0){
      M5.Lcd.setTextColor(YELLOW);
    }
    M5.Lcd.setCursor(30, 50);
    M5.Lcd.print("Near : ");
    M5.Lcd.println(nearDeviceNum);
    Serial.print(" - NearDevice : ");
    Serial.println(nearDeviceNum);


    pBLEScan->clearResults(); // delete results fromBLEScan buffer to release memory
    Serial.println("Loop End.");
    delay(1000);

}
```

これでM5StickCで近く（1mちょいぐらい）の距離にあるCOCOAが入っているスマホの件数がわかる。


こんな感じ。

![IMG_0036.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106639/7a002f0f-b135-8f7b-ce42-2fca5a4c9ee6.jpeg)
![IMG_0037.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106639/679979b3-c354-d134-e0b2-a6d154f6e1be.jpeg)
![IMG_0038.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106639/207190db-c25e-decc-99b6-cffe1c0e3453.jpeg)



これで何ができるわけではないが、BLEを身近に扱うことができる一歩にはなった気がする。