依頼者プログラムから模擬計測値を入力したところで、その値と現在警報を発生中か否かを判定して、警報音の鳴動と警報文の表示制御を行っています。
今回、警報文の表示には、JavaFXのConfirmDialogクラスを使ってみました。表示された対話窓にある「了解」ボタンを押すと、onYes属性に定義した操作を実行する仕組みです。
企画を構築して実行すると枠付き窓が表示されます。模擬計測値が90.0を超えると、下図のような警報文の対話窓が表示されます。模擬計測値が設定値を超えている限り、了解ボタンを押しても何度でも警報が発生するようにしています。
プログラム例では、表示速度を3倍に速くしています。:-P)

package client;
import javafx.ui.*;
import javafx.ui.canvas.*;
import java.lang.System;
import client.ScadaClient;
class ScadaDataModel {
attribute presenting: Boolean;
attribute alarting: Boolean;
attribute timingGenerator: Number;
attribute numericDatum: Number;
attribute numericData: Number*;
attribute sc: ScadaClient;
function formatNumber(value:Number): String;
operation getDisplayColor(value:Number): Color;
}
attribute ScadaDataModel.timingGenerator
= bind [1..180] dur 60000 linear continue if presenting;
attribute ScadaDataModel.numericData
= foreach (i in [0..180]) 0;
function ScadaDataModel.formatNumber(value:Number): String {
return value format as <<##0.00>>;
}
operation ScadaDataModel.getDisplayColor(value:Number): Color {
var c:Color = green;
if (value > 90.0) {
c = red;
} else if (value > 75.0) {
c = Color {red: 1.0, green: 0.5, blue: 0.0};
}
return c;
}
trigger on new ScadaDataModel {
sc = new ScadaClient();
}
trigger on ScadaDataModel.timingGenerator = value {
numericDatum = sc.receiveData();
delete numericData[0];
insert numericDatum as last into numericData;
System.out.println("受信生データ: {numericDatum}");
System.out.println("書式化データ: {formatNumber(numericDatum)}");
if ((numericDatum > 90.0) and (not alarting)) {
alarting = true;
sc.startAlarm();
ConfirmDialog {
title: "警報"
message: "流量が上上限値を超過しました!"
visible: true
onYes:
operation() {
sc.stopAlarm();
alarting = false;
}
}
}
}
Frame {
var scadaData = ScadaDataModel {presenting: true, alarting: false}
title: "JavaFX SCADA UI"
centerOnScreen: true
width: 800
height: 600
background: Color {red: 0.9, green: 0.9, blue: 0.9}
onClose: operation() {System.exit(0);}
content: BorderPanel {
center: Canvas {
content:
[Group {
transform: translate(50, 50)
content:
[Rect {
height: 18
width: 50
arcHeight: 4
arcWidth: 4
stroke: blue
fill: white
},
Text {
content: bind scadaData.formatNumber(scadaData.numericDatum)
font: new Font("Monospaced", "PLAIN", 14)
x: 47
y: 4
halign: TRAILING
fill: bind scadaData.getDisplayColor(scadaData.numericDatum)
},
Text {
content: "m3/s"
x: 54
y: 6
}
]
},
Group {
transform: translate(200, 50)
content:
[
Rect {
height: 120
width: 55
stroke: blue
fill: white
},
Rect {
x: 10
y: 10
height: 100
width: 10
fill: LinearGradient {
x1: 0, y1: 0, x2: 0, y2: 1
stops:
[Stop {
offset: 0.1
color: red
},
Stop {
offset: 0.2
color: Color {red: 1.0, green: 0.5, blue: 0.0}
},
Stop {
offset: 0.4
color: Color {red: 0.5, green: 1.0, blue: 0.0}
}]
spreadMethod: PAD
}
},
Rect {
x: 10
y: 10
height: bind 100 - scadaData.numericDatum
width: 10
fill: Color {red: 0.5, green: 0.5, blue: 0.5}
},
Line {
x1: 23
y1: 10
x2: 23
y2: 110
stroke: black
},
Group {
transform: translate(23, 10)
content: foreach (i in [0,20..100])
Line {
transform: [translate(0, i)]
x1: 0
y1: 0
x2: 3
y2: 0
stroke: black
}
},
Group {
transform: translate(32, 10)
content: foreach (i in [0,20..100])
Text {
transform: [translate(0, 100 - i)]
content: "{i}"
font: new Font("Monospaced", "PLAIN", 8)
valign: MIDDLE
halign: LEADING
}
}
]
},
Group {
transform: translate(50, 200)
content:
[
Rect {
height: 120
width: 230
stroke: blue
fill: white
},
Rect {
x: 10
y: 35
height: 76
width: 181
fill: black
},
Rect {
x: 10
y: 20
height: 15
width: 181
fill: Color {red: 0.3, green: 0.3, blue: 0.3}
},
Rect {
x: 10
y: 10
height: 10
width: 181
fill: Color {red: 0.5, green: 0.5, blue: 0.5}
},
Line {
x1: 194
y1: 10
x2: 194
y2: 110
stroke: black
},
Group {
transform: translate(194, 10)
content: foreach (i in [0,20..100])
Line {
transform: [translate(0, i)]
x1: 0
y1: 0
x2: 3
y2: 0
stroke: black
}
},
Group {
transform: translate(203, 10)
content: foreach (i in [0,20..100])
Text {
transform: [translate(0, 100 - i)]
content: "{i}"
font: new Font("Monospaced", "PLAIN", 8)
valign: MIDDLE
halign: LEADING
}
},
Group {
transform: translate(10, 10)
content: foreach (i in [0..179])
Line {
transform: [translate(i, 0)]
x1: 0
y1: bind 100 - scadaData.numericData[i]
x2: 1
y2: bind 100 - scadaData.numericData[i + 1]
stroke: bind scadaData.getDisplayColor(scadaData.numericData[i + 1])
strokeWidth: 2
}
}
]
}
]
}
}
visible: true
}