Showing
17 changed files
with
450 additions
and
39 deletions
... | ... | @@ -15,6 +15,7 @@ |
15 | 15 | */ |
16 | 16 | package org.thingsboard.server.common.data.device.profile; |
17 | 17 | |
18 | +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; | |
18 | 19 | import lombok.Data; |
19 | 20 | import org.thingsboard.server.common.data.query.KeyFilter; |
20 | 21 | |
... | ... | @@ -22,10 +23,10 @@ import java.util.List; |
22 | 23 | import java.util.concurrent.TimeUnit; |
23 | 24 | |
24 | 25 | @Data |
26 | +@JsonIgnoreProperties(ignoreUnknown = true) | |
25 | 27 | public class AlarmCondition { |
26 | 28 | |
27 | 29 | private List<KeyFilter> condition; |
28 | - private TimeUnit durationUnit; | |
29 | - private long durationValue; | |
30 | + private AlarmConditionSpec spec; | |
30 | 31 | |
31 | 32 | } | ... | ... |
common/data/src/main/java/org/thingsboard/server/common/data/device/profile/AlarmConditionSpec.java
0 → 100644
1 | +/** | |
2 | + * Copyright © 2016-2020 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +package org.thingsboard.server.common.data.device.profile; | |
17 | + | |
18 | +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; | |
19 | +import com.fasterxml.jackson.annotation.JsonSubTypes; | |
20 | +import com.fasterxml.jackson.annotation.JsonTypeInfo; | |
21 | + | |
22 | +@JsonIgnoreProperties(ignoreUnknown = true) | |
23 | +@JsonTypeInfo( | |
24 | + use = JsonTypeInfo.Id.NAME, | |
25 | + include = JsonTypeInfo.As.PROPERTY, | |
26 | + property = "type") | |
27 | +@JsonSubTypes({ | |
28 | + @JsonSubTypes.Type(value = SimpleAlarmConditionSpec.class, name = "SIMPLE"), | |
29 | + @JsonSubTypes.Type(value = DurationAlarmConditionSpec.class, name = "DURATION"), | |
30 | + @JsonSubTypes.Type(value = RepeatingAlarmConditionSpec.class, name = "REPEATING")}) | |
31 | +public interface AlarmConditionSpec { | |
32 | + | |
33 | + AlarmConditionSpecType getType(); | |
34 | + | |
35 | +} | ... | ... |
1 | +/** | |
2 | + * Copyright © 2016-2020 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +package org.thingsboard.server.common.data.device.profile; | |
17 | + | |
18 | +public enum AlarmConditionSpecType { | |
19 | + | |
20 | + SIMPLE, | |
21 | + DURATION, | |
22 | + REPEATING | |
23 | + | |
24 | +} | ... | ... |
common/data/src/main/java/org/thingsboard/server/common/data/device/profile/AlarmSchedule.java
0 → 100644
1 | +/** | |
2 | + * Copyright © 2016-2020 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +package org.thingsboard.server.common.data.device.profile; | |
17 | + | |
18 | +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; | |
19 | +import com.fasterxml.jackson.annotation.JsonSubTypes; | |
20 | +import com.fasterxml.jackson.annotation.JsonTypeInfo; | |
21 | + | |
22 | +@JsonIgnoreProperties(ignoreUnknown = true) | |
23 | +@JsonTypeInfo( | |
24 | + use = JsonTypeInfo.Id.NAME, | |
25 | + include = JsonTypeInfo.As.PROPERTY, | |
26 | + property = "type") | |
27 | +@JsonSubTypes({ | |
28 | + @JsonSubTypes.Type(value = SimpleAlarmConditionSpec.class, name = "ANY_TIME"), | |
29 | + @JsonSubTypes.Type(value = DurationAlarmConditionSpec.class, name = "SPECIFIC_TIME"), | |
30 | + @JsonSubTypes.Type(value = RepeatingAlarmConditionSpec.class, name = "CUSTOM")}) | |
31 | +public interface AlarmSchedule { | |
32 | + | |
33 | + AlarmScheduleType getType(); | |
34 | + | |
35 | +} | ... | ... |
common/data/src/main/java/org/thingsboard/server/common/data/device/profile/AlarmScheduleType.java
0 → 100644
1 | +/** | |
2 | + * Copyright © 2016-2020 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +package org.thingsboard.server.common.data.device.profile; | |
17 | + | |
18 | +public enum AlarmScheduleType { | |
19 | + | |
20 | + ANY_TIME, | |
21 | + SPECIFIC_TIME, | |
22 | + CUSTOM | |
23 | + | |
24 | +} | ... | ... |
common/data/src/main/java/org/thingsboard/server/common/data/device/profile/AnyTimeSchedule.java
0 → 100644
1 | +/** | |
2 | + * Copyright © 2016-2020 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +package org.thingsboard.server.common.data.device.profile; | |
17 | + | |
18 | +public class AnyTimeSchedule implements AlarmSchedule { | |
19 | + | |
20 | + @Override | |
21 | + public AlarmScheduleType getType() { | |
22 | + return AlarmScheduleType.ANY_TIME; | |
23 | + } | |
24 | + | |
25 | +} | ... | ... |
common/data/src/main/java/org/thingsboard/server/common/data/device/profile/CustomTimeSchedule.java
0 → 100644
1 | +/** | |
2 | + * Copyright © 2016-2020 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +package org.thingsboard.server.common.data.device.profile; | |
17 | + | |
18 | +import lombok.Data; | |
19 | + | |
20 | +import java.util.List; | |
21 | + | |
22 | +@Data | |
23 | +public class CustomTimeSchedule implements AlarmSchedule { | |
24 | + | |
25 | + private String timezone; | |
26 | + private List<CustomTimeScheduleItem> items; | |
27 | + | |
28 | + @Override | |
29 | + public AlarmScheduleType getType() { | |
30 | + return AlarmScheduleType.CUSTOM; | |
31 | + } | |
32 | + | |
33 | +} | ... | ... |
1 | +/** | |
2 | + * Copyright © 2016-2020 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +package org.thingsboard.server.common.data.device.profile; | |
17 | + | |
18 | +import lombok.Data; | |
19 | + | |
20 | +import java.util.List; | |
21 | + | |
22 | +@Data | |
23 | +public class CustomTimeScheduleItem { | |
24 | + | |
25 | + private boolean enabled; | |
26 | + private Integer dayOfWeek; | |
27 | + private long startsOn; | |
28 | + private long endsOn; | |
29 | + | |
30 | +} | ... | ... |
1 | +/** | |
2 | + * Copyright © 2016-2020 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +package org.thingsboard.server.common.data.device.profile; | |
17 | + | |
18 | +import lombok.Data; | |
19 | + | |
20 | +import java.util.concurrent.TimeUnit; | |
21 | + | |
22 | +@Data | |
23 | +public class DurationAlarmConditionSpec implements AlarmConditionSpec { | |
24 | + | |
25 | + private TimeUnit unit; | |
26 | + private long value; | |
27 | + | |
28 | + @Override | |
29 | + public AlarmConditionSpecType getType() { | |
30 | + return AlarmConditionSpecType.SIMPLE; | |
31 | + } | |
32 | +} | ... | ... |
1 | +/** | |
2 | + * Copyright © 2016-2020 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +package org.thingsboard.server.common.data.device.profile; | |
17 | + | |
18 | +import lombok.Data; | |
19 | + | |
20 | +import java.util.concurrent.TimeUnit; | |
21 | + | |
22 | +@Data | |
23 | +public class RepeatingAlarmConditionSpec implements AlarmConditionSpec { | |
24 | + | |
25 | + private int count; | |
26 | + | |
27 | + @Override | |
28 | + public AlarmConditionSpecType getType() { | |
29 | + return AlarmConditionSpecType.SIMPLE; | |
30 | + } | |
31 | +} | ... | ... |
1 | +/** | |
2 | + * Copyright © 2016-2020 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +package org.thingsboard.server.common.data.device.profile; | |
17 | + | |
18 | +import lombok.Data; | |
19 | + | |
20 | +@Data | |
21 | +public class SimpleAlarmConditionSpec implements AlarmConditionSpec { | |
22 | + @Override | |
23 | + public AlarmConditionSpecType getType() { | |
24 | + return AlarmConditionSpecType.SIMPLE; | |
25 | + } | |
26 | +} | ... | ... |
1 | +/** | |
2 | + * Copyright © 2016-2020 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +package org.thingsboard.server.common.data.device.profile; | |
17 | + | |
18 | +import lombok.Data; | |
19 | + | |
20 | +import java.util.List; | |
21 | + | |
22 | +@Data | |
23 | +public class SpecificTimeSchedule implements AlarmSchedule { | |
24 | + | |
25 | + private String timezone; | |
26 | + private List<Integer> daysOfWeek; | |
27 | + private long startsOn; | |
28 | + private long endsOn; | |
29 | + | |
30 | + @Override | |
31 | + public AlarmScheduleType getType() { | |
32 | + return AlarmScheduleType.SPECIFIC_TIME; | |
33 | + } | |
34 | + | |
35 | +} | ... | ... |
... | ... | @@ -19,7 +19,11 @@ import lombok.Data; |
19 | 19 | import org.thingsboard.rule.engine.profile.state.PersistedAlarmRuleState; |
20 | 20 | import org.thingsboard.server.common.data.alarm.AlarmSeverity; |
21 | 21 | import org.thingsboard.server.common.data.device.profile.AlarmCondition; |
22 | +import org.thingsboard.server.common.data.device.profile.AlarmConditionSpec; | |
22 | 23 | import org.thingsboard.server.common.data.device.profile.AlarmRule; |
24 | +import org.thingsboard.server.common.data.device.profile.DurationAlarmConditionSpec; | |
25 | +import org.thingsboard.server.common.data.device.profile.RepeatingAlarmConditionSpec; | |
26 | +import org.thingsboard.server.common.data.device.profile.SimpleAlarmConditionSpec; | |
23 | 27 | import org.thingsboard.server.common.data.query.BooleanFilterPredicate; |
24 | 28 | import org.thingsboard.server.common.data.query.ComplexFilterPredicate; |
25 | 29 | import org.thingsboard.server.common.data.query.KeyFilter; |
... | ... | @@ -32,7 +36,9 @@ public class AlarmRuleState { |
32 | 36 | |
33 | 37 | private final AlarmSeverity severity; |
34 | 38 | private final AlarmRule alarmRule; |
39 | + private final AlarmConditionSpec spec; | |
35 | 40 | private final long requiredDurationInMs; |
41 | + private final long requiredRepeats; | |
36 | 42 | private PersistedAlarmRuleState state; |
37 | 43 | private boolean updateFlag; |
38 | 44 | |
... | ... | @@ -42,13 +48,31 @@ public class AlarmRuleState { |
42 | 48 | if (state != null) { |
43 | 49 | this.state = state; |
44 | 50 | } else { |
45 | - this.state = new PersistedAlarmRuleState(0L, 0L); | |
51 | + this.state = new PersistedAlarmRuleState(0L, 0L, 0L); | |
46 | 52 | } |
47 | - if (alarmRule.getCondition().getDurationValue() > 0) { | |
48 | - requiredDurationInMs = alarmRule.getCondition().getDurationUnit().toMillis(alarmRule.getCondition().getDurationValue()); | |
49 | - } else { | |
50 | - requiredDurationInMs = 0; | |
53 | + this.spec = getSpec(alarmRule); | |
54 | + long requiredDurationInMs = 0; | |
55 | + long requiredRepeats = 0; | |
56 | + switch (spec.getType()) { | |
57 | + case DURATION: | |
58 | + DurationAlarmConditionSpec duration = (DurationAlarmConditionSpec) spec; | |
59 | + requiredDurationInMs = duration.getUnit().toMillis(duration.getValue()); | |
60 | + break; | |
61 | + case REPEATING: | |
62 | + RepeatingAlarmConditionSpec repeating = (RepeatingAlarmConditionSpec) spec; | |
63 | + requiredRepeats = repeating.getCount(); | |
64 | + break; | |
51 | 65 | } |
66 | + this.requiredDurationInMs = requiredDurationInMs; | |
67 | + this.requiredRepeats = requiredRepeats; | |
68 | + } | |
69 | + | |
70 | + public AlarmConditionSpec getSpec(AlarmRule alarmRule) { | |
71 | + AlarmConditionSpec spec = alarmRule.getCondition().getSpec(); | |
72 | + if (spec == null) { | |
73 | + spec = new SimpleAlarmConditionSpec(); | |
74 | + } | |
75 | + return spec; | |
52 | 76 | } |
53 | 77 | |
54 | 78 | public boolean checkUpdate() { |
... | ... | @@ -61,38 +85,70 @@ public class AlarmRuleState { |
61 | 85 | } |
62 | 86 | |
63 | 87 | public boolean eval(DeviceDataSnapshot data) { |
64 | - if (requiredDurationInMs > 0) { | |
65 | - boolean eval = eval(alarmRule.getCondition(), data); | |
66 | - if (eval) { | |
67 | - if (state.getLastEventTs() > 0) { | |
68 | - if (data.getTs() > state.getLastEventTs()) { | |
69 | - state.setDuration(state.getDuration() + (data.getTs() - state.getLastEventTs())); | |
70 | - state.setLastEventTs(data.getTs()); | |
71 | - updateFlag = true; | |
72 | - } | |
73 | - } else { | |
88 | + switch (spec.getType()) { | |
89 | + case SIMPLE: | |
90 | + return eval(alarmRule.getCondition(), data); | |
91 | + case DURATION: | |
92 | + return evalDuration(data); | |
93 | + case REPEATING: | |
94 | + return evalRepeating(data); | |
95 | + default: | |
96 | + return false; | |
97 | + } | |
98 | + } | |
99 | + | |
100 | + private boolean evalRepeating(DeviceDataSnapshot data) { | |
101 | + boolean eval = eval(alarmRule.getCondition(), data); | |
102 | + if (eval) { | |
103 | + state.setEventCount(state.getEventCount() + 1); | |
104 | + updateFlag = true; | |
105 | + return state.getEventCount() > requiredRepeats; | |
106 | + } else { | |
107 | + if (state.getEventCount() > 0) { | |
108 | + state.setEventCount(0L); | |
109 | + updateFlag = true; | |
110 | + } | |
111 | + return false; | |
112 | + } | |
113 | + } | |
114 | + | |
115 | + private boolean evalDuration(DeviceDataSnapshot data) { | |
116 | + boolean eval = eval(alarmRule.getCondition(), data); | |
117 | + if (eval) { | |
118 | + if (state.getLastEventTs() > 0) { | |
119 | + if (data.getTs() > state.getLastEventTs()) { | |
120 | + state.setDuration(state.getDuration() + (data.getTs() - state.getLastEventTs())); | |
74 | 121 | state.setLastEventTs(data.getTs()); |
75 | - state.setDuration(0L); | |
76 | 122 | updateFlag = true; |
77 | 123 | } |
78 | - return state.getDuration() > requiredDurationInMs; | |
79 | 124 | } else { |
80 | - state.setLastEventTs(0L); | |
125 | + state.setLastEventTs(data.getTs()); | |
81 | 126 | state.setDuration(0L); |
82 | 127 | updateFlag = true; |
83 | - return false; | |
84 | 128 | } |
129 | + return state.getDuration() > requiredDurationInMs; | |
85 | 130 | } else { |
86 | - return eval(alarmRule.getCondition(), data); | |
131 | + if (state.getLastEventTs() > 0 || state.getDuration() > 0) { | |
132 | + state.setLastEventTs(0L); | |
133 | + state.setDuration(0L); | |
134 | + updateFlag = true; | |
135 | + } | |
136 | + return false; | |
87 | 137 | } |
88 | 138 | } |
89 | 139 | |
90 | 140 | public boolean eval(long ts) { |
91 | - if (requiredDurationInMs > 0 && state.getLastEventTs() > 0 && ts > state.getLastEventTs()) { | |
92 | - long duration = state.getDuration() + (ts - state.getLastEventTs()); | |
93 | - return duration > requiredDurationInMs; | |
94 | - } else { | |
95 | - return false; | |
141 | + switch (spec.getType()) { | |
142 | + case SIMPLE: | |
143 | + case REPEATING: | |
144 | + return false; | |
145 | + case DURATION: | |
146 | + if (requiredDurationInMs > 0 && state.getLastEventTs() > 0 && ts > state.getLastEventTs()) { | |
147 | + long duration = state.getDuration() + (ts - state.getLastEventTs()); | |
148 | + return duration > requiredDurationInMs; | |
149 | + } | |
150 | + default: | |
151 | + return false; | |
96 | 152 | } |
97 | 153 | } |
98 | 154 | |
... | ... | @@ -144,7 +200,6 @@ public class AlarmRuleState { |
144 | 200 | } |
145 | 201 | } |
146 | 202 | |
147 | - | |
148 | 203 | private boolean evalBoolPredicate(EntityKeyValue ekv, BooleanFilterPredicate predicate) { |
149 | 204 | Boolean value; |
150 | 205 | switch (ekv.getDataType()) { | ... | ... |
... | ... | @@ -62,18 +62,22 @@ class DeviceState { |
62 | 62 | private DeviceDataSnapshot latestValues; |
63 | 63 | private final ConcurrentMap<String, DeviceProfileAlarmState> alarmStates = new ConcurrentHashMap<>(); |
64 | 64 | |
65 | - public DeviceState(TbContext ctx, TbDeviceProfileNodeConfiguration config, DeviceId deviceId, DeviceProfileState deviceProfile) { | |
65 | + public DeviceState(TbContext ctx, TbDeviceProfileNodeConfiguration config, DeviceId deviceId, DeviceProfileState deviceProfile, RuleNodeState state) { | |
66 | 66 | this.persistState = config.isPersistAlarmRulesState(); |
67 | 67 | this.deviceId = deviceId; |
68 | 68 | this.deviceProfile = deviceProfile; |
69 | 69 | if (config.isPersistAlarmRulesState()) { |
70 | - state = ctx.findRuleNodeStateForEntity(deviceId); | |
71 | 70 | if (state != null) { |
72 | - pds = JacksonUtil.fromString(state.getStateData(), PersistedDeviceState.class); | |
71 | + this.state = state; | |
73 | 72 | } else { |
74 | - state = new RuleNodeState(); | |
75 | - state.setRuleNodeId(ctx.getSelfId()); | |
76 | - state.setEntityId(deviceId); | |
73 | + this.state = ctx.findRuleNodeStateForEntity(deviceId); | |
74 | + } | |
75 | + if (this.state != null) { | |
76 | + pds = JacksonUtil.fromString(this.state.getStateData(), PersistedDeviceState.class); | |
77 | + } else { | |
78 | + this.state = new RuleNodeState(); | |
79 | + this.state.setRuleNodeId(ctx.getSelfId()); | |
80 | + this.state.setEntityId(deviceId); | |
77 | 81 | pds = new PersistedDeviceState(); |
78 | 82 | pds.setAlarmStates(new HashMap<>()); |
79 | 83 | } | ... | ... |
... | ... | @@ -30,6 +30,8 @@ import org.thingsboard.server.common.data.DeviceProfile; |
30 | 30 | import org.thingsboard.server.common.data.EntityType; |
31 | 31 | import org.thingsboard.server.common.data.id.DeviceId; |
32 | 32 | import org.thingsboard.server.common.data.id.DeviceProfileId; |
33 | +import org.thingsboard.server.common.data.page.PageData; | |
34 | +import org.thingsboard.server.common.data.page.PageLink; | |
33 | 35 | import org.thingsboard.server.common.data.plugin.ComponentType; |
34 | 36 | import org.thingsboard.server.common.data.rule.RuleNodeState; |
35 | 37 | import org.thingsboard.server.common.msg.TbMsg; |
... | ... | @@ -65,11 +67,28 @@ public class TbDeviceProfileNode implements TbNode { |
65 | 67 | this.config = TbNodeUtils.convert(configuration, TbDeviceProfileNodeConfiguration.class); |
66 | 68 | this.cache = ctx.getDeviceProfileCache(); |
67 | 69 | scheduleAlarmHarvesting(ctx); |
68 | - //TODO: launch a process of fetching the alarm rule states from the database; | |
70 | + if (config.isFetchAlarmRulesStateOnStart()) { | |
71 | + PageLink pageLink = new PageLink(1024); | |
72 | + while (true) { | |
73 | + PageData<RuleNodeState> states = ctx.findRuleNodeStates(pageLink); | |
74 | + if (!states.getData().isEmpty()) { | |
75 | + for (RuleNodeState rns : states.getData()) { | |
76 | + if (rns.getEntityId().getEntityType().equals(EntityType.DEVICE) && ctx.isLocalEntity(rns.getEntityId())) { | |
77 | + getOrCreateDeviceState(ctx, new DeviceId(rns.getEntityId().getId()), rns); | |
78 | + } | |
79 | + } | |
80 | + } | |
81 | + if (!states.hasNext()) { | |
82 | + break; | |
83 | + } else { | |
84 | + pageLink = pageLink.nextPageLink(); | |
85 | + } | |
86 | + } | |
87 | + } | |
69 | 88 | } |
70 | 89 | |
71 | 90 | /** |
72 | - * 2. Dynamic values evaluation; | |
91 | + * TODO: Dynamic values evaluation; | |
73 | 92 | */ |
74 | 93 | @Override |
75 | 94 | public void onMsg(TbContext ctx, TbMsg msg) throws ExecutionException, InterruptedException { |
... | ... | @@ -85,7 +104,7 @@ public class TbDeviceProfileNode implements TbNode { |
85 | 104 | } else if (msg.getType().equals(DataConstants.ENTITY_DELETED)) { |
86 | 105 | deviceStates.remove(deviceId); |
87 | 106 | } else { |
88 | - DeviceState deviceState = getOrCreateDeviceState(ctx, deviceId); | |
107 | + DeviceState deviceState = getOrCreateDeviceState(ctx, deviceId, null); | |
89 | 108 | if (deviceState != null) { |
90 | 109 | deviceState.process(ctx, msg); |
91 | 110 | } else { |
... | ... | @@ -124,12 +143,12 @@ public class TbDeviceProfileNode implements TbNode { |
124 | 143 | deviceStates.clear(); |
125 | 144 | } |
126 | 145 | |
127 | - protected DeviceState getOrCreateDeviceState(TbContext ctx, DeviceId deviceId) { | |
146 | + protected DeviceState getOrCreateDeviceState(TbContext ctx, DeviceId deviceId, RuleNodeState rns) { | |
128 | 147 | DeviceState deviceState = deviceStates.get(deviceId); |
129 | 148 | if (deviceState == null) { |
130 | 149 | DeviceProfile deviceProfile = cache.get(ctx.getTenantId(), deviceId); |
131 | 150 | if (deviceProfile != null) { |
132 | - deviceState = new DeviceState(ctx, config, deviceId, new DeviceProfileState(deviceProfile)); | |
151 | + deviceState = new DeviceState(ctx, config, deviceId, new DeviceProfileState(deviceProfile), rns); | |
133 | 152 | deviceStates.put(deviceId, deviceState); |
134 | 153 | } |
135 | 154 | } | ... | ... |