Momentoで構築する: IoTデバイスのステータス

Momento Cacheを使用して、IoTデバイスの最新データを保存、更新、追跡する方法をご紹介します。

モノのインターネット(IoT)は私たちの身の回りに溢れています。スマートウォッチ、防犯カメラ、ペットの自動給餌器など、日常的に使われている機器には小さなセンサーが内蔵されており、インターネットにデータを送信することで、私たちはよりつながりやすくなっています。

IoTデバイスは大量のデータをプッシュします。センサーの種類にもよるが、ウェブサービスは1秒に数回から1時間に1回まで、デバイス(モノとしても知られている)からデータを受け取ることができます。デバイスのステータスは、残りのセンサーデータと一緒に送られてくるか、受信したデータから推測されます。

デバイスの現在の状態は、データ・プッシュのたびに提供されます。ステータス履歴は通常保存されません。毎日何万ものメトリクスを受信している場合、ステータス履歴の保存は費用対効果の高いソリューションではないかもしれません。

これは、Momento Cacheにとって完璧なユースケースです。短期間で頻繁に変化する情報を、瞬時にリアルタイムで更新することができます。それでは、Momentoでデバイスのステータスを追跡する方法を具体的に確認するために、ビルドに飛び込んでみましょう。

デバイストラッカーの構築

デバイス・トラッカーを構築するには、まずIoTアプリに含まれるコンポーネントを理解する必要があります。完全なソリューションは3つの部分で構成されます:

デバイス・インターフェース: デバイス情報をウェブサービスに送信する、デバイスにインストールされたファームウェアまたはソフトウェアです。
ウェブサービス: デバイス・データを取り込み、分析し、意味のある値にフォーマットするバックエンド・コード。
ユーザー・ダッシュボード: エンド・ユーザーにフォーマットされたデータを提示するインターフェース。

この単純なサンプル・アプリケーションでは、シングル・テナント・アプリケーションを構築し、24時間受信した全デバイス・データのリストを管理します。また、キャッシュ内の特定のデバイスの現在のステータスを設定し、以前のステータスを上書きします。

// POST /devices/{deviceId}/data

const handler = async (event) => {
    await initializeCacheClient();

    const deviceId = event.pathParameters.deviceId;
    const input = JSON.parse(event.body);
    await Promise.all([
        await cacheClient.set('iot', deviceId, input.status),
        await cacheClient.setAddElement('iot', 'devices', deviceId, { ttl: new CollectionTtl(86400, true) })
    ]);

    return { statusCode: 204 };
}

一意のデバイスIDを追跡するために、コレクションデータ型を使用します。セットはユニークな要素の順序なしコレクションなので、特定のIDを持つデバイスを何度追加しても、それを見るのは一度だけです。deviceセットアイテムの生存時間は86400秒で、これは24時間です。

個々のデバイスのステータスを追跡するために、標準的なスカラーset操作を使って値を格納します。最新の値だけを追跡すればよいので、このデータ型は完璧な選択です。

データが入ってくると、デバイス・リストが更新され、デバイスのステータスが上書きされます。たった7行のコードにしては、なかなかです!

ダッシュボードでは、現在のデータを取得する必要があります。過去24時間にウェブサービスにプッシュしたデバイスのリストを表示し、クリックせずに現在のステータスを提供できるようにしたいのです。


// GET /devices

const handler = async (event) => {
    await initializeCacheClient();

    let devices = [];
    const deviceResponse = await cacheClient.setFetch('iot', 'devices');
    if (deviceResponse instanceof CacheSetFetch.Hit) {
        const deviceList = deviceResponse.valueArrayString();
        await Promise.all(deviceList.map(async (deviceId) => {
            const statusResponse = await cacheClient.get('iot', deviceId);
            if (statusResponse instanceof CacheGet.Hit) {
                devices.push({ name: deviceId, status: statusResponse.valueString() });
            } else {
                devices.push({ name: deviceId, status: 'unknown' })
            }
        }));
    }

    return {
        statusCode: 200,
        body: JSON.stringify(devices)
    };
}

リストと現在のステータスを取得するために、まずデバイス名を含むセットを取得します。次に、リスト内の各デバイスに対してgetコールを並行して実行します。

デバイスのステータスがキャッシュ・ヒットしたら、そのまま返します。しかし、キャッシュ・ミスがあった場合は、そのデバイスからしばらく連絡がなかったことを意味します。デバイスからデータがプッシュされるたびに、ステータスを保持するキャッシュアイテムのTTL(time to live)をリセットします。TTLは、デバイスから連絡があると予想される間隔の長さの3倍になるように設定されます。

例えば、IoTデバイスから3秒ごとに連絡があると予想される場合、ステータスを保持するキャッシュ・アイテムのTTLを9秒に設定します。そうすることで、もし1つか2つのデータ・プッシュが私たちのサービスに失敗した場合、データを失効させる前にいくらか猶予を持たせることができます。

もしアイテムの有効期限が切れ、ルックアップ時にキャッシュミスが発生した場合は、unknownステータスを返し、デバイスがオフになっているか、修理不可能なエリアにあると見なします。

ベストプラクティス

IoTデバイスのステータスを追跡する際には、以下のベストプラクティスを念頭に置いてください:

・デバイスのリストを保存するには、setを使用します。セットは自動的にエントリーの重複を削除します。これは、インジェストする大規模なデータセットで必要になります!
・デバイスのステータスやその他のシングルトン値をスカラー値として保存します。こうすることで、古い情報を現在の値で上書きすることができる。
・キャッシュアイテムの生存時間(TTL)を、デバイスの予想データ受信レートの3倍以上に設定する。こうすることで、デバイスにちょっとした不具合が発生したり、ネットワークが一時的に利用できなくなったりしても、寛大な対応ができるようになる。

準備はできましたか?

Momento Cacheは、IoTデバイスのデータに最適なユースケースです。高速かつ軽量で、デバイスからしばらく連絡がない場合は自動的にデータを失効させます。

私と同じようにワクワクしているのなら、そろそろ始めましょう!まずは Momento Console にアクセスして、無料の認証トークンを取得しましょう!完全なサンプルは GitHub のリポジトリを見てください。断片的なものから全体的なものまで、ご自由にお使いください!

ご質問、ご感想、コメント、懸念事項がおありですか?ぜひご連絡ください!Discordまたはウェブサイトからご連絡ください。