Browse Source

DeviceProfileRuleNode

pull/3551/head
Andrii Shvaika 6 years ago
parent
commit
1278339e61
  1. 5
      common/data/src/main/java/org/thingsboard/server/common/data/device/profile/AlarmCondition.java
  2. 35
      common/data/src/main/java/org/thingsboard/server/common/data/device/profile/AlarmConditionSpec.java
  3. 24
      common/data/src/main/java/org/thingsboard/server/common/data/device/profile/AlarmConditionSpecType.java
  4. 1
      common/data/src/main/java/org/thingsboard/server/common/data/device/profile/AlarmRule.java
  5. 35
      common/data/src/main/java/org/thingsboard/server/common/data/device/profile/AlarmSchedule.java
  6. 24
      common/data/src/main/java/org/thingsboard/server/common/data/device/profile/AlarmScheduleType.java
  7. 25
      common/data/src/main/java/org/thingsboard/server/common/data/device/profile/AnyTimeSchedule.java
  8. 33
      common/data/src/main/java/org/thingsboard/server/common/data/device/profile/CustomTimeSchedule.java
  9. 30
      common/data/src/main/java/org/thingsboard/server/common/data/device/profile/CustomTimeScheduleItem.java
  10. 32
      common/data/src/main/java/org/thingsboard/server/common/data/device/profile/DurationAlarmConditionSpec.java
  11. 31
      common/data/src/main/java/org/thingsboard/server/common/data/device/profile/RepeatingAlarmConditionSpec.java
  12. 26
      common/data/src/main/java/org/thingsboard/server/common/data/device/profile/SimpleAlarmConditionSpec.java
  13. 35
      common/data/src/main/java/org/thingsboard/server/common/data/device/profile/SpecificTimeSchedule.java
  14. 107
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/profile/AlarmRuleState.java
  15. 16
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/profile/DeviceState.java
  16. 29
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/profile/TbDeviceProfileNode.java
  17. 1
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/profile/state/PersistedAlarmRuleState.java

5
common/data/src/main/java/org/thingsboard/server/common/data/device/profile/AlarmCondition.java

@ -15,6 +15,7 @@
*/
package org.thingsboard.server.common.data.device.profile;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Data;
import org.thingsboard.server.common.data.query.KeyFilter;
@ -22,10 +23,10 @@ import java.util.List;
import java.util.concurrent.TimeUnit;
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class AlarmCondition {
private List<KeyFilter> condition;
private TimeUnit durationUnit;
private long durationValue;
private AlarmConditionSpec spec;
}

35
common/data/src/main/java/org/thingsboard/server/common/data/device/profile/AlarmConditionSpec.java

@ -0,0 +1,35 @@
/**
* Copyright © 2016-2020 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.common.data.device.profile;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY,
property = "type")
@JsonSubTypes({
@JsonSubTypes.Type(value = SimpleAlarmConditionSpec.class, name = "SIMPLE"),
@JsonSubTypes.Type(value = DurationAlarmConditionSpec.class, name = "DURATION"),
@JsonSubTypes.Type(value = RepeatingAlarmConditionSpec.class, name = "REPEATING")})
public interface AlarmConditionSpec {
AlarmConditionSpecType getType();
}

24
common/data/src/main/java/org/thingsboard/server/common/data/device/profile/AlarmConditionSpecType.java

@ -0,0 +1,24 @@
/**
* Copyright © 2016-2020 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.common.data.device.profile;
public enum AlarmConditionSpecType {
SIMPLE,
DURATION,
REPEATING
}

1
common/data/src/main/java/org/thingsboard/server/common/data/device/profile/AlarmRule.java

@ -21,6 +21,7 @@ import lombok.Data;
public class AlarmRule {
private AlarmCondition condition;
private AlarmSchedule schedule;
// Advanced
private String alarmDetails;

35
common/data/src/main/java/org/thingsboard/server/common/data/device/profile/AlarmSchedule.java

@ -0,0 +1,35 @@
/**
* Copyright © 2016-2020 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.common.data.device.profile;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY,
property = "type")
@JsonSubTypes({
@JsonSubTypes.Type(value = SimpleAlarmConditionSpec.class, name = "ANY_TIME"),
@JsonSubTypes.Type(value = DurationAlarmConditionSpec.class, name = "SPECIFIC_TIME"),
@JsonSubTypes.Type(value = RepeatingAlarmConditionSpec.class, name = "CUSTOM")})
public interface AlarmSchedule {
AlarmScheduleType getType();
}

24
common/data/src/main/java/org/thingsboard/server/common/data/device/profile/AlarmScheduleType.java

@ -0,0 +1,24 @@
/**
* Copyright © 2016-2020 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.common.data.device.profile;
public enum AlarmScheduleType {
ANY_TIME,
SPECIFIC_TIME,
CUSTOM
}

25
common/data/src/main/java/org/thingsboard/server/common/data/device/profile/AnyTimeSchedule.java

@ -0,0 +1,25 @@
/**
* Copyright © 2016-2020 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.common.data.device.profile;
public class AnyTimeSchedule implements AlarmSchedule {
@Override
public AlarmScheduleType getType() {
return AlarmScheduleType.ANY_TIME;
}
}

33
common/data/src/main/java/org/thingsboard/server/common/data/device/profile/CustomTimeSchedule.java

@ -0,0 +1,33 @@
/**
* Copyright © 2016-2020 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.common.data.device.profile;
import lombok.Data;
import java.util.List;
@Data
public class CustomTimeSchedule implements AlarmSchedule {
private String timezone;
private List<CustomTimeScheduleItem> items;
@Override
public AlarmScheduleType getType() {
return AlarmScheduleType.CUSTOM;
}
}

30
common/data/src/main/java/org/thingsboard/server/common/data/device/profile/CustomTimeScheduleItem.java

@ -0,0 +1,30 @@
/**
* Copyright © 2016-2020 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.common.data.device.profile;
import lombok.Data;
import java.util.List;
@Data
public class CustomTimeScheduleItem {
private boolean enabled;
private Integer dayOfWeek;
private long startsOn;
private long endsOn;
}

32
common/data/src/main/java/org/thingsboard/server/common/data/device/profile/DurationAlarmConditionSpec.java

@ -0,0 +1,32 @@
/**
* Copyright © 2016-2020 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.common.data.device.profile;
import lombok.Data;
import java.util.concurrent.TimeUnit;
@Data
public class DurationAlarmConditionSpec implements AlarmConditionSpec {
private TimeUnit unit;
private long value;
@Override
public AlarmConditionSpecType getType() {
return AlarmConditionSpecType.SIMPLE;
}
}

31
common/data/src/main/java/org/thingsboard/server/common/data/device/profile/RepeatingAlarmConditionSpec.java

@ -0,0 +1,31 @@
/**
* Copyright © 2016-2020 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.common.data.device.profile;
import lombok.Data;
import java.util.concurrent.TimeUnit;
@Data
public class RepeatingAlarmConditionSpec implements AlarmConditionSpec {
private int count;
@Override
public AlarmConditionSpecType getType() {
return AlarmConditionSpecType.SIMPLE;
}
}

26
common/data/src/main/java/org/thingsboard/server/common/data/device/profile/SimpleAlarmConditionSpec.java

@ -0,0 +1,26 @@
/**
* Copyright © 2016-2020 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.common.data.device.profile;
import lombok.Data;
@Data
public class SimpleAlarmConditionSpec implements AlarmConditionSpec {
@Override
public AlarmConditionSpecType getType() {
return AlarmConditionSpecType.SIMPLE;
}
}

35
common/data/src/main/java/org/thingsboard/server/common/data/device/profile/SpecificTimeSchedule.java

@ -0,0 +1,35 @@
/**
* Copyright © 2016-2020 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.common.data.device.profile;
import lombok.Data;
import java.util.List;
@Data
public class SpecificTimeSchedule implements AlarmSchedule {
private String timezone;
private List<Integer> daysOfWeek;
private long startsOn;
private long endsOn;
@Override
public AlarmScheduleType getType() {
return AlarmScheduleType.SPECIFIC_TIME;
}
}

107
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/profile/AlarmRuleState.java

@ -19,7 +19,11 @@ import lombok.Data;
import org.thingsboard.rule.engine.profile.state.PersistedAlarmRuleState;
import org.thingsboard.server.common.data.alarm.AlarmSeverity;
import org.thingsboard.server.common.data.device.profile.AlarmCondition;
import org.thingsboard.server.common.data.device.profile.AlarmConditionSpec;
import org.thingsboard.server.common.data.device.profile.AlarmRule;
import org.thingsboard.server.common.data.device.profile.DurationAlarmConditionSpec;
import org.thingsboard.server.common.data.device.profile.RepeatingAlarmConditionSpec;
import org.thingsboard.server.common.data.device.profile.SimpleAlarmConditionSpec;
import org.thingsboard.server.common.data.query.BooleanFilterPredicate;
import org.thingsboard.server.common.data.query.ComplexFilterPredicate;
import org.thingsboard.server.common.data.query.KeyFilter;
@ -32,7 +36,9 @@ public class AlarmRuleState {
private final AlarmSeverity severity;
private final AlarmRule alarmRule;
private final AlarmConditionSpec spec;
private final long requiredDurationInMs;
private final long requiredRepeats;
private PersistedAlarmRuleState state;
private boolean updateFlag;
@ -42,13 +48,31 @@ public class AlarmRuleState {
if (state != null) {
this.state = state;
} else {
this.state = new PersistedAlarmRuleState(0L, 0L);
this.state = new PersistedAlarmRuleState(0L, 0L, 0L);
}
if (alarmRule.getCondition().getDurationValue() > 0) {
requiredDurationInMs = alarmRule.getCondition().getDurationUnit().toMillis(alarmRule.getCondition().getDurationValue());
} else {
requiredDurationInMs = 0;
this.spec = getSpec(alarmRule);
long requiredDurationInMs = 0;
long requiredRepeats = 0;
switch (spec.getType()) {
case DURATION:
DurationAlarmConditionSpec duration = (DurationAlarmConditionSpec) spec;
requiredDurationInMs = duration.getUnit().toMillis(duration.getValue());
break;
case REPEATING:
RepeatingAlarmConditionSpec repeating = (RepeatingAlarmConditionSpec) spec;
requiredRepeats = repeating.getCount();
break;
}
this.requiredDurationInMs = requiredDurationInMs;
this.requiredRepeats = requiredRepeats;
}
public AlarmConditionSpec getSpec(AlarmRule alarmRule) {
AlarmConditionSpec spec = alarmRule.getCondition().getSpec();
if (spec == null) {
spec = new SimpleAlarmConditionSpec();
}
return spec;
}
public boolean checkUpdate() {
@ -61,38 +85,70 @@ public class AlarmRuleState {
}
public boolean eval(DeviceDataSnapshot data) {
if (requiredDurationInMs > 0) {
boolean eval = eval(alarmRule.getCondition(), data);
if (eval) {
if (state.getLastEventTs() > 0) {
if (data.getTs() > state.getLastEventTs()) {
state.setDuration(state.getDuration() + (data.getTs() - state.getLastEventTs()));
state.setLastEventTs(data.getTs());
updateFlag = true;
}
} else {
switch (spec.getType()) {
case SIMPLE:
return eval(alarmRule.getCondition(), data);
case DURATION:
return evalDuration(data);
case REPEATING:
return evalRepeating(data);
default:
return false;
}
}
private boolean evalRepeating(DeviceDataSnapshot data) {
boolean eval = eval(alarmRule.getCondition(), data);
if (eval) {
state.setEventCount(state.getEventCount() + 1);
updateFlag = true;
return state.getEventCount() > requiredRepeats;
} else {
if (state.getEventCount() > 0) {
state.setEventCount(0L);
updateFlag = true;
}
return false;
}
}
private boolean evalDuration(DeviceDataSnapshot data) {
boolean eval = eval(alarmRule.getCondition(), data);
if (eval) {
if (state.getLastEventTs() > 0) {
if (data.getTs() > state.getLastEventTs()) {
state.setDuration(state.getDuration() + (data.getTs() - state.getLastEventTs()));
state.setLastEventTs(data.getTs());
state.setDuration(0L);
updateFlag = true;
}
return state.getDuration() > requiredDurationInMs;
} else {
state.setLastEventTs(0L);
state.setLastEventTs(data.getTs());
state.setDuration(0L);
updateFlag = true;
return false;
}
return state.getDuration() > requiredDurationInMs;
} else {
return eval(alarmRule.getCondition(), data);
if (state.getLastEventTs() > 0 || state.getDuration() > 0) {
state.setLastEventTs(0L);
state.setDuration(0L);
updateFlag = true;
}
return false;
}
}
public boolean eval(long ts) {
if (requiredDurationInMs > 0 && state.getLastEventTs() > 0 && ts > state.getLastEventTs()) {
long duration = state.getDuration() + (ts - state.getLastEventTs());
return duration > requiredDurationInMs;
} else {
return false;
switch (spec.getType()) {
case SIMPLE:
case REPEATING:
return false;
case DURATION:
if (requiredDurationInMs > 0 && state.getLastEventTs() > 0 && ts > state.getLastEventTs()) {
long duration = state.getDuration() + (ts - state.getLastEventTs());
return duration > requiredDurationInMs;
}
default:
return false;
}
}
@ -144,7 +200,6 @@ public class AlarmRuleState {
}
}
private boolean evalBoolPredicate(EntityKeyValue ekv, BooleanFilterPredicate predicate) {
Boolean value;
switch (ekv.getDataType()) {

16
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/profile/DeviceState.java

@ -62,18 +62,22 @@ class DeviceState {
private DeviceDataSnapshot latestValues;
private final ConcurrentMap<String, DeviceProfileAlarmState> alarmStates = new ConcurrentHashMap<>();
public DeviceState(TbContext ctx, TbDeviceProfileNodeConfiguration config, DeviceId deviceId, DeviceProfileState deviceProfile) {
public DeviceState(TbContext ctx, TbDeviceProfileNodeConfiguration config, DeviceId deviceId, DeviceProfileState deviceProfile, RuleNodeState state) {
this.persistState = config.isPersistAlarmRulesState();
this.deviceId = deviceId;
this.deviceProfile = deviceProfile;
if (config.isPersistAlarmRulesState()) {
state = ctx.findRuleNodeStateForEntity(deviceId);
if (state != null) {
pds = JacksonUtil.fromString(state.getStateData(), PersistedDeviceState.class);
this.state = state;
} else {
state = new RuleNodeState();
state.setRuleNodeId(ctx.getSelfId());
state.setEntityId(deviceId);
this.state = ctx.findRuleNodeStateForEntity(deviceId);
}
if (this.state != null) {
pds = JacksonUtil.fromString(this.state.getStateData(), PersistedDeviceState.class);
} else {
this.state = new RuleNodeState();
this.state.setRuleNodeId(ctx.getSelfId());
this.state.setEntityId(deviceId);
pds = new PersistedDeviceState();
pds.setAlarmStates(new HashMap<>());
}

29
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/profile/TbDeviceProfileNode.java

@ -30,6 +30,8 @@ import org.thingsboard.server.common.data.DeviceProfile;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.id.DeviceId;
import org.thingsboard.server.common.data.id.DeviceProfileId;
import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.common.data.plugin.ComponentType;
import org.thingsboard.server.common.data.rule.RuleNodeState;
import org.thingsboard.server.common.msg.TbMsg;
@ -65,11 +67,28 @@ public class TbDeviceProfileNode implements TbNode {
this.config = TbNodeUtils.convert(configuration, TbDeviceProfileNodeConfiguration.class);
this.cache = ctx.getDeviceProfileCache();
scheduleAlarmHarvesting(ctx);
//TODO: launch a process of fetching the alarm rule states from the database;
if (config.isFetchAlarmRulesStateOnStart()) {
PageLink pageLink = new PageLink(1024);
while (true) {
PageData<RuleNodeState> states = ctx.findRuleNodeStates(pageLink);
if (!states.getData().isEmpty()) {
for (RuleNodeState rns : states.getData()) {
if (rns.getEntityId().getEntityType().equals(EntityType.DEVICE) && ctx.isLocalEntity(rns.getEntityId())) {
getOrCreateDeviceState(ctx, new DeviceId(rns.getEntityId().getId()), rns);
}
}
}
if (!states.hasNext()) {
break;
} else {
pageLink = pageLink.nextPageLink();
}
}
}
}
/**
* 2. Dynamic values evaluation;
* TODO: Dynamic values evaluation;
*/
@Override
public void onMsg(TbContext ctx, TbMsg msg) throws ExecutionException, InterruptedException {
@ -85,7 +104,7 @@ public class TbDeviceProfileNode implements TbNode {
} else if (msg.getType().equals(DataConstants.ENTITY_DELETED)) {
deviceStates.remove(deviceId);
} else {
DeviceState deviceState = getOrCreateDeviceState(ctx, deviceId);
DeviceState deviceState = getOrCreateDeviceState(ctx, deviceId, null);
if (deviceState != null) {
deviceState.process(ctx, msg);
} else {
@ -124,12 +143,12 @@ public class TbDeviceProfileNode implements TbNode {
deviceStates.clear();
}
protected DeviceState getOrCreateDeviceState(TbContext ctx, DeviceId deviceId) {
protected DeviceState getOrCreateDeviceState(TbContext ctx, DeviceId deviceId, RuleNodeState rns) {
DeviceState deviceState = deviceStates.get(deviceId);
if (deviceState == null) {
DeviceProfile deviceProfile = cache.get(ctx.getTenantId(), deviceId);
if (deviceProfile != null) {
deviceState = new DeviceState(ctx, config, deviceId, new DeviceProfileState(deviceProfile));
deviceState = new DeviceState(ctx, config, deviceId, new DeviceProfileState(deviceProfile), rns);
deviceStates.put(deviceId, deviceState);
}
}

1
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/profile/state/PersistedAlarmRuleState.java

@ -26,5 +26,6 @@ public class PersistedAlarmRuleState {
private long lastEventTs;
private long duration;
private long eventCount;
}

Loading…
Cancel
Save