Skip to content
Snippets Groups Projects
Commit 81794ffc authored by René Schöne's avatar René Schöne
Browse files

Merge branch '32-add-processing-frequency-option-for-items' into 'dev'

Resolve "Add processing frequency option for items"

See merge request !11
parents 93fbab4a 2479587d
No related branches found
No related tags found
2 merge requests!19dev to master,!11Resolve "Add processing frequency option for items"
Pipeline #9863 passed
...@@ -21,6 +21,8 @@ aspect ItemHandling { ...@@ -21,6 +21,8 @@ aspect ItemHandling {
eq ItemWithDoubleState.getStateAsString() = Double.toString(getState()); eq ItemWithDoubleState.getStateAsString() = Double.toString(getState());
eq ItemWithStringState.getStateAsString() = getState(); eq ItemWithStringState.getStateAsString() = getState();
syn LastChanged Item.getLastChanged() = new LastChanged();
//--- getStateAsDouble --- //--- getStateAsDouble ---
syn double Item.getStateAsDouble(); syn double Item.getStateAsDouble();
// TupleHSB and String work like default // TupleHSB and String work like default
...@@ -285,7 +287,7 @@ aspect ItemHandling { ...@@ -285,7 +287,7 @@ aspect ItemHandling {
//--- stateUpdated --- //--- stateUpdated ---
/** /**
* Called, whenever the state of an item is updated. Does various things including: * Called, whenever the state of an item is updated. Does various things (except it has no parent) including:
* <ul> * <ul>
* <li>Send the new state via MQTT</li> * <li>Send the new state via MQTT</li>
* <li>Send the new state to Influx DB</li> * <li>Send the new state to Influx DB</li>
...@@ -294,6 +296,7 @@ aspect ItemHandling { ...@@ -294,6 +296,7 @@ aspect ItemHandling {
* @param shouldSendState whether to send the new state (currently affects MQTT and Influx) * @param shouldSendState whether to send the new state (currently affects MQTT and Influx)
*/ */
protected void Item.stateUpdated(boolean shouldSendState) { protected void Item.stateUpdated(boolean shouldSendState) {
if (getParent() == null) { return; }
if (shouldSendState) { if (shouldSendState) {
try { try {
// sendState() refined in MQTT and Influx aspect // sendState() refined in MQTT and Influx aspect
...@@ -302,8 +305,12 @@ aspect ItemHandling { ...@@ -302,8 +305,12 @@ aspect ItemHandling {
logger.catching(e); logger.catching(e);
} }
} }
if (this.getLastChanged().checkStateProcessingTime(relevantFrequencySetting())) {
this.getLastChanged().afterStateChangeProcessed();
getItemObserver().apply(); getItemObserver().apply();
} }
}
//--- sendState --- //--- sendState ---
protected void Item.sendState() throws Exception { protected void Item.sendState() throws Exception {
...@@ -459,6 +466,11 @@ aspect ItemHandling { ...@@ -459,6 +466,11 @@ aspect ItemHandling {
} }
//--- onReceiveStateChange ---
protected void Item.onReceiveStateChange() {
//Instant lastChange = this.
}
...@@ -506,4 +518,6 @@ aspect ItemHandling { ...@@ -506,4 +518,6 @@ aspect ItemHandling {
syn String ItemUpdate.getNewStateAsString(); syn String ItemUpdate.getNewStateAsString();
eq ItemUpdateColor.getNewStateAsString() = getNewHSB().toString(); eq ItemUpdateColor.getNewStateAsString() = getNewHSB().toString();
eq ItemUpdateDouble.getNewStateAsString() = Double.toString(getNewValue()); eq ItemUpdateDouble.getNewStateAsString() = Double.toString(getNewValue());
} }
aspect LastChanged {
public void LastChanged.afterStateChangeProcessed() {
this.setValue(Instant.now());
}
public boolean LastChanged.checkStateProcessingTime(FrequencySetting FrequencySetting) {
if (FrequencySetting==null) {
return true;
}
double frequency = FrequencySetting.getEventProcessingFrequency();
Instant lastStateChange = this.getValue();
if (lastStateChange==null) {
return true;
}
return lastStateChange.toEpochMilli() + (1/frequency)*1000 < Instant.now().toEpochMilli();
}
}
\ No newline at end of file
...@@ -11,6 +11,48 @@ aspect Navigation { ...@@ -11,6 +11,48 @@ aspect Navigation {
return result; return result;
} }
//--- enclosingGroup ---
inh Group Group.enclosingGroup();
inh Group Item.enclosingGroup();
eq Group.getItem().enclosingGroup() = this;
eq Group.getGroup().enclosingGroup() = this;
eq SmartHomeEntityModel.getGroup().enclosingGroup() = null;
eq SmartHomeEntityModel.getActivityItem().enclosingGroup() = null;
//--- relevantFrequencySetting ---
syn FrequencySetting Group.relevantFrequencySetting() {
// first, use value defined on group itself, if any
if (this.hasFrequencySetting()) {
return this.getFrequencySetting();
}
// recursively use enclosing group and use value from there, if any
Group parent = enclosingGroup();
if (parent != null) {
return parent.relevantFrequencySetting();
}
// if top-level group without FrequencySetting
return null;
}
syn FrequencySetting Item.relevantFrequencySetting() {
// first, use value defined on item itself, if any
if (this.hasFrequencySetting()) {
return this.getFrequencySetting();
}
// use enclosing group and use value from there, if any
Group parent = enclosingGroup();
if (parent != null) {
return parent.relevantFrequencySetting();
}
// if top-level item without FrequencySetting
return null;
}
//--- addItems ---
private void SmartHomeEntityModel.addItems(java.util.List<Item> result, JastAddList<Group> groups) { private void SmartHomeEntityModel.addItems(java.util.List<Item> result, JastAddList<Group> groups) {
groups.forEach(group -> group.getItemList().forEach(item -> result.add(item))); groups.forEach(group -> group.getItemList().forEach(item -> result.add(item)));
} }
...@@ -56,4 +98,5 @@ aspect Navigation { ...@@ -56,4 +98,5 @@ aspect Navigation {
eq Root.getRule().getRoot() = this; eq Root.getRule().getRoot() = this;
eq Root.getUser().getRoot() = this; eq Root.getUser().getRoot() = this;
eq Root.getLocation().getRoot() = this; eq Root.getLocation().getRoot() = this;
eq Root.getFrequencySetting().getRoot() = this;
} }
...@@ -98,9 +98,22 @@ aspect Resolving { ...@@ -98,9 +98,22 @@ aspect Resolving {
return java.util.Optional.empty(); return java.util.Optional.empty();
} }
syn java.util.Optional<FrequencySetting> Root.resolveFrequencySetting(String performanceId) {
for (FrequencySetting performance : getFrequencySettingList()) {
if (performance.getLabel().equals(performanceId)) {
return java.util.Optional.of(performance);
}
}
return java.util.Optional.empty();
}
// implementing resolving for relations // implementing resolving for relations
refine RefResolverStubs eq StateSyncGroup.resolveTargetItemByToken(String id, int position) { refine RefResolverStubs eq StateSyncGroup.resolveTargetItemByToken(String id, int position) {
return getRoot().getSmartHomeEntityModel().resolveItem(id).orElseThrow(() -> new RuntimeException("Item '" + id + "' not found!")); return getRoot().getSmartHomeEntityModel().resolveItem(id).orElseThrow(() -> new RuntimeException("Item '" + id + "' not found!"));
} }
refine RefResolverStubs eq ASTNode.globallyResolveFrequencySettingByToken(String id) {
return getRoot().resolveFrequencySetting(id).orElseThrow(() -> new RuntimeException("FrequencySetting '" + id + "' not found!"));
}
} }
...@@ -2,7 +2,8 @@ ...@@ -2,7 +2,8 @@
Rule ::= Condition* Action* ; Rule ::= Condition* Action* ;
abstract Condition ; abstract Condition ;
ItemStateCheckCondition : Condition ::= ItemStateCheck ; ItemStateCheckCondition : Condition ::= ItemStateCheck ;
ItemStateChangeCondition : Condition ::= Item; ItemStateChangeCondition : Condition ;
rel ItemStateChangeCondition.Item -> Item;
ExpressionCondition : Condition ::= LogicalExpression ; ExpressionCondition : Condition ::= LogicalExpression ;
abstract Action ; abstract Action ;
NoopAction : Action ; NoopAction : Action ;
...@@ -29,5 +30,6 @@ MultiplyDoubleToStateAction : SetStateAction ::= <Multiplier:double> ; ...@@ -29,5 +30,6 @@ MultiplyDoubleToStateAction : SetStateAction ::= <Multiplier:double> ;
ItemObserver ::= ; ItemObserver ::= ;
rel ItemObserver.TriggeredRule* <-> Rule.Observer* ; rel ItemObserver.TriggeredRule* <-> Rule.Observer* ;
FrequencySetting : LabelledModelElement ::= <EventProcessingFrequency:double> ;
StateSyncGroup : Rule ; StateSyncGroup : Rule ;
rel StateSyncGroup.TargetItem* -> Item; rel StateSyncGroup.TargetItem* -> Item;
...@@ -87,6 +87,9 @@ Comment = "//" [^\n\r]+ ...@@ -87,6 +87,9 @@ Comment = "//" [^\n\r]+
"incoming" { return sym(Terminals.INCOMING); } "incoming" { return sym(Terminals.INCOMING); }
"items" { return sym(Terminals.ITEMS); } "items" { return sym(Terminals.ITEMS); }
"itemType" { return sym(Terminals.ITEM_TYPE); } "itemType" { return sym(Terminals.ITEM_TYPE); }
"FrequencySetting" { return sym(Terminals.FREQUENCY_SETTING); }
"performance" { return sym(Terminals.PERFORMANCE); }
"procFreq" { return sym(Terminals.PROCESS_FREQUENCY); }
"label" { return sym(Terminals.LABEL); } "label" { return sym(Terminals.LABEL); }
"links" { return sym(Terminals.LINKS); } "links" { return sym(Terminals.LINKS); }
"metaData" { return sym(Terminals.META_DATA); } "metaData" { return sym(Terminals.META_DATA); }
......
...@@ -41,6 +41,7 @@ Root goal = ...@@ -41,6 +41,7 @@ Root goal =
| influx_root.ir goal.r {: r.setInfluxRoot(ir); return r; :} | influx_root.ir goal.r {: r.setInfluxRoot(ir); return r; :}
| machine_learning_root.ml goal.r {: r.setMachineLearningRoot(ml); return r; :} | machine_learning_root.ml goal.r {: r.setMachineLearningRoot(ml); return r; :}
| rule.rule goal.r {: r.addRule(rule); return r; :} | rule.rule goal.r {: r.addRule(rule); return r; :}
| frequency_setting.ip goal.r {: r.addFrequencySetting(ip); return r; :}
| thing.t {: return eph.createRoot(t); :} | thing.t {: return eph.createRoot(t); :}
| item.i {: return eph.createRoot(); :} | item.i {: return eph.createRoot(); :}
| group.g {: return eph.createRoot(g); :} | group.g {: return eph.createRoot(g); :}
...@@ -53,6 +54,7 @@ Root goal = ...@@ -53,6 +54,7 @@ Root goal =
| influx_root.ir {: return eph.createRoot(ir); :} | influx_root.ir {: return eph.createRoot(ir); :}
| machine_learning_root.ml {: return eph.createRoot(ml); :} | machine_learning_root.ml {: return eph.createRoot(ml); :}
| rule.rule {: return eph.createRoot(rule); :} | rule.rule {: return eph.createRoot(rule); :}
| frequency_setting.ip {: return eph.createRoot(ip); :}
; ;
%left RB_ROUND; %left RB_ROUND;
...@@ -128,28 +130,28 @@ Item item = ...@@ -128,28 +130,28 @@ Item item =
| ITEM COLON item_body.ib SEMICOLON {: return eph.retype(new DefaultItem(), ib); :} | ITEM COLON item_body.ib SEMICOLON {: return eph.retype(new DefaultItem(), ib); :}
; ;
// ITEM_TYPE Item: id="" label="" state="" category="" topic="" metaData={"key":"value"} ; // ITEM_TYPE Item: id="" label="" state="" category="" topic="" performance="" metaData={"key":"value"} ;
Item item_body = Item item_body =
ID EQUALS TEXT.n item_body.i {: return eph.setID(i, n); :} ID EQUALS TEXT.n item_body.i {: return eph.setID(i, n); :}
| LABEL EQUALS TEXT.n item_body.i {: i.setLabel(n); return i; :} | LABEL EQUALS TEXT.n item_body.i {: i.setLabel(n); return i; :}
| STATE EQUALS TEXT.n item_body.i {: i.setStateFromString(n); return i; :} | STATE EQUALS TEXT.n item_body.i {: i.setStateFromString(n); return i; :}
| TOPIC EQUALS TEXT.n item_body.i {: return eph.setTopic(i, n); :} | TOPIC EQUALS TEXT.n item_body.i {: return eph.setTopic(i, n); :}
| CATEGORY EQUALS TEXT.n item_body.i {: return eph.setCategory(i, n); :} | CATEGORY EQUALS TEXT.n item_body.i {: return eph.setCategory(i, n); :}
| PERFORMANCE EQUALS frequency_setting_ref.ip item_body.i {: i.setFrequencySetting(ip); return i; :}
| META_DATA EQUALS string_map.md item_body.i | META_DATA EQUALS string_map.md item_body.i
{: return eph.setMetaData(i, md); :} {: return eph.setMetaData(i, md); :}
| {: return eph.createItem(); :} | {: return eph.createItem(); :}
; ;
Item item_ref = Item item_ref = TEXT.n {: return Item.createRef(n); :};
TEXT.n {: return Item.createRef(n); :} FrequencySetting frequency_setting_ref = TEXT.n {: return FrequencySetting.createRef(n); :};
;
Group group = Group group =
GROUP COLON group_body.gb SEMICOLON {: return gb; :} GROUP COLON group_body.gb SEMICOLON {: return gb; :}
; ;
// Group: id="" groups=["GROUP_ID", "GROUP_ID"] items=["ITEM_ID", "ITEM_ID"] aggregation=""; // Group: id="" groups=["GROUP_ID", "GROUP_ID"] items=["ITEM_ID", "ITEM_ID"] performance="" aggregation="";
// Group: id="" groups=["GROUP_ID", "GROUP_ID"] items=["ITEM_ID", "ITEM_ID"] aggregation="" ("",""); // Group: id="" groups=["GROUP_ID", "GROUP_ID"] items=["ITEM_ID", "ITEM_ID"] performance="" aggregation="" ("","");
Group group_body = Group group_body =
ID EQUALS TEXT.n group_body.g {: return eph.setID(g, n); :} ID EQUALS TEXT.n group_body.g {: return eph.setID(g, n); :}
| LABEL EQUALS TEXT.n group_body.g {: g.setLabel(n); return g; :} | LABEL EQUALS TEXT.n group_body.g {: g.setLabel(n); return g; :}
...@@ -158,6 +160,7 @@ Group group_body = ...@@ -158,6 +160,7 @@ Group group_body =
| AGGREGATION EQUALS TEXT.n group_body.g {: return eph.setSimpleAggregationFunction(g, n); :} | AGGREGATION EQUALS TEXT.n group_body.g {: return eph.setSimpleAggregationFunction(g, n); :}
| AGGREGATION EQUALS TEXT.n round_string_list.params group_body.g | AGGREGATION EQUALS TEXT.n round_string_list.params group_body.g
{: return eph.setParameterizedAggregationFunction(g, n, params); :} {: return eph.setParameterizedAggregationFunction(g, n, params); :}
| PERFORMANCE EQUALS frequency_setting_ref.ip group_body.g {: g.setFrequencySetting(ip); return g; :}
| {: return new Group(); :} | {: return new Group(); :}
; ;
...@@ -365,3 +368,14 @@ IntegerKeyMap integer_map_body = ...@@ -365,3 +368,14 @@ IntegerKeyMap integer_map_body =
return result; return result;
:} :}
; ;
FrequencySetting frequency_setting =
FREQUENCY_SETTING COLON frequency_setting_body.ipb SEMICOLON {: return ipb; :}
;
// FrequencySetting: id="" procFreq="" persFreq="";
FrequencySetting frequency_setting_body =
ID EQUALS TEXT.n frequency_setting_body.ip {: return eph.setID(ip, n); :}
| PROCESS_FREQUENCY EQUALS TEXT.n frequency_setting_body.ip {: ip.setEventProcessingFrequency(Double.parseDouble(n)); return ip; :}
| {: return new FrequencySetting(); :}
;
// ---------------- Main ------------------------------ // ---------------- Main ------------------------------
Root ::= SmartHomeEntityModel User* MqttRoot InfluxRoot MachineLearningRoot Rule* Location* ; Root ::= SmartHomeEntityModel User* MqttRoot InfluxRoot MachineLearningRoot Rule* Location* FrequencySetting*;
// ---------------- Users ------------------------------ // ---------------- Users ------------------------------
User : LabelledModelElement ; User : LabelledModelElement ;
......
// ---------------- openHAB ------------------------------ // ---------------- openHAB ------------------------------
SmartHomeEntityModel ::= Thing* Group* ThingType* ChannelType* ChannelCategory* ItemCategory* /ActivityItem:Item/ ; SmartHomeEntityModel ::= Thing* Group* ThingType* ChannelType* ChannelCategory* ItemCategory* /ActivityItem:Item/ ;
abstract ModelElement ::= <ID:String> ; abstract ModelElement ::= <ID:String> ;
abstract LabelledModelElement : ModelElement ::= <Label:String> ; abstract LabelledModelElement : ModelElement ::= <Label:String> ;
abstract DescribableModelElement : LabelledModelElement ::= <Description:String> ; abstract DescribableModelElement : LabelledModelElement ::= <Description:String> ;
...@@ -25,10 +26,9 @@ rel Channel.LinkedItem* <-> Item.Channel? ; ...@@ -25,10 +26,9 @@ rel Channel.LinkedItem* <-> Item.Channel? ;
Parameter : DescribableModelElement ::= <Type:ParameterValueType> [DefaultValue:ParameterDefaultValue] <Context:String> <Required:boolean> ; Parameter : DescribableModelElement ::= <Type:ParameterValueType> [DefaultValue:ParameterDefaultValue] <Context:String> <Required:boolean> ;
ParameterDefaultValue ::= <Value:String> ; ParameterDefaultValue ::= <Value:String> ;
abstract Item : LabelledModelElement ::= <_fetched_data:boolean> MetaData:ItemMetaData* /ItemObserver/; abstract Item : LabelledModelElement ::= <_fetched_data:boolean> MetaData:ItemMetaData* /ItemObserver/ /LastChanged/;
rel Item.Category? -> ItemCategory ; rel Item.Category? -> ItemCategory ;
rel Item.FrequencySetting? -> FrequencySetting ;
abstract ItemWithBooleanState : Item ::= <_state:boolean> ; abstract ItemWithBooleanState : Item ::= <_state:boolean> ;
abstract ItemWithStringState : Item ::= <_state:String> ; abstract ItemWithStringState : Item ::= <_state:String> ;
...@@ -51,8 +51,14 @@ ItemMetaData ::= <Key:String> <Value:String> ; ...@@ -51,8 +51,14 @@ ItemMetaData ::= <Key:String> <Value:String> ;
ItemCategory ::= <Name:String> ; ItemCategory ::= <Name:String> ;
LastChanged ::= <Value:Instant> ;
Group : LabelledModelElement ::= Group* Item* [AggregationFunction:GroupAggregationFunction] ; Group : LabelledModelElement ::= Group* Item* [AggregationFunction:GroupAggregationFunction] ;
rel Group.FrequencySetting? -> FrequencySetting ;
abstract GroupAggregationFunction ; abstract GroupAggregationFunction ;
SimpleGroupAggregationFunction : GroupAggregationFunction ::= <FunctionName:SimpleGroupAggregationFunctionName> ; SimpleGroupAggregationFunction : GroupAggregationFunction ::= <FunctionName:SimpleGroupAggregationFunctionName> ;
ParameterizedGroupAggregationFunction : GroupAggregationFunction ::= <FunctionName:ParameterizedGroupAggregationFunctionName> ParameterizedGroupAggregationFunction : GroupAggregationFunction ::= <FunctionName:ParameterizedGroupAggregationFunctionName>
<Param1:String> <Param2:String> ; <Param1:String> <Param2:String> ;
...@@ -24,16 +24,18 @@ public class EraserParserHelper { ...@@ -24,16 +24,18 @@ public class EraserParserHelper {
private Map<String, Parameter> parameterMap = new HashMap<>(); private Map<String, Parameter> parameterMap = new HashMap<>();
private Map<String, Item> itemMap = new HashMap<>(); private Map<String, Item> itemMap = new HashMap<>();
private Map<String, Group> groupMap = new HashMap<>(); private Map<String, Group> groupMap = new HashMap<>();
private Map<String, FrequencySetting> FrequencySettingMap = new HashMap<>();
private Map<Thing, String> missingThingTypeMap = new HashMap<>(); private Map<Thing, String> missingThingTypeMap = new HashMap<>();
private Map<Channel, String> missingChannelTypeMap = new HashMap<>(); private Map<Channel, String> missingChannelTypeMap = new HashMap<>();
private Map<Item, String> missingTopicMap = new HashMap<>(); private Map<Item, String> missingTopicMap = new HashMap<>();
private Map<Item, String> missingItemCategoryMap = new HashMap<>(); private Map<Item, String> missingItemCategoryMap = new HashMap<>();
private Map<Designator, String> missingItemForDesignator = new HashMap<>(); private Map<Designator, String> missingItemForDesignator = new HashMap<>();
private Map<Thing, Iterable<String>> missingChannelListMap = new HashMap<>(); private Map<Thing, Iterable<String>> missingChannelListMap = new HashMap<>();
private Map<Channel, Iterable<String>> missingItemLinkListMap = new HashMap<>(); private Map<Channel, Iterable<String>> missingItemLinkListMap = new HashMap<>();
private Map<Item, Iterable<String>> missingControllingListMap = new HashMap<>();
private Map<Group, Iterable<String>> missingSubGroupListMap = new HashMap<>(); private Map<Group, Iterable<String>> missingSubGroupListMap = new HashMap<>();
private Map<Group, Iterable<String>> missingItemListMap = new HashMap<>(); private Map<Group, Iterable<String>> missingItemListMap = new HashMap<>();
private Map<ThingType, Iterable<String>> missingChannelTypeListMap = new HashMap<>(); private Map<ThingType, Iterable<String>> missingChannelTypeListMap = new HashMap<>();
...@@ -94,19 +96,20 @@ public class EraserParserHelper { ...@@ -94,19 +96,20 @@ public class EraserParserHelper {
resolveList(itemMap, missingItemLinkListMap, Channel::addLinkedItem); resolveList(itemMap, missingItemLinkListMap, Channel::addLinkedItem);
resolveList(groupMap, missingSubGroupListMap, Group::addGroup); resolveList(groupMap, missingSubGroupListMap, Group::addGroup);
resolveList(itemMap, missingItemListMap, this::addItemToGroup); resolveList(itemMap, missingItemListMap, this::addItemToGroup);
resolveList(channelTypeMap, missingChannelTypeListMap, ThingType::addChannelType); resolveList(channelTypeMap, missingChannelTypeListMap, ThingType::addChannelType);
resolveList(parameterMap, missingParameterListMap, ThingType::addParameter); resolveList(parameterMap, missingParameterListMap, ThingType::addParameter);
resolveList(itemMap, missingControllingListMap, Item::addControlling);
createUnknownGroupIfNecessary(); createUnknownGroupIfNecessary();
createChannelCategories(); createChannelCategories();
createItemCategories(); createItemCategories();
if (checkUnusedElements) { if (checkUnusedElements) {
checkUnusedElements(); checkUnusedElements();
} }
this.root.treeResolveAll(); this.root.treeResolveAll();
this.root.doFullTraversal();
} }
private void addItemToGroup(Group group, Item item) { private void addItemToGroup(Group group, Item item) {
...@@ -226,6 +229,12 @@ public class EraserParserHelper { ...@@ -226,6 +229,12 @@ public class EraserParserHelper {
return thing; return thing;
} }
public FrequencySetting setID(FrequencySetting FrequencySetting, String id) {
FrequencySetting.setID(id);
FrequencySettingMap.put(id,FrequencySetting);
return FrequencySetting;
}
public ThingType setID(ThingType thingType, String id) { public ThingType setID(ThingType thingType, String id) {
thingType.setID(id); thingType.setID(id);
thingTypeMap.put(id, thingType); thingTypeMap.put(id, thingType);
...@@ -259,6 +268,7 @@ public class EraserParserHelper { ...@@ -259,6 +268,7 @@ public class EraserParserHelper {
return c; return c;
} }
public Channel setLinks(Channel c, StringList linkNames) { public Channel setLinks(Channel c, StringList linkNames) {
missingItemLinkListMap.put(c, linkNames); missingItemLinkListMap.put(c, linkNames);
return c; return c;
...@@ -300,6 +310,7 @@ public class EraserParserHelper { ...@@ -300,6 +310,7 @@ public class EraserParserHelper {
itemWithCorrectType.setID(prototype.getID()); itemWithCorrectType.setID(prototype.getID());
itemWithCorrectType.setLabel(prototype.getLabel()); itemWithCorrectType.setLabel(prototype.getLabel());
itemWithCorrectType.setMetaDataList(prototype.getMetaDataList()); itemWithCorrectType.setMetaDataList(prototype.getMetaDataList());
itemWithCorrectType.setFrequencySetting(prototype.getFrequencySetting());
if (!(itemWithCorrectType instanceof ActivityItem)) { if (!(itemWithCorrectType instanceof ActivityItem)) {
String state = prototype.getStateAsString(); String state = prototype.getStateAsString();
itemWithCorrectType.disableSendState(); itemWithCorrectType.disableSendState();
...@@ -312,7 +323,6 @@ public class EraserParserHelper { ...@@ -312,7 +323,6 @@ public class EraserParserHelper {
} }
moveMissingForRetype(itemWithCorrectType, prototype, missingTopicMap); moveMissingForRetype(itemWithCorrectType, prototype, missingTopicMap);
moveMissingForRetype(itemWithCorrectType, prototype, missingControllingListMap);
moveMissingForRetype(itemWithCorrectType, prototype, missingItemCategoryMap); moveMissingForRetype(itemWithCorrectType, prototype, missingItemCategoryMap);
itemMap.put(prototype.getID(), itemWithCorrectType); itemMap.put(prototype.getID(), itemWithCorrectType);
...@@ -470,6 +480,12 @@ public class EraserParserHelper { ...@@ -470,6 +480,12 @@ public class EraserParserHelper {
return result; return result;
} }
public Root createRoot(FrequencySetting FrequencySetting) {
Root result = createRoot();
result.addFrequencySetting(FrequencySetting);
return result;
}
//+++ newStuff (to be categorized) +++ //+++ newStuff (to be categorized) +++
public Designator createDesignator(String itemName) { public Designator createDesignator(String itemName) {
Designator result = new Designator(); Designator result = new Designator();
......
...@@ -250,6 +250,7 @@ public class RulesTest { ...@@ -250,6 +250,7 @@ public class RulesTest {
assertEquals(2, counter.get(item), "Change of item to 7 should not trigger the rule, check2 violated"); assertEquals(2, counter.get(item), "Change of item to 7 should not trigger the rule, check2 violated");
} }
@Test @Test
public void testStateSyncGroupRewriteStructure() { public void testStateSyncGroupRewriteStructure() {
// init StateSyncGroup // init StateSyncGroup
...@@ -915,6 +916,35 @@ public class RulesTest { ...@@ -915,6 +916,35 @@ public class RulesTest {
assertEquals(2, counter.get(null), "Rule was not executed two times"); assertEquals(2, counter.get(null), "Rule was not executed two times");
} }
@Test
public void testFrequencySetting() {
TestUtils.ModelAndItem mai = createModelAndItem(0);
NumberItem numberItem = mai.item;
FrequencySetting itemPerformance = new FrequencySetting();
itemPerformance.setEventProcessingFrequency(10);
numberItem.setFrequencySetting(itemPerformance);
Rule rule = new Rule();
CountingAction counter = new CountingAction();
rule.addAction(counter);
rule.activateFor(numberItem);
numberItem.setState(1);
numberItem.setState(2);
assertEquals(1, counter.get(numberItem), "Action was triggered although FrequencySetting too small");
counter.reset();
waitMillis(100);
numberItem.setState(3);
assertEquals(1, counter.get(numberItem), "Action wasn't triggered although frequency FrequencySetting is small enough");
counter.reset();
numberItem.setState(4);
numberItem.setState(5);
assertEquals(0, counter.get(numberItem), "Action was triggered although FrequencySetting too small");
counter.reset();
}
private static void waitMillis(int millis) { private static void waitMillis(int millis) {
try { try {
Thread.sleep(millis); Thread.sleep(millis);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment