LIFFアプリを完成させる

LINE Things対応デバイスを操作するLIFFアプリの作成方法を、LINE ThingsのスターターLIFFアプリのソースコードを使って説明します。

注:LINE ThingsのスターターLIFFアプリを完成させるには、USER_SERVICE_UUIDに「トライアルプロダクトを作成する」で返されたサービス探索用service UUIDを指定してください。詳しくは、「見つかったLINE Things対応デバイスのGATTサーバーに接続する」を参照してください。

LIFFアプリを初期化する

liff.init()メソッドを実行すると、LIFF SDKの他のメソッドを実行できるようになります。

function initializeApp() {
    liff.init(() => initializeLiff(), error => uiStatusError(makeErrorMsg(error), false));
}

Bluetoothプラグインを有効化する

Bluetoothプラグインを有効化します。

function initializeLiff() {
    liff.initPlugins(['bluetooth']).then(() => {
        liffCheckAvailablityAndDo(() => liffRequestDevice());
    }).catch(error => {
        uiStatusError(makeErrorMsg(error), false);
    });
}

注:「チャネルにLIFFアプリを追加する」の説明に従って、チャネルにLIFFアプリを追加していないと、Bluetoothプラグインは有効化できません。

Bluetoothプラグインが利用できることを確認する

以下の内容を確認し、Bluetoothプラグインが利用できるかどうかを確認します。

  • チャネルのBluetoothサポートの有無
  • Bluetooth設定
  • LINE Thingsの利用規約に同意していること
  • 位置情報の取得権限(Androidのみ)
function liffCheckAvailablityAndDo(callbackIfAvailable) {
    // Check Bluetooth availability
    liff.bluetooth.getAvailability().then(isAvailable => {
        if (isAvailable) {
            uiToggleDeviceConnected(false);
            callbackIfAvailable();
        } else {
            uiStatusError("Bluetooth not available", true);
            setTimeout(() => liffCheckAvailablityAndDo(callbackIfAvailable), 10000);
        }
    }).catch(error => {
        uiStatusError(makeErrorMsg(error), false);
    });;
}

LINE Things対応デバイスを探索する

liff.bluetooth.requestDevice()を使用して、LINE Things対応デバイスを探索し、Bluetoothオブジェクトを取得します。

function liffRequestDevice() {
    liff.bluetooth.requestDevice().then(device => {
        liffConnectToDevice(device);
    }).catch(error => {
        uiStatusError(makeErrorMsg(error), false);
    });
}

注:requestDevice()で探索できるのは、ユーザーが友だち追加したアカウント(チャネル)に関連付けられているプロダクトのLINE Things対応デバイスのみです。LINE Things Developer Trialでは、「Messaging APIのチャネルを友だち追加する」の手順に従って友だち追加してください。

注:LINE Things対応デバイスは、一定間隔でアドバタイズメントを行います。

注:liff.bluetooth.requestDevice()を短い間隔で実行すると、スマートフォンが停止する場合があります。

見つかったLINE Things対応デバイスのGATTサーバーに接続する

LINE Things対応デバイスのGATTサーバーに接続し、サービス探索用service UUIDを指定して、プライマリーサービスとcharacteristicを取得します。

USER_SERVICE_UUIDには、「トライアルプロダクトを作成する」で返されたサービス探索用service UUIDを指定します。

// User service UUID: Change this to your generated service UUID
const USER_SERVICE_UUID         = '91E4E176-D0B9-464D-9FE4-52EE3E9F1552'; // LED, Button
// User service characteristics
const LED_CHARACTERISTIC_UUID   = 'E9062E71-9E62-4BC6-B0D3-35CDCD9B027B';
const BTN_CHARACTERISTIC_UUID   = '62FBD229-6EDD-4D1A-B554-5C4E1BB29169';

// PSDI Service UUID: Fixed value for Developer Trial
const PSDI_SERVICE_UUID         = 'E625601E-9E55-4597-A598-76018A0D293D'; // Device ID

(Omitted)

function liffConnectToDevice(device) {
    device.gatt.connect().then(() => {
        document.getElementById("device-name").innerText = device.name;
        document.getElementById("device-id").innerText = device.id;

        // Show status connected
        uiToggleDeviceConnected(true);

        // Get service
        device.gatt.getPrimaryService(USER_SERVICE_UUID).then(service => {
            liffGetUserService(service);
        }).catch(error => {
            uiStatusError(makeErrorMsg(error), false);
        });
        device.gatt.getPrimaryService(PSDI_SERVICE_UUID).then(service => {
            liffGetPSDIService(service);
        }).catch(error => {
            uiStatusError(makeErrorMsg(error), false);
        });

        // Device disconnect callback
        const disconnectCallback = () => {
            // Show status disconnected
            uiToggleDeviceConnected(false);

            // Remove disconnect callback
            device.removeEventListener('gattserverdisconnected', disconnectCallback);

            // Reset LED state
            ledState = false;
            // Reset UI elements
            uiToggleLedButton(false);
            uiToggleStateButton(false);

            // Try to reconnect
            initializeLiff();
        };

        device.addEventListener('gattserverdisconnected', disconnectCallback);
    }).catch(error => {
        uiStatusError(makeErrorMsg(error), false);
    });
}

function liffGetUserService(service) {
    // Button pressed state
    service.getCharacteristic(BTN_CHARACTERISTIC_UUID).then(characteristic => {
        liffGetButtonStateCharacteristic(characteristic);
    }).catch(error => {
        uiStatusError(makeErrorMsg(error), false);
    });

    // Toggle LED
    service.getCharacteristic(LED_CHARACTERISTIC_UUID).then(characteristic => {
        window.ledCharacteristic = characteristic;

        // Switch off by default
        liffToggleDeviceLedState(false);
    }).catch(error => {
        uiStatusError(makeErrorMsg(error), false);
    });
}

LINE Things対応デバイスの情報を読み込む

GATTサーバーに接続できたら、LINE Things対応デバイスがcharacteristicに保持している値を読み込めます。

注:service UUIDとcharacteristic UUIDは、LINE Things対応デバイスや読み込む情報によって異なります。LINE Things対応デバイスにあわせて指定してください。

以下は、PSDIを読み込む場合の例です。

const PSDI_CHARACTERISTIC_UUID  = '26E2B12B-85F0-4F3F-9FDD-91D114270E6E';

(Omitted)

function liffGetPSDIService(service) {
    // Get PSDI value
    service.getCharacteristic(PSDI_CHARACTERISTIC_UUID).then(characteristic => {
        return characteristic.readValue();
    }).then(value => {
        // Byte array to hex string
        const psdi = new Uint8Array(value.buffer)
            .reduce((output, byte) => output + ("0" + byte.toString(16)).slice(-2), "");
        document.getElementById("device-psdi").innerText = psdi;
    }).catch(error => {
        uiStatusError(makeErrorMsg(error), false);
    });
}

LINE Things対応デバイスに情報を書き込む

読み込みと同様、GATTサーバーに接続できたら、characteristicに値を書き込めます。

function liffToggleDeviceLedState(state) {
    // on: 0x01
    // off: 0x00
    window.ledCharacteristic.writeValue(
        state ? new Uint8Array([0x01]) : new Uint8Array([0x00])
    ).catch(error => {
        uiStatusError(makeErrorMsg(error), false);
    });
}

LINE Things対応デバイスに通知を依頼する

GATTサーバーに接続できたら、LINE Things対応デバイスからの通知を受け取ることもできます。

function liffGetButtonStateCharacteristic(characteristic) {
    // Add notification hook for button state
    // (Get notified when button state changes)
    characteristic.startNotifications().then(() => {
        characteristic.addEventListener('characteristicvaluechanged', e => {
            const val = (new Uint8Array(e.target.value.buffer))[0];
            if (val > 0) {
                // press
                uiToggleStateButton(true);
            } else {
                // release
                uiToggleStateButton(false);
                uiCountPressButton();
            }
        });
    }).catch(error => {
        uiStatusError(makeErrorMsg(error), false);
    });
}

LINE Things対応デバイスからの通知を停止する

通知の必要がなくなったら、LINE Things対応デバイスからの通知を停止します。

// Remove disconnect callback
device.removeEventListener('gattserverdisconnected', disconnectCallback);

{{ $t("form.question.helpful") }}

{{ $t("form.question.detail") }}

{{ $t("form.question.improve") }}

{{ $t("form.info.start") }}{{ $t("form.info.link") }}{{ $t("form.info.end") }}


{{ $t("form.result.success") }}
{{ $t("form.result.error") }}
{{ $t("form.result.errorLink") }}