大家好,
目前,我正在使用一个简单的温度传感器,它基本上每秒更新4次当前温度,并使用Drools中的以下规则进行筛选:
rule "temperature detected"
when
$acc: Number ( doubleValue > 22.0 ) from accumulate(
$sensorMessage: SensorMessage($topic: topic, $timeStamp: timestamp, $data: data) over window:time ( 10s ) from entry-point "temperature_sensor",
average ( $sensorMessage.getDouble("temperature", -100) )
)
then
logger.info("Received temperature data > 22.0 -> " + $acc);
end然而,在每次传感器更新之后,只要累积的平均温度大于22,超过10秒的窗口,就会记录控制台。
当然,这远非理想。
是否可以在接收到传感器更新后,继续侦听,直到没有收到任何更新,例如,3秒。然后记录首先检测到传感器更新的起始时间和结束时间。如果总共收到至少10个更新,并且满足了一些标准,则只记录这两个时间戳。
示例场景(T是某个目标温度):
<= T,则什么都不会发生,但是,如果超过T,则记录单个温度“警报”。F 211
发布于 2022-11-29 02:07:07
这就是我几个小时后想到的。有些要求对我来说并不清楚,比如什么是‘最后一个更新记录’,每一个都是‘最后一个’。下面可能仍然需要做一些工作,但您可能会有一个大致的想法:我们在更新和监视的会话中只有一个对象。
import java.lang.Double;
import java.util.ArrayList;
declare SensorMessage
@role(event)
@timestamp(timestamp)
@expires(10s)
end
rule "temperature monitoring"
when
$meta: SensorMetadata()
$acc: Double () from accumulate(
$message: SensorMessage() over window:time(1s),
average ($message.getTemperature())
)
then
$meta.setTemperature($acc);
update($meta);
end
rule "temperature activated"
when
$meta: SensorMetadata(highTemperature == false, temperature >= $meta.targetTemperature)
$lastMessage: SensorMessage($lastTimestamp: timestamp)
not (SensorMessage(timestamp > $lastMessage.timestamp))
then
$meta.setLastActivated($lastMessage.getTimestamp());
$meta.setHighTemperature(true);
update($meta);
System.out.printf("temperature activated %.2f%n", $meta.getTemperature());
end
rule "temperature deactivated"
when
$meta: SensorMetadata(highTemperature == true, temperature < $meta.targetTemperature)
$lastMessage: SensorMessage($lastTimestamp: timestamp)
not (SensorMessage(timestamp > $lastMessage.timestamp))
then
$meta.setHighTemperature(false);
update($meta);
System.out.printf("temperature deactivated %.2f%n", $meta.getTemperature());
end
rule "throttle state activated"
when
$meta: SensorMetadata(throttleState == false)
$lastMessage: SensorMessage($lastTimestamp: timestamp)
not (SensorMessage(timestamp > $lastMessage.timestamp))
$messages: ArrayList(size > 20) from collect(
$message: SensorMessage() over window:time(1s)
)
then
$meta.setLastThrottled($lastMessage.getTimestamp());
$meta.setThrottleState(true);
update($meta);
System.out.printf("throttle state activated %d%n", $messages.size());
end
rule "throttle state deactivated"
when
$meta: SensorMetadata(throttleState == true)
$lastMessage: SensorMessage($lastTimestamp: timestamp)
not (SensorMessage(timestamp > $lastMessage.timestamp))
$messages: ArrayList(size <= 20) from collect(
$message: SensorMessage() over window:time(1s)
)
then
$meta.setThrottleState(false);
update($meta);
System.out.printf("throttle state deactivated %d%n", $messages.size());
end测试
@DroolsSession(resources = "file:src/main/resources/draft/rule.drl", showStateTransitionPopup = true, ignoreRules = "* monitoring")
public class PlaygroundTest extends DroolsAssert {
@RegisterExtension
public DroolsAssert droolsAssert = this;
@Test
@TestRules(ignore = "throttle *", expectedCount = {
"2", "temperature activated",
"2", "temperature deactivated" })
public void testTemperatureActivationDeactivation() throws IOException {
insert(new SensorMetadata(22));
Date date = new Date(0);
for (int i = 0; i < 100; i++) {
double temperature = i == 80 ? 100 : i == 81 ? -100 : i < 50 ? i : 1 / i;
insertAndFire(new SensorMessage(date, temperature));
date = addMilliseconds(date, 1);
advanceTime(MILLISECONDS, 1);
}
advanceTime(10, SECONDS);
assertFactsCount(1);
}
@Test
@TestRules(ignore = "temperature *", expectedCount = {
"2", "throttle state activated",
"2", "throttle state deactivated" })
public void testThrottleMode() throws IOException {
insert(new SensorMetadata(22));
Date date = new Date(0);
for (int i = 0; i < 100; i++) {
insertAndFire(new SensorMessage(date, 22));
int advanceTime = i * 3;
date = addMilliseconds(date, advanceTime);
advanceTime(MILLISECONDS, advanceTime);
}
advanceTime(10, SECONDS);
assertFactsCount(1);
}
}和模型
public class SensorMessage {
private Date timestamp;
private double temperature;
public SensorMessage(Date timestamp, double temperature) {
this.timestamp = timestamp;
this.temperature = temperature;
}
// getters
}public class SensorMetadata {
private volatile Date lastActivated;
private volatile Date lastThrottled;
private double temperature;
private boolean highTemperature;
private boolean throttleState;
private double targetTemperature;
public SensorMetadata(double targetTemperature) {
this.targetTemperature = targetTemperature;
}
// getters and setters
}https://stackoverflow.com/questions/74488300
复制相似问题