LoginSignup
8
10

More than 3 years have passed since last update.

SwitchBot温湿度計のデータをM5StickC(ESP32)+Arduinoで取得する

Posted at

EaqDcEOUYAE4g-g.jpeg

この小さいBLE温湿度計がBLEでデータが取れて電池もよく持つし安い!ということなので試しに買ってみました。

しかも、いまAmazonでセール中だということなので今すぐ買おう→→→→ https://amzn.to/2YFaSYx

M5StickC+Arduinoでデータが取れました、のところまで。

SwitchBotBleReader.ino.c
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEScan.h>
#include <BLEAdvertisedDevice.h>

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

//BLEAddress addr01       = BLEAddress("xx:xx:xx:xx:xx:xx");
//BLEAddress addr02       = BLEAddress("yy:yy:yy:yy:yy:yy");
BLEUUID serviceUUID     = BLEUUID("cba20d00-224d-11e6-9fb8-0002a5d5c51b");
BLEUUID serviceDataUUID = BLEUUID("00000d00-0000-1000-8000-00805f9b34fb");

class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
    void onResult(BLEAdvertisedDevice advertisedDevice) {
      /*
      if(advertisedDevice.getAddress().equals(addr01) || advertisedDevice.getAddress().equals(addr02)){
        // OK
      }else{
        return;
      }
      printf("Advertised Device: %s \n", advertisedDevice.toString().c_str());
      */
      if(!advertisedDevice.haveServiceUUID()) return;
      if(!advertisedDevice.getServiceUUID().equals(serviceUUID)) return;
      printf("SwitchBot Meter!\n");

      if(!advertisedDevice.haveServiceData()) return;
      printf("ServiceDataUUID=%s\n", advertisedDevice.getServiceDataUUID().toString().c_str());
      std::string s = advertisedDevice.getServiceData();
      printf("ServiceData len=%d [", s.length());
      for(int i=0; i<s.length(); i++){
        printf("%02X ", s.c_str()[i]);
      }
      printf("]\n");
      if(!advertisedDevice.getServiceDataUUID().equals(serviceDataUUID)) return;

      const char* servicedata = s.c_str();
      int battery = servicedata[2] & 0b01111111;
      bool isTemperatureAboveFreezing = servicedata[4] & 0b10000000;
      float temperature = ( servicedata[3] & 0b00001111 ) / 10.0 + ( servicedata[4] & 0b01111111 );
      if(!isTemperatureAboveFreezing){
        temperature = -temperature;
      }
      int humidity = servicedata[5] & 0b01111111;

      bool isEncrypted            = ( servicedata[0] & 0b10000000 ) >> 7;
      bool isDualStateMode        = ( servicedata[1] & 0b10000000 ) >> 7;
      bool isStatusOff            = ( servicedata[1] & 0b01000000 ) >> 6;
      bool isTemperatureHighAlert = ( servicedata[3] & 0b10000000 ) >> 7;
      bool isTemperatureLowAlert  = ( servicedata[3] & 0b01000000 ) >> 6;
      bool isHumidityHighAlert    = ( servicedata[3] & 0b00100000 ) >> 5;
      bool isHumidityLowAlert     = ( servicedata[3] & 0b00010000 ) >> 4;
      bool isTemperatureUnitF     = ( servicedata[5] & 0b10000000 ) >> 7;

      printf("----\n");
      printf("address:     %s\n",   advertisedDevice.getAddress().toString().c_str());
      printf("battery:     %d\n",   battery);
      printf("temperature: %.1f\n", temperature);
      printf("humidity:    %d\n",   humidity);
      printf("\n");
      printf("isEncrypted:            %d\n", isEncrypted);
      printf("isDualStateMode:        %d\n", isDualStateMode);
      printf("isStatusOff:            %d\n", isStatusOff);
      printf("isTemperatureHighAlert: %d\n", isTemperatureHighAlert);
      printf("isTemperatureLowAlert:  %d\n", isTemperatureLowAlert);
      printf("isHumidityHighAlert:    %d\n", isHumidityHighAlert);
      printf("isHumidityLowAlert:     %d\n", isHumidityLowAlert);
      printf("isTemperatureUnitF:     %d\n", isTemperatureUnitF);
      printf("----\n");
    }
};

void setup() {
  Serial.begin(115200);
  Serial.println("Scanning...");

  BLEDevice::init("");
  pBLEScan = BLEDevice::getScan(); //create new scan
  pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks(), true);
  pBLEScan->setActiveScan(true); //active scan uses more power, but get results faster
  pBLEScan->setInterval(100);
  pBLEScan->setWindow(99);  // less or equal setInterval value
}

void loop() {
  // put your main code here, to run repeatedly:
  BLEScanResults foundDevices = pBLEScan->start(scanTime, false);
//  Serial.print("Devices found: ");
//  Serial.println(foundDevices.getCount());
//  Serial.println("Scan done!");
  pBLEScan->clearResults();   // delete results fromBLEScan buffer to release memory
  delay(2000);
}

データフォーマットはこちらの記事が詳しいです
https://qiita.com/warpzone/items/11ec9bef21f5b965bce3

参考ツイート
https://twitter.com/urekat/status/1272349274173407235

8
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
10