Observable を活用したIoTデータ可視化の探索からカスタムウィジェット開発までのチュートリアル


投稿日 / 投稿者名

2022.2.10 / アプリチーム

はじめに

本レポートは、Things Cloud の利用例をより知っていただくための実利用レポートとして作成したものです。
Things Cloud は極力後方互換性を持つよう開発されていますが、今後のリリースにより、一部画面やコマンド、手順などが変更となったり、利用できない可能性があることをあらかじめご了承ください。
なお、作成にあたり、以下バージョンを用いています。

難易度 ★★


所要時間(目安)

60分

概要

本レポートでは、ノートブック型 JavaScript 実行環境を提供するプラットフォーム Observable を活用したIoTデータ可視化の探索方法と、Observable 上で作成したアウトプット(グラフ、表など)を Things Cloud のカスタムウィジェットへ移行する方法を紹介します。

カスタムウィジェット開発には通常であればプログラミング経験や前提知識を要しますが、本レポートでは、カスタムウィジェットや Observable ノートブックのテンプレートを提供しています。Things Cloud 特有の前提知識が必要となる箇所を最小限にしているため、0からカスタムウィジェットを開発するよりも小さなコストで開発でき、IoT データ可視化の探索や試行錯誤に注力いただけます。

Observable の詳細な使い方については NTT Communications Engineer's Blog でもご紹介しています。是非ご覧ください。

前提条件

本レポートでは、通常のカスタムウィジェット開発で必要とされる、以下スキルについては極力不要となるように考慮されています。

完成イメージ

備考: 棒グラフはThings Cloudの標準ウィジェット機能では提供されておりません。 本記事では、ObservableのPlotライブラリを用い、簡単に作成しています。

開発の流れ

以下の流れで作業を進めます。

  1. ダウンロード、ローカルで確認
  2. データの前準備
  3. Observable側の準備
  4. カスタムウィジェットの準備
  5. ローカルで確認
  6. デプロイ

1. ダウンロード、ローカルで確認

作業の流れ

この章の操作をgifアニメーションにしています。クリックすると拡大して表示されます。

テンプレートzip をダウンロード

以下のファイルをダウンロードします。

zip ファイルを解凍し、適当なディレクトリに保存して下さい。ここがカスタムウィジェットプログラムを作成するディレクトリになります。

ファイル構成

以下の12ファイルが解凍されます。

└─cockpit-chart
        app.module.ts
        chart-template-config.component.ts
        chart-template.component.css
        chart-template.component.html
        chart-template.component.ts
        chart-template.service.ts
        index.ts
        ng1.ts
        package.json
        polyfills.ts
        preview-chart-template.ts
        tsconfig.json
ファイルについて

本記事では、以下2ファイルを編集します。

# ファイル名 説明
1 chart-template.component.ts Angularコンポーネント、chart-template-component ウィジェットを表すプログラムです。このファイルを編集します。
2 package.json npm で利用されるパッケージ定義ファイルです。

以下ファイルはビルドに必要なものですが、編集不要です。

# ファイル名 説明
1 app.module.ts Angularで利用されるコンポーネント構成を定義するプログラムです。
2 chart-template-config.component.ts Angularコンポーネントで、ウィジェットの config ダイアログを表すプログラムです。
3 chart-template.component.css chart-template-component のスタイルシート定義ファイルです。
4 chart-template.component.html chart-template-component の html テンプレートファイルです。
5 chart-template.service-ts chart-template-component から利用する関数を定義したプログラムです。
6 index.ts Angularで利用されるプログラムです。
7 ng1.ts Angularで利用されるプログラムです。
8 polyfills.ts Angular で利用されるプログラムです。
9 preview-chart-template.ts ウィジェットのプレビューイメージを定義するプログラムです。
10 tsconfig.json TypeScriptのコンパイルオプションを定義します。

ビルド

ダウンロードしたテンプレート zip にはサンプルのウィジェットが含まれていますので、正常に構築できるか試しましょう。

ビルド、実行には Node.js および c8ycli をインストールする必要があります。

Node.js のインストール

Node.js から Node.jsの最新版(v16.14以降)をインストールして下さい。

c8ycli

続いて、以下コマンドにより c8ycli コマンドをグローバルインストールして下さい。

$ npm install -g @c8y/cli

npm は Node.js に含まれるパッケージ管理ソフトです。

npm install

解凍ファイルを格納したディレクトリで、以下コマンドを実行します。

$ cd chart-cockpit
$ npm install

npm install では、関連パッケージをインターネットから自動的にダウンロードします。

数分~数十分程度時間がかかる場合があります。

  :
(省略)
  :
  :
npm WARN cockpit-chart@1.0.0 No description
npm WARN cockpit-chart@1.0.0 No repository field.

added 1785 packages from 813 contributors and audited 1792 packages in 314.714s

71 packages are looking for funding
  run `npm fund` for details

found 118 vulnerabilities (4 low, 74 moderate, 40 high)
  run `npm audit fix` to fix them, or `npm audit` for details

上記のようなメッセージが出れば完了です。

package.json の編集

package.jsonscriptsstartc8ycli server にすることで、npm run start コマンドで、localhostでの動作確認ができます。また、localhostへのリクエストを -u オプションによって指定した URL へプロキシするように指定できます。同じように scriptsbuilddeployc8ycli コマンドをあらかじめ設定することで、c8ycli コマンドを意識せず、npm run ...コマンドにより実行することができます。

{
  "name": "cockpit-chart",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "c8ycli server -u https://<テナント名>.je1.thingscloud.ntt.com",
    "build": "c8ycli build",
    "deploy": "c8ycli deploy"
  },
  "keywords": [],
  :
}

npm run start を実行した後、Webブラウザに以下のURL ( http://localhost:9000/apps/cockpit-chart/ ) を入力し、アクセスします。アクセス後、テナントID・ユーザ名・パスワードの入力が求められるためこれらを入力し、リクエストをプロキシしているテナントへログインします。ログイン後、アプリケーションの動作確認ができるようになります。

npm run start

次のコマンドを入力します。

$ npm run start

http://localhost:9000/apps/cockpit-chart/ 98 % - after emitting - angular-compiler

上記 % 表示が 100 になるまでお待ちください。

完了すると、以下表示となります。数分以上かかる場合があります。

http://localhost:9000/apps/cockpit-chart/ done - finished in 123 s - 237.738 ms

ブラウザから閲覧

Chrome, Firefox, Edge などのブラウザのアドレスバーに、http://localhost:9000/apps/cockpit-chart/ を入力し、テナントID、ユーザー、パスワードを入力して下さい。

テナントID は、あらかじめテナントにログインし、右上のユーザーボタンで確認しておいて下さい。

詳細は、ユーザーオプションと設定 に記載があります。

ログイン後、コックピットアプリケーションの「ホーム」で右上の「ウィジェットを追加」をクリックして下さい。以下のように、「ChartTemplate Widget」が選択できるようになっていれば、build は成功です。

2. データの前準備

作業の流れ

この章の操作をgifアニメーションにしています。クリックすると拡大して表示されます。

ここでは、グラフへ出力させるためのデータを準備します。今回は説明のために、Things Cloudの機能であるシミュレータを利用します。
また、お手持ちのIoTセンサーやデータがあればそちらもご利用可能です。

シミュレータの準備

今回はシミュレータ機能でデフォルトで用意されている温度シミュレータを利用します。シミュレータを追加する手順は以下となります。

  1. Things Cloudのデバイス管理画面を開き、シミュレータ -> シミュレータを追加 をクリック
  2. プリセット 温度計測 を選択し、作成 をクリック
  3. 作成した温度シミュレータを 実行中 へ変更 (データが生成されるまで少し時間がかかります)

以上でシミュレータの準備は完了となります。シミュレータについて、詳しくはこちらをご覧ください。

3. Observable側の準備

作業の流れ

この章の操作をgifアニメーションにしています。クリックすると拡大して表示されます。

ここでは、カスタムウィジェットでグラフを作成する前に、Observable Notebook上でグラフを作成する手順をご紹介します。 まずはObservablehqへログインし、Things Cloud Chart Template Widgetへアクセスします。

備考: こちらのNotebookをカスタマイズされたい場合は、ご自身のアカウントでこのNotebookをforkします。forkの方法は以下となります。

  1. Things Cloud Chart Template Widgetを開く
  2. 右上の3点ボタンから Fork をクリック

Observable Notebookについて

Things Cloud Chart Template Widget の解説をします。

まず、以下ではChartTemplateServiceクラスをimportしています。
別の Observable Notebook からimportしており、詳細は割愛させていただきますが、Things Cloudから各種データを取得するNotebookとなっております。 Service Import

データの取得

以下では、importした ChartTemplateService を用いて、Things Cloudからデータを取得しています。
データを取得する際に必要なデータは、デバイス/グループの ManagedObject ID及び取得するデータのフィルター条件となるので、それらを引数として、データを取得するメソッドを呼び出しております。
今回は温度シミュレータのMeasurementデータを取得するので、Measurementフィルターを設定し、chartTemplateServicegetMeasurementsArray メソッドを呼び出し変数へ格納します。

ManagedObject IDの取得方法

対象のManagedObject ID取得方法は以下となります。

グループの場合

  1. コックピット画面へログインし、対象のグループをクリックします。
  2. urlの {{tenantUrl}/apps/cockpit/index.html#/group/{{groupid}} の {{groupid}} 部分がManagedObject IDとなります。

デバイスの場合

  1. コックピット画面へログインし、対象のデバイスをクリックします。
  2. urlの {{tenantUrl}/apps/cockpit/index.html#/device/{{deviceid}} の {{deviceid}} 部分がManagedObject IDとなります。

Managed Object ID及びフィルター条件は適宜変更下さい。

Observableでのデータ取得

注意 Measurement, Alarm, Event データの time プロパティは Date 型で格納され、Observable では UTC 時刻として取り扱われます。必要に応じて時刻をずらす変換を行ってください。

グラフの表示

以下では、取得したデータからグラフを表示しています。
温度シミュレータのデータ(Measurement)を取得し、温度範囲ごとのカウント数をヒストグラムとして表示させています。
Observableで独自に実装されているPlotというメソッドを使用し、グラフを作成できます。
Observable Plotに関し、詳細は こちら をご覧ください。

Observable Plot

テナント情報

Observable上でのThings Cloudからのデータ取得は、データ取得のためのテナント情報が必要となります。
テナント情報入力欄で以下を入力ししばらく待機すると、グラフが表示されます。

4. カスタムウィジェットの準備

作業の流れ

この章の操作をgifアニメーションにしています。クリックすると拡大して表示されます。

グラフの表示

Observableのノートブックで表示したいグラフが描けたら、セルのJavaScriptコードをコピーして、カスタムウィジェットのコンポーネント cockpit-chart/chart-template.component.tscreatePlot 関数 に貼り付けます。

コピー&ペーストする時は、以下にご注意ください。

:
@Component({
  selector: "chart-template",
  templateUrl: "./chart-template.component.html",
  styleUrls: ["./chart-template.component.css"],
})
export class ChartTemplate implements OnInit {
  :
  /**
   * Observable Plot ライブラリを使いグラフを描画する
   * 
   * Observable 上でデータ可視化を試行錯誤し、その結果を以下に貼り付ける。貼り付け時の注意点は以下の通り
   * - データの変数(measurements, events, alarms, devices)に this を追加する
   * - 以下はカスタムウィジェットでの表示に必要なため、残しておく
   *    - const plot = 
   *    - return plot;
   * 
   * @returns グラフ描画用のsvg要素
   * 
   */
  createPlot(): any {
    // 以下に Observable で作成したグラフ描画部分を追記してください
    const plot = Plot.plot({
      marks: [
        Plot.rectY(this.measurements, Plot.binX({y: "count"}, {x: "c8y_Temperature_T_value", fill: "source_id"}))
      ]
    });

    return plot;
  }
}

データの取得

Things Cloud のデータは、chart-template.service.tsChartTemplateService クラスで、@c8y/client を使い、取得しています。このクラスでは、グラフに表示したいデータをフィルタリング情報をもとに取得し、またグラフに読み込ませやすいデータにクレンジングしています。

カスタムウィジェットのコンポーネント cockpit-chart/chart-template.component.tsChartTemplateService クラスを利用できるように設定し、get{Measurements or Alarms or Events}Array メソッドからグラフに表示するデータを取得しています。メジャーメント、アラーム、イベントのデータを取得できますので、ご活用ください。

:
@Component({
  selector: "chart-template",
  templateUrl: "./chart-template.component.html",
  styleUrls: ["./chart-template.component.css"],
})
export class ChartTemplate implements OnInit {
  :
  ngOnInit(): void {
    (async () => {
      // Measurements データ取得
      const measurementsFilter = ({
        fragmentType: 'c8y_Temperature',
        dateFrom: new Date("2022-01-01"),
        dateTo: new Date("2030-01-01"),
        pageSize: ChartTemplate.PAGE_SIZE,
      });
      this.measurements = await this.chartTemplateService.getMeasurementsArray(this.config.device.id, measurementsFilter);

      // Alarms データ取得
      const alarmsFilter = ({
        type: '',
        dateFrom: new Date("2022-01-01"),
        dateTo: new Date("2030-01-01"),
        pageSize: ChartTemplate.PAGE_SIZE,
      });
      this.alarms = await this.chartTemplateService.getAlarmsArray(this.config.device.id, alarmsFilter);
    
      // Events データ取得
      const eventsFilter = ({
        fragmentType: '',
        dateFrom: new Date("2022-01-01"),
        dateTo: new Date("2030-01-01"),
        pageSize: ChartTemplate.PAGE_SIZE,
      });
      this.events = await this.chartTemplateService.getEventsArray(this.config.device.id, eventsFilter);
      
      // グラフを表示
      this.chart.nativeElement.appendChild(this.createPlot()); 

    })();
  }
  :
}
対象のアセット もしくは デバイス

this.config.device.id には、カスタムウィジェットの構成画面で選択したデバイス、またはアセット(グループ)のIDが 設定されますので、変更する必要はありません。

filterに指定できるパラメータ
パラメータ
指定例 説明 Measurement Alarm Event
dateFrom dateFrom: “2022-02-01T00:00:00+09:00” データを取得する開始日時を指定します
dateTo dateTo: “2022-02-06T00:00:00+09:00” データを取得する終了日時を指定します
pageSize pageSize: 50 データを一度に取得する数を指定します
withTotalPages withTotalPages: true withTotalPages: true を指定すると、currentPage 指定ができます
currentPage currentPage: 1 withTotalPages: true を指定した場合に、取得するページの位置を指定できます
type type: “c8y_UnavailabilityAlarm” 取得するデータのタイプ名を指定します
valueFragmentType valueFragmentType: “c8y_Temperature” メジャーメントの値を格納しているフラグメントタイプを指定します - -
valueFragmentSeries valueFragmentSeries: “T” valueFragmentType と合わせて、取得するフラグメントシリーズ名を指定します - -
fragmentType fragmentType: “com_TestMeasurement” 取得するデータのフラグメントタイプ名を指定します -
status status: “ACTIVE” 取得するアラームのステータスを指定します。“ACKNOWLEDGED”, “CLEARED”, “ACTIVE” を指定可能です - -
severity severity: “CRITICAL” 取得するアラームの重大度を指定します。“CRITICAL”, “MAJOR”, “MINOR”, “WARNING” を指定可能です - -
resolved resolved: true true を指定した場合、“CLEARED” ステータスのもののみが対象となり、false を指定した場合、“ACTIVE”/“ACKNOWLEDGED” のものが対象となります。 - -

5. ローカル環境での動作確認

作業の流れ

この章の操作をgifアニメーションにしています。クリックすると拡大して表示されます。

package.json の編集がされていることを確認下さい。

ダッシュボードで、ウィジェットの追加から「ChartTemplate Widget」を選択した後、保存します。以下のようなウィジェットが作成されれば成功です。すでにウィジェットを追加済みの場合は、ブラウザをリロードします。

この時点ではプロキシしているテナントで修正中のカスタムウィジェットを確認することはできません。デプロイ後に、プロキシしているテナントでもカスタムウィジェットを確認することができます。

6. Things Cloud へのデプロイ

作業の流れ

この章の操作をgifアニメーションにしています。クリックすると拡大して表示されます。

ローカル環境での動作が正常であることを確認したら、Things Cloud へデプロイします。アプリケーションのルートディレクトリ (cockpit-chart/ 直下) に移動し、以下のコマンドを実行します。

$ npm run build
$ npm run deploy
prompt: Instance URL:  (http://demos.cumulocity.com) テナントのURLを入力 (例: https://<テナント名>.je1.thingscloud.ntt.com)
prompt: Username:  (admin) ユーザ名を入力
prompt: Password: パスワードを入力

npm run build コマンドを実行し、アプリケーションをビルドします。ビルド後、アプリケーションのディレクトリに dist/ ディレクトリが作成されます。このディレクトリが作成されたことを確認したら、npm run deploy コマンドで Things Cloud へアプリケーションをデプロイします。デプロイコマンド実行時に、アプリケーションのデプロイ先 URL とユーザ情報の入力が必要になります。

参考

以下に本レポートを実施する上で参考となる Web サイトへのURLを記載します。