首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Drools -如何使用窗口应用高级过滤?

Drools -如何使用窗口应用高级过滤?
EN

Stack Overflow用户
提问于 2022-11-18 10:32:38
回答 1查看 81关注 0票数 4

大家好,

目前,我正在使用一个简单的温度传感器,它基本上每秒更新4次当前温度,并使用Drools中的以下规则进行筛选:

代码语言:javascript
运行
复制
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是某个目标温度):

  • 如果运动传感器在2秒内发送20次更新,则记录第一次更新的时间和最后一次更新的时间。
  • 如果运动传感器1秒内发送6次更新,5秒后再进行6次更新,则什么也不会发生,因为我们期望更多的运动传感器更新为运动。如果温度传感器在1秒内发送10次更新,并且所有10次更新的平均值为<= T,则什么都不会发生,但是,如果超过T,则记录单个温度“警报”。

F 211

EN

回答 1

Stack Overflow用户

发布于 2022-11-29 02:07:07

这就是我几个小时后想到的。有些要求对我来说并不清楚,比如什么是‘最后一个更新记录’,每一个都是‘最后一个’。下面可能仍然需要做一些工作,但您可能会有一个大致的想法:我们在更新和监视的会话中只有一个对象。

代码语言:javascript
运行
复制
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

测试

代码语言:javascript
运行
复制
@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);
    }
}

和模型

代码语言:javascript
运行
复制
public class SensorMessage {
    private Date timestamp;
    private double temperature;

    public SensorMessage(Date timestamp, double temperature) {
        this.timestamp = timestamp;
        this.temperature = temperature;
    }
    // getters
}

代码语言:javascript
运行
复制
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
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74488300

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档