Web SDK for Angular を利用したカスタムウィジェットの作り方1

投稿日/更新日/投稿者名

2020.7.31 / 2020.10.27 / 川戸美輝

2025.1.30 / 吉冨寿一郎

はじめに

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

  • ver 1018.0.259 (frontend)
  • ver 1018.0.405 (backend)

また、本レポートで使用している 「Web SDK for Angular」 は、「AngularJS のための Web SDK」とは異なります。以下の2点が大きな違いです。

  • 使用フレームワークのバージョンが AngularJS v1.x から Angular へアップデート
  • CLI (コマンドラインインタフェース) が c8y (cumulocity-tools) から c8ycli (@c8y/cli) へ変更



難易度 ★★


概要

Web SDK for Angular を利用して、デフォルトで提供しているウィジェット以外に自らウィジェットを開発する手法について、サンプルとして開発した「View Widget」を用いて説明します。

Web SDK for Angular を利用したアプリケーション開発における基本的な部分は、カスタムアプリケーションの作り方と重複した内容もございますので、こちらも合わせて読む事で一層理解が深まると考えられます。

本レポートで紹介するカスタムウィジェットの作り方は2つのページから構成されており、それぞれの内容は下記の通りです。

  • 本レポートの紹介内容
    • Angular版 カスタムウィジェットの作り方1 :静的な情報のみを表示するウィジェット「View Widget」の開発(本ページ)
    • Angular版 カスタムウィジェットの作り方2 :1で作成したウィジェットに「デバイスから取得したデータを表示」する機能を追加

  • 本ページで学べること
    • Web SDK for Angular を使ったカスタムウィジェットの開発方法
    • ローカル開発環境での動作確認の仕方、Things Cloud へのデプロイ方法



前提条件

  • 次の言語/フレームワークを扱えること
    • HTML5
    • CSS
    • TypeScript
    • Angular v14.0.0以上推奨
  • 開発環境に以下をインストールしていること
    • Node.js v18推奨
    • npm (Node.js と一緒にインストールされます)
    • @c8y/cli パッケージ (c8ycli コマンドの使用に必要です)



所要時間(目安)

  • 約30分(本レポートに記載されたコードをそのまま利用する場合)



つくるもの

今回は、シンプルなウィジェット「View Widget」の作成を通して、カスタムウィジェット開発の基礎を学びます。



【完成イメージ】

image
ウィジェット作成画面に「View Widget」が表示されます。

image
「View Widget」を選択し、メッセージを設定します。

image
このようにウィジェットとして表示されます。

なお、本レポート完了時にできあがる成果物は こちら からダウンロードできます。
node_modules/ は上記のファイル一式に含まれていないため、npm install コマンドでインストールする必要があります。



開発の流れ

  1. 開発用ディレクトリの作成
  2. コンポーネントファイルの作成
  3. app.module.ts の編集
  4. ローカル環境での動作確認
  5. Things Cloud へのデプロイ
  6. 実環境での動作確認



ウィジェット開発の準備

開発用ディレクトリの作成

開発用のディレクトリを以下のコマンドで作成し、作成したディレクトリへ移動します。

# CLI をインストール
$ npm install -g @c8y/cli

# アプリケーションディレクトリの作成
$ c8ycli new 
# 任意のアプリケーション名を設定
? Enter the name of the project:  my-cockpit
? Which base version do you want to scaffold from? other
# Things Cloudのfrontendバージョンを設定
# 確認方法: Things Cloudへログイン > 右上のユーザアイコンをクリック > プラットフォーム情報
? Enter the desired version:  1018.0.259 
? Which base project do you want to scaffold from? cockpit

Applications downloaded.
Files copied.
npm initialized.
package.json updated.
Application created. Go into the folder "my-cockpit" and run npm install

$ cd my-cockpit

package.json に記載されているライブラリを以下のコマンドでインストールします。

$ npm install

上記の操作を実行すると、以下のような構成でディレクトリが作成されます。

<<root folder>>
	|
	└── my-cockpit
            ├── app.module.spec.ts
            ├── app.module.ts
            ├── i18n.ts
            ├── index.ts
            ├── jest.config.js
            ├── ng1.ts
            ├── node_modules
            ├── package-lock.json
            ├── package.json
            ├── polyfills.ts
            ├── setup-jest.js
            ├── tsconfig.json
            └── tsconfig.spec.json

package.jsonに記載されているデフォルトのUIバージョンと、使用しているbackendバージョンが異なる場合があります。 その場合、実行時のコンソールに「You are running version 1006.0.9 of the UI and version 1005.0.16 of backend!」のようなメッセージが表示されますが、本レポートで作成するアプリケーションの動作範囲内であれば問題ありません。

ウィジェットの開発

1.コンポーネントの作成

ウィジェットは大きく、以下の2つの要素から構成されます。

  • ウィジェット (Widget):ダッシュボードに追加された時に表示されるコンポーネント(view-widget.component.ts
  • 設定 (Configuration):ユーザダッシュボードにウィジェットを追加する際に表示されるコンポーネント(view-widget-config.component.ts

したがって、先程作成した開発用ディレクトリに2つのコンポーネントファイルを作成する必要があります。

はじめに、view-widget.component.ts を作成し、以下のように編集します。

import { Component, Input } from '@angular/core';

@Component({
	selector: 'c8y-custom-widget',
	template: `<p class="text">{{config?.text || 'No text'}}</p>`
})

export class WidgetDemo {
	@Input() config;
}

このコンポーネントは、config に設定された文字列を表示するという機能のみを持っています。

続いて、view-widget-config.component.ts を作成し、以下のように編集します。

import { Component, Input } from '@angular/core';

@Component({
	selector: "custom-widget-config",
	template: `<div class="form-group">
		<c8y-form-group>
			<label translate>Text</label>
			<textarea style="width:100%" [(ngModel)]="config.text"></textarea>
		</c8y-form-group>
	</div>`
})

export class WidgetConfigDemo {
	@Input() config: any = {};
}

このコンポーネントで、実際にテキスト入力を受けつけます。 config オブジェクトを追加することで、ウィジェット作成時に設定したメッセージが、config を介して作成したウィジェットへ反映されるようになります。



2.アプリケーションにウィジェットを追加

カスタムコックピットにウィジェットを追加するため、hookComponent を使用し entryComponent として作成したコンポーネントを定義します。 そのため、app.module.ts を以下のように編集します。 主な変更点は、1.hookComponentの追加import 2.Widgetコンポーネントのインポート 3.entryComponents定義の追加 です。 app.module.tsの内容を、以下に示されているコードに変更してください。

import { NgModule } from '@angular/core';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { RouterModule as NgRouterModule } from '@angular/router';
import { UpgradeModule as NgUpgradeModule } from '@angular/upgrade/static';
import { CoreModule, RouterModule, hookComponent } from '@c8y/ngx-components'; //hookComponent追加
import {
  DashboardUpgradeModule,
  UpgradeModule,
  HybridAppModule,
  UPGRADE_ROUTES
} from '@c8y/ngx-components/upgrade';
import { SubAssetsModule } from '@c8y/ngx-components/sub-assets';
import { ChildDevicesModule } from '@c8y/ngx-components/child-devices';
import {
  CockpitDashboardModule,
  ReportDashboardModule
} from '@c8y/ngx-components/context-dashboard';
import { ReportsModule } from '@c8y/ngx-components/reports';
import { SensorPhoneModule } from '@c8y/ngx-components/sensor-phone';
import { BinaryFileDownloadModule } from '@c8y/ngx-components/binary-file-download';
import { SearchModule } from '@c8y/ngx-components/search';
import { AssetsNavigatorModule } from '@c8y/ngx-components/assets-navigator';
import { CockpitConfigModule } from '@c8y/ngx-components/cockpit-config';
import { DatapointLibraryModule } from '@c8y/ngx-components/datapoint-library';
import { cockpitWidgets } from '@c8y/ngx-components/widgets/cockpit';
import { PluginSetupStepperModule } from '@c8y/ngx-components/ecosystem/plugin-setup-stepper';
import { ContextDashboardModule } from '@c8y/ngx-components/context-dashboard';
//Widgetコンポーネントをインポート
import { WidgetDemo } from './view-widget.component';
import { WidgetConfigDemo } from './view-widget-config.component';

@NgModule({
  imports: [
    BrowserAnimationsModule,
    RouterModule.forRoot(),
    NgRouterModule.forRoot([...UPGRADE_ROUTES], { enableTracing: false, useHash: true }),
    CoreModule.forRoot(),
    ReportsModule,
    NgUpgradeModule,
    AssetsNavigatorModule,
    DashboardUpgradeModule,
    CockpitDashboardModule,
    SensorPhoneModule,
    ReportDashboardModule,
    BinaryFileDownloadModule,
    SearchModule,
    SubAssetsModule.config(),
    ChildDevicesModule,
    CockpitConfigModule,
    DatapointLibraryModule.forRoot(),
    cockpitWidgets(),
    PluginSetupStepperModule,
    ContextDashboardModule,
    // Upgrade module must be the last
    UpgradeModule
  ],
  declarations: [WidgetDemo, WidgetConfigDemo],	
  entryComponents: [WidgetDemo, WidgetConfigDemo], //エントリーコンポーネントとして定義
  providers: [
    hookComponent({
      id: 'hoge.view.widget', //一意なIDを設定
      label: 'View Widget',
      description: 'Can display a demo',
      component: WidgetDemo, //コンポーネントを関連付け
      configComponent: WidgetConfigDemo,
      //デバイス選択画面の非表示オプション(デバイスの情報が不要なため、任意で追加)
      data: {
        ng1: {
          options: {
            noDeviceTarget: true
          }
        }
      }
    })
  ]
})
export class AppModule extends HybridAppModule {
  constructor(protected upgrade: NgUpgradeModule) {
    super();
  }
}



3.ウィジェットに表示するテキストの見た目を変更する

ここまでの作業で、既にカスタムウィジェットの動作に必要な部分は完成しています。 本項では、おまけとしてウィジェットに表示するテキストの見た目を変更する手法を紹介します。

ウィジェットに表示するテキストの見た目は、CSSを介して簡単に変更する事ができます。 以下のように、view-widget.component.ts内のstylesで設定します。 今回は最もシンプルな例として、文字サイズの変更と文字色の変更を行います。

@Component({
	selector: 'c8y-custom-widget',
	template: `<p class="text" >{{config?.text || 'No text'}}</p>`,
	styles: [ `p{ font-size: 30px; color: red }` ]
})



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

以下のコマンドにより、ローカルホストでの動作確認ができます。以下では、ローカルホストへのリクエストを -u オプションで指定した URL へプロキシしています。

$ c8ycli server -u https://<テナント名>.je1.thingscloud.ntt.com

もしくは、package.json"scripts""start" の項目の c8ycli server 以降に -u https://<テナント名>.je1.thingscloud.ntt.com を追加することでリクエストを指定 URL へプロキシできるようになります。(この場合は、npm start コマンドを使用します。)


c8ycli server -u https://<テナント名>.je1.thingscloud.ntt.com もしくは、npm start を実行した後、出力されたURL ( http://localhost:9000/apps/my-cockpit/ ) をwebブラウザに入力し、アクセスします。アクセス後、以下の画面でテナントID・ユーザ名・パスワードを入力し、テナントへログインします。ログイン後、アプリケーションの動作確認ができるようになります。

ここで、テナントIDとはt<number>の形で定義される固有の識別子を指します。テナントIDの確認方法は、基本的には以下の3種類です。

  • テナントへログインし、右上のユーザアイコンをクリックして、プラットフォーム情報から確認する
  • APIを使用してテナント情報を取得する(参考ページ
  • 親テナントの管理アプリケーションにログインし、サブテナントメニューから確認する

image

ログインに成功したら、画面左のメニューから任意のグループを選択し、ダッシュボードを追加します。 追加されたダッシュボードにウィジェットを追加し、View Widgetを選択します。 表示したいメッセージを入力して保存することで、ダッシュボード上に作成したウィジェットが表示されます。


【動作例】

image

CSSを記述しない場合、ウィジェットには以下のようにプレーンなテキストが表示されます。

image

ダッシュボードを追加メニューが表示されない場合、次の手順に従って一度Things Cloudにデプロイすることで、ローカル環境でも正常に動作する場合があります。



Things Cloud へのデプロイ

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

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

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

最後に、デプロイしたアプリケーションにアクセスし、ブランドロゴ等が正常に表示されている事を確認します。

image

さいごに

本レポートでは、Things Cloud の既存コックピットとは異なるコックピット (my-cockpit) を作成し、my-cockpit上にカスタムウィジェットをデプロイしました。そのため、既存のコックピットからは今回作成したカスタムウィジェットの動作は確認できません。実際に既存のコックピットで動作するカスタムウィジェットを開発する場合は、既存のコックピットに対してデプロイを行ってください。 ただし、既存のコックピットに対してデプロイを行う場合、別途開発者が設定しない限り、Branding UI のバージョンも同時に変更されますのでご注意ください。


Web SDK for Angular を利用する上では、以下のWebサイトが参考になります。 ※ Cumulocity社の Web サイトが含まれます。