メインコンテンツまでスキップ

Formula(計算式、fomula)使用ガイド

タグ登録時に fomula フィールドへ算術式を入力すると、ドライバが PLC から読み取った生値(raw value)を後処理し、変換後の値をキャッシュ / Sparkplug / REST レスポンスに使用します。

項目
実装クラスplantpulse.app.edge.component.collector.plc.PLCValueFomula
呼び出し位置PLCValueReader.read() の 3 段階目(raw → format → fomula → キャッシュ更新)
ライブラリplantpulse-edge-fomula.jar (plantpulse.edge.fomula.FormulaEngine)
変数置換${VALUE}(現在のタグ値) / ${tag_id}(他タグの最終値、LastValueMap キャッシュ)
適用対象 data_typeFloat / Double / Integer / Long のみ適用。その他の型(String、Boolean、…)はそのまま通過
結果Formula.evaluate(...)BigDecimal → 型ごとのレンダリング(整数系は整数、Float/Double は小数)

動作フロー

  1. ドライバから raw 文字列値を受け取る(例:"16384")。

  2. PLCValueFomula.fomulaValue(address, value) を呼び出し。

  3. address.getFomula() が空であればそのまま返却。

  4. data_type が Float / Double / Integer / Long でなければ そのまま返却。

  5. 計算式が参照する名前を確認 — VALUE は今読み取った値、それ以外は LastValueMap にある他タグの最終値。

  6. 参照タグが一度も収集されていない場合は例外:

    Variable value referenced by the formula is not yet in cache : formula=[`<fomula>`], variable=[`<name>`]
  7. 計算式が参照する名前のみを値にバインドして評価 → BigDecimal → 型ごとの文字列を返却。


変数の種類

表記意味出典
${VALUE}現在のタグの raw 値ドライバが読み取った直後の値
${TAG_ID_X}他タグの最終値LastValueMap(全タグ共用キャッシュ)

LastValueMap は全タグの最終 raw / 後処理値を保持します。同一 OPC 内の他タグだけでなく、別の OPC のタグも参照できます(ただし、そのタグが一度でも収集されキャッシュに存在している必要があります)。

変数が存在しない場合

${TAG_ZERO} を参照したが TAG_ZERO が一度も収集されていない場合、値をバインドできず例外が発生します。参照タグの timecycle をより短くするか、参照タグが先に収集されるよう auto_collect=true で登録してください。(保存時の構文チェックはこのケースを通過させます — 収集順序の問題であり、式の誤りではありません。)


式の文法

Excel と同じ書き方をします。 関数名と意味が Excel と同一なので、Excel で使っていた式をほぼ そのまま移せます。大文字・小文字は区別しません(IF = if)。

カテゴリトークン備考
算術+, -, *, /, ^^ はべき乗
比較>, <, >=, <=, =, <>= は等しい、<> は等しくない(Excel と同一)
グループ(, )括弧が優先
定数PI, E円周率、自然対数の底
条件IF, SWITCH, AND, OR, NOTIF(조건, 참일때, 거짓일때)
丸めROUND, ROUNDUP, ROUNDDOWN, CEILING, FLOOR, INT, TRUNCROUND(값, 자리수)
数値ABS, SIGN, MOD, POWER, SQRT, CBRT, EXP, FACTMOD の剰余の符号は除数に従う
集計MIN, MAX, SUM, AVERAGE, COALESCE引数は複数可
対数LOG, LOG10, LNLOG = 常用対数(底10)LN = 自然対数
三角SIN, COS, TAN, ASIN, ACOS, ATAN, ATAN2ラジアン基準(Excel と同一)
双曲線SINH, COSH, TANH, ASINH, ACOSH, ATANH
角度変換DEGREES, RADIANSラジアン ↔ 度
サポートしないもの
  • ビット演算(&, |
  • ユーザー定義関数
  • 文字列演算 / 日付演算 これらが必要な場合は、後続の段階(外部関数 / 後処理ノード)で扱ってください。
不正な計算式は保存されません

文法が正しくない計算式は保存時に拒否されます(UI 保存 / CSV アップロード / バックアップ復元すべて)。 タグ設定モーダルでサンプル値を入力して結果を事前確認できます。

計算中の失敗(0 除算、参照値が数値でない等)は収集エラーとして記録され、該当タグの 品質が低下します。もっともらしい数値を代わりに保存することはありません。

変数表記

${VALUE} と素の名前 VALUE の両方が使えます。他タグも同様です — ${TAG_ZERO} = TAG_ZERO。既存に保存された ${...} の計算式はそのまま動作します。

${VALUE}*0.1 기존 표기
VALUE*0.1 같은 뜻
IF(VALUE>100, 100, VALUE*0.1) 엑셀식

豊富な例集

1. 単純スケール(×0.1)

項目
data_typeFloat
fomula${VALUE}*0.1
入力 → 出力163841638.4

用途:整数 raw → 小数点 1 桁の実数。温度 / 圧力 / 流量センサが整数で値を送る場合。

2. 単位変換(mV → V)

項目
data_typeFloat
fomula${VALUE}/1000
入力 → 出力33003.3

3. オフセット補正(摂氏 → ケルビン)

項目
data_typeFloat
fomula${VALUE}+273.15
入力 → 出力25298.15

4. 他タグの参照(ゼロ点補正)

項目
data_typeFloat
fomula${VALUE}-${TAG_ZERO}
入力 → 出力VALUE=1024, TAG_ZERO=241000

TAG_ZERO は他タグの ID。ゼロ点 / Tare 補正に使用します。

5. 多項式(二乗)

項目
data_typeFloat
fomula${VALUE}*${VALUE}*0.001
入力 → 出力10010.0

6. 関数 — 平方根

項目
data_typeFloat
fomulasqrt(${VALUE})
入力 → 出力14412.0

7. 関数 — 三角(sin, radian)

項目
data_typeFloat
fomulasin(${VALUE})
入力 → 出力1.5708(≈π/2) → 1.0

角度(degree)入力の場合は sin(${VALUE}*pi/180)

8. 複数タグ — キャリブレーション(gain × x + offset)

項目
data_typeFloat
fomula${VALUE}*${TAG_GAIN}+${TAG_OFFSET}
入力 → 出力VALUE=100, GAIN=0.05, OFFSET=27.0

装置ごとの補正係数を別タグ(または HTTP-bind タグ)で管理するパターン。

9. 型変換 / 強制的な実数化

項目
data_typeFloat
fomula${VALUE}*1.0
入力 → 出力123123.0

Integer で入ってきた値を Float にキャストするだけにしたい場合。

10. べき乗 / 指数

項目
data_typeFloat
fomula${VALUE}^2
入力 → 出力525.0

11. 対数

項目
data_typeFloat
fomulalog(${VALUE})
入力 → 出力1002.0

ln(...) も使用可能(自然対数)。

12. 複合 — RMS の dB 変換

項目
data_typeFloat
fomula20*log(${VALUE})
入力 → 出力100060.0

REST 登録例(curl)

タグ単体の登録:

curl -X POST http://<edge-host>/api/v1/opc/OPC_LS_XBM_0001/tag \
-H "Content-Type: application/json" \
-d '{
"tag_id": "OPC_LS_XBM_0001_TAG_PRESS",
"tag_name": "Pressure (kPa)",
"plc_address": "D00100",
"data_type": "Float",
"format": "REAL",
"fomula": "${VALUE}*0.1",
"description": "스케일 ×0.1 적용"
}'

OPC + タグを一括登録する場合は、tag_list[] の中に fomula を入れてください。

値の read(後処理された値が返されます):

curl -s http://<edge-host>/api/v1/tag/OPC_LS_XBM_0001_TAG_PRESS/value | jq
# {
# "result": "OK",
# "data": {
# "tag_id": "OPC_LS_XBM_0001_TAG_PRESS",
# "value": "1638.4",
# ...
# }
# }

よくあるエラーと解決

メッセージ / 症状原因解決
계산식에 해당하는 변수값이 아직 캐시에 없습니다 : 계산식=[${VALUE}-${TAG_ZERO}]参照タグ(TAG_ZERO)が一度も収集されていない参照タグを先に登録し、auto_collect=true で 1 サイクル回しておく
계산식이 참조하는 값이 숫자가 아닙니다参照タグの値が数値でない(例:data_type=String のタグを参照)数値型タグを参照するよう修正
Closing brace not found / Missing second operand括弧の対応が取れていない、または演算子の後に被演算子が欠落保存時に拒否されるため、モーダルのエラーメッセージが位置まで示します
後処理が適用されない(raw がそのまま返る)data_type が String/BooleanFloat/Double/Integer/Long に変更する、または後処理が必要なら別の加工段階を使用
結果が常に 0raw 値が実際に 0raw read 値をまず GET /api/v1/tag/.../value で確認。(旧パーサは ${VALUE}* のような不完全な式を黙って 0 として計算していましたが、現在はそのような式は保存段階で拒否されます。)
収集エラー FORMAT_FAILED + 品質低下0 による除算や sqrt が負数などで計算失敗Infinity/NaN を保存せずエラーとして表出させます。式にガードを入れてください — 例:IF(TAG_ZERO=0, 0, VALUE/TAG_ZERO)

動作メモ

  • LastValueMapシングルトン(in-memory)。ゲートウェイ再起動時に初期化される → 最初のサイクルでは他タグ参照が失敗する場合があります。
  • 計算は全区間 BigDecimal のため、Long/QWord の大きな整数も最終桁まで保存されます(旧 double 評価で発生していた損失はありません)。
  • 結果は Double.toString() → 文字列キャッシュ。画面 / Sparkplug 発行時に再び data_type にキャストされます(Sparkplug DataTypeMapper 参照)。
  • 同一 OPC 内で複数タグの fomula が互いを参照すると、収集順序によって最初のサイクルが部分的に失敗することがあります。運用上大きな問題ではありませんが(次のサイクルからは正常)、きれいに動かすには参照対象タグをより短い timecycle の別 OPC に配置してください。