#author("2022-11-22T02:46:35+09:00","","")
#author("2022-11-22T02:47:31+09:00","","")
[[M5Stack]]


* iBeacon Sample [#ye134665]
&ref(ibeacon.c);

 #include <stdint.h>
 
 #include <M5Atom.h>
 #include <BLEDevice.h>
 #include <BLEServer.h>
 #include <BLEBeacon.h>
 
 //
 // iBeacon PDU
 //
 // Preamble          [1]
 // Access Address    [4]               0x8E89BED6
 // ProtocolData Unit [2-39]
 //   Header            [2]
 //   AdvA              [6]
 //   AdvData           [31]
 //     AD Structure1
 //       Length            [1]         0x02
 //       AD Type           [1]         0x01:Flags (GAP通信における制御情報)
 //       AD Data           [Length-1]  0x06 (iBeacon の場合大抵 0x06)
 //                                     bit0: LE Limited Discoverable Mode
 //                                     bit1: LE General Discoverable Mode
 //                                     bit2: BR/EDR Not Supported
 //                                     bit3: Simultaneous LE and BR/EDR to Same Device Capable (Controller)
 //                                     bit4: Simultaneous LE and BR/EDR to Same Device Capable (Host)
 //     AD Structure2
 //       Length            [1]         0x1A
 //       AD Type           [1]         0xFF:Manifacture Specific Data (任意送信データ)
 //       AD Data           [Length-1]
 //         Campany ID        [2]       0x4C00 ※Apple の Campany ID を使う必要がある。
 //         Beacon Type       [2]       0x0215
 //         UUID              [16]      UUID   <★>
 //         Major Num         [2]       Major  <★>
 //         Minor Num         [2]       Minor  <★>
 //         TX Power          [2]       TX     <★>
 //     Padding           [1]           0x00
 // CRC               [3]
 //
 // [備考] 三菱の BLE の Campany ID は、 0x0014 
 //

 ////////////////////////////////////////////////////////////////////////////////
 //
 // 構造体定義
 //

 /**
  * ビーコン情報構造体
  */
 struct BeaconInfo {
   const char* uuid;
   uint16_t    major;
   uint16_t    minor;
   int8_t      tx_power;
 };

 /**
  * LED情報構造体
  */
 struct LedInfo {
   uint8_t r;
   uint8_t g;
   uint8_t b;
 };

 /**
  * ボタン押下毎に切り替える情報構造体
  */
 struct BeaconData {
   struct BeaconInfo beacon;
   struct LedInfo    led;
 };

 // データ!
 struct BeaconData beaconData[] = {
 //{{ UUID                                  ,  major,  minor, tx_power}, {   R,   G,   B }},
   {{ "00000000-0000-0000-0000-000000000000", 0x0000, 0x0000, -65     }, {   0,   0,   0 }}, // OFF
 
   {{ "ff000000-0000-0000-0000-000000000014", 0x0001, 0x0001, -65     }, {   0,   0, 255 }},
   {{ "ff000000-0000-0000-0000-000000000014", 0x0002, 0x0001, -65     }, {   0, 255,   0 }},
   {{ "ff000000-0000-0000-0000-000000000014", 0x0003, 0x0001, -65     }, { 255,   0,   0 }},
   {{ "ff000000-0000-0000-0000-000000000014", 0x0004, 0x0001, -65     }, {   0, 255, 255 }},
   {{ "ff000000-0000-0000-0000-000000000014", 0x0005, 0x0001, -65     }, { 255,   0, 255 }},
   {{ "ff000000-0000-0000-0000-000000000014", 0x0006, 0x0001, -65     }, { 255, 255,   0 }},
   {{ "ff000000-0000-0000-0000-000000000014", 0x0007, 0x0001, -65     }, { 255, 255, 255 }},
 
   {{ "ff000000-0000-0000-0000-000000000014", 0x0001, 0x0002, -65     }, {   0, 127, 255 }},
   {{ "ff000000-0000-0000-0000-000000000014", 0x0001, 0x0003, -65     }, { 127,   0, 255 }},
   {{ "ff000000-0000-0000-0000-000000000014", 0x0001, 0x0004, -65     }, { 127, 127, 255 }},
 
   {{ "ff000000-0000-0000-0000-000000000014", 0x0002, 0x0002, -65     }, {   0, 255, 127 }},
   {{ "ff000000-0000-0000-0000-000000000014", 0x0002, 0x0003, -65     }, { 127, 255,   0 }},
   {{ "ff000000-0000-0000-0000-000000000014", 0x0002, 0x0004, -65     }, { 127, 255, 127 }},
 
   {{ "ff000000-0000-0000-0000-000000000014", 0x0003, 0x0002, -65     }, { 255,   0, 127 }},
   {{ "ff000000-0000-0000-0000-000000000014", 0x0003, 0x0003, -65     }, { 255, 127,   0 }},
   {{ "ff000000-0000-0000-0000-000000000014", 0x0003, 0x0004, -65     }, { 255, 127, 127 }},
 
   {{ NULL                                  , 0x0000, 0x0000, -65     }, {   0,   0,   0 }} // 番兵
 };


 ////////////////////////////////////////////////////////////////////////////////
 //
 // プロトタイプ宣言
 //
 static void toUUID(uint8_t* uuid, const char* uuid_str);
 static uint8_t hexstrToNum(const uint8_t* str);
 static void updateBeacon(struct BeaconInfo* info);

 ////////////////////////////////////////////////////////////////////////////////
 //
 // 変数
 //
 static BLEAdvertising* pAdvertising;
 static int data_idx = 0;


 /**
  * ビーコン情報を更新します。
  * 
  * @param info ビーコンの情報
  */
 static
 void updateBeacon(struct BeaconInfo* info) {
   BLEBeacon oBeacon = BLEBeacon();
   oBeacon.setManufacturerId(0x4C00);
 
   uint8_t uuid[16];
   toUUID(uuid, info->uuid);
   Serial.println(uuid[0]);
   oBeacon.setProximityUUID(BLEUUID(uuid, 16, false));
   oBeacon.setMajor(info->major);
   oBeacon.setMinor(info->minor);
   oBeacon.setSignalPower(info->tx_power);
   BLEAdvertisementData oAdvertisementData = BLEAdvertisementData();
   BLEAdvertisementData oScanResponseData  = BLEAdvertisementData();
 
   oAdvertisementData.setFlags(0x04);
   std::string strServiceData = "";
   strServiceData += (char)26;     // Len
   strServiceData += (char) 0xFF;  // Type
   strServiceData += oBeacon.getData();
   oAdvertisementData.addData(strServiceData);
 
   pAdvertising->setAdvertisementData(oAdvertisementData);
   pAdvertising->setScanResponseData(oScanResponseData);
 }

 CRGB dispColor(uint8_t r, uint8_t g, uint8_t b) {
   return (CRGB)(( r << 16) | (g << 8) | b);
 }


 /**
  * 開始!
  */
 void setup() {
   // LCD    : true
   // Power  : false
   // Serial : true
   M5.begin(true, false, true);
   Serial.begin(115200);
   BLEDevice::init("");
   M5.dis.drawpix(0, dispColor(0, 0, 0));
   pAdvertising = BLEDevice::getAdvertising();
   data_idx = 0;
   updateBeacon(&(beaconData[data_idx].beacon));
 }

 void loop() {
   M5.update();  // For ボタン情報取得
   if (M5.Btn.wasPressed())
   { // ボタンが押下された際に、iBeacon を切り替える。
     Serial.println("wasPressed");
     // インデックスを進める (末尾であれば、0 にする)
     data_idx = (beaconData[data_idx + 1].beacon.uuid == NULL) ? 0 : (data_idx + 1);
 
     // ビーコンの設定更新
     updateBeacon(&(beaconData[data_idx].beacon));
   }
 
   if (data_idx != 0)
   {
     // ビーコン送信開始
     pAdvertising->start();
     M5.dis.drawpix(0, dispColor(
       beaconData[data_idx].led.r,
       beaconData[data_idx].led.g,
       beaconData[data_idx].led.b));
     delay(100);
     // ビーコン送信終了
     pAdvertising->stop();
   }
 
   M5.dis.drawpix(0, dispColor(0, 0, 0));
   delay(900);
 }

 /**
  * 文字列方言の UUID を 16 byte のバイナリに変換します。
  * 
  * @param uuid 変換後のバイナリ格納用
  * @param uuid_str 文字列表現のUUID [xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx 形式]
  */
 static
 void toUUID(uint8_t* uuid, const char* uuid_str)
 {
   const uint8_t* ptr = (const uint8_t*) uuid_str;
   for (int i = 0; i < 16; i++)
   {
     if (*ptr == '-')
     {
       ptr++;
     }
     uuid[i] = hexstrToNum(ptr);
     ptr += 2;
   }
 }


 /**
  * 指定された16進数文字列を数値に変換します。
  *
  * @param str 16進数表現の文字列
  * @return 数値
  */
 static
 uint8_t hexstrToNum(const uint8_t* str)
 {
     const uint8_t* ptr = str;
     uint8_t msb = (*ptr > '9') ? (*ptr - 7) : *ptr;
     ptr++;
     uint8_t lsb = (*ptr > '9') ? (*ptr - 7) : *ptr;
     return ((msb & 0x0f) << 4) | (lsb & 0x0f);
 }
トップ   差分 バックアップ リロード   一覧 検索 最終更新   ヘルプ   最終更新のRSS