SWPF-JSON 文法ガイド
SWPF-JSON 文法ガイド(初心者向け・サンプル付き)
swpf_common / swpf_automation の実装(RuleEvaluator.php / SwpfAutomationContextBuilder.php など)に合わせて、迷わず新規作成できるようにまとめたものです。1. RULE_JSON は「テンプレートIDを選ぶための JSON」
SWPF の RULE_JSON は、ざっくり言うと:
- センサー生データ → PARAMS_JSON で PARAMS_MAP を作る
- RULE_JSON が PARAMS_MAP を参照して if 条件を評価
- then / else で「templateid(テンプレートID)」を選ぶ
- 選ばれたテンプレート(
TEMPLATE_JSON)が、最終的な コマンド や 式(EXPRESSION) を決めます
RULE_JSON 自体は「メール本文」や「コマンド」を直接持つものではなく、基本は どのテンプレートIDを使うか を決めるためのルールです
(ただしselectedNodeとして JSON を返すので、leaf に追加情報を入れること自体は可能です。実運用では templateid を中心に運用するのが安全です)
2. まず理解するべき登場人物
2.1 RAW(生データ)
例:IoTデバイスから来る JSON など(温度、湿度…)
{
"temp": 28.4,
"humid": 62,
"device": {"id": "A-001"}
}
2.2 PARAMS_JSON(テンプレート側の設定)
「論理名 → 生データのパス」 の対応表です(ParamsMapBuilder.php で利用)。
{
"TEMP": "temp",
"HUMID": "humid",
"DEVICE_ID": "device.id"
}
2.3 PARAMS_MAP(評価器が参照する実値マップ)
上の PARAMS_JSON に従い、RAWから抽出して作った値:
{
"TEMP": 28.4,
"HUMID": 62,
"DEVICE_ID": "A-001"
}
✅ RULE_JSON の `{ "var": "TEMP" }` は、この PARAMS_MAP のキーを参照します。
3. RULE_JSON の全体構造(最小形)
RULE_JSON は基本的に次の形です:
{
"if": { ...条件式... },
"then": { ...実行したい templateid ... },
"else": { ...実行したい templateid ... }
}
if:条件式(真偽を返すツリー)then:条件が true のときelse:条件が false のとき
4. if 条件式の文法(Bool式)
if の中は、次の4タイプのみをサポートしています:
1) and 2) or 3) not 4) op(比較)
4.0 AND / OR の基本(配列で書く)
and と or は、条件式オブジェクトを配列で並べるのが基本です。
AND(すべて true で true)
配列内の条件が すべて true のとき true になります。途中で false になった時点で短絡評価(そこで終了)します。
{
"and": [
{ "op": ">=", "a": { "var": "TEMP" }, "b": 20 },
{ "op": "<=", "a": { "var": "TEMP" }, "b": 30 }
]
}
OR(どれか 1 つ true で true)
配列内の条件のうち どれか 1 つでも true なら true になります。途中で true が出た時点で短絡評価(そこで終了)します。
{
"or": [
{ "op": ">=", "a": { "var": "TEMP" }, "b": 30 },
{ "op": ">=", "a": { "var": "HUMID" }, "b": 80 }
]
}
※ SWPF実装では、and/or の配列要素は「オブジェクト(JSONの {})」が前提です。AND は不正要素があると false で終わりやすく、OR は errors に積みつつ継続します。
4.1 and(全部 true なら true)
{
"and": [
{ "op": ">=", "a": { "var": "TEMP" }, "b": 20 },
{ "op": "<=", "a": { "var": "TEMP" }, "b": 30 }
]
}
意味:20 <= TEMP <= 30
4.2 or(どれか 1つ true なら true)
{
"or": [
{ "op": ">=", "a": { "var": "TEMP" }, "b": 30 },
{ "op": ">=", "a": { "var": "HUMID" }, "b": 80 }
]
}
意味:TEMP >= 30 または HUMID >= 80
4.3 not(結果を反転)
{
"not": { "op": ">=", "a": { "var": "TEMP" }, "b": 30 }
}
意味:TEMP >= 30 ではない
4.4 op(比較ノード)
比較は次の op をサポートします:
>>=<<=(※ 両方 numeric のときだけ比較)==!=(PHP の緩い比較)
基本形:
{ "op": ">=", "a": { "var": "TEMP" }, "b": 30 }
5. 値ノード(a / b の書き方)
比較 op の a と b に入れられる値は次のどちらかです。
5.1 変数参照ノード { "var": "KEY" }
{ "var": "TEMP" }
KEYは PARAMS_MAP のキー(例:TEMP)
5.2 定数ノード { "value": ... }
定数は 直接数値を書く方法 と、明示的に { "value": ... } を使う方法があります。
{ "op": ">", "a": { "var": "TEMP" }, "b": 28 }
または
{ "op": ">", "a": { "var": "TEMP" }, "b": { "value": 28 } }
✅ どちらでもOKです(実装上は scalar をそのまま値として扱います)
6. then / else の書き方(templateid)
then/else では、最終的に `templateid` を指定します。
6.1 templateid が1つのとき(最もシンプル)
{
"if": { "op": ">=", "a": { "var": "TEMP" }, "b": 30 },
"then": { "templateid": "HOT" },
"else": { "templateid": "DEFAULT" }
}
6.2 templateid を複数にすると「順次実行」される
SwpfAutomationContextBuilder.php では、RULE_JSON から templateid を 複数収集して、 テンプレート(やプロファイル)の設定を 順に deep merge する仕様が維持されています。
{
"if": { "op": ">=", "a": { "var": "TEMP" }, "b": 30 },
"then": { "templateid": ["HOT", "MAIL_ADMIN"] },
"else": { "templateid": ["DEFAULT"] }
}
イメージ:
HOTを実行し、次にMAIL_ADMINを実行する- 結果として「MAIL_ADMIN」の実行結果が返される
ただし2026/1/1時点の仕様では一番最後のTEMPLATE_ID以外は式の評価のみに限定されます。制御等のプラグインを含む処理を複数実施したい場合は、それぞれACTION_TEMPLATEエンティティに登録するようにしてください。
7. ネスト(入れ子) if の書き方
then/else の中に、さらに if/then/else を置けます。 RuleEvaluator.php は選択ノードを 最大 10 階層まで降りて最終ノードを決定します(無限ループ防止)。
{
"if": { "op": "<=", "a": { "var": "TEMP" }, "b": 15 },
"then": { "templateid": "COLD" },
"else": {
"if": { "op": ">=", "a": { "var": "TEMP" }, "b": 30 },
"then": { "templateid": "HOT" },
"else": { "templateid": "DEFAULT" }
}
}
8. 「else を何もしない(NOP)」にしたい場合
例えば「HOT のときだけ通知したい」など。
8.1 else を空にする(おすすめ)
{
"if": { "op": ">=", "a": { "var": "TEMP" }, "b": 30 },
"then": { "templateid": "HOT" },
"else": {}
}
または
{
"if": { "op": ">=", "a": { "var": "TEMP" }, "b": 30 },
"then": { "templateid": "HOT" },
"else": []
}
SWPF 側では templateid が空だと command が空になり NOP 扱いになりやすい設計です。
※ 実行系が「空の templateid をどう扱うか」は executor の実装に依存しますが、現在の設計では “command empty / NOP” に寄せています。
9. 実用サンプル集(コピペ用)
9.1 温度しきい値(3段階)
- TEMP <= 15 →
COLD - TEMP >= 30 →
HOT - それ以外 →
DEFAULT
{
"if": { "op": "<=", "a": { "var": "TEMP" }, "b": 15 },
"then": { "templateid": "COLD" },
"else": {
"if": { "op": ">=", "a": { "var": "TEMP" }, "b": 30 },
"then": { "templateid": "HOT" },
"else": { "templateid": "DEFAULT" }
}
}
9.2 温度 × 湿度(両方で警告)
- TEMP >= 28 かつ HUMID >= 80 →
ALERT_HOT_HUMID - それ以外 →
DEFAULT
{
"if": {
"and": [
{ "op": ">=", "a": { "var": "TEMP" }, "b": 28 },
{ "op": ">=", "a": { "var": "HUMID" }, "b": 80 }
]
},
"then": { "templateid": "ALERT_HOT_HUMID" },
"else": { "templateid": "DEFAULT" }
}
9.3 “範囲外” をまとめて検知(not + and)
- 20〜30 の範囲外 →
TEMP_OUT_OF_RANGE - 範囲内 →
DEFAULT
{
"if": {
"not": {
"and": [
{ "op": ">=", "a": { "var": "TEMP" }, "b": 20 },
{ "op": "<=", "a": { "var": "TEMP" }, "b": 30 }
]
}
},
"then": { "templateid": "TEMP_OUT_OF_RANGE" },
"else": { "templateid": "DEFAULT" }
}
9.4 どれかが危険(or)
- TEMP >= 35 または HUMID >= 90 →
DANGER - それ以外 →
DEFAULT
{
"if": {
"or": [
{ "op": ">=", "a": { "var": "TEMP" }, "b": 35 },
{ "op": ">=", "a": { "var": "HUMID" }, "b": 90 }
]
},
"then": { "templateid": "DANGER" },
"else": { "templateid": "DEFAULT" }
}
10. よくあるミスと対策
10.1 { "var": "TEMP" } が未定義(PARAMS_MAP に無い)
RuleEvaluator.php は Undefined var を errors に積み、値は null になりがちです。 その結果、> >= などの 数値比較は false になりやすいです(is_numeric が通らない)。
✅ 対策:
- PARAMS_JSON に
TEMPを定義しているか - RAW 側に
tempが本当に来ているか - dot.path(例:
device.id)の階層が合っているか
10.2 比較で文字列が混ざる
> >= < <= は 両方 numeric のときのみ動きます。 文字列 "28.4" でも is_numeric は true なので通りますが、"HIGH" などは比較できません。
10.3 書式ミス(and/or/not の中が配列になっていない等)
and/orは配列([])が必要ですnotは単一の子ノードが必要ですopはop/a/bの形が必要です
11. チートシート(最小パターン集)
if(比較)
{ "op": ">=", "a": { "var": "TEMP" }, "b": 30 }
and
{ "and": [ <expr>, <expr> ] }
or
{ "or": [ <expr>, <expr> ] }
not
{ "not": <expr> }
最小 RULE_JSON
{
"if": { "op": ">=", "a": { "var": "TEMP" }, "b": 30 },
"then": { "templateid": "HOT" },
"else": { "templateid": "DEFAULT" }
}
12. 参考:実装上の“仕様メモ”(重要)
- ネスト if の解決:最大 10 階層(無限ループ対策)
- 比較:
>>=<<=は 両方 numeric のときのみ==!=は PHP の緩い比較- templateid の収集:
swpf_common側は leaf のtemplateidを抽出(文字列/配列)swpf_automation側はtemplateidキーを再帰走査して拾う(収集用途)
付録:RULE_JSON を作るときの手順(おすすめ)
1) RAW の例を用意する(実際に来る JSON) 2) PARAMS_JSON を書く(論理名 → パス) 3) PARAMS_MAP を頭の中で作る(TEMP/HUMID が取れる状態にする) 4) RULE_JSON は最初は 最小形から作る(温度だけ) 5) 動いたら and/or/not を足していく 6) 最後に必要なら templateid を配列にして deep merge を使う
当サイトまたはIoTカスタムモジュール、開発支援に関するお問い合わせはこちらのメールフォームからお気軽にお問い合わせください。