コンテンツにスキップ
JelinaJelina Documentation技術ドキュメント
公式サイトに戻る

フロントエンドへのリアルタイム配信と直接制御

アーキテクチャ概要 の「実行」には、ポイント書き込み、アラーム、MQTT に加え、フロントエンドへの直接サービス提供も含まれます。Edge-EMS Builder は 2 つの WebSocket チャネルを備え、独自フロントエンドでリアルタイムデータ配信を受信し、デバイスへ制御指令を直接送信できます。中間層の追加開発は不要です。

チャネル パス 認証方式 用途
フロントエンド配信チャネル ws://<host>:<port>/front ログイン Token(アカウント・パスワードでログインして取得) 独自フロントエンド向け。ロール権限を検証し、購読配信と直接書き込みに対応
データ読み書きチャネル ws://<host>:<port>/data/rw 静的 data-rw-token(ems.yaml で設定) バックエンド統合向け。ログインに依存せず、低遅延の読み書きでシステム間連携に適する

両チャネルのメッセージ形式は同じで、認証方式と権限確認の粒度だけが異なります。このページでは /front を中心に説明しますが、/data/rw も同様に使用できます。

接続時は Query パラメーターで渡します。

ws://<host>:<port>/front?socketId=<任意の接続ID>&token=<ログインToken>
ws://<host>:<port>/data/rw?socketId=<任意の接続ID>&token=<data-rw-token>

要求フレーム(フロントエンド → Edge-EMS Builder)の共通構造:

{
"topic": "read | write | clear",
"messageId": "応答照合用の任意の一意な ID",
"keep": true,
"content": [
{ "dataKey": "pcsActivePower" }
]
}

応答フレーム(Edge-EMS Builder → フロントエンド)は、messageId で要求と 1 対 1 に対応します。

{
"code": "200",
"message": "Processed successfully",
"topic": "read",
"messageId": "...",
"time": "2026-07-23T10:00:00+08:00",
"data": { "...": "..." }
}

3. リアルタイム配信の受信(購読 = read + keep)

Section titled “3. リアルタイム配信の受信(購読 = read + keep)”

Edge-EMS Builder の配信モデルでは、特定 Topic へのパブリッシュ/サブスクライブではなく、各接続が独自の「配信設定」を宣言します。

  1. フロントエンドが topic: "read" を送信し、content に対象の dataKey(またはグループ全体を対象にする groupCode)を指定し、keep を true にします。
  2. Edge-EMS Builder は content をその接続(socketId)の配信設定として保存し、現在値を即座に 1 回返します。
  3. 以後、バックグラウンドタスクが毎秒、接続中の全フロントエンド socket を走査し、それぞれの配信設定に従って最新値を送信します。フロントエンドによる繰り返しポーリングは不要です。
  4. 継続配信が不要な場合は keep を false にするか省略します。この場合、Edge-EMS Builder は 30s のみ配信します。
  5. 接続の配信設定を解除するには、topic: "clear" を送信します。
// 購読:pcsActivePower と bmsSOC の最新値を継続監視
{
"topic": "read",
"messageId": "sub-001",
"keep": true,
"content": [
{ "dataKey": "pcsActivePower" },
{ "dataKey": "bmsSOC" }
]
}
// またはグループ単位で購読(子グループを含む全ポイントを監視)
{
"topic": "read",
"messageId": "sub-002",
"keep": true,
"content": [
{ "groupCode": "pcs-group-01" }
]
}

同じ接続で read + keep:true を複数回送信して、配信設定を追加・更新できます。dataKey と groupCode の少なくとも一方を指定してください。

フロントエンドは topic: "write" を送信し、content に書き込む dataKey と dataValue を指定します。データ型の指定は不要です。Edge-EMS Builder が dataKey から生データ(Collection)、集約データ(Aggregation)、時間帯別データ(Customization)を識別し、対応する書き込み処理へ振り分けます。

{
"topic": "write",
"messageId": "ctrl-001",
"content": [
{ "dataKey": "pcsActivePower", "dataValue": "300" }
]
}

時間帯別データ(Customization)への書き込みでは、有効期間を指定できます。

{
"topic": "write",
"messageId": "ctrl-002",
"resetCustomValue": true,
"content": [
{
"dataKey": "import_price",
"dataValue": "0.85",
"availableDate": "2026-06-25T00:00:00+08:00",
"expiredDate": "2026-06-25T08:00:00+08:00"
}
]
}
  • resetCustomValue: true は、対象の時間帯別データの既存値を消去してから今回の内容を書き込みます。スケジュール全体の置き換えに使用し、新旧の時間帯の重複競合を防ぎます。
  • 他の共有デバイスのポイントへ書き込む場合は、該当する content 要素に deviceCode を追加します。Edge-EMS Builder は共有データ書き込みと識別し、対象デバイスへ振り分けます。
  • /data/rw に静的 data-rw-token で接続した場合:ロール確認なしで許可します。バックエンドのシステム間統合向けです。
  • /front にログイン Token で接続した場合:アカウントのロールがスーパー管理者・管理者・オペレーターのいずれかか確認します。閲覧者は書き込みできません。画面側と同じ権限規則で、フロントエンドの権限を迂回する書き込み経路はありません。

DAILY_REPEAT は availableTime / expiredTime(例:08:00:00~12:00:00)を使用し、全体の有効日付範囲は時間帯別ポイントに設定します。完全な日時範囲を使用するのは DAILY_CHANGE です。両方式のパラメーターを混在させないでください。日付をまたぐ時間帯は分割します。

/front は Ping/Pong ハートビートで接続を確認します。クライアントは切断時の code/message を処理し、再接続後に購読を再設定してください。書き込み要求を購読とともに自動再送してはいけません。

デバイス書き込みは CommBridge の応答またはタイムアウトの結果で判断し、送信成功だけで実行完了と見なさないでください。デバイス制御ログ で処理中、成功、失敗を確認できます。収集データ書き込みの係数逆変換は CommBridge が行うため、呼び出し元で二重換算しないでください。

保守時の書き込み停止 中、保護対象の制御書き込みは 200162 を返します。再試行のために自動で書き込み停止を解除しないでください。

5. フロントエンド統合の完全な例

Section titled “5. フロントエンド統合の完全な例”
const ws = new WebSocket(`ws://<host>:<port>/front?socketId=web-ui-01&token=${loginToken}`);
ws.onopen = () => {
// リアルタイムデータを購読:PCS 有効電力と SOC を監視
ws.send(JSON.stringify({
topic: 'read',
messageId: 'sub-' + Date.now(),
keep: true,
content: [
{ dataKey: 'pcsActivePower' },
{ dataKey: 'bmsSOC' }
]
}));
};
ws.onmessage = (event) => {
const resp = JSON.parse(event.data);
if (resp.topic === 'read') {
// 毎秒受信する最新値で、画面のメーターやグラフを更新
renderDashboard(resp.data);
}
if (resp.topic === 'write') {
// 書き込み結果の通知:resp.successContent / resp.errorContent
showWriteResult(resp);
}
};
// ユーザーが画面で「電力を 300kW に設定」ボタンをクリックしたとき:
function setPower(value) {
ws.send(JSON.stringify({
topic: 'write',
messageId: 'ctrl-' + Date.now(),
content: [{ dataKey: 'pcsActivePower', dataValue: String(value) }]
}));
}

このコードは、「ページ読込み時にリアルタイム購読 → 毎秒画面更新 → ユーザー操作で制御指令を直接送信 → 書き込み結果の受信」という代表的なフロントエンドのループをカバーします。追加のバックエンド中継サービスは不要です。

  • /front または /data/rw で書き込むデータは、トリガープランや式エンジンが読むものと同一のデータです。フロントエンド制御の最終結果をデバイスから収集・読み戻した後、集約式やトリガー判定に再利用できます。データモデル を参照してください。
  • 独自フロントエンドだけでなくクラウドのダッシュボードにも同時配信する場合、両経路は共存できます。/front で独自画面へ配信しながら、MQTT クラウド・エッジ連携 で同じデータをクラウドへ報告できます。
  • aems-write-data AI 設定 Skill は /data/rw と /front の呼び出しをまとめており、自然言語で AI Agent に書き込み指令のデバッグを依頼できます。
  • HTTP/WebSocket API の全一覧:Edge-EMS Builder 技術サポートへ「Edge-EMS Builder HTTP API ドキュメント」をお問い合わせください。
  • 書き込んだデータを式エンジンやトリガープランで利用する方法:式エンジン、トリガープラン
  • デバイスをまたいだ書き込みと共有先の仕組み:デバイス協調と共有先