LoginSignup
0
1

More than 1 year has passed since last update.

【BLEHF2Service(.h/.cpp)編】micro:bitにおけるDAL(V1)とCODAL(V2)とのBLEサービス実装の違いを確認する

Posted at

V1とV2での実装の違い

次の記事で、micro:bitにおけるDAL(V1)とCODAL(V2)とのBLEサービス実装の違いを確認していますが、本記事では、BLEHF2Serviceサービスを例に、その違いを確認しました。

おさらい(pxt-microbitにおけるbluetoothの実装)

pxt-microbitでは、bluetoothが実装されており、ソースコードが公開されています。
https://github.com/microsoft/pxt-microbit/tree/master/libs/bluetooth

DALとCODAL

micro:bitには、大きく分けて、V1とV2とが存在し、V1では、DALを使用し、V2では、CODALを使用します。
DAL/CODALで、V1とV2の違いを吸収して共通化されているのですが、bluetoothに関しては、共通化されていません。

micro:bit ランタイムとNordic nRF5 SDK

MakeCodeで、HEX形式ファイルをビルドする際に、micro:bitランタイムやNordic nRF5 SDKといったライブラリが必要です。これらのライブラリは、micro:bitのバージョンにより異なります。

micro:bit ランタイム nRF5
V1 dal Soft Device 110
V2 codal Soft Device 113

その為、拡張機能を独自に実装する際には、micro:bitの各バージョンに合わせたライブラリに対する実装が必要ですので、プリプロセッサ ディレクティブによる切り分けた実装を行います(MICROBIT_CODALがゼロ以外かどうか)。

MICROBIT_CODAL micro:bit
ゼロ V1 - DAL
ゼロ以外 V2 - CODAL

BLE(Gattサーバー)の操作

ペリフェラルとしてBLEサービスを提供するために、Gattサーバーを操作しますが、V1とV2とではその実装方法が異なります。
Gattサーバーを操作する為に、V1の場合は、uBit.bleに委譲した実装を行い、V2の場合は、MicroBitBLEServiceクラスを継承した実装を行います。

uBit.bleの正体
V1/V2ともにuBit.bleは、BLEDevice型(ble.h)ですが、V2におけるuBit.bleの実体は、MicrobitBLEManager型(クラス)です。
ソースコード

codal-microbit-v2/inc/bluetooth/MicroBitBLEManager.h

class MicroBitBLEManager;
typedef MicroBitBLEManager BLEDevice;

BLEHF2Service における実装の違い

pxt-microbit/bluetoothのソースコードに含まれるBLEHF2Serviceサービスを例に、実装の違いを確認します。

BLEHF2Service.h - 違い

BLEHF2Service.hにおける、大きな違いは、次の2つです。

  • MicroBitBLEServiceを継承しているかどうか
  • Characteristicハンドルを配列で保持するかどうか
# 項目 (V1)DAL (V2)CODAL
1 #include "MicroBitConfig.h" (共通) (共通)
2 #include "MicroBitThermometer.h" (共通) (共通)
3 #include "EventModel.h" (共通) (共通)
4 #include "pxt.h" (共通) (共通)
5 #define HF2_ID 9501 (共通) (共通)
6 #define BLEHF2_FLAG_SERIAL_OUT 0x80 (共通) (共通)
7 #define BLEHF2_FLAG_SERIAL_ERR 0xC0 (共通) (共通)
8 #define BLEHF2_DATA_LENGTH 19 (共通) (共通)
9 extern const uint8_t BLEHF2ServiceUUID[]; (共通) (共通-未使用)
10 extern const uint8_t BLEHF2TxCharacteristicUUID[]; (共通) (共通-未使用)
11 struct BLEHF2Packet {...}; (共通) (共通)
11 #include "ble/BLE.h" (V1)
11 #include "MicroBitBLEManager.h" (V2)
12 #include "MicroBitBLEService.h" (V2)
13 継承元 (なし) MicroBitBLEService
14 コンストラクタ (同等) (同等)
15 void sendSerial(const char *data, int len, bool isError); (同等) (同等)
16 BLEDevice &ble; (同等) (同等)
17 BLEHF2Packet txCharacteristicMessage; (同等) (同等)
18 Charactersiticハンドル等の保持 変数 継承と配列

BLEHF2Service.h - 共通(はじめ)

BLEHF2Service.h
#ifndef BLE_HF2_SERVICE_H
#define BLE_HF2_SERVICE_H

#include "MicroBitConfig.h"
#include "MicroBitThermometer.h"
#include "EventModel.h"
#include "pxt.h"

#define HF2_ID 9501

#define BLEHF2_FLAG_SERIAL_OUT 0x80
#define BLEHF2_FLAG_SERIAL_ERR 0xC0
#define BLEHF2_DATA_LENGTH 19

// UUIDs for our service and characteristics
extern const uint8_t  BLEHF2ServiceUUID[];
extern const uint8_t  BLEHF2TxCharacteristicUUID[];

struct BLEHF2Packet {
  uint8_t command;
  uint8_t data[BLEHF2_DATA_LENGTH];
};

BLEHF2Service.h - (V2) CODAL

BLEHF2Service.h
//================================================================
#if MICROBIT_CODAL
//================================================================

#include "MicroBitBLEManager.h"
#include "MicroBitBLEService.h"

class BLEHF2Service : public MicroBitBLEService
{
    public:

    /**
      * Constructor.
      * Create a representation of the TemperatureService
      * @param _ble The instance of a BLE device that we're running on.
      */
    BLEHF2Service(BLEDevice &_ble);

    /**
    * Sends text
    */
    void sendSerial(const char *data, int len, bool isError);

    private:

    // Bluetooth stack we're running on.
    BLEDevice &ble;

    // memory for buffers.
    BLEHF2Packet txCharacteristicMessage;
    
    // Index for each charactersitic in arrays of handles and UUIDs
    typedef enum mbbs_cIdx
    {
        mbbs_cIdxMESSAGE,
        mbbs_cIdxCOUNT
    } mbbs_cIdx;
    
    // UUIDs for our service and characteristics
    static const uint8_t  service_base_uuid[ 16];
    static const uint8_t  char_base_uuid[ 16];
    static const uint16_t serviceUUID;
    static const uint16_t charUUID[ mbbs_cIdxCOUNT];
    
    // Data for each characteristic when they are held by Soft Device.
    MicroBitBLEChar      chars[ mbbs_cIdxCOUNT];

    public:
    
    int              characteristicCount()          { return mbbs_cIdxCOUNT; };
    MicroBitBLEChar *characteristicPtr( int idx)    { return &chars[ idx]; };
};

BLEHF2Service.h - (V1) DAL

BLEHF2Service.h
//================================================================
#else // MICROBIT_CODAL
//================================================================

#include "ble/BLE.h"

class BLEHF2Service
{
    public:

    /**
      * Constructor.
      * Create a representation of the TemperatureService
      * @param _ble The instance of a BLE device that we're running on.
      */
    BLEHF2Service(BLEDevice &_ble);

    /**
    * Sends text
    */
    void sendSerial(const char *data, int len, bool isError); 

    private:

    // Bluetooth stack we're running on.
    BLEDevice &ble;

    // memory for buffers.
    BLEHF2Packet txCharacteristicMessage;

    // Handles to access each characteristic when they are held by Soft Device.
    GattAttribute::Handle_t txCharacteristicHandle;
};

BLEHF2Service.h - 共通(おわり)

BLEHF2Service.h

//================================================================
#endif // MICROBIT_CODAL
//================================================================

#endif

BLEHF2Service.cpp - 違い

BLEHF2Service.cppにおける、大きな違いは、次の2つです。

  • UUIDをロング(ベース)とショートで扱っているかどうか
  • bleインスタンスを操作するか、継承元に委譲しているかどうか
# 項目 (V1)DAL (V2)CODAL
1 MicroBitConfig.h (共通) (共通)
2 BLEHF2Service.h (共通) (共通)
3 MicroBitEvent.h (共通) (共通)
4 ble/UUID.h (V1)
5 const uint8_t BLEHF2Service::service_base_uuid[]; (V2)
6 const uint8_t BLEHF2Service::char_base_uuid[]; (V2)
7 const uint16_t BLEHF2Service::serviceUUID = 0xf5e6; (V2)
8 const uint16_t BLEHF2Service::charUUID[ mbbs_cIdxCOUNT] = { 0xf5e6 }; (V2)
9 GattCharacteristic (V1)
10 GattService (V1)
11 ble.addService(service); (V1)
12 CreateService( serviceUUID); (V2)
13 CreateCharacteristic (V2)
14 接続状況 ble.getGapState().connected getConnected()
15 notify ble.gattServer().notify() notifyChrValue()
16 const uint8_t BLEHF2ServiceUUID[]; (V1)
17 const uint8_t BLEHF2TxCharacteristicUUID[]; (V1)

違いの補足説明(BLEHF2Service.cpp)

【(V1) DAL】
UUIDをロング形式で定義しています。
サービスの構築のために、コンストラクタで、GattCharacteristicインスタンスやGattServiceインスタンスを生成し、bleインスタンスにサービスを追加しています。
sendSerialメソッドでは、bleインスタンスを操作し、接続状況の取得やnotify呼び出しを行っています。

【(V2) CODAL】
UUIDをロング形式のベース部分とショート形式とで定義しています。
サービス構築のために、コンストラクタで、継承元のメソッドを呼び出してサービスを追加しています。
sendSerialメソッドでも、継承元のメソッドを呼び出し、接続状況の取得やnotify呼び出しを行っています。尚、notifyChrValue()メソッドの引数では、Characteristicハンドルの値ではなく、配列変数の添え字を渡しています。

BLEHF2Service.cpp - 共通(はじめ)

BLEHF2Service.cpp
#include "MicroBitConfig.h"
#include "BLEHF2Service.h"
#include "MicroBitEvent.h"

BLEHF2Service.cpp - (V2) CODAL

BLEHF2Service.cpp
//================================================================
#if MICROBIT_CODAL
//================================================================

const uint8_t  BLEHF2Service::service_base_uuid[ 16] =
{ 0xb1,0x12,0x00,0x00,0x26,0x79,0x30,0xda,0xa2,0x6e,0x02,0x73,0xb6,0x04,0x38,0x49 };

const uint8_t  BLEHF2Service::char_base_uuid[ 16] =
{ 0xb1,0x12,0x00,0x00,0x26,0x79,0x30,0xda,0xa2,0x6e,0x02,0x73,0xb6,0x04,0x38,0x4a };

const uint16_t BLEHF2Service::serviceUUID               = 0xf5e6;
const uint16_t BLEHF2Service::charUUID[ mbbs_cIdxCOUNT] = { 0xf5e6 };


BLEHF2Service::BLEHF2Service(BLEDevice &_ble) :
        ble(_ble)
{
    // Initialise our characteristic values.
    memset(&txCharacteristicMessage, 0, sizeof(txCharacteristicMessage));
    
    // Register the base UUID and create the service.
    RegisterBaseUUID( service_base_uuid);
    CreateService( serviceUUID);

    RegisterBaseUUID( char_base_uuid);
    CreateCharacteristic( mbbs_cIdxMESSAGE, charUUID[ mbbs_cIdxMESSAGE],
                         (uint8_t *)&txCharacteristicMessage,
                         sizeof(txCharacteristicMessage), sizeof(txCharacteristicMessage),
                         microbit_propNOTIFY);
}

void BLEHF2Service::sendSerial(const char *data, int len, bool isError) {
    if (getConnected())
    {
        int32_t sent = 0;
        while(sent < len) {
            int32_t n = min(BLEHF2_DATA_LENGTH, len - sent);
            txCharacteristicMessage.command = (isError ? BLEHF2_FLAG_SERIAL_OUT : BLEHF2_FLAG_SERIAL_ERR) | n;
            memcpy(&txCharacteristicMessage.data, data + sent, n);
            notifyChrValue(mbbs_cIdxMESSAGE,(uint8_t *)&txCharacteristicMessage, sizeof(txCharacteristicMessage));
            sent += n;
        }
    }
}

BLEHF2Service.cpp - (V1) DAL

BLEHF2Service.cpp

//================================================================
#else // MICROBIT_CODAL
//================================================================

#include "ble/UUID.h"

BLEHF2Service::BLEHF2Service(BLEDevice &_ble) :
        ble(_ble)
{
    GattCharacteristic  txCharacteristic(BLEHF2TxCharacteristicUUID, (uint8_t *)&txCharacteristicMessage, 0,
    sizeof(txCharacteristicMessage), GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY);

    // Initialise our characteristic values.
    memset(&txCharacteristicMessage, 0, sizeof(txCharacteristicMessage));

    // Set default security requirements
    txCharacteristic.requireSecurity(SecurityManager::MICROBIT_BLE_SECURITY_LEVEL);

    // setup GATT table
    GattCharacteristic *characteristics[] = {&txCharacteristic};
    GattService service(BLEHF2ServiceUUID, characteristics, sizeof(characteristics) / sizeof(GattCharacteristic *));
    ble.addService(service);

    // retreive handles
    txCharacteristicHandle = txCharacteristic.getValueHandle();

    // initialize data
    ble.gattServer().write(txCharacteristicHandle,(uint8_t *)&txCharacteristicMessage, sizeof(txCharacteristicMessage));
}

void BLEHF2Service::sendSerial(const char *data, int len, bool isError) {
    if (ble.getGapState().connected)
    {
        int32_t sent = 0;
        while(sent < len) {
            int32_t n = min(BLEHF2_DATA_LENGTH, len - sent);
            txCharacteristicMessage.command = (isError ? BLEHF2_FLAG_SERIAL_OUT : BLEHF2_FLAG_SERIAL_ERR) | n;
            memcpy(&txCharacteristicMessage.data, data + sent, n);
            ble.gattServer().notify(txCharacteristicHandle,(uint8_t *)&txCharacteristicMessage, sizeof(txCharacteristicMessage));
            sent += n;
        }
    }
}

const uint8_t  BLEHF2ServiceUUID[] = {
    0xb1,0x12,0xf5,0xe6,0x26,0x79,0x30,0xda,0xa2,0x6e,0x02,0x73,0xb6,0x04,0x38,0x49
};

const uint8_t  BLEHF2TxCharacteristicUUID[] = {
    0xb1,0x12,0xf5,0xe6,0x26,0x79,0x30,0xda,0xa2,0x6e,0x02,0x73,0xb6,0x04,0x38,0x4a
};

BLEHF2Service.cpp - 共通(おわり)

BLEHF2Service.cpp
//================================================================
#endif // MICROBIT_CODAL
//================================================================

まとめ

BLEHF2Serviceサービスの実装においても、Gattサーバーを操作する為に、V1の場合は、uBit.bleに委譲した実装を行い、V2の場合は、MicroBitBLEServiceクラスを継承した実装を行っていることを確認しました。

0
1
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
0
1