- Jelina 概要
- EMS Builder
- 統合と連携
フロントエンドへのリアルタイム配信と直接制御
アーキテクチャ概要 の「実行」には、ポイント書き込み、アラーム、MQTT に加え、フロントエンドへの直接サービス提供も含まれます。Edge-EMS Builder は 2 つの WebSocket チャネルを備え、独自フロントエンドでリアルタイムデータ配信を受信し、デバイスへ制御指令を直接送信できます。中間層の追加開発は不要です。
1. 2 つの WebSocket チャネル
Section titled “1. 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>2. メッセージ形式
Section titled “2. メッセージ形式”要求フレーム(フロントエンド → 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 へのパブリッシュ/サブスクライブではなく、各接続が独自の「配信設定」を宣言します。
- フロントエンドが
topic: "read"を送信し、contentに対象のdataKey(またはグループ全体を対象にするgroupCode)を指定し、keepをtrueにします。 - Edge-EMS Builder は
contentをその接続(socketId)の配信設定として保存し、現在値を即座に 1 回返します。 - 以後、バックグラウンドタスクが毎秒、接続中の全フロントエンド socket を走査し、それぞれの配信設定に従って最新値を送信します。フロントエンドによる繰り返しポーリングは不要です。
- 継続配信が不要な場合は
keepをfalseにするか省略します。この場合、Edge-EMS Builder は 30s のみ配信します。 - 接続の配信設定を解除するには、
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の少なくとも一方を指定してください。
4. デバイスの直接制御(write)
Section titled “4. デバイスの直接制御(write)”フロントエンドは 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 で接続した場合:アカウントのロールがスーパー管理者・管理者・オペレーターのいずれかか確認します。閲覧者は書き込みできません。画面側と同じ権限規則で、フロントエンドの権限を迂回する書き込み経路はありません。
毎日繰り返すスケジュール
Section titled “毎日繰り返すスケジュール”DAILY_REPEAT は availableTime / expiredTime(例:08:00:00~12:00:00)を使用し、全体の有効日付範囲は時間帯別ポイントに設定します。完全な日時範囲を使用するのは DAILY_CHANGE です。両方式のパラメーターを混在させないでください。日付をまたぐ時間帯は分割します。
接続と実行結果
Section titled “接続と実行結果”/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) }] }));}このコードは、「ページ読込み時にリアルタイム購読 → 毎秒画面更新 → ユーザー操作で制御指令を直接送信 → 書き込み結果の受信」という代表的なフロントエンドのループをカバーします。追加のバックエンド中継サービスは不要です。
6. 他の機能との関係
Section titled “6. 他の機能との関係”/frontまたは/data/rwで書き込むデータは、トリガープランや式エンジンが読むものと同一のデータです。フロントエンド制御の最終結果をデバイスから収集・読み戻した後、集約式やトリガー判定に再利用できます。データモデル を参照してください。- 独自フロントエンドだけでなくクラウドのダッシュボードにも同時配信する場合、両経路は共存できます。
/frontで独自画面へ配信しながら、MQTT クラウド・エッジ連携 で同じデータをクラウドへ報告できます。 aems-write-dataAI 設定 Skill は/data/rwと/frontの呼び出しをまとめており、自然言語で AI Agent に書き込み指令のデバッグを依頼できます。
次のステップ
Section titled “次のステップ”- HTTP/WebSocket API の全一覧:Edge-EMS Builder 技術サポートへ「Edge-EMS Builder HTTP API ドキュメント」をお問い合わせください。
- 書き込んだデータを式エンジンやトリガープランで利用する方法:式エンジン、トリガープラン
- デバイスをまたいだ書き込みと共有先の仕組み:デバイス協調と共有先