#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); }