テキスト版を開く

この記事の内容
1. アラームシステムが沈黙したまま失敗することはほとんどない
ほとんどのIoTプロジェクトがアラームに求めるのは「何かが壊れたら音を鳴らす」という一点だけだ。しかし、実際にアラームシステムを破綻させるのは沈黙ではない——それは 誰も読まないアラートである。
この問題の規模に関する公開データ:
| 指標 | 値 | 出典 |
|---|---|---|
| セキュリティオペレーションセンターにおける日次のアラート量 | 約2,992件/日、うち約 63%は未対応 | Vectra AI 2026 |
| 同じ状況、異なるサンプル | 約2,047件/日、うち300件(15%)はリソース不足のため未確認 | Binalyze, 2026 State of the SOC (400人のCISOを対象としたSapio調査) |
| 過負荷の結果 | 91% のCISOが情報過多を報告; 77% が警告や脆弱性を見逃した原因だと回答 | 同上 |
| 産業分野の誤警報率 | センサーアラームの40%~90% が誤報であることが判明(ドリフト、環境ノイズ、キャリブレーションの劣化) | 産業メンテナンス研究にわたり一貫した範囲 |
| 繰り返しのコスト | 同種のアラートを繰り返すごとに、オペレーターが対応する確率はおよそ 30% | 産業アラーム管理研究 |
換算する価値のある数字:180台の資産を監視するプラントでは、35%の誤検知率が年間約1,200技術者時間を無駄な追跡に費やす——およそ US$42,000 /年。
(最初の2行はIoTではなくセキュリティオペレーション由来である。しかし仕組みは同一だ:ノイズフロアが大きいほど、重要な唯一のアラートはその中に消えやすい。)
したがって本記事は、より多くのアラートを生成することについてではない。3つの特性についてである:
- 時間通りに届く — アラームは1報告サイクル以内に発火し、保証され文書化される;
- スパムにならない — 1つのイベントは1つのアラームを生成し、条件が解消されれば自動的にクリアされる;
- 適切な人に届く — 緊急は電話へ、定常はリストへ、両者は決して混ざらない。
2. 最初に計算すべき3つの時間予算
LoRaWANでは、最初の設計ステップはスクリプトを書くことではない。物理的事実を受け入れることだ: 電池駆動のエンドデバイスは、何か問題が起きたからといって早く目覚めることはない。これにより3つのタイムラインが生じる:
| 段階 | 決定要因 | 典型的な規模 | できること |
|---|---|---|---|
| 検出遅延 | アップリンク周期(収集間隔+変化時報告) | 5~60分;COVが一度も発動しなければさらに長い | 収集間隔を短縮するかCOV閾値を厳しくする |
| ダウンリンク遅延 | Class Aデバイスは自身のアップリンク後にのみ受信ウィンドウを開く(LoRaWAN 1.0.4のデフォルトでRX1 ≈ 1秒、RX2 ≈ 2秒);逃すと次のアップリンクまで待つ | 最良で1~2秒、最悪でアップリンク周期全体 | 重要なループにはClass Cを使用;そうでなければ遅延をSLAに明記する |
| オフライン検出 | プラットフォームは「最終活動時刻+2×ハートビート周期」後にデバイスをオフラインとマークする | 設定されたハートビートに依存 | ハートビートをアップリンク周期の2~3倍に設定する |
要点: LoRaWANは秒レベルのアラームを提供できないが、1報告サイクルより遅れることのないアラームは提供できる。 顧客が受け入れテストで発見する前に、この一文を提案書に入れておくこと。
この記事の知識をプロジェクトに活かす
ManThink(門思科技)は、デバイス接続、ネットワーク、データ活用に向けたIoT製品を提供しています。この記事の技術情報とあわせて、以下の製品情報をご覧ください。
3. 3つの構成要素、そして3つすべてが必要
ThinkLinkでのアラームは「デバイスに閾値を設定する」ことではない。3つの部分が連携して機能する:
| 部分 | 役割 | 設定場所 |
|---|---|---|
| トリガーモデル | アップリンクごとにスクリプトを実行し、条件を評価し、アクションを返す | モデル管理 → トリガーモデル → デバイスにアタッチ |
| 組み込みALARM RPC | 受け付ける action: new / clear、アラームレコードを作成またはクリアし、通知グループへディスパッチする |
デバイス管理 → デバイス詳細 → RPC → 追加 ALARM |
| 通知グループ | 誰がどのチャネルで受け取るかを決定する | アラーム管理 → 通知グループ |
順序は固定:まず ALARM RPCをアタッチし、次にトリガーモデル、そして(任意で)通知グループ。どれか1つでも欠けるとアラームは沈黙する——「スクリプトが存在するから鳴る」などということはない。
1台のデバイスは 複数 トリガーモデルを使用するため、複数条件のシナリオを一つのスクリプトに詰め込む必要はありません。
4。実行環境:vm2サンドボックス内のベア関数本体
ほぼ全員がつまずく詳細が一つあります: エディタはベア関数本体を期待します。 プラットフォームはあなたのコードを function triggerRunner() { ... } でラップしてから呼び出すため、別の function trigger_script(...) {} ラッパーを追加してはいけません。 trigger_script 形式は、どの変数が利用可能かを示すためにドキュメント内にのみ記載されています。
サンドボックスはvm2で、以下の制限があります:
| 項目 | 値 |
|---|---|
| 実行タイムアウト | 1000 ms;超過するとこのトリガーは完全にスキップされます |
eval / WebAssembly |
無効 |
async / await |
非対応;スクリプトは同期的に実行されます |
require / import |
非対応 |
setTimeout / setInterval / console |
利用不可 — 遅延実行には delayms 戻り値フィールドを使用してください、デバッグにはトリガーモデルのログを使用してください |
process / path / fs |
利用不可 |
Buffer |
SafeBuffer、以下のみを公開: alloc、 from、 isBuffer、 byteLength、 compare、 concat |
直接使用できる注入変数: device、 thingModelId、 org_params、 env、 plugins、 Buffer、さらに六つの tklHelper クラス(BufferTKL、 PayloadParser、 MSparser、 Utils、 TriggerHelper、 RPCHelper)。
アラームに最も重要な device のフィールド:
| フィールド | 意味 |
|---|---|
device.telemetry_data[thingModelId] |
そのデバイスモデルの最新テレメトリスナップショット(計測値のエントリポイント) |
device.server_attrs |
プラットフォーム側の属性;しきい値、通知グループ、リンクされたEUIに適した場所 |
device.shared_attrs |
デバイスと双方向に同期される属性 |
device.active_time |
最後のアップリンクのタイムスタンプ(ISO 8601) |
device.heart_period |
オフライン検出に使用されるハートビート期間(秒) |
device.eui / device.name |
デバイス識別子と名前 |
注意: device とヘルパークラスはフリーズ状態で注入されます — これらへの代入は効果がありません。戻り値が唯一の出力チャネルです。
5。四つの戻り値フィールド、そのうち一つは自由なノイズフィルター
トリガースクリプトは null (何もしない)または以下のフィールドを持つオブジェクトを返します:
| フィールド | 型 | 意味 |
|---|---|---|
delayms |
数値 | 実行前の遅延(ミリ秒) actions |
abort_previous_timer |
真偽値 | この値が trueの場合、以前の保留中の遅延タスクをキャンセルし、このタスクに置き換えます |
should_dispatch |
真偽値 | デフォルトは false:前回からデータが変わっていない場合、ディスパッチはスキップされます。強制するには true を設定してください |
actions |
配列 | 順番に実行されるRPC呼び出し |
各 actions 項目のフィールド:
| フィールド | 意味 |
|---|---|
method |
RPCメソッド名(alarm アラーム用) |
methodId |
の代替 method。両方存在する場合はこちらが優先される |
params._eui |
対象デバイスのEUI — の内部 paramsであり、アクションのトップレベルフィールドではない |
should_dispatch デフォルトは false で、これが無料で得られる最初のノイズフィルターです。 連続するアップリンクで同一のデータが来ても、アクションは再ディスパッチされません。多くのチームはこれを知らず、その上に独自の重複排除を構築しています。
6。コピーして使えるスクリプト
温度とバッテリー、しきい値と通知グループを server_attrs に外部化し、しきい値の変更がスクリプトに触れないようにします:
// トリガースクリプトは素の関数本体です。プラットフォームが triggerRunner() でラップします let tdata = device?.telemetry_data?.[thingModelId]; if (!tdata) return null;
const LIMIT_TEMP = device.server_attrs?.alarm_temp ?? 60; const LIMIT_BAT = device.server_attrs?.alarm_battery ?? 20; const notify = device.server_attrs?.notify ?? [];
let actions = [];
// 1) 過熱:重複排除が機能するようタイトルとレベルを安定させる let hot = tdata.temperature >= LIMIT_TEMP; actions.push({ method: "alarm", params: { _eui: device.eui, name: "overheat_alarm", title: "[Overheat] " + device.name, level: "urgent", desc: "Temperature above limit, immediate action required", action: hot ? "new" : "clear", notify: notify } });
// 2) バッテリー低下:記録のみ、通知しない(notify配列を空に) let lowBat = tdata.battery <= LIMIT_BAT; actions.push({ method: "alarm", params: { _eui: device.eui, name: "low_battery_alarm", title: "[Low battery] " + device.name, level: "mid", desc: "Battery below threshold, schedule a replacement", action: lowBat ? "new" : "clear", notify: [] } });
return { delayms: 0, abort_previous_timer: true, actions };
ALARM RPCのパラメータ:
| パラメータ | 意味 |
|---|---|
name |
アラームイベントの一意な識別子。アラーム種別ごとに1つの名前 |
action |
new 発生させます。 clear 解除します。 no 何もしません |
title |
UIに表示されるタイトル |
desc |
説明テキスト |
level |
low / mid / high / urgent |
notify |
通知グループ名の配列。 空の配列は記録するが送信しないことを意味します |
マッチング server_attrs デバイス上の:
| フィールド | 例 | 目的 |
|---|---|---|
alarm_temp |
60 | 温度しきい値 |
alarm_battery |
20 | バッテリーしきい値 |
notify |
["ops-team"] |
通知グループリスト |
戻り値オブジェクトを手作業で構築したくない場合は、 TriggerHelper を拡張して _alarmProcess(info)をオーバーライドします。コンストラクタは device.server_attrs.notify を自動的に読み取り、標準の戻り値構造を生成します(フィールド名は groupで、ALARM RPCの notify に対応します)。 _alarmProcess が falseを返す場合、またはアクションが noの場合、 alarm() は nullを返します。
7。4つの重大度レベルとルーティングマトリクス
レベルはちょうど4つあります: low (情報)、 mid (警告)、 high (エラー)、 urgent (重大)。レベル自体は何もトリガーしません — 重要なのはレベル × 通知グループの組み合わせです:
| 状況 | 推奨レベル | notify | 期待される対応 |
|---|---|---|---|
| 水漏れ、ガス、サーバールームの過熱 | urgent |
オンコールグループ(WeCom webhook) | 即座に |
| 範囲外だが許容範囲(温度ドリフト) | high |
運用チームへのメール | 同じシフト内 |
| バッテリー低下、信号品質の劣化 | mid |
空の配列、リストのみ | 計画的な作業 |
| パラメータ変更、ファームウェアバージョンの不一致 | low |
空の配列 | 次回点検時 |
キックオフ時にこの表を顧客と合意してください。アラームの重大度は技術的な問題ではなく、責任の所在の問題です — すべてのレベルに名前付きの担当者が必要です、そうでなければ urgent は他のすべてと同様に無視されるだけになります。
8。ノイズを削減する6つの方法
-
そのままにする
should_dispatch。 そのfalseデフォルトでは、データが変化していなければ再ディスパッチされません。毎回強制ディスパッチが本当に必要な場合にのみ設定してください。true毎回強制ディスパッチが本当に必要な場合にのみ設定してください。 -
維持する
name、title、levelおよびdescを安定させます。 プラットフォームは、名前、タイトル、説明、レベルが同一のアラームを抑制します。したがって にライブの測定値を連結しないでくださいdesc— 61.2 と 61.5 は別々のアラームであり、重複排除が壊れ、朝起きたら四十件のエントリが並ぶことになります。値を表示する必要がある場合は、バンドまたはカテゴリ(「上限超過」)を表示してください。 -
デフォルトは
clearです。 設定するactionをclearに設定し、newに切り替えるのは条件が成立している場合のみにしてください。そうすれば、各アップリンクが復旧チェックを兼ね、正常に戻ればアラームは自然に消えます。逆(newを違反時のみ送信)にすると、デバイスがオフラインになった場合にアラームが永久に残ります。 -
使用する
delaymsを永続性チェックに使用します。 ノイズの多い測定値(ドアコンタクト、水漏れ、瞬間的な逸脱)については、最初の違反で発報しないでください。delaymsを返すabort_previous_timer: trueを指定して、新しいアップリンクごとに前回の保留中のアクションをキャンセルします — 持続的な逸脱のみがアラームになるのに十分な長さ存続します。 -
しきい値とグループを
server_attrsに置きます。 そうすれば、しきい値の変更にスクリプトの編集、新しいバージョン、再アタッチは不要です。五百台のデバイスが一つのトリガーモデルを共有し、それぞれが独自のしきい値を保持できます — これがこのスケールを可能にします。 -
エスカレーションには二つのシグナルを要求します。 湿度も動いている中の温度高は、温度だけが急上昇するのとは信頼度のレベルが異なります。単一パラメータの違反は
midにとどまり、二つのパラメータが同時に成立するとhighにエスカレートします。これにより、誤検知のかなりの割合が除去されます。
9。通知グループ:実際にサポートされている内容
通知グループはアラーム管理 → 通知グループにあります。Id Name、名前、通知方法、連絡先は必須で、タグとメモは任意です。
| 項目 | 実際の動作 |
|---|---|
| 組み込みメソッド | メール (デフォルト)および WeCom webhook |
| 連絡先 | 複数選択 |
| 有効化スイッチ | デフォルトでオフ — 自分でオンにする必要があります |
| DingTalk / Slack / Telegram | 組み込みフォームにはありません。カスタム RPC が必要です |
これは強調に値します。DingTalk、Slack、Telegram を組み込みチャネルと説明するのは不正確です。これらはカスタム RPC 経由で到達可能であり、それは実在しますがチェックボックスではありません。ありのままに記載するか、受け入れテストが提案と一致しなくなります。
実践的な習慣を一つ:グループ名を device.server_attrs 内の配列として保存し(例えば notify: ["ops-team"])、それをそのまま notifyに渡します。そうすれば、重大度ルーティングはスクリプトの変更ではなく属性の変更になります — 同じトリガーモデルが 500 デバイス全体で各デバイスを独自のグループにルーティングできます。
10。直接適用できる三つのレシピ
| シナリオ | 条件 | レベル | 通知 | クリア条件 |
|---|---|---|---|---|
| KS52 水漏れ | water_leak == 1 |
urgent |
オンコール WeCom グループ | 正常な測定値を持つ次のアップリンク |
| バッテリー低下 | battery <= 20 |
mid |
空の配列(リストのみ) | バッテリー交換後 |
| デバイスオフライン | active_time 2 × より古い heart_period |
high |
運用チームのメール | 次のアップリンク |
オフライン検出に関する注意点が一つ:プラットフォームは三つの異なるオンライン概念を公開しています(リストと統計で使用されるアクティビティ時間基準、 server_attrs.online 検出器、および MQTT data.online 通知)。これらは互換ではありません。トリガースクリプトでオフラインアラームを実装する場合、 active_time と heart_periodを使用していることを明示し、文書化してください。
11。ローンチ前チェックリスト
- [ ]
ALARMRPC が対象デバイスにアタッチされている(トリガーモデルだけでなく) - [ ] トリガーモデルがデバイスのトリガータブでアタッチされている(単に作成されただけでなく)
- [ ]
_euiがparams内に存在し、アクションのトップレベルにない - [ ]
nameが一意で安定しており、アラームタイプごとに一つの名前 - [ ]
levelが四つの有効な値のいずれかである — レベルが欠けているとアラームなしを意味する - [ ] しきい値とグループが
server_attrsにあり、それらが存在しない場合のスクリプトのデフォルトがある - [ ]
actionデフォルトはclearであり、「送信」ではないnew違反時のみ - [ ]
descライブの測定値を埋め込まない(そうしないと重複排除が失敗する) - [ ] 通知グループが手動で有効化されている(デフォルトはオフ)
- [ ] 両方の
newとclearのパスがエディタのテストタブで実行済みである
12。繰り返し見られる八つの誤り
| 症状 | 原因 |
|---|---|
| スクリプトが実行されない | トリガーモデルは作成されたがデバイスに接続されていない |
| スクリプトは実行されるがアラームが表示されない | その ALARM RPC がデバイスに接続されていない |
| アラームのスパム | ライブ値が連結されて descに入り、重複排除を回避している |
| 解除されないアラーム | のみが new 送信される。デバイスがオフラインになるとアラームが宙に浮いたままになる |
| しきい値の変更が反映されない | スクリプト内でしきい値がハードコードされているのに、スクリプト内の server_attrs |
ReferenceError を編集していた |
使用された console、 setTimeout または process。いずれもサンドボックスが注入しないもの |
| スクリプトがハングしたように見える | 使用された async/await。サンドボックスは同期式である |
| 「すべて既読にする」を復旧とみなす | それは既読状態であり、アラームの解除と通知の配信は別物である |
まとめ
使えるアラームシステムはスクリプトで決まるのではない。三つの判断で決まる: 何を本当の異常とみなすか、誰が知る必要があるか、そしていつ静かにしているべきか。 ThinkLink はこの三つすべてをスクリプトと属性設定に委ねる — 一つのモデルで異なるしきい値を持つ 500 デバイスに対応できるほど柔軟だが、その代償として運用開始前に誰かがルールを熟考する必要がある。
上記六つのノイズ低減手法のうち、最も見落とされやすい二つは番号 2( desc を安定させる)と番号 3(デフォルトを clearにする)である。どちらかを飛ばすと、最初の一週間はシステムは問題なく見える — そして誰もアラーム一覧を二度と開かなくなる。
シリーズ次回(第 23 号):データを工場内に保つ — ThinkLink Edge(TKE)のオンプレミス展開、ハードウェア選定と Docker Compose から、クラウドとのモノモデルの双方向移行まで。
ManThink:デバイス接続からデータ活用まで
新規導入や既存システムの更新をご検討中ですか。導入地域、デバイス数、現場のインターフェース、通信・電源環境をManThinkにお知らせください。製品選定やシステム連携の要件についてご相談いただけます。
具体的な機種、構成、適用条件は、公式製品情報とプロジェクト要件に基づいてご確認ください。