diff --git a/eraser-base/src/main/jastadd/Item.jrag b/eraser-base/src/main/jastadd/Item.jrag
index 5c03824f96b9de7db5a5ddeb0c4a330b516db4f9..2473947b7cba1be7e26f5b265e41fc9e75fdec0c 100644
--- a/eraser-base/src/main/jastadd/Item.jrag
+++ b/eraser-base/src/main/jastadd/Item.jrag
@@ -300,9 +300,7 @@ aspect ItemHandling {
         logger.catching(e);
       }
     }
-    if (hasItemObserver()) {
-      getItemObserver().apply();
-    }
+    getItemObserver().apply();
   }
 
   //--- sendState ---
@@ -407,6 +405,7 @@ aspect ItemHandling {
         SetStateFromTriggeringItemAction action = new SetStateFromTriggeringItemAction();
         action.setAffectedItem(controlledItem);
         rule.addAction(action);
+
         rule.activateFor(controllerItem);
 
         return rule;
@@ -463,21 +462,21 @@ aspect ItemHandling {
 
 
   //--- copyStateTo ---
-  protected abstract void Item.copyStateTo(Item stateReceiver);
-  protected void ItemWithBooleanState.copyStateTo(Item stateReceiver) {
-    stateReceiver.setStateFromBoolean(this.getState());
+  protected abstract void Item.copyStateTo(Item... stateReceivers);
+  protected void ItemWithBooleanState.copyStateTo(Item... stateReceivers) {
+    Arrays.asList(stateReceivers).forEach(s -> s.setStateFromBoolean(this.getState()));
   }
-  protected void ItemWithStringState.copyStateTo(Item stateReceiver) {
-    stateReceiver.setStateFromString(this.getState());
+  protected void ItemWithStringState.copyStateTo(Item... stateReceivers) {
+    Arrays.asList(stateReceivers).forEach(s -> s.setStateFromString(this.getState()));
   }
-  protected void ItemWithDoubleState.copyStateTo(Item stateReceiver) {
-    stateReceiver.setStateFromDouble(this.getState());
+  protected void ItemWithDoubleState.copyStateTo(Item... stateReceivers) {
+    Arrays.asList(stateReceivers).forEach(s -> s.setStateFromDouble(this.getState()));
   }
-  protected void ColorItem.copyStateTo(Item stateReceiver) {
-    stateReceiver.setStateFromColor(this.getState());
+  protected void ColorItem.copyStateTo(Item... stateReceivers) {
+    Arrays.asList(stateReceivers).forEach(s -> s.setStateFromColor(this.getState()));
   }
-  protected void DateTimeItem.copyStateTo(Item stateReceiver) {
-    stateReceiver.setStateFromInstant(this.getState());
+  protected void DateTimeItem.copyStateTo(Item... stateReceivers) {
+    Arrays.asList(stateReceivers).forEach(s -> s.setStateFromInstant(this.getState()));
   }
 
   private void ColorItem.setBrightness(int value) {
diff --git a/eraser-base/src/main/jastadd/Rules.jrag b/eraser-base/src/main/jastadd/Rules.jrag
index 26c18ae2f1faba258a2db6aa60d5b0c6cf974575..7e550453b2e7a0140b8a019fc885d509e8f67cdb 100644
--- a/eraser-base/src/main/jastadd/Rules.jrag
+++ b/eraser-base/src/main/jastadd/Rules.jrag
@@ -24,29 +24,20 @@ aspect Rules {
   eq Item.getItemObserver().observedItem() = this;
 
   public void Rule.activateFor(Item item) {
-    // 1) Get or create new ItemObserver, and add it to Root
-    ItemObserver itemObserver;
-    if (item.hasItemObserver()) {
-      itemObserver = item.getItemObserver();
-      // 1.a) Check if observer already triggers this rule
-      for (Rule rule : itemObserver.getTriggeredRules()) {
-        if (rule.equals(this)) {
-        logger.warn("Rule already activated for item {}. Ignoring.", item);
-        return;
-        }
+    // 1) Get ItemObserver
+    ItemObserver itemObserver = item.getItemObserver();
+    // 1.a) Check if observer already triggers this rule
+    for (Rule rule : itemObserver.getTriggeredRules()) {
+      if (rule.equals(this)) {
+      logger.warn("Rule already activated for item {}. Ignoring.", item);
+      return;
       }
-    } else {
-      itemObserver = new ItemObserver();
-      item.setItemObserver(itemObserver);
     }
-    // 2) Link event and itemObserver
     itemObserver.addTriggeredRule(this);
   }
 
   public void Rule.deactivateFor(Item item) {
-    if (item.hasItemObserver()) {
-        item.getItemObserver().removeTriggeredRule(this);
-    }
+    item.getItemObserver().removeTriggeredRule(this);
 
   }
 
@@ -74,12 +65,7 @@ aspect Rules {
   }
 
   public void Rule.removeActivationOf(Item item) {
-    if (item.hasItemObserver()) {
-      item.getItemObserver().removeTriggeredRule(this);
-    } else {
-      // there is no observer yet
-      logger.warn("Item {} was never activated before.", item);
-    }
+    item.getItemObserver().removeTriggeredRule(this);
   }
 
   // --- Condition.holdsFor ---
@@ -122,3 +108,21 @@ aspect Rules {
   }
 
 }
+
+aspect StateSyncGroup {
+  rewrite StateSyncGroup {
+    to Rule {
+      Item controllingItem = ((ItemObserver)getParent()).observedItem();
+      
+      SetStateFromTriggeringItemAction action = new SetStateFromTriggeringItemAction();
+
+      /*
+      action.setAffectedItems(getItems())
+      */
+      
+      Rule rule = new Rule();
+      rule.addAction(action);
+      return rule;
+    }
+  }
+}
diff --git a/eraser-base/src/main/jastadd/Rules.relast b/eraser-base/src/main/jastadd/Rules.relast
index 25a0fd2b41f3f1051e03d06ace4f41b6907030e6..79d24a4259ee7c37d3b587f9eab96d645bb3dc99 100644
--- a/eraser-base/src/main/jastadd/Rules.relast
+++ b/eraser-base/src/main/jastadd/Rules.relast
@@ -28,3 +28,7 @@ MultiplyDoubleToStateAction : SetStateAction ::= <Multiplier:double> ;
 
 ItemObserver ::= ;
 rel ItemObserver.TriggeredRule* <-> Rule.Observer* ;
+
+
+StateSyncGroup : Rule ::= Item*;
+
diff --git a/eraser-base/src/main/jastadd/eraser.flex b/eraser-base/src/main/jastadd/eraser.flex
index 5f70414fa4005ad1baf1b0623459ce7c5f2f69f2..e81c7f7f33cb847ead9d5caea9d273265869c084 100644
--- a/eraser-base/src/main/jastadd/eraser.flex
+++ b/eraser-base/src/main/jastadd/eraser.flex
@@ -57,6 +57,7 @@ Comment = "//" [^\n\r]+
 "Influx"       { return sym(Terminals.INFLUX); }
 "ML"           { return sym(Terminals.ML); }
 "Rule"         { return sym(Terminals.RULE); }
+//"SyncState"    { return sym(Terminals.SYNCSTATE); }
 // special items (group already has a token definition)
 "Activity"     { return sym(Terminals.ACTIVITY); }
 "Color"        { return sym(Terminals.COLOR); }
diff --git a/eraser-base/src/main/jastadd/eraser.parser b/eraser-base/src/main/jastadd/eraser.parser
index 68967a5655bf12cab2e2127db29e1f0ac5ebd808..74abecdd89e1817f8ae4dfe0ad997d470d24c8a2 100644
--- a/eraser-base/src/main/jastadd/eraser.parser
+++ b/eraser-base/src/main/jastadd/eraser.parser
@@ -154,6 +154,17 @@ Group group_body =
   |                                                   {: return new Group(); :}
   ;
 
+
+
+//  SYNCSTATE COLON syncstate_body.ssb SEMICOLON {: eph.addStateSyncGroup(ssb); :};
+//  StateSyncGroup ssg = SYNCSTATE COLON syncstate_body.ssb SEMICOLON {: return ssb; :};
+//
+//// SyncState: items=["ITEM_ID", "ITEM_ID"];
+//StateSyncGroup syncstate_body =
+//     ITEMS EQUALS string_list.items syncstate_body.ss       {: return eph.setItems(ss, items); :}
+//  |                                                         {: return new StateSyncGroup(); :}
+//  ;
+
 ThingType thing_type =
      THING_TYPE COLON thing_type_body.ttb SEMICOLON   {: return ttb; :}
   ;
diff --git a/eraser-base/src/main/jastadd/shem.relast b/eraser-base/src/main/jastadd/shem.relast
index ca1878ac6d2722a3e2a1671e066b19c5175c7be6..9e7252ffc151f6b276b96dbe6ff3e0bad0479818 100644
--- a/eraser-base/src/main/jastadd/shem.relast
+++ b/eraser-base/src/main/jastadd/shem.relast
@@ -25,7 +25,7 @@ rel Channel.LinkedItem* <-> Item.Channel? ;
 Parameter : DescribableModelElement ::= <Type:ParameterValueType> [DefaultValue:ParameterDefaultValue] <Context:String> <Required:boolean> ;
 ParameterDefaultValue ::= <Value:String> ;
 
-abstract Item : LabelledModelElement ::= <_fetched_data:boolean> MetaData:ItemMetaData* [ItemObserver] ;
+abstract Item : LabelledModelElement ::= <_fetched_data:boolean> MetaData:ItemMetaData* ItemObserver;
 rel Item.Category? -> ItemCategory ;
 
 abstract ItemWithBooleanState : Item ::= <_state:boolean> ;
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 795d469bc786cfde73b12f8329956cbb79bb953a..87cd2764f8955c472b37e6abc887fa5c04d0a9b8 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
@@ -24,6 +24,7 @@ public class EraserParserHelper {
   private Map<String, Parameter> parameterMap = new HashMap<>();
   private Map<String, Item> itemMap = new HashMap<>();
   private Map<String, Group> groupMap = new HashMap<>();
+  private Map<String, StateSyncGroup> stateSyncMap = new HashMap<>();
 
   private Map<Thing, String> missingThingTypeMap = new HashMap<>();
   private Map<Channel, String> missingChannelTypeMap = new HashMap<>();
@@ -36,6 +37,7 @@ 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<StateSyncGroup, Iterable<String>> missingSyncItemListMap = new HashMap<>();
   private Map<ThingType, Iterable<String>> missingChannelTypeListMap = new HashMap<>();
   private Map<ThingType, Iterable<String>> missingParameterListMap = new HashMap<>();
 
@@ -93,10 +95,15 @@ public class EraserParserHelper {
     resolveList(itemMap, missingItemLinkListMap, Channel::addLinkedItem);
     resolveList(groupMap, missingSubGroupListMap, Group::addGroup);
     resolveList(itemMap, missingItemListMap, this::addItemToGroup);
+    resolveList(itemMap, missingSyncItemListMap, this::addItemToStateSync);
+
     resolveList(channelTypeMap, missingChannelTypeListMap, ThingType::addChannelType);
     resolveList(parameterMap, missingParameterListMap, ThingType::addParameter);
     resolveList(itemMap, missingControllingListMap, Item::addControlling);
 
+    // TODO: activate state sync stuff
+    this.activateStateSyncItems();
+
     createUnknownGroupIfNecessary();
     createChannelCategories();
     createItemCategories();
@@ -110,6 +117,12 @@ public class EraserParserHelper {
     group.addItem(item);
   }
 
+  private void addItemToStateSync(StateSyncGroup stateSyncGroup, Item item) {
+    stateSyncGroup.addItem(item);
+  }
+
+
+
   private void fillUnused() {
     unusedElements.addAll(thingTypeMap.values());
     unusedElements.addAll(channelTypeMap.values());
@@ -153,7 +166,7 @@ public class EraserParserHelper {
     unusedElements.forEach(elem -> logger.info("{} '{}' defined, but not referenced.", elem.getClass().getSimpleName(), ident(elem)));
   }
 
-  private String ident(ASTNode elem) {
+  private String ident(Object elem) {
     if (elem instanceof ModelElement) {
       return ((ModelElement) elem).getID();
     } else if (elem instanceof MqttTopic) {
@@ -166,7 +179,7 @@ public class EraserParserHelper {
     return elem.toString();
   }
 
-  private <Src extends ASTNode, Target extends ASTNode> void resolveList(
+  private <Src, Target extends ASTNode> void resolveList(
       Map<String, Target> resolved, Map<Src, Iterable<String>> missing, BiConsumer<Src, Target> adder) {
     missing.forEach(
         (elem, keyList) -> keyList.forEach(
@@ -174,14 +187,14 @@ public class EraserParserHelper {
     missing.clear();
   }
 
-  private <Src extends ASTNode, Target extends ASTNode> void resolve(
+  private <Src, Target extends ASTNode> void resolve(
       Map<String, Target> resolved, Map<Src, String> missing, BiConsumer<Src, Target> setter) {
     missing.forEach(
         (elem, key) -> resolve0(resolved, key, elem, setter));
     missing.clear();
   }
 
-  private <Src extends ASTNode, Target extends ASTNode> void resolve0(
+  private <Src, Target extends ASTNode> void resolve0(
       Map<String, Target> resolved, String key, Src elem, BiConsumer<Src, Target> action) {
     Target value = resolved.get(key);
     if (value == null) {
@@ -195,6 +208,14 @@ public class EraserParserHelper {
     action.accept(elem, value);
   }
 
+    private void activateStateSyncItems() {
+    for (StateSyncGroup stateSyncGroup : new ArrayList<StateSyncGroup>()) {
+
+      for (Item item : stateSyncGroup.getItems()) {
+      }
+    }
+  }
+
   //--- Thing and ThingType ---
 
   public Thing addThingType(Thing t, String typeName) {
@@ -292,11 +313,6 @@ public class EraserParserHelper {
     return item;
   }
 
-  public Item setControlling(Item item, StringList controlling) {
-    missingControllingListMap.put(item, controlling);
-    return item;
-  }
-
   public Item retype(Item itemWithCorrectType, Item prototype) {
     itemWithCorrectType.setID(prototype.getID());
     itemWithCorrectType.setLabel(prototype.getLabel());
@@ -478,6 +494,17 @@ public class EraserParserHelper {
     return result;
   }
 
+  //--- SyncState ---
+  public StateSyncGroup setItems(StateSyncGroup ssg, StringList itemNames) {
+    missingSyncItemListMap.put(ssg, itemNames);
+    return ssg;
+  }
+
+  public void addStateSyncGroup(StateSyncGroup ssg) {
+    System.out.println("Gotcha");
+  }
+
+
   public Rule createRule(Condition c, Action a) {
     Rule result = new Rule();
     result.addCondition(c);