Web SDK for Angular を利用したカスタムアプリケーションの作り方
投稿日/投稿者名
2019.10.7 / 高橋桃花
はじめに
本レポートは、Things Cloud の利用例をより知っていただくための実利用レポートとして作成したものです。Things Cloud は極力後方互換性を持つよう開発されていますが、今後のリリースにより、一部画面やコマンド、手順などが変更となったり、利用できない可能性があることをあらかじめご了承ください。 なお、作成にあたり、以下バージョンを用いています。
- ver 9.16.16 (backend)
また、本レポートで使用している 「Web SDK for Angular」 は、「AngularJS のための Web SDK」とは異なります。以下の2点が大きな違いです。
- 使用フレームワークのバージョンが AngularJS v1.x から Angular へアップデート
- CLI (コマンドラインインタフェース) が
c8y
(cumulocity-tools) からc8ycli
(@c8y/cli) へ変更
難易度 ★★★
概要
- Web SDK for Angular を利用して、アプリメニューに追加できるカスタムアプリケーションを作成します。このカスタムアプリケーションへ、 Things Cloud API から ManagedObject の一覧情報を取得し、デバイス一覧と各デバイスの位置情報を表示する機能を追加します。
- 本レポートで学べること
- Web SDK for Angular を使ったカスタムアプリケーションの開発方法
@c8y/client
ライブラリを用いて Things Cloud API からリアルタイムにデータを取得する方法- ローカル開発環境での動作確認の仕方、Things Cloud へのデプロイ方法
前提条件
- 次の言語/フレームワークを扱えること
- HTML5
- CSS
- TypeScript
- Angular v6.0.0以上推奨
- 開発環境に以下をインストールしていること
- Node.js (v10.16.3以上推奨)
- npm (Node.js と一緒にインストールされます)
- @c8y/cli パッケージ (
c8ycli
コマンドの使用に必要です)
- 位置情報を取得するため、以下のどちらかを満たしていること
- Things Cloud に接続済みの位置情報が取得できるデバイスがある
- Things Cloud で位置情報シミュレータを利用している
なお、本レポートでは手軽に扱える位置情報シミュレータを利用します。
【参考】シミュレータを利用する方法
シミュレータを利用する方法は、以下をご覧ください。(プリセット
で位置情報の更新イベントを選択)
シミュレータは通常のデバイスと同様課金対象となりますのでご了承ください。本レポート実施後、不要なシミュレータは削除してください。
シミュレータの利用には、シミュレータを操作する権限が必要になります。権限追加操作には admins 権限が必要なため、権限が無い場合は Things Cloud のシステム管理者に依頼してください。
権限の追加方法は以下のとおりです。
- 「管理」>「アカウント」>「ロール」>「デバイス管理ユーザ」で「シミュレータ」の項目にチェックを入れ、保存をクリック
- 「管理」>「アカウント」>「ユーザ」で自身のアカウントのグローバルロールに「デバイス管理ユーザ」を追加し、適用をクリック
所要時間(目安)
- 約30分(本レポートに記載されたコードをそのまま利用する場合)
つくるもの
Web SDK for Angular を利用して、アプリメニューに追加できるカスタムアプリケーションを作成します。このカスタムアプリケーションへ、 Things Cloud API から ManagedObject の一覧情報を取得し、デバイス一覧と各デバイスの位置情報を表示する機能を追加します。
【完成イメージ】
アプリメニューで作成したアプリケーションを選択できるようになります。
アプリケーションの画面では、テナントから取得したデバイス一覧と、デバイスの現在値が表示されます。これらの値はリアルタイムに更新されます。
なお、本レポート完了時にできあがる成果物は こちら からダウンロードできます。
※ node_modules/
は上記のファイル一式に含まれていないため、npm install
コマンドでインストールする必要があります。
開発の流れ
- アプリケーション用ディレクトリ作成
- コンポーネントファイルの編集
- app.module.ts の編集
- ビューファイルの編集
- ローカル開発環境での動作確認
- Things Cloud へのデプロイ
- 位置情報シミュレータを作成して動作を確認してみましょう
1. アプリケーション開発の準備
- アプリケーション開発用のディレクトリを以下のコマンドで作成し、作成したディレクトリへ移動します。
# CLI をインストール
$ npm install -g @c8y/cli
# アプリケーションディレクトリの作成
$ c8ycli new my-app
Application created. Go into the folder "my-app" and run npm install
$ cd my-app
- package.json に記載されているライブラリを以下のコマンドでインストールします。
$ npm install
package.json に記載されているデフォルトの UI バージョンは 1000.6.14 (本レポート執筆当時) です。UI と backend のバージョンが異なるため、コンソール画面には「You are running version 1004.6.14 of the UI and version 9.16.16 of backend!」という文字列が表示されますが、本レポートで作成するアプリケーションの動作の範囲内であれば問題ありません。
2. コンポーネントの作成・編集
- 以下のような構成になるように、コンポーネントのファイル群を作成します。ここでは、デバイス一覧を取得・表示するコンポーネントを作成するため、コンポーネントの名前を
devices
としてみましょう。
my-app/
└── devices/
├── devices.component.html
└── devices.component.ts
【参考】本レポート記載のアプリケーションを開発する際に必要となるファイル一覧
my-app/
├── app.module.ts
├── devices/
│ ├── devices.component.html
│ └── devices.component.ts
├── node_modules/
├── index.ts
├── package-lock.json
├── package.json
├── polyfills.ts
└── tsconfig.json
- devices.component.ts を以下のように編集します。
import { Component } from '@angular/core';
import { InventoryService, IManagedObject, IObservableOptions } from '@c8y/client';
@Component({
selector: 'app-device',
templateUrl: 'devices.component.html'
})
export class DevicesComponent {
devices: IManagedObject;
// 初回 GET リクエスト時のページングとリストのフィルタ設定
private filter: object = {
fragmentType: 'c8y_IsDevice',
pageSize: 2000
}
// Observable 型データのオプション設定
private options: IObservableOptions = {
realtime: true
}
// コンストラクタで InventoryService を依存性注入(Dependency Injection)
constructor(private inventory: InventoryService) {
this.loadDevices();
}
// デバイス一覧情報を取得
loadDevices() {
const list$ = this.inventory.list$(this.filter, this.options);
list$.subscribe((data) => {
this.devices = data;
});
}
}
devices.component.ts の内容を順に説明していきます。
:
:
// 初回 GET リクエスト時のページングとリストのフィルタ設定
private filter: object = {
fragmentType: 'c8y_IsDevice', // c8y_IsDevice フラグメントを指定
pageSize: 2000 // クエリ結果のページングを 2000 に設定
}
:
:
初回 GET リクエスト時のページングとリストのフィルタを設定します。list$
メソッドにより Observable 型のデータを取得するとき、初回は GET /inventory/managedObjects によりデータを取得します。その後は、リアルタイム通知 の仕組みを用いて ManagedObject の変更が通知されます。
import { InventoryService, IManagedObject, IObservableOptions } from '@c8y/client';
:
:
// Observable 型データのオプション設定
private options: IObservableOptions = {
realtime: true
}
:
:
Observable 型のデータにはオプションを設定できます。ここでは、realtime
を true
に設定し、ManagedObject の変更を検知できるようにします。
import { InventoryService, IManagedObject, IObservableOptions } from '@c8y/client';
:
:
// コンストラクタで InventoryService を依存性注入(Dependency Injection)
constructor(private inventory: InventoryService) {
this.loadDevices();
}
:
:
Things Cloud API からデータを取得するには、@cli/client
ライブラリを使用します。
ここでは、ManagedObject の一覧情報を取得したいため client ライブラリから InventoryService をインポートし、依存性注入します。
:
devices: IManagedObject;
:
// デバイス一覧情報を取得
loadDevices() {
const list$ = this.inventory.list$(this.filter, this.options);
list$.subscribe((data) => {
this.devices = data;
});
}
:
:
次に、API からデータを取得します。Inventory のデータを取得する例として、以下の2つのメソッドがあります。
メソッド | 内容 | パラメータ | 返却型 |
---|---|---|---|
client.<endpoint>.list$(filter, options) |
対象となるエンドポイントの一覧情報を取得 | filter : object (オプショナル)クエリ結果のページングとリストのフィルタの設定 options : IObservableOptions (オプショナル)Observable 型データの設定オプション |
ObservableList<TData> : サブスクライブできる Observable 型のリスト |
client.<endpoint>.detail$(entityOrId, options) |
対象 id を持つ ManagedObject の詳細情報を取得 | entityOrId : stringoptions : IObservableOptions (オプショナル)Observable 型データの設定オプション |
number |
上記のメソッドは Observable 型のデータを返します。Promise 型を返したい場合は、list()
、detail()
のように末尾の $
を削除してください。
ここでは、一覧情報を取得するため、list$
メソッドを利用して ManagedObject のリストを取得します。先程定義したフィルタとオプションをパラメータとしてメソッドに渡します。list$
をサブスクライブし、データの変更を監視します。
3. app.module.ts の編集
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { RouterModule } from '@angular/router';
import { CoreModule, BootstrapComponent, CommonModule } from '@c8y/ngx-components';
import { DevicesComponent } from './devices/devices.component'; // DevicesComponent をインポート
@NgModule({
imports: [
BrowserModule,
RouterModule.forRoot([{ path: '', component: DevicesComponent }], // アプリケーションのルートモジュールに DevicesComponent を指定
{ enableTracing: false, useHash: true }),
// c8y- プレフィックスが付くコンポーネントを使用するためのモジュール
CoreModule,
// データアクセスと翻訳のためのモジュール、@c8y/client の使用に必要
CommonModule
],
declarations: [DevicesComponent], // DevicesComponent を追加
bootstrap: [BootstrapComponent]
})
export class AppModule {}
app.module.ts
に以下の3つを追加・編集します。
- CommonModule, DevicesComponent をインポート
@NgModule
のimports
内で、アプリケーションのルートモジュールに DevicesComponent を指定、CommonModule を追加declarations
に DevicesComponent を追加
4. ビューの作成・編集
次に、devices.component.html を以下のように編集します。
<c8y-title>デバイス一覧</c8y-title>
<table class="table">
<tr>
<th>ID</th>
<th>名前</th>
<th>現在位置</th>
</tr>
<tr *ngFor="let device of devices">
<td *ngIf="device.c8y_IsDevice !== undefined">{{device.id}}</td>
<td *ngIf="device.c8y_IsDevice !== undefined">{{device.name}}</td>
<td *ngIf="device.c8y_Position !== undefined">lat: {{device.c8y_Position.lat}}, lng: {{device.c8y_Position.lng}}, alt: {{device.c8y_Position.alt}}</td>
</tr>
</table>
Interpolation記法 {{}}
により、データバインディングを実現します。コンポーネント側で devices
データの変更があった場合には、ビュー側も変更されます。
表の .table
クラスは CUMULOCITY IoT UI Style Guide を使用しています。
5. ローカル開発環境での動作確認
以下のコマンドにより、ローカルホストでの動作確認ができます。以下では、ローカルホストへのリクエストを -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
コマンドを使用します。)
{
"name": "my-app",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "c8ycli server -u https://<テナント名>.je1.thingscloud.ntt.com",
"build": "c8ycli build",
"deploy": "c8ycli deploy",
"locale-extract": "c8ycli locale-extract"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"@angular/animations": "7.2.2",
"@angular/common": "7.2.2",
"@angular/compiler": "7.2.2",
"@angular/core": "7.2.2",
"@angular/forms": "7.2.2",
"@angular/http": "7.2.2",
"@angular/platform-browser": "7.2.2",
"@angular/platform-browser-dynamic": "7.2.2",
"@angular/router": "7.2.2",
"@angular/upgrade": "7.2.2",
"@c8y/ngx-components": "1004.6.14",
"core-js": "^2.6.2",
"rxjs": "~6.3.3",
"zone.js": "~0.8.28",
"@c8y/style": "1004.6.14"
},
"devDependencies": {
"@angular-devkit/build-angular": "~0.10.4",
"@angular/compiler-cli": "7.2.2",
"@angular/language-service": "7.2.2",
"typescript": "3.1.6",
"@c8y/cli": "1004.6.14"
},
"c8y": {
"application": {
"name": "my-app",
"contextPath": "my-app",
"key": "my-app-application-key"
},
"cli": {}
}
}
c8ycli server -u https://<テナント名>.je1.thingscloud.ntt.com
もしくは、npm start
を実行した後、Webブラウザに以下のURL ( http://localhost:9000/apps/my-app/
) を入力し、アクセスします。アクセス後、テナント名・ユーザ名・パスワードの入力が求められるためこれらを入力し、リクエストをプロキシしているテナントへログインします。ログイン後、アプリケーションの動作確認ができるようになります。
6. Things Cloud へのデプロイ
ローカル開発環境での動作が正常であることを確認したら、Things Cloud へデプロイします。アプリケーションのルートディレクトリ (my-app/ 直下) に移動し、以下のコマンドを実行します。
$ 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 とユーザ情報の入力が必要になります。
7. 位置情報シミュレータを作成して動作を確認してみましょう
位置情報シミュレータを作成して、デプロイしたアプリケーションの動作を確認してみましょう。
- 位置情報シミュレータを新たに作成
- シミュレータのスイッチを ON にしてステータスを実行中へ変更
- アプリケーションを開き、新たに作成したシミュレータとその位置情報が更新されていることを確認
以上により、Web SDK for Angular を利用したカスタムアプリケーションの作成は完了です。
【参考】
以下に Web SDK for Angular を利用する上で参考となる Web サイトを記載しています。
※ 以下はソフトウェア・エー・ジー株式会社の Web サイトです。