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

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

2020.7.31 / 2020.10.27 / 川戸美輝



はじめに

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

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



難易度 ★★


概要

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

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

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




前提条件



所要時間(目安)



つくるもの

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



【完成イメージ】

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

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

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

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



開発の流れ

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



ウィジェット開発の準備

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

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

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

# アプリケーションディレクトリの作成
$ c8ycli new my-cockpit cockpit
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.ts
			├── index.ts
			├── ng1.ts
			├── package.json
			├── package-lock.json
			├── polyfills.ts
			├── tsconfig.json
			└── node_modules
					├── ・・・
					:

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

ブランディングの設定

本レポートでは、カスタムウィジェットを動作させるためのアプリケーションを新規作成します。 新規作成したアプリケーションは、ブランドロゴや配色が Cumulocity IoT のデフォルトのものになるため、 package.jsonを編集し、アプリケーションのブランドロゴ等を変更します。 本行程は、カスタムウィジェットの動作には関係せず、カスタムウィジェットの作成方法を学ぶ上で必須ではありません。
不要な方は次のウィジェットの開発までお進み下さい。

また、ブランドロゴ変更の詳細はロゴや配色を変更する方法をご確認下さい。

以下ブランディングの設定手順

まず、こちらからui-assets.zipをダウンロードします。 その後、次の図の通り、作業テナントの管理アプリケーションアプリケーションタブからファイルをアップロードします。

image

続いて、package.jsonにおける、"c8y":の内容を以下の通り変更します。
これにより、アプリケーションの配色がbrandingCssVarsにて指定した値に変更され、ブランドロゴ等は先ほどテナントにアップロードしたui-assetの情報を基に変更されます。

"c8y": {
	"application": {
		"name": "my-cockpit",
		"contextPath": "my-cockpit",
		"key": "my-cockpit-application-key",
		"tabsHorizontal": true,
		"upgrade": true,
		"rightDrawer": true,
		"sensorAppOneLink": "http://onelink.to/pca6qe",
		"contentSecurityPolicy": "base-uri 'none'; default-src 'self' 'unsafe-inline' http: https: ws: wss:; connect-src 'self' *.billwerk.com http: https: ws: wss:;  script-src 'self' open.mapquestapi.com *.twitter.com *.twimg.com 'unsafe-inline' 'unsafe-eval' data:; style-src * 'unsafe-inline' blob:; img-src * data:; font-src * data:; frame-src *;",
		"brandingCssVars": {
			"brand-primary": "#1357ad",
			"brand-complementary": "#a4c8cd",
			"brand-dark": "#0e407f",
			"brand-light": "#94aac5",
			"gray-text": "#444",
			"link-color": "#1357ad",
			"link-hover-color": "#0b3468",
			"body-background-color": "#f8f8f8",
			"brand-logo-img": "url(/apps/public/ui-assets-ntt/logo.svg?nocache=8324918234)",
			"brand-logo-img-height": "25%",
			"navigator-platform-logo": "url(/apps/public/ui-assets-ntt/tenant-logo.svg?nocache=8324918234)",
			"navigator-platform-logo-height": "23%",
			"navigator-font-family": "'Frutiger Neue', 'Helvetica Neue', Helvetica, Arial, sans-serif",
			"navigator-app-name-size": "16px",
			"navigator-app-icon-size": "0",
			"navigator-bg-color": "#1357ad",
			"navigator-header-bg": "white",
			"navigator-title-color": "#1357ad",
			"navigator-text-color": "rgba(255, 255, 255, 0.7)",
			"navigator-separator-color": "rgba(255, 255, 255, 0.05)",
			"navigator-active-color": "white",
			"navigator-active-bg": "#104993",
			"header-color": "white",
			"header-text-color": "#1357ad",
			"header-hover-color": "var(--brand-primary, #1357ad)",
			"header-border-color": "rgba(117, 117, 117, 0.05)",
			"font-family-base": "'Frutiger Neue', 'Helvetica Neue', Helvetica, Arial, sans-serif",
			"headings-font-family": "'Frutiger Neue', 'Helvetica Neue', Helvetica, Arial, sans-serif"
		},
		"extraCssUrls": ["/apps/public/ui-assets-ntt/style.css"],
		"faviconUrl": "/apps/public/ui-assets-ntt/favicon.ico?nocache=08563753891373449",
		"globalTitle": "NTT",
		"docsBaseUrl": "https://developer.ntt.com/iot/docs",
		"sensorPhone": false,
		"supportUrl": "https://casemanager.servicenow.ntt.com/tc",
		"languages": {
			"ja_JP": {
				"name": "Japanese",
				"nativeName": "日本語",
				"url": "/apps/public/ui-assets/ja_JP.json"
			}
		}
	},
	"cli": {}
}

今回使用した配色の設定は、ロゴや配色を変更する方法で紹介する、 public-optionsに含まれるoptions.jsonの内容を使用しています。さらに詳しい情報は こちら をご参照ください。



ウィジェットの開発

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

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

したがって、先程作成した開発用ディレクトリに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.アプリケーションにウィジェットを追加

カスタムコックピットにウィジェットを追加するため、COMPONENT_KOOK を使用し entryComponent として作成したコンポーネントを定義します。 そのため、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, HOOK_COMPONENT } from '@c8y/ngx-components';	//HOOK_COMPONENT追加

import { UpgradeModule, HybridAppModule, UPGRADE_ROUTES } from '@c8y/ngx-components/upgrade';
import { AssetsNavigatorModule } from '@c8y/ngx-components/assets-navigator';
import { ReportsModule } from '@c8y/ngx-components/reports';
import { ContextDashboardModule } from '@c8y/ngx-components/context-dashboard';

//ウィジェットコンポーネントをインポート
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(),
		AssetsNavigatorModule,
		ReportsModule,
		NgUpgradeModule,
		ContextDashboardModule,
		// Upgrade module must be the last
		UpgradeModule
	],
	
	//追加
	declarations: [WidgetDemo, WidgetConfigDemo],	
	entryComponents: [WidgetDemo, WidgetConfigDemo], //エントリーコンポーネントとして定義
	providers: [{
		provide: HOOK_COMPONENT,		//HOOK_COMPONENTと共にマルチプロバイダーフックを追加
		multi: true,
		useValue: {
			id: 'kawato.view.widget', //一意なIDを設定
			label: 'View Widget',
			description: 'Can display a text',
			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 コマンドを使用します。)

ローカルで動作確認を行う場合、ブランディングの設定にてアップロードしたui-assetsへアクセスできないため、 ブランドロゴ等は表示されないことに注意してください。 ここでは、作成したウィジェットが正常に動作することのみを確認します。


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

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

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サイトが参考になります。 ※ ソフトウェア・エー・ジー株式会社の Web サイトです。