diff --git a/eraser-base/src/main/jastadd/Item.jrag b/eraser-base/src/main/jastadd/Item.jrag index e7b6bfb808eb4f1c40ce86442f85340ae8f1ebf7..0ded5474bca071a4ba360e2491b8c633ba91df11 100644 --- a/eraser-base/src/main/jastadd/Item.jrag +++ b/eraser-base/src/main/jastadd/Item.jrag @@ -287,7 +287,7 @@ aspect ItemHandling { //--- 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> * <li>Send the new state via MQTT</li> * <li>Send the new state to Influx DB</li> @@ -296,6 +296,7 @@ aspect ItemHandling { * @param shouldSendState whether to send the new state (currently affects MQTT and Influx) */ protected void Item.stateUpdated(boolean shouldSendState) { + if (getParent() == null) { return; } if (shouldSendState) { try { // sendState() refined in MQTT and Influx aspect @@ -304,7 +305,7 @@ aspect ItemHandling { logger.catching(e); } } - if (this.getStateData().checkStateProcessingTime(getRelevantItemPerformance())) { + if (this.getStateData().checkStateProcessingTime(relevantItemPerformance())) { this.getStateData().afterStateChangeProcessed(); getItemObserver().apply(); } diff --git a/eraser-base/src/main/jastadd/Navigation.jrag b/eraser-base/src/main/jastadd/Navigation.jrag index 1e73d8b151a03e792af75458369000f40cdca1eb..42fd1bf89ed8a972d68af4ab1e7ac1b5c956ef56 100644 --- a/eraser-base/src/main/jastadd/Navigation.jrag +++ b/eraser-base/src/main/jastadd/Navigation.jrag @@ -11,21 +11,29 @@ aspect Navigation { return result; } - protected ItemPerformance GroupItemComposite.getRelevantItemPerformance() { - ASTNode parent = getParent(); - //TODO: Remove try catch - try { - Group g = this.getEnclosingGroup(); - if (this.getItemPerformance()==null && g!=null) { - return g.getRelevantItemPerformance(); - } - } catch(Exception e) { - + inh ItemPerformance Item.relevantItemPerformance(); + inh ItemPerformance Group.relevantItemPerformance(); + eq Group.getItem(int index).relevantItemPerformance() { + Item item = getItem(index); + // first, use value defined on item itself, if any + if (item.hasItemPerformance()) { + return item.getItemPerformance(); + } + // then on this group, if defined + if (this.hasItemPerformance()) { + return this.getItemPerformance(); + } + // recursively use enclosing group and use value from there, if any + Group parent = getEnclosingGroup(); + if (parent != null) { + return parent.relevantItemPerformance(); } - return this.getItemPerformance(); + // if top-level group without ItemPerformance + return null; } - inh Group GroupItemComposite.getEnclosingGroup(); + inh Group Group.getEnclosingGroup(); + inh Group Item.getEnclosingGroup(); private void SmartHomeEntityModel.addItems(java.util.List<Item> result, JastAddList<Group> groups) { groups.forEach(group -> group.getItemList().forEach(item -> result.add(item))); diff --git a/eraser-base/src/main/jastadd/Rules.relast b/eraser-base/src/main/jastadd/Rules.relast index 8746ae62081ec92c6d203253032acc831cad06d8..e695d9250bf890d80657b027aee7ecde1dd57343 100644 --- a/eraser-base/src/main/jastadd/Rules.relast +++ b/eraser-base/src/main/jastadd/Rules.relast @@ -2,7 +2,8 @@ Rule ::= Condition* Action* ; abstract Condition ; ItemStateCheckCondition : Condition ::= ItemStateCheck ; -ItemStateChangeCondition : Condition ::= Item; +ItemStateChangeCondition : Condition ; +rel ItemStateChangeCondition.Item -> Item; ExpressionCondition : Condition ::= LogicalExpression ; abstract Action ; NoopAction : Action ; diff --git a/eraser-base/src/main/jastadd/eraser.parser b/eraser-base/src/main/jastadd/eraser.parser index 63ad20d42f9edc3424b472bccf4e072d78b6e0a1..a5aa61240c0c0eba0daec6286ebadafb9af68291 100644 --- a/eraser-base/src/main/jastadd/eraser.parser +++ b/eraser-base/src/main/jastadd/eraser.parser @@ -41,6 +41,7 @@ Root goal = | influx_root.ir goal.r {: r.setInfluxRoot(ir); return r; :} | machine_learning_root.ml goal.r {: r.setMachineLearningRoot(ml); return r; :} | rule.rule goal.r {: r.addRule(rule); return r; :} + | item_performance.ip goal.r {: r.addItemPerformance(ip); return r; :} | thing.t {: return eph.createRoot(t); :} | item.i {: return eph.createRoot(); :} | group.g {: return eph.createRoot(g); :} @@ -53,7 +54,7 @@ Root goal = | influx_root.ir {: return eph.createRoot(ir); :} | machine_learning_root.ml {: return eph.createRoot(ml); :} | rule.rule {: return eph.createRoot(rule); :} - | item_performance.ip {: return eph.createRoot(ip); :} + | item_performance.ip {: return eph.createRoot(ip); :} ; %left RB_ROUND; @@ -129,29 +130,28 @@ Item item = | 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 = ID EQUALS TEXT.n item_body.i {: return eph.setID(i, n); :} | LABEL EQUALS TEXT.n item_body.i {: i.setLabel(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); :} | CATEGORY EQUALS TEXT.n item_body.i {: return eph.setCategory(i, n); :} - | PERFORMANCE EQUALS TEXT.n item_body.i {: return eph.setPerformance(i, n); :} + | PERFORMANCE EQUALS item_performance_ref.ip item_body.i {: i.setItemPerformance(ip); return i; :} | META_DATA EQUALS string_map.md item_body.i {: return eph.setMetaData(i, md); :} | {: return eph.createItem(); :} ; -Item item_ref = - TEXT.n {: return Item.createRef(n); :} - ; +Item item_ref = TEXT.n {: return Item.createRef(n); :}; +ItemPerformance item_performance_ref = TEXT.n {: return ItemPerformance.createRef(n); :}; Group group = 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"] 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"] performance="" aggregation="" ("",""); Group group_body = ID EQUALS TEXT.n group_body.g {: return eph.setID(g, n); :} | LABEL EQUALS TEXT.n group_body.g {: g.setLabel(n); return g; :} @@ -160,7 +160,7 @@ Group group_body = | AGGREGATION EQUALS TEXT.n group_body.g {: return eph.setSimpleAggregationFunction(g, n); :} | AGGREGATION EQUALS TEXT.n round_string_list.params group_body.g {: return eph.setParameterizedAggregationFunction(g, n, params); :} - | PERFORMANCE EQUALS TEXT.n group_body.g {: return eph.setPerformance(g, n); :} + | PERFORMANCE EQUALS item_performance_ref.ip group_body.g {: g.setItemPerformance(ip); return g; :} | {: return new Group(); :} ; @@ -378,4 +378,4 @@ ItemPerformance item_performance_body = ID EQUALS TEXT.n item_performance_body.ip {: return eph.setID(ip, n); :} | PROCESS_FREQUENCY EQUALS TEXT.n item_performance_body.ip {: ip.setEventProcessingFrequency(Double.parseDouble(n)); return ip; :} | {: return new ItemPerformance(); :} - ; \ No newline at end of file + ; diff --git a/eraser-base/src/main/jastadd/shem.relast b/eraser-base/src/main/jastadd/shem.relast index ee3f42d0cf3f61691ee16f1936f6e8547911ed41..250c5714daf2a79e6846b7f51bb8a4dfb662f332 100644 --- a/eraser-base/src/main/jastadd/shem.relast +++ b/eraser-base/src/main/jastadd/shem.relast @@ -25,12 +25,10 @@ rel Channel.LinkedItem* <-> Item.Channel? ; Parameter : DescribableModelElement ::= <Type:ParameterValueType> [DefaultValue:ParameterDefaultValue] <Context:String> <Required:boolean> ; ParameterDefaultValue ::= <Value:String> ; -abstract GroupItemComposite : LabelledModelElement ; -rel GroupItemComposite.ItemPerformance -> ItemPerformance ; -abstract Item : GroupItemComposite ::= <_fetched_data:boolean> MetaData:ItemMetaData* /ItemObserver/ /StateData/; +abstract Item : LabelledModelElement ::= <_fetched_data:boolean> MetaData:ItemMetaData* /ItemObserver/ /StateData/; rel Item.Category? -> ItemCategory ; - +rel Item.ItemPerformance? -> ItemPerformance ; abstract ItemWithBooleanState : Item ::= <_state:boolean> ; abstract ItemWithStringState : Item ::= <_state:String> ; @@ -56,7 +54,9 @@ ItemCategory ::= <Name:String> ; StateData ::= <LastChangeDate:Instant> ; -Group : GroupItemComposite ::= Group* Item* [AggregationFunction:GroupAggregationFunction] ; +Group : LabelledModelElement ::= Group* Item* [AggregationFunction:GroupAggregationFunction] ; +rel Group.ItemPerformance? -> ItemPerformance ; + abstract GroupAggregationFunction ; SimpleGroupAggregationFunction : GroupAggregationFunction ::= <FunctionName:SimpleGroupAggregationFunctionName> ; ParameterizedGroupAggregationFunction : GroupAggregationFunction ::= <FunctionName:ParameterizedGroupAggregationFunctionName> diff --git a/eraser-base/src/main/java/de/tudresden/inf/st/eraser/parser/EraserParserHelper.java b/eraser-base/src/main/java/de/tudresden/inf/st/eraser/parser/EraserParserHelper.java index 3f6b1df53f0709793100d72b619896ead298a3d4..f5eeee1dac81c08d7f4bd4f7e686ca098b4726b2 100644 --- a/eraser-base/src/main/java/de/tudresden/inf/st/eraser/parser/EraserParserHelper.java +++ b/eraser-base/src/main/java/de/tudresden/inf/st/eraser/parser/EraserParserHelper.java @@ -38,7 +38,6 @@ public class EraserParserHelper { private Map<Item, Iterable<String>> missingControllingListMap = new HashMap<>(); private Map<Group, Iterable<String>> missingSubGroupListMap = new HashMap<>(); private Map<Group, Iterable<String>> missingItemListMap = new HashMap<>(); - private Map<GroupItemComposite, String> missingItemPerformanceMap = new HashMap<>(); private Map<ThingType, Iterable<String>> missingChannelTypeListMap = new HashMap<>(); private Map<ThingType, Iterable<String>> missingParameterListMap = new HashMap<>(); @@ -97,7 +96,6 @@ public class EraserParserHelper { resolveList(itemMap, missingItemLinkListMap, Channel::addLinkedItem); resolveList(groupMap, missingSubGroupListMap, Group::addGroup); resolveList(itemMap, missingItemListMap, this::addItemToGroup); - resolve(itemPerformanceMap, missingItemPerformanceMap, this::setPerformanceOnItem); resolveList(channelTypeMap, missingChannelTypeListMap, ThingType::addChannelType); resolveList(parameterMap, missingParameterListMap, ThingType::addParameter); resolveList(itemMap, missingControllingListMap, Item::addControlling); @@ -118,10 +116,6 @@ public class EraserParserHelper { group.addItem(item); } - private void setPerformanceOnItem(GroupItemComposite performanceElement, ItemPerformance itemPerformance) { - performanceElement.setItemPerformance(itemPerformance); - } - private void fillUnused() { unusedElements.addAll(thingTypeMap.values()); unusedElements.addAll(channelTypeMap.values()); @@ -304,13 +298,6 @@ public class EraserParserHelper { return item; } - public GroupItemComposite setPerformance(GroupItemComposite performanceElement, String performanceName) { - missingItemPerformanceMap.put(performanceElement, performanceName); - return performanceElement; - } - - - public Item setMetaData(Item item, StringKeyMap metaData) { for (AbstractMap.SimpleEntry<String, String> entry : metaData) { item.addMetaData(new ItemMetaData(entry.getKey(), entry.getValue()));