M5Stack

iBeacon Sample

fileibeacon.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);
}

添付ファイル: fileibeacon.c 202件 [詳細]
トップ   差分 バックアップ リロード   一覧 検索 最終更新   ヘルプ   最終更新のRSS