コンポーネント
自作の処理をエッジPCで動かす。画面でスクリプトを書くか、コンテナイメージを指定してコンポーネントとバージョンを登録する
標準機能では賄えない自作の処理を、現場のエッジPC上で Docker コンテナとして動かす機能です。処理の中身は次の 3 通りで用意できます。
| 用意のしかた | 向いている場面 | 必要なもの |
|---|---|---|
| スクリプトを書く | Python / Node.js の短い処理。管理画面だけで完結させたい | ブラウザのみ |
| イメージを指定する | public ECR・Docker Hub で公開されているイメージをそのまま使う | ブラウザのみ |
| 自作のイメージを CLI で送る | ライブラリを足したい、Dockerfile から作り込みたい | 手元の Docker と CLI |
カメラの死活監視・録画の外部ストレージへの同期・Kinesis Video Streams への取り込みは、公開コンポーネントとして最初から用意してあり、そのままデプロイできます。
コンテナの起動と停止は ThingsConnect が管理します。ThingsConnect 本体(カメラ・センサ・録画)とは独立して動くので、独自処理が落ちても本体の動作には影響しません。
AI 推論デバイスとの使い分け
「エッジで処理を動かす」機能は 2 つあります。やりたいことが AI モデルの実行だけなら、この機能は不要です。
| AI 推論デバイス | 独自コンポーネント(本ページ) | |
|---|---|---|
| 使う場面 | 取り込み済みのカメラ映像にモデルを当てたい | 任意の自作処理を動かしたい(映像を使う場合はカメラへ直接接続する) |
| 用意するもの | モデルの選択のみ(プリセット or URL) | スクリプト(画面で書く)または Docker イメージ |
| 必要な知識 | 画面操作のみ | Python / Node.js、または Docker |
| データの扱い | 結果が自動で分析・ダッシュボードに載る | コンテナ内で完結(分析・ダッシュボードとの連携は未対応) |
| 管理画面 | 「デバイス」 | 「カスタム処理」→「コンポーネント」「デプロイ」「グループ」 |
カメラ映像に AI モデルを当てたいだけであれば AI 推論を使う を参照してください。
全体像
- コンポーネント(アプリの定義)とバージョン(実際の中身)は別物です。1 つのコンポーネントに複数バージョンをぶら下げ、どれをデプロイするか選びます。バージョンごとに、スクリプトかイメージかを選べます。
- コンポーネント詳細の「コンポーネント名」は、エッジPC 詳細の「稼働中のコンポーネント」に出る名前です。
- デプロイはエッジPC 単位、またはグループ単位です。既に動いている ThingsConnect 本体はそのままで、独自コンポーネントが加わります。
公開コンポーネント
コンポーネント一覧で 公開 の印が付いているものは、ThingsConnect が用意したコンポーネントです。すべての組織に最初から表示され、環境変数を入れてデプロイするだけで使えます。
| 名前 | できること |
|---|---|
| カメラ死活監視 | RTSP カメラが映らない・暗い・白飛び・固まったを定期的に判定し、ログに出す |
| 録画の同期(S3・Azure・GCS) | エッジPC の録画をお客様のストレージへ定期的にコピーする |
| Kinesis Video Streams 取り込み | カメラの映像をお客様の Amazon Kinesis Video Streams へ直接送る |
- 公開コンポーネントは削除やバージョンの登録ができません。新しいバージョンは ThingsConnect が追加します。バージョンの状態が
準備中の間はデプロイできません(イメージの用意が終わると選べるようになります)。 - ソースは redimpulz/thingsconnect-components(MIT ライセンス)で公開しています。イメージは public ECR に置いてあり、場所はコンポーネント詳細の「中身」の列に表示されます。
- 中身を変えたいときは、公開イメージを
FROMで拡張するか Dockerfile を写して作り替え、自分のコンポーネントとして登録してください。 - どの公開コンポーネントも、実機での動作確認はまだです。 うまく動かない点があればご連絡ください。
使い始める前に
エッジPCに Docker が必要です。 どの方法で登録したコンポーネントも、エッジPC 上では Docker コンテナとして動きます。セットアップコマンドが最初から入れるので、通常は何もすることがありません。
Docker を入れずにセットアップした機体(--skip-docker を付けた場合や、古い手順で構築した場合)では、次を実行してください。Docker の導入から、ThingsConnect が Docker を使えるようにする設定までを済ませます。
wget -qO- https://<ダッシュボード>/api/edge-setup/install.sh | sudo bash
トークンは要りません(既にセットアップ済みのため)。Docker を手で入れただけでは、デプロイが Docker engine is not installed で失敗します。
コンポーネントを作る
サイドバーの「カスタム処理」→「コンポーネント」→「コンポーネントを追加」で、名前と説明(任意)を入力します。まだ中身はありません。
名前には英数字を 1 文字以上含めてください。 日本語だけの名前は登録できません。日本語を使いたい場合は「カメラ死活監視 camera-watchdog」のように英数字を混ぜてください。
バージョンを登録する
コンポーネント詳細の 「バージョンを登録」 を押し、上部のタブで 「スクリプトを書く」 か 「イメージを指定」 を選びます。バージョン番号には、直前のバージョンのパッチを 1 つ上げた番号(例: 1.0.0 の次は 1.0.1)が入った状態で開きます。環境変数・ポート・リソース上限などの実行時の設定はどちらのタブでも共通です。
スクリプトを書く
画面のエディタにコードを書き、そのまま登録します。イメージのビルドは要りません。
ランタイムを選ぶ
| ランタイム | 最初に実行するファイル | 使えるライブラリ |
|---|---|---|
| Python 3.12 | main.py |
numpy、opencv-python-headless、requests、paho-mqtt、ffmpeg(コマンド) |
| Node.js 22 | main.js |
標準ライブラリのみ |
開いた時点で、一定間隔でログを出すだけの雛形が入っています。書き始める前にランタイムを変えると、雛形も切り替わります。
コードを書く
エディタ上部の + でファイルを足せます(例: util.py)。フォルダは lib/util.py のように / で区切ります。
「登録」を押す
スクリプトは次の条件で動きます。
- 追加のライブラリは入れられません。 上の表に無いライブラリが要るときは、ランタイムのイメージを
FROMで拡張して自作のイメージにします(ランタイムのソースは redimpulz/thingsconnect-components のruntimes/にあります)。 - コードはコンテナの
/appに読み取り専用で置かれます。ファイルを書くときは/tmpを使います(--read-onlyを付ける場合は--tmpfs=/tmpも付けます)。 - コンテナは root 以外のユーザーで動きます。
- 標準出力に書いた行が、ログに出ます。 Python のランタイムはバッファリングを切ってあります。
- ファイルは 20 個・合計 512 KB までです。最初に実行するファイル(
main.py/main.js)は必須です。ファイル名に使えるのは英数字・.・_・-です。 - 常駐する処理として書きます(定期実行したい処理も、雛形のようにループさせます)。
イメージを指定する
公開されているイメージを、URI で指定して登録します。
| 指定できるイメージ | 例 |
|---|---|
| public ECR の公開イメージ | public.ecr.aws/docker/library/alpine:3.21 |
| Docker Hub の公開イメージ | nginx:1.27、rclone/rclone:1.68 |
CLI の push で送ったイメージ |
push の実行時に表示される URI(自分の組織のものに限る) |
- それ以外のレジストリ(ghcr.io・quay.io・社内のプライベートレジストリなど)は指定できません。 登録時に「対応していないレジストリです」と表示されます。
- 登録した時点の中身に固定します。 タグは登録時に digest(
sha256:...)へ置き換えて保存するので、後から同じタグのイメージが差し替えられても、配る中身は変わりません。中身を更新するときは新しいバージョンとして登録し直します。 - バージョンの一覧の「中身」の列には、指定したタグ付きの名前が表示されます。
自作のイメージを CLI で送る
Dockerfile からイメージを作り込みたい場合は、手元の PC でビルドし、CLI で ThingsConnect が用意した保管場所へ送ります。AWS アカウントを自分で持つ必要はありません。
手元に CLI を入れる
Docker と Node.js 24 以降が必要です。
npm i -g @thingsconnect/cli
thingsconnect --version動作を確認できているのは Linux のみで、macOS・Windows と社内プロキシ下での動作は未確認です。
CLI が古いと ThingsConnect 側が受け付けません。 その場合は「この CLI(バージョン)はサポート対象外です」と表示されるので、npm i -g @thingsconnect/cli で更新してください。
API トークンを発行する
管理ダッシュボードの **「組織」→「組織設定」→「API・MCP」**の「API トークン」で、スコープに 「コンポーネント登録」(デプロイも CLI で行うなら 「デプロイ」 も)を選んで発行します(→ 組織設定)。トークンは発行したときに一度だけ表示されます。
CLI にトークンを渡す
login で保存すると、以降のコマンドで指定が要らなくなります。トークンは対話入力なので、コマンド履歴やプロセス一覧に残りません。
thingsconnect login --api-url https://<API のホスト>
# API トークン: (貼り付けて Enter)
thingsconnect whoami # 組織とスコープを確認する保存先は ~/.config/thingsconnect/config.json です。thingsconnect logout で削除できます。CI などで対話入力できない場合は環境変数も使えます。
export THINGSCONNECT_API_URL=https://<API のホスト>
export THINGSCONNECT_API_TOKEN=<API トークン>接続先が複数ある場合は、--profile で名前を付けて保存すると切り替えられます。保存した名前が以降の既定になります。
thingsconnect login --api-url https://<別の API のホスト> --profile dev
thingsconnect profiles # 保存済みの接続先を一覧表示する(* が既定)
thingsconnect use prod # 既定の接続先を切り替える
thingsconnect --profile dev list # そのコマンドだけ接続先を変える
thingsconnect logout --profile dev # そのプロファイルだけ削除するwhoami と deploy は接続先の URL とプロファイル名を表示するので、実行前に対象の環境を確認できます。
イメージをビルドして登録する
自作処理の Dockerfile があるディレクトリで実行します。ビルド・アップロード・バージョン登録をまとめて実行します。環境変数やポートもここで指定できます(実行時の設定)。コンポーネントは thingsconnect create --name "My Edge Processor" で CLI からも作れます。
thingsconnect push --component my-edge-processor --version 1.0.0 --context .public ECR・Docker Hub の公開イメージは、ビルドを伴わない register でも登録できます(画面の「イメージを指定」と同じ扱いです)。
thingsconnect register --component my-edge-processor --version 1.0.0 --image <イメージ URI>登録したバージョンをエッジPCへ配る手順はデプロイを参照してください。
実行時の設定
バージョン登録の画面(「バージョンを登録」)または CLI のオプションで指定します。スクリプトでもイメージでも同じです。
| 設定 | 画面の項目 | CLI | 例 |
|---|---|---|---|
| 環境変数の既定値 | 環境変数(KEY=VALUE / 1 行 1 つ) | --env |
API_URL=https://example.com |
| ポート公開 | ポート(host:container[/udp] / 1 行 1 つ) | --port |
8080:80 |
| メモリ上限 | メモリ上限 | --memory |
512m |
| CPU 上限 | CPU 上限 | --cpus |
0.5 |
| 追加の実行オプション | 追加 docker run 引数 | --run-arg |
--read-only |
指定できるオプション
エッジPCを保護するため、指定できるフラグは許可制です。下記以外を書くと登録時にエラーになります。
| 用途 | フラグ |
|---|---|
| 書き込み制限 | --read-only、--tmpfs=<path>(メモリ上。ホストではありません) |
| 権限を落とす | --cap-drop=<CAP>、--user=<uid[:gid]> |
| 資源の追加制限 | --pids-limit、--memory-reservation、--memory-swap、--cpu-shares、--ulimit |
| 名前解決・ホスト名 | --dns、--add-host、--hostname |
| 起動方法 | --workdir、--entrypoint、--stop-signal、--stop-timeout、--label |
値を取るフラグは --flag=value の形で書いてください。 --flag value のように 2 つに分けると、値の側が別のフラグとして扱われエラーになります。
許可していない主なものと理由は次のとおりです。
--privileged/--cap-add/--security-opt/--userns— 隔離そのものを弱める--volume/--mount/--volumes-from/--device— ホストのファイルやデバイスをコンテナに渡す(録画だけは下の「録画を読み取り専用で渡す」で受け取れます)--network— ホストのネットワークに直結できてしまう--restart/--detach— 起動・再起動は ThingsConnect が管理します
ホストのファイルを読み書きしたい、といった要件がある場合は個別にご相談ください。
録画を読み取り専用で渡す
バージョンの登録時に 「録画を読み取り専用で渡す(/recordings)」(CLI では --mount-recordings)を指定すると、エッジPC の録画がコンテナの /recordings に読み取り専用で見えます。録画はカメラごとのフォルダに、10 分ごとの MP4 ファイルとして並んでいます。書き込み・削除はできません。お客様のストレージへ録画を送るだけなら、公開コンポーネントの「録画の同期」を使えます。
データの保存先(増設ディスク・NAS)はデプロイのときに決まります。エッジPC の保存先を変えたら、コンポーネントをデプロイし直してください。
バージョンの更新と削除
- 更新: 新しいバージョン番号で登録し、改めてデプロイします。バージョンは上書きできません(同じ番号での再登録はエラーになります)。
- 前のバージョンを元にする: バージョン行の 「この版から新しい版を作る」 のアイコンを押すと、そのバージョンのスクリプト(またはイメージの指定)と実行時の設定が入った状態で登録画面が開きます。「バージョンを登録」ボタンから開いた場合は、最新のバージョンの内容が入ります。
- 削除: コンポーネント詳細でバージョンを削除、またはコンポーネントごと削除します。エッジPC やグループにデプロイ中のバージョンは削除できないので、先にデプロイから外してください。削除すると、
pushしたイメージも消えます(同じイメージを使うバージョンが残っていれば残します)。
thingsconnect delete --component my-edge-processor --version 1.0.0
コンテナから何に触れるか
コンテナは隔離された環境で動くため、エッジPCのカメラ・センサに直接はアクセスできません。現状で届く範囲は次のとおりです。
| 対象 | 可否 | 補足 |
|---|---|---|
| LAN 上の機器(IP カメラの RTSP、シリアルサーバ経由のセンサ など) | ○ | ネットワーク経由で自由に接続できます |
| インターネット上のサービス | ○ | 社内システムや外部 API の呼び出しに使えます |
| USB カメラ・ラズパイの CSI カメラ | ✗ | ホストのデバイスをコンテナに渡す指定(--device)は許可していません |
シリアル接続のセンサ(/dev/ttyUSB* 等) |
✗ | 同上。シリアルサーバ経由で TCP にすれば接続できます |
| ThingsConnect が取り込み済みのカメラ映像 | ✗ | コンテナからは届きません。カメラの RTSP URL へ直接接続してください |
| ThingsConnect の録画ファイル | ○ | 「録画を読み取り専用で渡す」を指定したバージョンだけ、/recordings から読めます(書き込みはできません) |
| AI アプリのイベント | ○ | 物体検出の「連携」で カスタム処理へ渡す トリガーを作ると受け取れます(下記)。撮影ジョブの起動と同じトークンを使います |
| ThingsConnect の撮影ジョブの起動 | ○ | --add-host=host.docker.internal:host-gateway を付け、エッジ内トリガー用のトークンで呼びます(→ 撮影)。実機での到達確認はまだです |
| ThingsConnect の計測値の取り込み | ✗ | ThingsConnect 側の認証情報を受け取る手段がありません(デプロイ時の環境変数で渡せるのは、利用者が既に持っている値だけです) |
AI アプリのイベントを受け取る
物体検出・ナンバープレート検知の詳細画面の「連携」で「すること」を カスタム処理へ渡す にしたトリガーを作ると(→ AI アプリを使う)、同じエッジPC のコンテナがイベントを受け取れます。「区域に人が入ったら社内システムに登録する」のような処理を、スクリプトに書けます。
Docker 起動オプションに --add-host=host.docker.internal:host-gateway を付けます。
エッジ内トリガー用のトークン(トリガーの作成画面と、撮影ジョブの編集画面に出ます)を、デプロイ時の環境変数(シークレット)で LOCAL_TOKEN として渡します。
GET http://host.docker.internal:3001/local/events を繰り返し呼びます。発火が無ければ最大 waitSeconds 秒(既定 25 秒、最大 30 秒)待ってから空で返ります。前回の応答の next を after に渡すと、その続きだけが返ります。
import json
import os
import requests
URL = "http://host.docker.internal:3001/local/events"
HEADERS = {"Authorization": f"Bearer {os.environ['LOCAL_TOKEN']}"}
after = None
while True:
params = {"waitSeconds": 25} if after is None else {"after": after, "waitSeconds": 25}
try:
res = requests.get(URL, headers=HEADERS, params=params, timeout=40)
res.raise_for_status()
except requests.RequestException as err:
print(json.dumps({"error": str(err)}), flush=True)
continue
body = res.json()
for item in body["events"]:
event = item["event"]
# ここに処理を書く(例: 社内システムへ登録する)。
print(json.dumps({"trigger": item["trigger"]["name"], "type": event["eventType"], "detail": event["detail"]}, ensure_ascii=False), flush=True)
after = body["next"]
| 応答の項目 | 内容 |
|---|---|
events[].seq |
発火の番号。エッジPC の起動のたびに 1 から数え直します |
events[].trigger |
発火したトリガーの id と name |
events[].event |
イベント本体。eventType(presenceStart / presenceEnd / plateRead)・deviceId・ts・ruleId・detail(在/不在は ruleName・matchedCount・detections・photoKey、ナンバーは plate・confidence・bbox・photoKey) |
next |
次に after へ渡す番号 |
現時点の制限
- コンテナの実行方式は Docker のみです。
- コンテナが自ら終了したときの挙動は未検証です。 常駐する処理として書いてください(終了したときに自動で起動し直されるかは確認できていません)。
困ったときは
| 症状 | 確認すること |
|---|---|
push が失敗する |
手元で Docker が動いているか。THINGSCONNECT_API_URL / THINGSCONNECT_API_TOKEN が正しいか |
| 「対応していないレジストリです」と出る | public ECR・Docker Hub の公開イメージか。それ以外のイメージは CLI の push で送り直す |
| 「イメージが見つかりません」と出る | イメージ名・タグの綴り。公開されているか。push したイメージなら送信が終わっているか |
| 「〜のイメージを準備中です」と出る | スクリプトのランタイムを用意している途中です。しばらく待ってから登録し直す |
デプロイが FAILED |
エッジPCに Docker が入っているか。実行オプションに禁止指定が無いか。Docker Hub のイメージなら取得の回数制限に当たっていないか |
Docker engine is not installed で失敗する |
Docker を後から手で入れた場合に出ます。使い始める前にのコマンドを実行してください |
| 状態が進まない | エッジPCがオンラインか(エッジPCの登録と監視) |
| コンテナが起動しない | ログにエラーが出ていないか。イメージなら手元で docker run して同じ設定で動くか確認する |
| デプロイ時の環境変数がエラーになる | 指定したキーをそのバージョンが宣言しているか(値を空にして登録し直す)。値にシングルクォート・改行が入っていないか |
その他の切り分けは トラブルシューティング を参照してください。