diff --git a/.gitignore b/.gitignore
index 25afa1e8010584cbbae9191e70e3a8f583cfc8ac..36cdad0353f377d56af524afa0d541ae825fd5d2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,3 +6,4 @@ venv/
 */build/
 logs/
 datasets/
+public/
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index b3ccd4b8432af954364597c4617366fed3fe2ce1..c7d42cdb85ddc55d98908db8e313e36c47c5e3b5 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,7 +1,10 @@
 stages:
-- build
-- test
-- report
+  - build
+  - test
+  - report
+  - ragdoc_build
+  - ragdoc_view
+  - publish
 
 variables:
   # Instruct Testcontainers to use the daemon of DinD.
@@ -17,33 +20,29 @@ variables:
 before_script:
   - export GRADLE_USER_HOME=`pwd`/.gradle
 
+cache:
+  paths:
+    - .gradle/wrapper
+    - .gradle/caches
+
 build:
   image: openjdk:8
-  tags:
-    - docker
   stage: build
   script:
     - ./gradlew --console=plain --build-cache assemble
-  cache:
-    key: "$CI_COMMIT_REF_NAME"
-    policy: push
+  artifacts:
     paths:
-      - build
-      - .gradle
+      - "eraser-base/src/gen"
 
 test:
   image: openjdk:8
   tags:
     - docker
   stage: test
+  needs:
+    - build
   script:
     - ./gradlew --continue --console=plain --info check jacocoTestReport
-  cache:
-    key: "$CI_COMMIT_REF_NAME"
-    policy: pull
-    paths:
-      - build
-      - .gradle
   artifacts:
     when: always
     paths:
@@ -53,24 +52,66 @@ test:
 
 coverage:
   image: python:3.7.1-alpine
-  tags:
-    - docker
   stage: report
-  dependencies:
-  - test
+  needs:
+    - test
   script:
 #    - ./gradlew --continue --console=plain -x test jacocoTestReport
     - pip install --user untangle
     - python print-coverage.py
   coverage: "/Covered (\\d{1,3}\\.\\d{2}%) of instructions for all projects\\./"
-  cache:
-    key: "$CI_COMMIT_REF_NAME"
-    policy: pull
-    paths:
-      - build
-      - .gradle
   allow_failure: true
   artifacts:
     when: always
     paths:
       - $JACOCO_REPORT
+
+ragdoc_build:
+  image:
+    name: "git-st.inf.tu-dresden.de:4567/jastadd/ragdoc-builder"
+    entrypoint: [""]
+  stage: ragdoc_build
+  needs:
+    - build
+  script:
+    - JAVA_FILES=$(find eraser-base/src/ -name '*.java')
+    - /ragdoc-builder/start-builder.sh -excludeGenerated -d data/ $JAVA_FILES
+  artifacts:
+    paths:
+      - "data/"
+
+ragdoc_view:
+  image:
+    name: "git-st.inf.tu-dresden.de:4567/jastadd/ragdoc-view:relations"
+    entrypoint: [""]
+  stage: ragdoc_view
+  needs:
+    - ragdoc_build
+  script:
+    - DATA_DIR=$(pwd -P)/data
+    - mkdir -p pages/docs/ragdoc
+    - OUTPUT_DIR=$(pwd -P)/pages/docs/ragdoc
+    - cd /ragdoc-view
+    - ( cd src/ && rm -rf data && ln -s $DATA_DIR )
+    - /ragdoc-view/build-view.sh --output-path=$OUTPUT_DIR
+    - ls -lah $OUTPUT_DIR
+  artifacts:
+    paths:
+      - "pages/docs/ragdoc"
+
+pages:
+  image: python:3.8-buster
+  stage: publish
+  needs:
+    - test
+    - ragdoc_view
+  before_script:
+    - pip install -U mkdocs mkdocs-macros-plugin mkdocs-git-revision-date-plugin
+  script:
+    - cd pages && mkdocs build
+  only:
+    - dev
+    - master
+  artifacts:
+    paths:
+    - "public"
diff --git a/.gitmodules b/.gitmodules
index e77282f413a7cf57a9ad0b61b13d7397531c013f..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,3 +0,0 @@
-[submodule "ragdoc-view"]
-	path = ragdoc-view
-	url = ../../jastadd/ragdoc-view/
diff --git a/eraser-base/build.gradle b/eraser-base/build.gradle
index d7d479060974e959b4caeefa1e592897d922f028..7b5aa8060bbd083c4e05b41fa9bc77a85c6642ff 100644
--- a/eraser-base/build.gradle
+++ b/eraser-base/build.gradle
@@ -129,35 +129,6 @@ sourceSets.main {
     }
 }
 
-javadoc {
-    // this is only run to get the index file etc.
-    failOnError = false
-}
-
-String[] arguments = ["libs/rd-builder.jar", "-d", "doc/"]
-def allSrcFiles = sourceSets.main.allSource.findAll { it.name.endsWith('java') }.toArray()
-def ragdocViewSrcData = '../ragdoc-view/src/data/'
-
-task ragdocFixed(type: JavaExec, dependsOn: assemble) {
-    group = 'documentation'
-    description = 'Create ragdoc json documentation files'
-    main = "-jar"
-    args arguments + allSrcFiles
-}
-
-task cleanRagdoc(type: Delete) {
-    group = 'documentation'
-    delete fileTree(ragdocViewSrcData + '/*')
-}
-
-task copyRagdoc(type: Copy, dependsOn: cleanRagdoc) {
-    group = 'documentation'
-    description = 'Copy ragdoc json documentation files to ragdoc-viewer'
-    from 'doc/'
-    into ragdocViewSrcData
-    eachFile { println it.file }
-}
-
 generateAst.dependsOn preprocess
 generateAst.inputs.files file("./src/main/jastadd/mainGen.ast"), file("./src/main/jastadd/mainGen.jadd")
 //compileJava.dependsOn jastadd
diff --git a/eraser-base/src/test/java/de/tudresden/inf/st/eraser/RulesTest.java b/eraser-base/src/test/java/de/tudresden/inf/st/eraser/RulesTest.java
index 1c5289208cee3c5f4ca1f07f55d0cbc5d9d52ac3..1a1ea62a2d4611fa00da7252510a325fe40cf41f 100644
--- a/eraser-base/src/test/java/de/tudresden/inf/st/eraser/RulesTest.java
+++ b/eraser-base/src/test/java/de/tudresden/inf/st/eraser/RulesTest.java
@@ -5,6 +5,7 @@ import de.tudresden.inf.st.eraser.jastadd.model.*;
 import de.tudresden.inf.st.eraser.util.ParserUtils;
 import de.tudresden.inf.st.eraser.util.TestUtils;
 import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.Disabled;
 
 import java.io.IOException;
 import java.util.HashMap;
@@ -632,6 +633,7 @@ public class RulesTest {
     assertEquals(1, affectedItem.getState(), DELTA, "Change of item state should set the state of the affected item");
   }
 
+  @Disabled("Not working reliably, need to be made more robust")
   @Test
   public void testCronJobRule() {
     Rule rule = new Rule();
diff --git a/pages/.gitignore b/pages/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..a95071c4b0fd05bccf528339a15b2e93458bc694
--- /dev/null
+++ b/pages/.gitignore
@@ -0,0 +1 @@
+/docs/ragdoc/
diff --git a/pages/custom_theme/footer.html b/pages/custom_theme/footer.html
new file mode 100644
index 0000000000000000000000000000000000000000..e76f0a2b54f97d9b338c9ca8cf36646da77e35a1
--- /dev/null
+++ b/pages/custom_theme/footer.html
@@ -0,0 +1,11 @@
+{% block footer %}
+<p>{% if config.copyright %}
+<small>{{ config.copyright }}<br></small>
+{% endif %}
+<hr>
+Built with <a href="https://www.mkdocs.org/">MkDocs</a> using a <a href="https://github.com/snide/sphinx_rtd_theme">theme</a> provided by <a href="https://readthedocs.org">Read the Docs</a>.
+{% if page and page.meta and page.meta.revision_date %}
+<small><br><i>Last updated {{ page.meta.revision_date.strftime('%B %d, %Y at %H:%M') }}</i></small>
+{% endif %}
+</p>
+{% endblock %}
diff --git a/pages/docs/DSL.md b/pages/docs/DSL.md
new file mode 100644
index 0000000000000000000000000000000000000000..c58ec900fdab199ba904b915758c409fc1e1569c
--- /dev/null
+++ b/pages/docs/DSL.md
@@ -0,0 +1,100 @@
+# The eraser-DSL
+
+Find a general description in the [Model description](Model-description) page, and the parser ([dev](https://git-st.inf.tu-dresden.de/OpenLicht/eraser/blob/dev/eraser-base/src/main/jastadd/eraser.parser), [master](https://git-st.inf.tu-dresden.de/OpenLicht/eraser/blob/master/eraser-base/src/main/jastadd/eraser.parser)) and printing ([dev](https://git-st.inf.tu-dresden.de/OpenLicht/eraser/blob/dev/eraser-base/src/main/jastadd/Printing.jrag), [master](https://git-st.inf.tu-dresden.de/OpenLicht/eraser/blob/master/eraser-base/src/main/jastadd/Printing.jrag)).
+
+The DSL is line-based, so on each line, one model element will be defined.
+All shown specifications for one element are optional and can be reordered, but at least `id` must be present to identify the element.
+References to other elements are done by using their IDs as strings, and can be forward references.
+The following elements can be described (in the master branch if not otherwise noted):
+
+## ChannelType
+
+```
+ChannelType: id="" label="" description="" itemType="" category="" readyOnly;
+```
+
+- The item type has to be one of the [item names defined for Eclipse Smart Home](https://www.eclipse.org/smarthome/documentation/concepts/items.html)
+- The category can either be one of the [categories defined for Eclipse Smart Home](https://www.eclipse.org/smarthome/documentation/concepts/categories.html#channel-categories), or a custom one.
+- Both item type and category are defined as enums ([dev](https://git-st.inf.tu-dresden.de/OpenLicht/eraser/blob/dev/eraser-base/src/main/jastadd/enums.jadd), [master](https://git-st.inf.tu-dresden.de/OpenLicht/eraser/blob/master/eraser-base/src/main/jastadd/enums.jadd))
+- The flag `readOnly` is currently without any effect
+
+## Channel
+
+```
+Channel: id="" type="" links=["ITEM_ID", "ITEM_ID"];
+```
+
+- `type` must reference a [ChannelType](#channeltype), and must be set
+- `links` must reference [items](#item)
+
+## Group
+
+```
+Group: id="" groups=["GROUP_ID", "GROUP_ID"] items=["ITEM_ID", "ITEM_ID"] aggregation=AGG;
+```
+
+- `groups` must reference other [groups](#group)
+- `items` must reference [items](#item)
+- `AGG` in `aggregation` can either be one of `EQUALITY`, `AVG`, `MAX`, `MIN`, `SUM`; or one of `AND`, `OR`, `NAND`, `NOR`, followed by a list of arguments surrounded by round brackets, e.g., `aggregation = AVG` or `aggregation = AND ("off", "on")`. The semantics are described in the [openHAB docs](https://www.openhab.org/docs/configuration/items.html#group-type-and-state)
+
+## Item
+
+```
+ITEM_TYPE Item: id="" label="" state="" category="" topic="" controls=["ITEM_ID", "ITEM_ID"] metaData={"key":"value"};
+```
+
+- `ITEM_TYPE` can be one of the following: `Color`, `Contact`, `DateTime`, `Dimmer`, `Image`, `Location`, `Number`, `Player`, `RollerShutter`, `String`, `Switch`. If left out, the item will behave as if `String` was used.
+- `state` is given as a string and will be interpreted depending on the type of the item
+- `topic` implicitely defines a [MQTT](mqtt) topic which is used to update the item in both directions. The full topic is prefixed with `incoming`-prefix if receiving updates from openHAB, and `outgoing`-prefix if sending updates to openHAB
+- `category` is currently not used
+- `controls` is only available on `dev`. It defines connection of one item controls the state of another item as the state of the first item changes.
+- `metaData` contains key-value-pairs comprising its meta data
+
+## Parameter
+
+```
+Parameter: id="" label="" description="" type="" default="" required;
+```
+
+- `type` has to be one of the following: `Boolean`, `Decimal`, `Integer`, `Text`
+- `default` is currently an arbitrary String, thus it is not checked whether it matches the type
+
+## ThingType
+
+```
+ThingType: id="" label="" description="" parameters=["PARAM_ID", "PARAM_ID"] channelTypes=["CHANNEL_TYPE_ID", "CHANNEL_TYPE_ID"];
+```
+
+- `parameters` must reference [parameters](#parameter)
+- `channelTypes` must reference [channel types](#channeltype)
+
+## Thing
+
+```
+Thing: id="" label="" type="" channels=["CHANNEL_ID", "CHANNEL_ID"] ;
+```
+
+- `type` must reference a [thing type](#thingtype), and must be set
+- `channels` must reference [channels](#channel)
+
+## Mqtt
+
+```
+Mqtt: incoming="" outgoing="" host="";
+```
+
+- MQTT is used to communicate/synchronize with openHAB
+- `incoming` defines the prefix for received MQTT messages, see [topic description in item](#item). Defaults to an empty string, which should be avoided.
+- `outgoing` defines the prefix for sent MQTT messages, see [topic description in item](#item). Defaults to an empty string, which should be avoided.
+- `host` defines the URL of the host running an MQTT broker. The port will be set to `1883` and cannot be changed.
+
+## Influx
+
+```
+Influx: user="" password="" dbName="" host="" ;
+```
+
+- Influx is used to store historical item states
+- `user` and `password` define connection credentials
+- `dbName` defines the name of the database to use
+- `host` defines the URL of the host running an InfluxDB. The port will be set to `8086` and cannot be changed.
diff --git a/pages/docs/Inner-workings.md b/pages/docs/Inner-workings.md
new file mode 100644
index 0000000000000000000000000000000000000000..ebbb861f8a380b26abe079584c28f263165d1110
--- /dev/null
+++ b/pages/docs/Inner-workings.md
@@ -0,0 +1,106 @@
+# Inner workings
+
+Please also refer to the [API documentation](ragdoc/index.html)
+
+## openHAB synchronization via MQTT
+
+MQTTRoot contains `incomingPrefix`, `outgoingPrefix` and `host` tokens.
+
+Items have a MQTT-topic associated, both from which they get updates via MQTT and publish changes of their state via MQTT.
+
+Eraser will subscribe to `incomingPrefix/#`, i.e., every update of topics starting with `incomingPrefix` is listened to.
+Also, if the a new host is set (`MQTTRoot.Host`), the connection is re-established.
+Listening means, that upon a new message, the topic string is resolved to a non-terminal MQTT-topic using `Root.resolveTopic`. This topic non-terminal has a reference to its item, which in turn has its state updated with the body of the MQTT message. Each different item type has its own way to set its state from a string (`Item.setStateFromString`).
+
+Whenever a state of an item is set from within the KB, this change will be published via MQTT, if `shouldSendState` is set to true, or the default setting (`DefaultShouldSendState`) is set to true.
+The topic will be prefix with `outgoingPrefix`. Every item type has its own way to print its state to a string (`Item.getStateAsString`), which is used as a MQTT message body.
+
+
+## Item state history via InfluxDB
+
+Connecting to Influx is done with the Java binding `org.influxdb:influxdb-java`. To represent the data to send and receive, `ItemPoints` are used defined in the `ItemHistoryPoints.jrag` aspect file.
+There is one class for each item type capturing the specifics for translating item states to data points.
+
+A pretty cool way to add new behavior when setting the item state is to use JastAdd's refinement:
+
+```
+refine MQTT public void Item.sendState() throws Exception {
+  refined();
+  getRoot().getInfluxRoot().influxAdapter().write(pointFromState());
+}
+```
+
+This adds writing a new data point to influx after the former behavior (which includes sending the update via MQTT, as described above).
+However, those two are intended to be independent of each other.
+
+For retrieving the history, an asynchronous approach was chosen and is described in the following. The sequence diagram shows the important methods called, where ItemType denotes a specific subclass of Item, e.g., `ColorItem` or `ItemWithDoubleState`, and Item denotes the general, common superclass `Item`.
+
+![item-history](img/item-history.png)
+
+To get the history, `getHistory` is called on a specific item returning a list of datapoints of a matching type, e.g., a list of `DoubleStatePoint` for an `ItemWithDoubleState`.
+
+The code in `getHistory` is actuall the same for every type, namely: `return proxied(this::_history);`
+This calls `proxied` (shown in yellow above) which first asynchronously updates the history and returns the current value using `_history()` (shown in orange).
+For updating the history, first `historyUpdating` is checked, and if appropriate, the current InfluxAdapter is used to invoke `asyncQuery` and use the return value to set a new `history_token`.
+This token contains the history, and is returned by the `_history` attribute. If data was never fetched before, an empty list is returned.
+
+## Rules
+
+For events in rules to trigger, `ItemObserver` objects are used. The following figure shows three rules (A, B, C) triggered by two different items (`item1` und `item2`):
+
+![rules-object](img/rules-object.png)
+
+To get those wirings, the following code can be used:
+
+```java
+Root model = createModel();
+NumberedItem item1 = createNumberedItem();
+ColorItem item2 = createColorItem();
+addToModel(model, item1);
+addToModel(model, item2);
+
+Rule rA = new Rule();
+ItemStateNumberCheck check1 = new ItemStateNumberCheck(ComparatorType.GreaterOrEqualThan, 4);
+ItemStateNumberCheck check2 = new ItemStateNumberCheck(ComparatorType.LessThan, 6);
+rA.addCondition(new ItemStateCheckCondition(check1));
+rA.addCondition(new ItemStateCheckCondition(check2));
+rA.setAction(new LambdaAction(item -> System.out.println("A was triggered by " + item.getLabel())));
+rA.setAction(new LambdaAction(item -> item.disableSendState()));
+rA.activateFor(item1);
+
+Rule rB = new Rule();
+Rule rC = new Rule();
+// .. conditions, actions of B and C
+rB.activateFor(item1);
+rB.activateFor(item2);
+rC.activateFor(item1);
+```
+
+Changes to `item1` trigger all three rules, whereas changing `item2` only triggers the second rule B.
+Triggering a rule works as follows:
+
+![rules-sequence](img/rules-sequence.png)
+
+When the state of `item1` is changed, its observer checks, whether the new change is different to the previous change. If that is the case, it triggers all associated rules, i.e, it calls `rule.trigger()` for every rule in the `TriggeredRuleList`.
+The rule checks all conditions (if any), and if all hold, executes all actions (if any).
+
+In this shown case, `item1` was changed, thus all rules `rA`, `rB`, and `rC` are triggered, if the state has changed. The full sequence send for the two latter events is not shown above for brevity.
+
+### Condition Types
+
+Currently only one condition is supported, which compares the state of an ItemWithDoubleState with a given constant. It borrows its functionality from `ItemStateCheck`, which has a comparator (`>=`, `>`, `=`, `!=`, `<`, `<=`) and a double constant.
+
+### Action Types
+
+| Name | Children | Description |
+|------|----------|-------------|
+| Action | _none_ | Abstract super class for all actions |
+| LambdaAction | <ul><li>`<Lambda:Action2EditConsumer>` An arbitrary lambda consuming an `Item`</li></ul> | Does arbitrary stuff, use only if none of the classes below fit. |
+| TriggerRuleAction | <ul><li>`rel Rule -> Rule` Relation to the rule to trigger</li></ul> | Triggers another rule passing the same item to it. |
+| _SetStateAction_ (abstract) | <ul><li>`rel AffectedItem -> Item` The item to change the state of</li></ul> | Abstract class for changing the state of one affected item. |
+| SetStateFromConstantStringAction | <ul><li>`rel AffectedItem -> Item` (from SetStateAction)</li><li>`<NewState:String>` The new state to set</li></ul> | Sets the given constant as the new state for the affected item |
+| SetStateFromLambdaAction | <ul><li>`rel AffectedItem -> Item` (from SetStateAction)</li><li>`<NewStateProvider:NewStateProvider>` A lambda to get the new state</li></ul> | Sets the given variable as the new state for the affected item |
+| SetStateFromTriggeringItemAction | <ul><li>`rel AffectedItem -> Item` (from SetStateAction)</li></ul> | Sets the state of the triggering item as the new state for the affected item |
+| SetStateFromItemsAction | <ul><li>`rel AffectedItem -> Item` (from SetStateAction)</li><li>`<Combinator:ItemsToStringFunction>` A function taking a list of items and returning a string</li><li>`rel SourceItem* -> Item` A list of input items</li></ul> | Uses the combinator to combine all input items to a new state, which is set for the affected item |
+| AddDoubleToStateAction | <ul><li>`rel AffectedItem -> Item` (from SetStateAction)</li><li>`<Increment:double>` A constant value to add</li></ul> | Increments the state of the affected item by the given constant increment |
+| MultiplyDoubleToStateAction | <ul><li>`rel AffectedItem -> Item` (from SetStateAction)</li><li>`<Multiplier:double>` A constant value to multipy</li></ul> | Multiplies the state of the affected item by the given constant multiplier |
diff --git a/pages/docs/Learner.md b/pages/docs/Learner.md
new file mode 100644
index 0000000000000000000000000000000000000000..89a7ed477b766a2c26906aa6e9a5a7b7c14ea9a7
--- /dev/null
+++ b/pages/docs/Learner.md
@@ -0,0 +1,102 @@
+# Learner
+
+_This document is only available in German_
+
+Der Learner ist ein Interface zur Encog Bibliothek. Er dient nur dazu Modelle zu traineren und zu Laufzeit des Systems anzupassen. Im Folgenden zeigen wir Beispiele wie der Learner zu Verwenden ist.
+
+## Training mit externen Datensatz
+
+```java
+learner.setCsvFolderPath("/csvs");
+
+ArrayList<Integer> targetColumns = new ArrayList<>();
+targetColumns.add(5);
+targetColumns.add(7);
+
+int modelID = 1;
+
+learner.loadDataSet("test1", targetColumns, modelID);
+
+ArrayList<Integer> inputMaxes = new ArrayList<>();
+inputMaxes.add(100); // e.g., first Columns is light intensity sensor with max value of 100
+// ...
+
+ArrayList<Integer> inputMins = new ArrayList<>();
+inputMins.add(0); // e.g., first Columns is light intensity sensor with min value of 0
+// ...
+
+ArrayList<Integer> inputMaxes = new ArrayList<>();
+targetMaxes.add(255); // e.g., first output value is R value of lamp with max value of 255
+// ...
+
+ArrayList<Integer> inputMins = new ArrayList<>();
+targetMins.add(0); // e.g., first output value is R value of lamp with min value of 0
+// ...
+
+int inputCount = 5; 
+int outputCount = 2;
+int hiddenCount = 1;
+int hiddenNeuronCount = 4;
+
+learner.train(inputCount, outputCount, hiddenCount, hiddenNeuronCount, imodelID, inputMaxes, inputMins,  targetMaxes, targetMins);
+
+Model model = learner.getTrainedModel(modelID);
+```
+
+## Training mit Daten von interner Datenbank
+
+```java
+ArrayList<Integer> targetColumns = new ArrayList<>();
+targetColumns.add(5);
+targetColumns.add(7);
+
+int modelID = 1;
+
+ArrayList<Integer> inputMaxes = new ArrayList<>();
+inputMaxes.add(100); // e.g., first Columns is light intensity sensor with max value of 100
+// ...
+
+ArrayList<Integer> inputMins = new ArrayList<>();
+inputMins.add(0); // e.g., first Columns is light intensity sensor with min value of 0
+// ...
+
+ArrayList<Integer> inputMaxes = new ArrayList<>();
+targetMaxes.add(255); // e.g., first output value is R value of lamp with max value of 255
+// ...
+
+ArrayList<Integer> inputMins = new ArrayList<>();
+targetMins.add(0); // e.g., first output value is R value of lamp with min value of 0
+...
+
+int inputCount = 5; 
+int outputCount = 2;
+int hiddenCount = 1;
+int hiddenNeuronCount = 4;
+
+Table table = database.getData("query"); // Database Klasse, Methode und Table existieren nicht, nur ein Beispiel
+
+double [][] data = table.toArray(); // Methode und Table existieren nicht, nur ein Beispiel
+
+learner.train(data, inputCount, outputCount, hiddenCount, hiddenNeuronCount, imodelID, inputMaxes, inputMins,  targetMaxes, targetMins, targetColumns);
+
+Model model = learner.getTrainedModel(modelID);
+```
+
+## Retraining
+
+```java
+ArrayList<Integer> targetColumns = new ArrayList<>();
+targetColumns.add(5);
+targetColumns.add(7);
+
+int modelID = 1;
+
+data[][] dataVector = database.getNewestVector(); // Database Klasse und Methode existieren nicht nur ein Beispiel
+
+learner.reTrain(dataVector, targetColumns, modelID);
+```
+
+## Inference
+
+Bei der Nutzung der von Machine Learning muss in vielen Fällen die Einagbe und Ausgaben normalisiert bzw. denormalisiert werden.
+Die Normalisierer können vom Learner angefragt werden mit getNormalizerInput und getNormalizerTar angefragt werden.
diff --git a/pages/docs/MachineLearning.md b/pages/docs/MachineLearning.md
new file mode 100644
index 0000000000000000000000000000000000000000..de5ab0652dca58141d4f976bd4f1f46c76480a89
--- /dev/null
+++ b/pages/docs/MachineLearning.md
@@ -0,0 +1,227 @@
+# Machine Learning Basics
+
+The relevant parts of the grammar ([dev](https://git-st.inf.tu-dresden.de/OpenLicht/eraser/blob/dev/eraser-base/src/main/jastadd/main.relast) | [master](https://git-st.inf.tu-dresden.de/OpenLicht/eraser/blob/dev/eraser-base/src/main/jastadd/main.relast)) are the following (updated on Feburary, 11th 2019):
+
+## General information machine learning
+
+```
+abstract MachineLearningModel ::= <OutputApplication:DoubleDoubleFunction> ;
+abstract ItemPreference ::= ;
+ItemPreferenceColor : ItemPreference ::= <PreferredHSB:TupleHSB> ;
+ItemPreferenceDouble : ItemPreference ::= <PreferredValue:double> ;
+rel ItemPreference.Item -> Item ;
+
+// neural network
+NeuralNetworkRoot : MachineLearningModel ::= InputNeuron* HiddenNeuron* OutputLayer ;
+OutputLayer ::= OutputNeuron* <Combinator:DoubleArrayDoubleFunction> ;
+abstract Neuron ::= Output:NeuronConnection* ;
+NeuronConnection ::= <Weight:double> ;
+InputNeuron : Neuron ;
+HiddenNeuron : Neuron ::= <ActivationFormula:DoubleArrayDoubleFunction> ;
+OutputNeuron : HiddenNeuron ::= <Label:String> ;
+rel NeuronConnection.Neuron <-> Neuron.Input* ;
+rel InputNeuron.Item -> Item ;
+rel OutputLayer.AffectedItem -> Item ;
+
+// decision tree
+DecisionTreeRoot : MachineLearningModel ::= RootRule:DecisionTreeRule ;
+abstract DecisionTreeElement ::= Preference:ItemPreference*;
+abstract DecisionTreeRule : DecisionTreeElement ::= Left:DecisionTreeElement Right:DecisionTreeElement <Label:String> ;
+ItemStateCheckRule : DecisionTreeRule ::= ItemStateCheck ;
+abstract ItemStateCheck ::= <Comparator:ComparatorType> ;
+ItemStateNumberCheck : ItemStateCheck ::= <Value:double> ;
+ItemStateStringCheck : ItemStateCheck ::= <Value:String> ;
+DecisionTreeLeaf : DecisionTreeElement ::= <ActivityIdentifier:int> <Label:String> ;
+
+// dummy model
+DummyMachineLearningModel : MachineLearningModel ::= <Current:DecisionTreeLeaf> ;
+```
+
+A machine learning model implements a classification task, thus it has an attribute `classify` returning a general class `Leaf` whose type depends to the specific model.
+This leaf represents the result of a classification, and comprises a double value and a set of `ItemPreference`s.
+Such a double value can be scaled using the `OutputApplication`, which is a function mapping one double value to another.
+If the neural network only outputs values from 0 to 3, but a range from 0 to 100 is needed, the OutputApplication function can multiply the result with 33.
+
+## Neural networks
+
+A neural network is, generally speaken, a set of neurons connected through weighted connections.
+Those neurons are typically put into layers such that connections of neurons are only possible between neurons in adjecent layers.
+Currently in `eraser`, only the output layer is explicitely modelled.
+
+Neurons are either Input-, Hidden-, or OutputNeurons.
+InputNeurons typically form the first (implicit) layer and are connected to Items, thus get their state from the state of the connected Item.
+HiddenNeurons are between input and output, and have an individual `ActivationFormula` taking all input values from the neuron and return its state.
+OutputNeurons also have an activation formula, and are children of the `OutputLayer`.
+In this output layer, a `Combinator` is defined, which merges the values of all output neurons into one double value as result of the whole neural network.
+
+### Construction of a neural network
+
+Most of the code snippets in this section are taken from [NeuralNetworkTest in the `dev` branch](https://git-st.inf.tu-dresden.de/OpenLicht/eraser/blob/dev/eraser-base/src/test/java/de/tudresden/inf/st/eraser/NeuralNetworkTest.java).
+To construct a neural network, first the root element needs to be created using `createEmpty`, which sets the output application function to the identity function:
+
+```
+NeuralNetworkRoot neuralNetworkRoot = NeuralNetworkRoot.createEmpty()
+```
+
+Then all neurons are created using the matching type, e.g.:
+
+```java
+InputNeuron inputNeuron = new InputNeuron();
+HiddenNeuron hiddenNeuron = new HiddenNeuron();
+hiddenNeuron.setActivationFormula(inputs -> 4 * inputs[0]);
+OutputNeuron outputNeuron1 = new OutputNeuron();
+outputNeuron1.setLabel("first");
+outputNeuron1.setActivationFormula(inputs -> inputs[0] > 4 ? 1d : 0d);
+```
+
+Afterwards, the connections are set using the convenience method `connectTo` taking the target neuron and a weight:
+
+```java
+inputNeuron.connectTo(hiddenNeuron, 1);
+hiddenNeuron.connectTo(outputNeuron1, 0.4);
+```
+
+As an important next step, the output layer and all neurons are added to the model:
+
+```java
+neuralNetworkRoot.addInputNeuron(inputNeuron);
+neuralNetworkRoot.addHiddenNeuron(hiddenNeuron);
+OutputLayer outputLayer = new OutputLayer();
+outputLayer.addOutputNeuron(outputNeuron1);
+neuralNetworkRoot.setOutputLayer(outputLayer);
+```
+
+Connect the items to the neural network.
+This will assign the first item in the list to the first input neuron, the second to the second, and so on.
+
+```java
+Item item;
+neuralNetworkRoot.connectItems(Arrays.asList(item));
+```
+
+The combinator function is set using a lambda expression:
+
+```java
+outputLayer.setCombinator(outputs -> {
+  int n = 0;
+  for (double d : outputs) {
+    n = (n << 1) | (d == 0 ? 0 : 1);
+  }
+  return (double) n;
+});
+```
+
+Finally, the affected item needs to be set in the output layer:
+
+```java
+Item affectedItem;
+outputLayer.setAffectedItem(affectedItem);
+```
+
+To verify, that the network was correctly built, the `check` method can be used.
+It will check the various formulas (output, combinator, activation), valid connections, set weights and connected items.
+The return value is `true` if no errors were found, and `false` otherwise.
+In case of any warnings or errors, they are printed out using the logger.
+
+```java
+boolean everythingValid = neuralNetworkRoot.check();
+```
+
+### Using a neural network
+
+Once a model has been built, it can be used either to recognize activities, or to learn preferences:
+
+```java
+Root model;
+// either recognize activities, ...
+model.getMachineLearningRoot().setActivityRecognition(neuralNetworkRoot);
+// ... or learn preferences
+model.getMachineLearningRoot().setPreferenceLearning(neuralNetworkRoot);
+```
+
+Once add the complete model, the classification can be invoked:
+
+```java
+Leaf leaf = neuralNetworkRoot.classify();
+```
+
+Depending on the use case, the leaf can either be interpreted as an activity, or as an item preference.
+For an activity, the classification result is used as an acitivty identifier:
+
+```java
+int identifier = leaf.getActivityIdentifier();
+Optional<Activity> activity = model.resolveActivity(identifier);
+```
+
+Alternatively, the result can be a preference as written in the following.
+In case of a neural network, currently only one item will be affected (the one set as AffectedItem in the output layer).
+
+```java
+List<ItemPreference> preferences = leaf.computePreferences();
+for (ItemPreference p : preferences) {
+	p.apply();
+}
+```
+
+## Decision Trees
+
+A decision tree is a tree of decisions.
+Every decision rule refers to an item and compares the state of this item to a given constant.
+The leaf of the tree don't contain any decisions anymore, instead they capture the classification result.
+
+### Construction of a decision tree
+
+Like above, most of the code was taken from the according test, in this case the [DecisionTreeTest](https://git-st.inf.tu-dresden.de/OpenLicht/eraser/blob/dev/eraser-base/src/test/java/de/tudresden/inf/st/eraser/DecisionTreeTest.java).
+
+To begin with, construct a new `DecisionTreeRoot`.
+
+```java
+DecisionTreeRoot dtroot = new DecisionTreeRoot();
+```
+
+Next, create your first decision.
+In this case, the rule will decided whether the state of the referenced item is below or above 4.
+Instead of the leafs, other rules could be inserted referencing the same or another Item.
+
+```java
+DecisionTreeLeaf isLessThanFour = new DecisionTreeLeaf();
+DecisionTreeLeaf isFourOrGreater = new DecisionTreeLeaf();
+ItemStateNumberCheck check = new ItemStateNumberCheck(ComparatorType.LessThan, 4f);
+JastAddList<ItemPreference> preferences = new JastAddList();
+dtroot.setRootRule(new Rule(preferences, isLessThanFour, isFourOrGreater, "check item1", check));
+```
+
+For every leaf, its label, the resulting activity identifier and item preferences have to be set.
+
+```java
+Item affectedItem;
+isLessThanFour.setLabel("less than four");
+isLessThanFour.setActivityIdentifier(1);
+isLessThanFour.addItemPreference(new ItemPreferenceDouble(2, affectedItem));
+isFourOrGreater.setLabel("four or greater");
+isFourOrGreater.setActivityIdentifier(3);
+isFourOrGreater.addItemPreference(new ItemPreferenceColor(new TupleHSB(1, 2, 3), affectedItem));
+```
+
+The automatic connection of items to all elements of a decision tree is currently not supported.
+Instead the items can only be set manually.
+
+```java
+Item item;
+try {
+	DecisionTreeRoot.connectItems(Arrays.asList(item));
+} catch(UnsupportedOperationException e) {
+	check.setItem(item);
+}
+```
+
+### Using a decision tree
+
+The result of the classification is the leaf at the end of the "decision path".
+If the item has for example a state of 3, the leaf `isLessThanFour` will be returned.
+
+```java
+Leaf leaf = dtroot.classify();
+```
+
+A `DecisionTreeLeaf` directly has an activity identifier and item preferences attached to it, thus can be used in the same way as described [above](#using-a-neural-network).
diff --git a/pages/docs/Model-description.md b/pages/docs/Model-description.md
new file mode 100644
index 0000000000000000000000000000000000000000..f3edf840caf5ccccc2df01cab11c2b8e8ff21ae1
--- /dev/null
+++ b/pages/docs/Model-description.md
@@ -0,0 +1,58 @@
+# Model description
+
+The latest version of the model: [master](https://git-st.inf.tu-dresden.de/rschoene/eraser/blob/master/eraser-base/src/main/jastadd/main.relast) | [dev](https://git-st.inf.tu-dresden.de/rschoene/eraser/blob/dev/eraser-base/src/main/jastadd/main.relast)
+
+Below, all parts of the model are described in more detail. Each part resides in a separate grammar file.
+
+## Main
+
+Root ::= OpenHAB2Model User* MqttRoot InfluxRoot MachineLearningRoot Rule* Location* ;
+
+- `OpenHAB2Model`: Content from openHAB
+- `User*`: Users in the system (work in progress)
+- `MqttRoot`: Everything needed for MQTT (communication with openHAB)
+- `InfluxRoot`: Everything needed for Influx (time series database for item state history)
+- `MachineLearningModelRoot`: The learned models for activity recognition and preference resolving
+- `Rule*`: Self-made ECA rules
+- `Location*`: Locations associated with users, activities, preferences (work in progress)
+
+## openHAB
+
+> OpenHAB2Model ::= Thing* Group* ThingType* ChannelType* ChannelCategory* ItemCategory* /ActivityItem:Item/
+
+The structure is mostly extracted from openHAB. There are some abstract superclasses to share common token, such as `ID`, `label` or `description`. Some differences to openHAB include:
+
+- Links are not modelled explicitely, but instead the items are directly referenced within channels
+- Item type was reified instead of a token describing the type. This has the advantage, that the state can be used in a more type-safe way. On the downside, more code is required in some instances, such as for item history, and there is no easy `getState` method.
+
+Explainations for the other types:
+
+- **Things** represent physical entities, such as a Hue lamp, a complex (or simple) sensor, a monitor, a webservice. They are typed and described by ThingTypes.
+- **ThingTypes** describe the blueprint for a Thing, like a class does for objects in OO languages. They also have **ChannelTypes** describing possible capabilities.
+- **Items** are the capabilities of the things, e.g., the color temperature of a lamp, the measured temperature value of a sensor, a method of a webservice (the last one is probably a bad design). They have a type as described above.
+- Things have **Channels** (one for each ChannelType of their ThingType) linking their effective capabilities to items via **Links**, such that those items represent the current value of this capability. A channel has a **ChannelCategory** describing the capability, e.g., `BatteryLevel`, `Switch`, `Presence`
+- **Groups** contain other groups, and other items
+
+## MQTT
+
+- Topics are a flat list, referencing items to be updated upon a message in this topic
+- All topics have one common prefix to subscribe to topics, and another common prefix to publish topics
+
+## Influx
+
+Basically, here are just some tokens containing information for connection to Influx, such as username, password, host
+
+## Machine Learning
+
+Handling of machine learning models currently undergoes a change.
+
+There is a distinction between internal and external models, both implement a encoder interface to get data into those models, and decoder interface to extract data from the models.
+There are two internal models which are supported: decision trees and neural networks.
+
+Decision tree are modelled straight-forward, there are inner nodes and leafs. Inner nodes reference an item and check a certain condition for this item to decide whether to follow the left or the right path of the inner node. The classification is equal to the leaf node at the end of the path.
+
+Neural networks are also straight-forward, but probably inefficient for bigger networks in the current implementation. Every neuron is a non-terminal which has ingoing and outgoing connections (using bidirectional relations), input neurons reference an item and propagate its state, hidden and output neurons have an activation function, bias neurons always return a constant value. The output layer contains all output neurons and has a combinator function to calculate the classification result.
+
+## Rules
+
+Simple ECA rules can be modelled. A rule has a list of conditions and a list of actions. An event can be triggered by some items (via their ItemObserver), i.e., whenever an item changes its state to a different value. Conditions use a logical expression, which can contain simple mathematical expressions, comparisons, and simple logical operations. Actions are organized currently by their purpose, but are wll be simplified to reference only affected items and a number expression to calculate the new value for those items.
diff --git a/pages/docs/config.md b/pages/docs/config.md
new file mode 100644
index 0000000000000000000000000000000000000000..ce4ae0f28a7b816a7ba03a6766c7e8f0c0feccc3
--- /dev/null
+++ b/pages/docs/config.md
@@ -0,0 +1,75 @@
+# Configuration
+
+This page describes the main configuration options when starter eraser.
+Whenever a file is specified here, it will be a combination of `file` and `external`. With `external` set to `true`, the given path is used to access the file system, using the directory of the `eraser.starter` module as current directory for relative paths. If `external` is set to `false` the file is looked up in the bundled JAR file.
+
+## Starting configuration `starter-settings.yaml`
+
+In this file, everything is being configured, i.e., which components will be started, and how they are set up.
+It has global options (mostly boolean) and sections for components, both declared on the top-level.
+
+### Global options
+
+|       Name      |   Type  |                            Description                             | Default |
+|-----------------|---------|--------------------------------------------------------------------|---------|
+| `useMAPE`       | Boolean | Start the feedback loop                                            | True    |
+| `sharedLearner` | Boolean | Use the same learner instance for activity and preference learning | False   |
+| `mqttUpdate`    | Boolean | Get updates from openHAB into the knowledge base                   | True    |
+| `initModelWith` | Choice  | Method to initialize model. Possible values: "load", "openhab"     | "load"  |
+
+### Section `rest`
+
+This section configures the REST server providing an API to interact with eraser.
+
+|         Name        |   Type  |                                       Description                                        | Default |
+|---------------------|---------|------------------------------------------------------------------------------------------|---------|
+| `use`               | Boolean | Start the REST server                                                                    | True    |
+| `port`              | Integer | Port of the REST server                                                                  | 4567    |
+| `createDummyMLData` | Boolean | Add some dummy data for activities and events. Only effective when using the REST server | False   |
+
+### Section `load`
+
+This section defines how to initialize eraser when using the [option `initModelWith`](#global-options) with the value "load".
+
+|    Name    |   Type   |                            Description                            | Default |
+|------------|----------|-------------------------------------------------------------------|---------|
+| `file`     | Filename | File to read in, expected format: `.eraser`                       | _None_  |
+| `external` | Boolean  | False: Use file bundled in the JAR. True: Use file in filesystem. | False   |
+
+### Sections `activity` and `preference`
+
+These section have equivalent options and define the activity recogntion taking place in the Analyze phase, and the preference learning triggered in the Plan phase respectively.
+
+|    Name    |   Type   |                            Description                             | Default |
+|------------|----------|--------------------------------------------------------------------|---------|
+| `file`     | Filename | File to read in, expected format: `.eraser`                        | _None_  |
+| `external` | Boolean  | False: Use file bundled in the JAR. True: Use file in filesystem.  | False   |
+| `dummy`    | Boolean  | Use dummy model in which the current activity is directly editable | false   |
+| `id`       | Integer  | Model id. Currently unused                                         | 1       |
+
+
+### Section `openhab`
+
+This section configures the communication with openHAB.
+
+|         Name        |  Type  |                         Description                          | Default |
+|---------------------|--------|--------------------------------------------------------------|---------|
+| `url`               | String | The URL from which to import and at which openHAB is running | _None_  |
+| `metadataNamespace` | String | The metadata namespace used for items                        | _None_  |
+
+## Configuring start of eraser
+
+To build eraser, execute
+
+```bash
+./gradlew :eraser.starter:installDist
+```
+
+This will create bundled JARs and a script to launch the starter. Both will be located in `eraser.starter/build/install/eraser.starter/`.
+To start, change to this directory and invoke
+
+```bash
+./bin/eraser.starter -f starter-setting.yaml
+```
+
+Beforehand, the configuration has to be changed according to your needs.
diff --git a/pages/docs/contributing.md b/pages/docs/contributing.md
new file mode 100644
index 0000000000000000000000000000000000000000..bddb5e917a41b77195e915faec5f1652c68cd6f8
--- /dev/null
+++ b/pages/docs/contributing.md
@@ -0,0 +1,95 @@
+# Contributing
+
+Please also refer to the [API documentation](ragdoc/index.html)
+
+Steps to create the initial multi-project setup from a single-project setup
+
+- create a new Gradle project named `eraser` using IntelliJ
+- manually create subdirectory `eraser-base`, move `src/` to this directory
+- change `build.gradle` to
+
+```Groovy
+allprojects  {
+	group = 'de.tudresden.inf.st'
+	version = '1.0.0-SNAPSHOT'
+}
+
+subprojects {
+	apply plugin: 'java'
+	sourceCompatibility = 1.8
+	targetCompatibility = 1.8
+
+	task packageSources(type: Jar) {
+		classifier = 'sources'
+		from sourceSets.main.allSource
+	}
+
+	artifacts.archives packageSources
+	configurations {
+		testArtifacts.extendsFrom testRuntime
+	}
+
+	task testJar(type: Jar) {
+		classifier "test"
+		from sourceSets.test.output
+	}
+
+	artifacts {
+		testArtifacts testJar
+	}
+}
+```
+- create new `eraser-base/build.gradle` with the following content
+
+```Groovy
+repositories {
+    mavenCentral()
+}
+
+apply plugin: 'jastadd'
+
+dependencies {
+    testCompile group: 'junit', name: 'junit', version: '4.12'
+}
+
+buildscript {
+    repositories.mavenLocal()
+    repositories.mavenCentral()
+    dependencies {
+        classpath 'org.jastadd:jastaddgradle:1.12.2'
+    }
+}
+
+jastadd {
+    configureModuleBuild()
+    modules "jastadd_modules"
+
+    module = "expressions"
+
+    astPackage = 'de.tudresden.inf.st.eraser.jastadd.model'
+    genDir = 'src/gen/java'
+
+    buildInfoDir = 'src/gen-res'
+}
+```
+- create new directory `eraser-base/src/main/jastadd` and put in JADD and JRAG files
+- create new `eraser-base/jastadd_modules` with the following content:
+
+```Groovy
+module("expressions") {
+
+	java {
+		basedir "src/main/java/"
+		include "**/*.java"
+	}
+
+	jastadd {
+		basedir "src/main/jastadd/"
+		include "**/*.ast"
+		include "**/*.jadd"
+		include "**/*.jrag"
+	}
+}
+```
+- optionally create a `.gitignore` to not commit `.idea` and `.gradle` directories
+- optionally create a Main Java class
diff --git a/pages/docs/img/config-eraser-binding.png b/pages/docs/img/config-eraser-binding.png
new file mode 100644
index 0000000000000000000000000000000000000000..be402279d557960dab5e89dabba12a39ef2b22f9
Binary files /dev/null and b/pages/docs/img/config-eraser-binding.png differ
diff --git a/pages/docs/img/config-mqtt-binding.png b/pages/docs/img/config-mqtt-binding.png
new file mode 100644
index 0000000000000000000000000000000000000000..2157fe69d8efb03ab80540eca8023900d3496b2a
Binary files /dev/null and b/pages/docs/img/config-mqtt-binding.png differ
diff --git a/pages/docs/img/item-history.png b/pages/docs/img/item-history.png
new file mode 100644
index 0000000000000000000000000000000000000000..ebf497bb55fe9babe73b4e9694605139db19da5b
Binary files /dev/null and b/pages/docs/img/item-history.png differ
diff --git a/pages/docs/img/item-history.uxf b/pages/docs/img/item-history.uxf
new file mode 100644
index 0000000000000000000000000000000000000000..98efa99a8668269eb18628f00c0419210599aed3
--- /dev/null
+++ b/pages/docs/img/item-history.uxf
@@ -0,0 +1,239 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<diagram program="umlet" version="14.3.0">
+  <zoom_level>10</zoom_level>
+  <element>
+    <id>UMLGeneric</id>
+    <coordinates>
+      <x>50</x>
+      <y>100</y>
+      <w>150</w>
+      <h>30</h>
+    </coordinates>
+    <panel_attributes>_:Caller-Thread_</panel_attributes>
+    <additional_attributes/>
+  </element>
+  <element>
+    <id>UMLGeneric</id>
+    <coordinates>
+      <x>370</x>
+      <y>100</y>
+      <w>150</w>
+      <h>30</h>
+    </coordinates>
+    <panel_attributes>_:Updater-Thread_</panel_attributes>
+    <additional_attributes/>
+  </element>
+  <element>
+    <id>Relation</id>
+    <coordinates>
+      <x>110</x>
+      <y>120</y>
+      <w>30</w>
+      <h>80</h>
+    </coordinates>
+    <panel_attributes>lt=.</panel_attributes>
+    <additional_attributes>10.0;10.0;10.0;60.0</additional_attributes>
+  </element>
+  <element>
+    <id>UMLGeneric</id>
+    <coordinates>
+      <x>110</x>
+      <y>180</y>
+      <w>20</w>
+      <h>340</h>
+    </coordinates>
+    <panel_attributes>
+layer=-1</panel_attributes>
+    <additional_attributes/>
+  </element>
+  <element>
+    <id>Relation</id>
+    <coordinates>
+      <x>120</x>
+      <y>180</y>
+      <w>210</w>
+      <h>60</h>
+    </coordinates>
+    <panel_attributes>lt=&lt;&lt;-
+TypedItem.getHistory</panel_attributes>
+    <additional_attributes>10.0;40.0;40.0;40.0;40.0;10.0;10.0;10.0</additional_attributes>
+  </element>
+  <element>
+    <id>Relation</id>
+    <coordinates>
+      <x>120</x>
+      <y>230</y>
+      <w>150</w>
+      <h>60</h>
+    </coordinates>
+    <panel_attributes>lt=&lt;&lt;-
+Item.proxied</panel_attributes>
+    <additional_attributes>20.0;40.0;40.0;40.0;40.0;10.0;10.0;10.0</additional_attributes>
+  </element>
+  <element>
+    <id>Relation</id>
+    <coordinates>
+      <x>430</x>
+      <y>120</y>
+      <w>30</w>
+      <h>290</h>
+    </coordinates>
+    <panel_attributes>lt=.</panel_attributes>
+    <additional_attributes>10.0;10.0;10.0;270.0</additional_attributes>
+  </element>
+  <element>
+    <id>UMLGeneric</id>
+    <coordinates>
+      <x>430</x>
+      <y>390</y>
+      <w>20</w>
+      <h>60</h>
+    </coordinates>
+    <panel_attributes/>
+    <additional_attributes/>
+  </element>
+  <element>
+    <id>Relation</id>
+    <coordinates>
+      <x>130</x>
+      <y>370</y>
+      <w>320</w>
+      <h>40</h>
+    </coordinates>
+    <panel_attributes>lt=&lt;-
+InfluxAdapter.asyncQuery</panel_attributes>
+    <additional_attributes>300.0;20.0;10.0;20.0</additional_attributes>
+  </element>
+  <element>
+    <id>Relation</id>
+    <coordinates>
+      <x>130</x>
+      <y>280</y>
+      <w>310</w>
+      <h>60</h>
+    </coordinates>
+    <panel_attributes>lt=&lt;&lt;-
+ItemType.influxMeasurementName</panel_attributes>
+    <additional_attributes>10.0;40.0;40.0;40.0;40.0;10.0;10.0;10.0</additional_attributes>
+  </element>
+  <element>
+    <id>Relation</id>
+    <coordinates>
+      <x>130</x>
+      <y>320</y>
+      <w>200</w>
+      <h>60</h>
+    </coordinates>
+    <panel_attributes>lt=&lt;&lt;-
+ItemType.pointClass</panel_attributes>
+    <additional_attributes>10.0;40.0;40.0;40.0;40.0;10.0;10.0;10.0</additional_attributes>
+  </element>
+  <element>
+    <id>Relation</id>
+    <coordinates>
+      <x>440</x>
+      <y>390</y>
+      <w>220</w>
+      <h>60</h>
+    </coordinates>
+    <panel_attributes>lt=&lt;&lt;-
+Item.set_history_token</panel_attributes>
+    <additional_attributes>10.0;40.0;40.0;40.0;40.0;10.0;10.0;10.0</additional_attributes>
+  </element>
+  <element>
+    <id>UMLSpecialState</id>
+    <coordinates>
+      <x>430</x>
+      <y>460</y>
+      <w>20</w>
+      <h>20</h>
+    </coordinates>
+    <panel_attributes>type=termination</panel_attributes>
+    <additional_attributes/>
+  </element>
+  <element>
+    <id>Relation</id>
+    <coordinates>
+      <x>430</x>
+      <y>440</y>
+      <w>30</w>
+      <h>40</h>
+    </coordinates>
+    <panel_attributes>lt=.</panel_attributes>
+    <additional_attributes>10.0;10.0;10.0;20.0</additional_attributes>
+  </element>
+  <element>
+    <id>UMLGeneric</id>
+    <coordinates>
+      <x>120</x>
+      <y>270</y>
+      <w>20</w>
+      <h>240</h>
+    </coordinates>
+    <panel_attributes>
+layer=3
+bg=yellow</panel_attributes>
+    <additional_attributes/>
+  </element>
+  <element>
+    <id>UMLNote</id>
+    <coordinates>
+      <x>290</x>
+      <y>220</y>
+      <w>120</w>
+      <h>60</h>
+    </coordinates>
+    <panel_attributes>/_history/
+overloaded for
+each Itemtype</panel_attributes>
+    <additional_attributes/>
+  </element>
+  <element>
+    <id>Relation</id>
+    <coordinates>
+      <x>250</x>
+      <y>230</y>
+      <w>60</w>
+      <h>40</h>
+    </coordinates>
+    <panel_attributes>lt=.</panel_attributes>
+    <additional_attributes>40.0;10.0;10.0;20.0</additional_attributes>
+  </element>
+  <element>
+    <id>UMLGeneric</id>
+    <coordinates>
+      <x>130</x>
+      <y>440</y>
+      <w>20</w>
+      <h>60</h>
+    </coordinates>
+    <panel_attributes>
+layer=5
+bg=orange</panel_attributes>
+    <additional_attributes/>
+  </element>
+  <element>
+    <id>Relation</id>
+    <coordinates>
+      <x>130</x>
+      <y>400</y>
+      <w>210</w>
+      <h>60</h>
+    </coordinates>
+    <panel_attributes>lt=&lt;&lt;-
+syn ItemType._history</panel_attributes>
+    <additional_attributes>20.0;40.0;40.0;40.0;40.0;10.0;10.0;10.0</additional_attributes>
+  </element>
+  <element>
+    <id>Relation</id>
+    <coordinates>
+      <x>140</x>
+      <y>450</y>
+      <w>280</w>
+      <h>60</h>
+    </coordinates>
+    <panel_attributes>lt=&lt;&lt;-
+Item.fetchHistory(history_token)</panel_attributes>
+    <additional_attributes>10.0;40.0;30.0;40.0;30.0;10.0;10.0;10.0</additional_attributes>
+  </element>
+</diagram>
diff --git a/pages/docs/img/rules-object.png b/pages/docs/img/rules-object.png
new file mode 100644
index 0000000000000000000000000000000000000000..6db9a497ad78cc8403790a48aeb601f6db8e20ab
Binary files /dev/null and b/pages/docs/img/rules-object.png differ
diff --git a/pages/docs/img/rules-object.uxf b/pages/docs/img/rules-object.uxf
new file mode 100644
index 0000000000000000000000000000000000000000..e4018519eea968565cb4ad5201ea97a9d9767085
--- /dev/null
+++ b/pages/docs/img/rules-object.uxf
@@ -0,0 +1,361 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<diagram program="umlet" version="14.3.0">
+  <zoom_level>10</zoom_level>
+  <element>
+    <id>UMLClass</id>
+    <coordinates>
+      <x>360</x>
+      <y>90</y>
+      <w>160</w>
+      <h>50</h>
+    </coordinates>
+    <panel_attributes>item1:NumberItem
+--
+state: Double
+</panel_attributes>
+    <additional_attributes/>
+  </element>
+  <element>
+    <id>UMLClass</id>
+    <coordinates>
+      <x>750</x>
+      <y>90</y>
+      <w>160</w>
+      <h>50</h>
+    </coordinates>
+    <panel_attributes>item2:ColorItem
+--
+state: TupleHSB</panel_attributes>
+    <additional_attributes/>
+  </element>
+  <element>
+    <id>UMLClass</id>
+    <coordinates>
+      <x>750</x>
+      <y>180</y>
+      <w>160</w>
+      <h>30</h>
+    </coordinates>
+    <panel_attributes>io2:ItemObserver
+bg=orange</panel_attributes>
+    <additional_attributes/>
+  </element>
+  <element>
+    <id>UMLClass</id>
+    <coordinates>
+      <x>360</x>
+      <y>180</y>
+      <w>160</w>
+      <h>30</h>
+    </coordinates>
+    <panel_attributes>io1:ItemObserver
+bg=yellow</panel_attributes>
+    <additional_attributes/>
+  </element>
+  <element>
+    <id>Relation</id>
+    <coordinates>
+      <x>430</x>
+      <y>130</y>
+      <w>30</w>
+      <h>70</h>
+    </coordinates>
+    <panel_attributes>lt=&lt;&lt;&lt;&lt;&lt;-</panel_attributes>
+    <additional_attributes>10.0;10.0;10.0;50.0</additional_attributes>
+  </element>
+  <element>
+    <id>Relation</id>
+    <coordinates>
+      <x>810</x>
+      <y>130</y>
+      <w>30</w>
+      <h>70</h>
+    </coordinates>
+    <panel_attributes>lt=&lt;&lt;&lt;&lt;&lt;-</panel_attributes>
+    <additional_attributes>10.0;10.0;10.0;50.0</additional_attributes>
+  </element>
+  <element>
+    <id>Relation</id>
+    <coordinates>
+      <x>350</x>
+      <y>200</y>
+      <w>60</w>
+      <h>180</h>
+    </coordinates>
+    <panel_attributes>lt=&lt;-
+</panel_attributes>
+    <additional_attributes>10.0;160.0;40.0;160.0;40.0;10.0</additional_attributes>
+  </element>
+  <element>
+    <id>Relation</id>
+    <coordinates>
+      <x>420</x>
+      <y>200</y>
+      <w>100</w>
+      <h>170</h>
+    </coordinates>
+    <panel_attributes>lt=&lt;-
+</panel_attributes>
+    <additional_attributes>80.0;150.0;80.0;130.0;10.0;130.0;10.0;10.0</additional_attributes>
+  </element>
+  <element>
+    <id>Relation</id>
+    <coordinates>
+      <x>480</x>
+      <y>60</y>
+      <w>470</w>
+      <h>320</h>
+    </coordinates>
+    <panel_attributes>lt=&lt;-
+</panel_attributes>
+    <additional_attributes>390.0;300.0;450.0;300.0;450.0;20.0;190.0;20.0;190.0;190.0;10.0;190.0;10.0;150.0</additional_attributes>
+  </element>
+  <element>
+    <id>Relation</id>
+    <coordinates>
+      <x>610</x>
+      <y>200</y>
+      <w>230</w>
+      <h>190</h>
+    </coordinates>
+    <panel_attributes>lt=&lt;-
+</panel_attributes>
+    <additional_attributes>10.0;170.0;50.0;170.0;50.0;80.0;210.0;80.0;210.0;10.0</additional_attributes>
+  </element>
+  <element>
+    <id>UMLClass</id>
+    <coordinates>
+      <x>200</x>
+      <y>350</y>
+      <w>160</w>
+      <h>30</h>
+    </coordinates>
+    <panel_attributes>rA:Rule
+bg=yellow</panel_attributes>
+    <additional_attributes/>
+  </element>
+  <element>
+    <id>UMLClass</id>
+    <coordinates>
+      <x>220</x>
+      <y>480</y>
+      <w>110</w>
+      <h>30</h>
+    </coordinates>
+    <panel_attributes>aA1:Action</panel_attributes>
+    <additional_attributes/>
+  </element>
+  <element>
+    <id>UMLClass</id>
+    <coordinates>
+      <x>230</x>
+      <y>440</y>
+      <w>110</w>
+      <h>30</h>
+    </coordinates>
+    <panel_attributes>cA2:Condition</panel_attributes>
+    <additional_attributes/>
+  </element>
+  <element>
+    <id>Relation</id>
+    <coordinates>
+      <x>210</x>
+      <y>370</y>
+      <w>40</w>
+      <h>100</h>
+    </coordinates>
+    <panel_attributes>lt=&lt;&lt;&lt;&lt;&lt;-</panel_attributes>
+    <additional_attributes>10.0;10.0;10.0;80.0;20.0;80.0</additional_attributes>
+  </element>
+  <element>
+    <id>Relation</id>
+    <coordinates>
+      <x>320</x>
+      <y>370</y>
+      <w>50</w>
+      <h>140</h>
+    </coordinates>
+    <panel_attributes>lt=&lt;&lt;&lt;&lt;&lt;-</panel_attributes>
+    <additional_attributes>30.0;10.0;30.0;120.0;10.0;120.0</additional_attributes>
+  </element>
+  <element>
+    <id>UMLClass</id>
+    <coordinates>
+      <x>460</x>
+      <y>350</y>
+      <w>160</w>
+      <h>30</h>
+    </coordinates>
+    <panel_attributes>rB:Rule
+</panel_attributes>
+    <additional_attributes/>
+  </element>
+  <element>
+    <id>UMLClass</id>
+    <coordinates>
+      <x>710</x>
+      <y>350</y>
+      <w>160</w>
+      <h>30</h>
+    </coordinates>
+    <panel_attributes>rC:Rule
+bg=yellow</panel_attributes>
+    <additional_attributes/>
+  </element>
+  <element>
+    <id>UMLClass</id>
+    <coordinates>
+      <x>540</x>
+      <y>350</y>
+      <w>80</w>
+      <h>30</h>
+    </coordinates>
+    <panel_attributes>bg=orange
+fg=white</panel_attributes>
+    <additional_attributes/>
+  </element>
+  <element>
+    <id>UMLClass</id>
+    <coordinates>
+      <x>460</x>
+      <y>350</y>
+      <w>90</w>
+      <h>30</h>
+    </coordinates>
+    <panel_attributes>bg=yellow
+fg=white</panel_attributes>
+    <additional_attributes/>
+  </element>
+  <element>
+    <id>UMLClass</id>
+    <coordinates>
+      <x>230</x>
+      <y>400</y>
+      <w>110</w>
+      <h>30</h>
+    </coordinates>
+    <panel_attributes>cA1:Condition</panel_attributes>
+    <additional_attributes/>
+  </element>
+  <element>
+    <id>Relation</id>
+    <coordinates>
+      <x>210</x>
+      <y>370</y>
+      <w>40</w>
+      <h>60</h>
+    </coordinates>
+    <panel_attributes>lt=&lt;&lt;&lt;&lt;&lt;-</panel_attributes>
+    <additional_attributes>10.0;10.0;10.0;40.0;20.0;40.0</additional_attributes>
+  </element>
+  <element>
+    <id>UMLClass</id>
+    <coordinates>
+      <x>220</x>
+      <y>520</y>
+      <w>110</w>
+      <h>30</h>
+    </coordinates>
+    <panel_attributes>aA2:Action</panel_attributes>
+    <additional_attributes/>
+  </element>
+  <element>
+    <id>Relation</id>
+    <coordinates>
+      <x>320</x>
+      <y>370</y>
+      <w>50</w>
+      <h>180</h>
+    </coordinates>
+    <panel_attributes>lt=&lt;&lt;&lt;&lt;&lt;-</panel_attributes>
+    <additional_attributes>30.0;10.0;30.0;160.0;10.0;160.0</additional_attributes>
+  </element>
+  <element>
+    <id>UMLClass</id>
+    <coordinates>
+      <x>470</x>
+      <y>480</y>
+      <w>110</w>
+      <h>30</h>
+    </coordinates>
+    <panel_attributes>aA1:Action</panel_attributes>
+    <additional_attributes/>
+  </element>
+  <element>
+    <id>Relation</id>
+    <coordinates>
+      <x>570</x>
+      <y>370</y>
+      <w>50</w>
+      <h>140</h>
+    </coordinates>
+    <panel_attributes>lt=&lt;&lt;&lt;&lt;&lt;-</panel_attributes>
+    <additional_attributes>30.0;10.0;30.0;120.0;10.0;120.0</additional_attributes>
+  </element>
+  <element>
+    <id>UMLClass</id>
+    <coordinates>
+      <x>480</x>
+      <y>400</y>
+      <w>110</w>
+      <h>30</h>
+    </coordinates>
+    <panel_attributes>cB1:Condition</panel_attributes>
+    <additional_attributes/>
+  </element>
+  <element>
+    <id>Relation</id>
+    <coordinates>
+      <x>460</x>
+      <y>370</y>
+      <w>40</w>
+      <h>60</h>
+    </coordinates>
+    <panel_attributes>lt=&lt;&lt;&lt;&lt;&lt;-</panel_attributes>
+    <additional_attributes>10.0;10.0;10.0;40.0;20.0;40.0</additional_attributes>
+  </element>
+  <element>
+    <id>UMLClass</id>
+    <coordinates>
+      <x>470</x>
+      <y>520</y>
+      <w>110</w>
+      <h>30</h>
+    </coordinates>
+    <panel_attributes>aA2:Action</panel_attributes>
+    <additional_attributes/>
+  </element>
+  <element>
+    <id>Relation</id>
+    <coordinates>
+      <x>570</x>
+      <y>370</y>
+      <w>50</w>
+      <h>180</h>
+    </coordinates>
+    <panel_attributes>lt=&lt;&lt;&lt;&lt;&lt;-</panel_attributes>
+    <additional_attributes>30.0;10.0;30.0;160.0;10.0;160.0</additional_attributes>
+  </element>
+  <element>
+    <id>UMLClass</id>
+    <coordinates>
+      <x>720</x>
+      <y>420</y>
+      <w>110</w>
+      <h>30</h>
+    </coordinates>
+    <panel_attributes>aA1:Action</panel_attributes>
+    <additional_attributes/>
+  </element>
+  <element>
+    <id>Relation</id>
+    <coordinates>
+      <x>820</x>
+      <y>370</y>
+      <w>50</w>
+      <h>80</h>
+    </coordinates>
+    <panel_attributes>lt=&lt;&lt;&lt;&lt;&lt;-</panel_attributes>
+    <additional_attributes>30.0;10.0;30.0;60.0;10.0;60.0</additional_attributes>
+  </element>
+</diagram>
diff --git a/pages/docs/img/rules-sequence.png b/pages/docs/img/rules-sequence.png
new file mode 100644
index 0000000000000000000000000000000000000000..57020da1ca87d0249966613da6a49db97d6bb9ef
Binary files /dev/null and b/pages/docs/img/rules-sequence.png differ
diff --git a/pages/docs/img/rules-sequence.uxf b/pages/docs/img/rules-sequence.uxf
new file mode 100644
index 0000000000000000000000000000000000000000..3cbe6465412002d8192be55664f72c923a3ae748
--- /dev/null
+++ b/pages/docs/img/rules-sequence.uxf
@@ -0,0 +1,482 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<diagram program="umlet" version="14.3.0">
+  <zoom_level>10</zoom_level>
+  <element>
+    <id>UMLGeneric</id>
+    <coordinates>
+      <x>240</x>
+      <y>280</y>
+      <w>110</w>
+      <h>30</h>
+    </coordinates>
+    <panel_attributes>_item1:Item_</panel_attributes>
+    <additional_attributes/>
+  </element>
+  <element>
+    <id>UMLGeneric</id>
+    <coordinates>
+      <x>280</x>
+      <y>340</y>
+      <w>20</w>
+      <h>90</h>
+    </coordinates>
+    <panel_attributes/>
+    <additional_attributes/>
+  </element>
+  <element>
+    <id>UMLActor</id>
+    <coordinates>
+      <x>120</x>
+      <y>330</y>
+      <w>60</w>
+      <h>110</h>
+    </coordinates>
+    <panel_attributes>User</panel_attributes>
+    <additional_attributes/>
+  </element>
+  <element>
+    <id>Relation</id>
+    <coordinates>
+      <x>170</x>
+      <y>340</y>
+      <w>130</w>
+      <h>40</h>
+    </coordinates>
+    <panel_attributes>lt=&lt;&lt;-
+setState</panel_attributes>
+    <additional_attributes>110.0;20.0;10.0;20.0</additional_attributes>
+  </element>
+  <element>
+    <id>UMLGeneric</id>
+    <coordinates>
+      <x>420</x>
+      <y>410</y>
+      <w>20</w>
+      <h>100</h>
+    </coordinates>
+    <panel_attributes/>
+    <additional_attributes/>
+  </element>
+  <element>
+    <id>Relation</id>
+    <coordinates>
+      <x>420</x>
+      <y>300</y>
+      <w>30</w>
+      <h>130</h>
+    </coordinates>
+    <panel_attributes>lt=.</panel_attributes>
+    <additional_attributes>10.0;10.0;10.0;110.0</additional_attributes>
+  </element>
+  <element>
+    <id>UMLGeneric</id>
+    <coordinates>
+      <x>360</x>
+      <y>280</y>
+      <w>150</w>
+      <h>30</h>
+    </coordinates>
+    <panel_attributes>_io1:ItemObserver_
+bg=yellow</panel_attributes>
+    <additional_attributes/>
+  </element>
+  <element>
+    <id>Relation</id>
+    <coordinates>
+      <x>290</x>
+      <y>400</y>
+      <w>150</w>
+      <h>40</h>
+    </coordinates>
+    <panel_attributes>lt=&lt;&lt;&lt;-
+apply</panel_attributes>
+    <additional_attributes>130.0;20.0;10.0;20.0</additional_attributes>
+  </element>
+  <element>
+    <id>Relation</id>
+    <coordinates>
+      <x>290</x>
+      <y>350</y>
+      <w>130</w>
+      <h>60</h>
+    </coordinates>
+    <panel_attributes>lt=&lt;&lt;&lt;-
+sendState0</panel_attributes>
+    <additional_attributes>10.0;40.0;30.0;40.0;30.0;10.0;10.0;10.0</additional_attributes>
+  </element>
+  <element>
+    <id>Relation</id>
+    <coordinates>
+      <x>430</x>
+      <y>420</y>
+      <w>130</w>
+      <h>60</h>
+    </coordinates>
+    <panel_attributes>lt=&lt;&lt;&lt;-
+check if
+stateEquals</panel_attributes>
+    <additional_attributes>10.0;40.0;30.0;40.0;30.0;10.0;10.0;10.0</additional_attributes>
+  </element>
+  <element>
+    <id>Relation</id>
+    <coordinates>
+      <x>430</x>
+      <y>470</y>
+      <w>190</w>
+      <h>40</h>
+    </coordinates>
+    <panel_attributes>lt=&lt;&lt;&lt;-
+trigger</panel_attributes>
+    <additional_attributes>170.0;20.0;10.0;20.0</additional_attributes>
+  </element>
+  <element>
+    <id>Relation</id>
+    <coordinates>
+      <x>600</x>
+      <y>300</y>
+      <w>30</w>
+      <h>210</h>
+    </coordinates>
+    <panel_attributes>lt=.</panel_attributes>
+    <additional_attributes>10.0;10.0;10.0;190.0</additional_attributes>
+  </element>
+  <element>
+    <id>UMLGeneric</id>
+    <coordinates>
+      <x>600</x>
+      <y>490</y>
+      <w>20</w>
+      <h>280</h>
+    </coordinates>
+    <panel_attributes>
+layer=-1</panel_attributes>
+    <additional_attributes/>
+  </element>
+  <element>
+    <id>UMLGeneric</id>
+    <coordinates>
+      <x>560</x>
+      <y>280</y>
+      <w>110</w>
+      <h>30</h>
+    </coordinates>
+    <panel_attributes>_rA:Rule_
+bg=yellow</panel_attributes>
+    <additional_attributes/>
+  </element>
+  <element>
+    <id>UMLGeneric</id>
+    <coordinates>
+      <x>710</x>
+      <y>280</y>
+      <w>110</w>
+      <h>30</h>
+    </coordinates>
+    <panel_attributes>_cA1:Condition_</panel_attributes>
+    <additional_attributes/>
+  </element>
+  <element>
+    <id>UMLGeneric</id>
+    <coordinates>
+      <x>750</x>
+      <y>570</y>
+      <w>20</w>
+      <h>50</h>
+    </coordinates>
+    <panel_attributes/>
+    <additional_attributes/>
+  </element>
+  <element>
+    <id>Relation</id>
+    <coordinates>
+      <x>750</x>
+      <y>300</y>
+      <w>30</w>
+      <h>290</h>
+    </coordinates>
+    <panel_attributes>lt=.</panel_attributes>
+    <additional_attributes>10.0;10.0;10.0;270.0</additional_attributes>
+  </element>
+  <element>
+    <id>UMLGeneric</id>
+    <coordinates>
+      <x>830</x>
+      <y>280</y>
+      <w>110</w>
+      <h>30</h>
+    </coordinates>
+    <panel_attributes>_aA1:Action_</panel_attributes>
+    <additional_attributes/>
+  </element>
+  <element>
+    <id>UMLGeneric</id>
+    <coordinates>
+      <x>870</x>
+      <y>690</y>
+      <w>20</w>
+      <h>20</h>
+    </coordinates>
+    <panel_attributes/>
+    <additional_attributes/>
+  </element>
+  <element>
+    <id>Relation</id>
+    <coordinates>
+      <x>870</x>
+      <y>300</y>
+      <w>30</w>
+      <h>410</h>
+    </coordinates>
+    <panel_attributes>lt=.</panel_attributes>
+    <additional_attributes>10.0;10.0;10.0;390.0</additional_attributes>
+  </element>
+  <element>
+    <id>Relation</id>
+    <coordinates>
+      <x>610</x>
+      <y>560</y>
+      <w>160</w>
+      <h>40</h>
+    </coordinates>
+    <panel_attributes>lt=&lt;&lt;&lt;-
+holdsFor(item1)</panel_attributes>
+    <additional_attributes>140.0;20.0;10.0;20.0</additional_attributes>
+  </element>
+  <element>
+    <id>Relation</id>
+    <coordinates>
+      <x>280</x>
+      <y>420</y>
+      <w>30</w>
+      <h>360</h>
+    </coordinates>
+    <panel_attributes>lt=.</panel_attributes>
+    <additional_attributes>10.0;10.0;10.0;340.0</additional_attributes>
+  </element>
+  <element>
+    <id>Relation</id>
+    <coordinates>
+      <x>420</x>
+      <y>500</y>
+      <w>30</w>
+      <h>210</h>
+    </coordinates>
+    <panel_attributes>lt=.</panel_attributes>
+    <additional_attributes>10.0;10.0;10.0;190.0</additional_attributes>
+  </element>
+  <element>
+    <id>Relation</id>
+    <coordinates>
+      <x>610</x>
+      <y>600</y>
+      <w>160</w>
+      <h>30</h>
+    </coordinates>
+    <panel_attributes>lt=&lt;.</panel_attributes>
+    <additional_attributes>10.0;10.0;140.0;10.0</additional_attributes>
+  </element>
+  <element>
+    <id>UMLFrame</id>
+    <coordinates>
+      <x>590</x>
+      <y>630</y>
+      <w>310</w>
+      <h>130</h>
+    </coordinates>
+    <panel_attributes>alt
+layer=1
+bg=white
+--
+[if all conditions hold]
+
+
+
+-.
+[else]
+</panel_attributes>
+    <additional_attributes/>
+  </element>
+  <element>
+    <id>Relation</id>
+    <coordinates>
+      <x>280</x>
+      <y>300</y>
+      <w>30</w>
+      <h>60</h>
+    </coordinates>
+    <panel_attributes>lt=.</panel_attributes>
+    <additional_attributes>10.0;10.0;10.0;40.0</additional_attributes>
+  </element>
+  <element>
+    <id>Relation</id>
+    <coordinates>
+      <x>610</x>
+      <y>680</y>
+      <w>280</w>
+      <h>40</h>
+    </coordinates>
+    <panel_attributes>lt=&lt;&lt;&lt;-
+applyFor(item1)
+layer=2</panel_attributes>
+    <additional_attributes>260.0;20.0;10.0;20.0</additional_attributes>
+  </element>
+  <element>
+    <id>Relation</id>
+    <coordinates>
+      <x>430</x>
+      <y>700</y>
+      <w>190</w>
+      <h>30</h>
+    </coordinates>
+    <panel_attributes>lt=&lt;.</panel_attributes>
+    <additional_attributes>10.0;10.0;170.0;10.0</additional_attributes>
+  </element>
+  <element>
+    <id>Relation</id>
+    <coordinates>
+      <x>430</x>
+      <y>760</y>
+      <w>190</w>
+      <h>30</h>
+    </coordinates>
+    <panel_attributes>lt=&lt;.</panel_attributes>
+    <additional_attributes>10.0;10.0;170.0;10.0</additional_attributes>
+  </element>
+  <element>
+    <id>UMLGeneric</id>
+    <coordinates>
+      <x>990</x>
+      <y>760</y>
+      <w>20</w>
+      <h>50</h>
+    </coordinates>
+    <panel_attributes/>
+    <additional_attributes/>
+  </element>
+  <element>
+    <id>Relation</id>
+    <coordinates>
+      <x>990</x>
+      <y>300</y>
+      <w>30</w>
+      <h>480</h>
+    </coordinates>
+    <panel_attributes>lt=.</panel_attributes>
+    <additional_attributes>10.0;10.0;10.0;460.0</additional_attributes>
+  </element>
+  <element>
+    <id>UMLGeneric</id>
+    <coordinates>
+      <x>950</x>
+      <y>280</y>
+      <w>110</w>
+      <h>30</h>
+    </coordinates>
+    <panel_attributes>_rB:Rule_
+
+</panel_attributes>
+    <additional_attributes/>
+  </element>
+  <element>
+    <id>Relation</id>
+    <coordinates>
+      <x>430</x>
+      <y>780</y>
+      <w>580</w>
+      <h>40</h>
+    </coordinates>
+    <panel_attributes>lt=&lt;&lt;&lt;-
+trigger</panel_attributes>
+    <additional_attributes>560.0;20.0;10.0;20.0</additional_attributes>
+  </element>
+  <element>
+    <id>UMLGeneric</id>
+    <coordinates>
+      <x>420</x>
+      <y>690</y>
+      <w>20</w>
+      <h>120</h>
+    </coordinates>
+    <panel_attributes/>
+    <additional_attributes/>
+  </element>
+  <element>
+    <id>Relation</id>
+    <coordinates>
+      <x>290</x>
+      <y>800</y>
+      <w>150</w>
+      <h>30</h>
+    </coordinates>
+    <panel_attributes>lt=&lt;.</panel_attributes>
+    <additional_attributes>10.0;10.0;130.0;10.0</additional_attributes>
+  </element>
+  <element>
+    <id>UMLGeneric</id>
+    <coordinates>
+      <x>280</x>
+      <y>760</y>
+      <w>20</w>
+      <h>60</h>
+    </coordinates>
+    <panel_attributes/>
+    <additional_attributes/>
+  </element>
+  <element>
+    <id>Relation</id>
+    <coordinates>
+      <x>280</x>
+      <y>810</y>
+      <w>30</w>
+      <h>50</h>
+    </coordinates>
+    <panel_attributes>lt=.</panel_attributes>
+    <additional_attributes>10.0;10.0;10.0;30.0</additional_attributes>
+  </element>
+  <element>
+    <id>Relation</id>
+    <coordinates>
+      <x>420</x>
+      <y>800</y>
+      <w>30</w>
+      <h>60</h>
+    </coordinates>
+    <panel_attributes>lt=.</panel_attributes>
+    <additional_attributes>10.0;10.0;10.0;40.0</additional_attributes>
+  </element>
+  <element>
+    <id>Relation</id>
+    <coordinates>
+      <x>600</x>
+      <y>760</y>
+      <w>30</w>
+      <h>100</h>
+    </coordinates>
+    <panel_attributes>lt=.</panel_attributes>
+    <additional_attributes>10.0;10.0;10.0;80.0</additional_attributes>
+  </element>
+  <element>
+    <id>UMLClass</id>
+    <coordinates>
+      <x>1000</x>
+      <y>280</y>
+      <w>60</w>
+      <h>30</h>
+    </coordinates>
+    <panel_attributes>bg=orange
+fg=white</panel_attributes>
+    <additional_attributes/>
+  </element>
+  <element>
+    <id>UMLClass</id>
+    <coordinates>
+      <x>950</x>
+      <y>280</y>
+      <w>60</w>
+      <h>30</h>
+    </coordinates>
+    <panel_attributes>bg=yellow
+fg=white</panel_attributes>
+    <additional_attributes/>
+  </element>
+</diagram>
diff --git a/pages/docs/img/rules.uxf b/pages/docs/img/rules.uxf
new file mode 100644
index 0000000000000000000000000000000000000000..fb5fd373e77d85290ec7e64f0ce01c35763ef982
--- /dev/null
+++ b/pages/docs/img/rules.uxf
@@ -0,0 +1,382 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<diagram program="umlet" version="14.3.0">
+  <zoom_level>10</zoom_level>
+  <element>
+    <id>UMLClass</id>
+    <coordinates>
+      <x>230</x>
+      <y>30</y>
+      <w>160</w>
+      <h>50</h>
+    </coordinates>
+    <panel_attributes>item1:NumberItem
+--
+state: Double
+</panel_attributes>
+    <additional_attributes/>
+  </element>
+  <element>
+    <id>UMLClass</id>
+    <coordinates>
+      <x>620</x>
+      <y>30</y>
+      <w>160</w>
+      <h>50</h>
+    </coordinates>
+    <panel_attributes>item2:ColorItem
+--
+state: TupleHSB</panel_attributes>
+    <additional_attributes/>
+  </element>
+  <element>
+    <id>UMLClass</id>
+    <coordinates>
+      <x>620</x>
+      <y>120</y>
+      <w>160</w>
+      <h>30</h>
+    </coordinates>
+    <panel_attributes>io2:ItemObserver
+bg=orange</panel_attributes>
+    <additional_attributes/>
+  </element>
+  <element>
+    <id>UMLClass</id>
+    <coordinates>
+      <x>230</x>
+      <y>120</y>
+      <w>160</w>
+      <h>30</h>
+    </coordinates>
+    <panel_attributes>io1:ItemObserver
+bg=yellow</panel_attributes>
+    <additional_attributes/>
+  </element>
+  <element>
+    <id>Relation</id>
+    <coordinates>
+      <x>300</x>
+      <y>70</y>
+      <w>30</w>
+      <h>70</h>
+    </coordinates>
+    <panel_attributes>lt=&lt;&lt;&lt;&lt;&lt;-</panel_attributes>
+    <additional_attributes>10.0;10.0;10.0;50.0</additional_attributes>
+  </element>
+  <element>
+    <id>Relation</id>
+    <coordinates>
+      <x>680</x>
+      <y>70</y>
+      <w>30</w>
+      <h>70</h>
+    </coordinates>
+    <panel_attributes>lt=&lt;&lt;&lt;&lt;&lt;-</panel_attributes>
+    <additional_attributes>10.0;10.0;10.0;50.0</additional_attributes>
+  </element>
+  <element>
+    <id>Relation</id>
+    <coordinates>
+      <x>220</x>
+      <y>140</y>
+      <w>60</w>
+      <h>230</h>
+    </coordinates>
+    <panel_attributes>lt=&lt;-
+</panel_attributes>
+    <additional_attributes>10.0;210.0;40.0;210.0;40.0;10.0</additional_attributes>
+  </element>
+  <element>
+    <id>Relation</id>
+    <coordinates>
+      <x>290</x>
+      <y>140</y>
+      <w>240</w>
+      <h>230</h>
+    </coordinates>
+    <panel_attributes>lt=&lt;-
+</panel_attributes>
+    <additional_attributes>200.0;210.0;220.0;210.0;220.0;130.0;10.0;130.0;10.0;10.0</additional_attributes>
+  </element>
+  <element>
+    <id>Relation</id>
+    <coordinates>
+      <x>350</x>
+      <y>0</y>
+      <w>470</w>
+      <h>370</h>
+    </coordinates>
+    <panel_attributes>lt=&lt;-
+</panel_attributes>
+    <additional_attributes>390.0;350.0;450.0;350.0;450.0;20.0;190.0;20.0;190.0;190.0;10.0;190.0;10.0;150.0</additional_attributes>
+  </element>
+  <element>
+    <id>Relation</id>
+    <coordinates>
+      <x>480</x>
+      <y>140</y>
+      <w>230</w>
+      <h>270</h>
+    </coordinates>
+    <panel_attributes>lt=&lt;-
+</panel_attributes>
+    <additional_attributes>10.0;250.0;50.0;250.0;50.0;80.0;210.0;80.0;210.0;10.0</additional_attributes>
+  </element>
+  <element>
+    <id>UMLClass</id>
+    <coordinates>
+      <x>70</x>
+      <y>290</y>
+      <w>160</w>
+      <h>30</h>
+    </coordinates>
+    <panel_attributes>rA:Rule</panel_attributes>
+    <additional_attributes/>
+  </element>
+  <element>
+    <id>UMLClass</id>
+    <coordinates>
+      <x>120</x>
+      <y>420</y>
+      <w>110</w>
+      <h>30</h>
+    </coordinates>
+    <panel_attributes>aA:Action</panel_attributes>
+    <additional_attributes/>
+  </element>
+  <element>
+    <id>UMLClass</id>
+    <coordinates>
+      <x>120</x>
+      <y>380</y>
+      <w>110</w>
+      <h>30</h>
+    </coordinates>
+    <panel_attributes>cA:Condition</panel_attributes>
+    <additional_attributes/>
+  </element>
+  <element>
+    <id>UMLClass</id>
+    <coordinates>
+      <x>120</x>
+      <y>340</y>
+      <w>110</w>
+      <h>30</h>
+    </coordinates>
+    <panel_attributes>e1A:Event
+bg=yellow</panel_attributes>
+    <additional_attributes/>
+  </element>
+  <element>
+    <id>Relation</id>
+    <coordinates>
+      <x>80</x>
+      <y>310</y>
+      <w>60</w>
+      <h>60</h>
+    </coordinates>
+    <panel_attributes>lt=&lt;&lt;&lt;&lt;&lt;-</panel_attributes>
+    <additional_attributes>10.0;10.0;10.0;40.0;40.0;40.0</additional_attributes>
+  </element>
+  <element>
+    <id>Relation</id>
+    <coordinates>
+      <x>80</x>
+      <y>310</y>
+      <w>60</w>
+      <h>100</h>
+    </coordinates>
+    <panel_attributes>lt=&lt;&lt;&lt;&lt;&lt;-</panel_attributes>
+    <additional_attributes>10.0;10.0;10.0;80.0;40.0;80.0</additional_attributes>
+  </element>
+  <element>
+    <id>Relation</id>
+    <coordinates>
+      <x>80</x>
+      <y>310</y>
+      <w>60</w>
+      <h>140</h>
+    </coordinates>
+    <panel_attributes>lt=&lt;&lt;&lt;&lt;&lt;-</panel_attributes>
+    <additional_attributes>10.0;10.0;10.0;120.0;40.0;120.0</additional_attributes>
+  </element>
+  <element>
+    <id>UMLClass</id>
+    <coordinates>
+      <x>330</x>
+      <y>290</y>
+      <w>160</w>
+      <h>30</h>
+    </coordinates>
+    <panel_attributes>rB:Rule</panel_attributes>
+    <additional_attributes/>
+  </element>
+  <element>
+    <id>UMLClass</id>
+    <coordinates>
+      <x>380</x>
+      <y>460</y>
+      <w>110</w>
+      <h>30</h>
+    </coordinates>
+    <panel_attributes>aB:Action</panel_attributes>
+    <additional_attributes/>
+  </element>
+  <element>
+    <id>UMLClass</id>
+    <coordinates>
+      <x>380</x>
+      <y>420</y>
+      <w>110</w>
+      <h>30</h>
+    </coordinates>
+    <panel_attributes>cB:Condition</panel_attributes>
+    <additional_attributes/>
+  </element>
+  <element>
+    <id>UMLClass</id>
+    <coordinates>
+      <x>380</x>
+      <y>340</y>
+      <w>110</w>
+      <h>30</h>
+    </coordinates>
+    <panel_attributes>e1B:Event
+bg=yellow</panel_attributes>
+    <additional_attributes/>
+  </element>
+  <element>
+    <id>Relation</id>
+    <coordinates>
+      <x>340</x>
+      <y>310</y>
+      <w>60</w>
+      <h>60</h>
+    </coordinates>
+    <panel_attributes>lt=&lt;&lt;&lt;&lt;&lt;-</panel_attributes>
+    <additional_attributes>10.0;10.0;10.0;40.0;40.0;40.0</additional_attributes>
+  </element>
+  <element>
+    <id>Relation</id>
+    <coordinates>
+      <x>340</x>
+      <y>310</y>
+      <w>60</w>
+      <h>140</h>
+    </coordinates>
+    <panel_attributes>lt=&lt;&lt;&lt;&lt;&lt;-</panel_attributes>
+    <additional_attributes>10.0;10.0;10.0;120.0;40.0;120.0</additional_attributes>
+  </element>
+  <element>
+    <id>Relation</id>
+    <coordinates>
+      <x>340</x>
+      <y>310</y>
+      <w>60</w>
+      <h>180</h>
+    </coordinates>
+    <panel_attributes>lt=&lt;&lt;&lt;&lt;&lt;-</panel_attributes>
+    <additional_attributes>10.0;10.0;10.0;160.0;40.0;160.0</additional_attributes>
+  </element>
+  <element>
+    <id>UMLClass</id>
+    <coordinates>
+      <x>580</x>
+      <y>290</y>
+      <w>160</w>
+      <h>30</h>
+    </coordinates>
+    <panel_attributes>rC:Rule</panel_attributes>
+    <additional_attributes/>
+  </element>
+  <element>
+    <id>UMLClass</id>
+    <coordinates>
+      <x>630</x>
+      <y>420</y>
+      <w>110</w>
+      <h>30</h>
+    </coordinates>
+    <panel_attributes>aC:Action</panel_attributes>
+    <additional_attributes/>
+  </element>
+  <element>
+    <id>UMLClass</id>
+    <coordinates>
+      <x>630</x>
+      <y>380</y>
+      <w>110</w>
+      <h>30</h>
+    </coordinates>
+    <panel_attributes>cC:Condition</panel_attributes>
+    <additional_attributes/>
+  </element>
+  <element>
+    <id>UMLClass</id>
+    <coordinates>
+      <x>630</x>
+      <y>340</y>
+      <w>110</w>
+      <h>30</h>
+    </coordinates>
+    <panel_attributes>e1C:Event
+bg=yellow</panel_attributes>
+    <additional_attributes/>
+  </element>
+  <element>
+    <id>Relation</id>
+    <coordinates>
+      <x>590</x>
+      <y>310</y>
+      <w>60</w>
+      <h>60</h>
+    </coordinates>
+    <panel_attributes>lt=&lt;&lt;&lt;&lt;&lt;-</panel_attributes>
+    <additional_attributes>10.0;10.0;10.0;40.0;40.0;40.0</additional_attributes>
+  </element>
+  <element>
+    <id>Relation</id>
+    <coordinates>
+      <x>590</x>
+      <y>310</y>
+      <w>60</w>
+      <h>100</h>
+    </coordinates>
+    <panel_attributes>lt=&lt;&lt;&lt;&lt;&lt;-</panel_attributes>
+    <additional_attributes>10.0;10.0;10.0;80.0;40.0;80.0</additional_attributes>
+  </element>
+  <element>
+    <id>Relation</id>
+    <coordinates>
+      <x>590</x>
+      <y>310</y>
+      <w>60</w>
+      <h>140</h>
+    </coordinates>
+    <panel_attributes>lt=&lt;&lt;&lt;&lt;&lt;-</panel_attributes>
+    <additional_attributes>10.0;10.0;10.0;120.0;40.0;120.0</additional_attributes>
+  </element>
+  <element>
+    <id>UMLClass</id>
+    <coordinates>
+      <x>380</x>
+      <y>380</y>
+      <w>110</w>
+      <h>30</h>
+    </coordinates>
+    <panel_attributes>e2B:Event
+bg=orange</panel_attributes>
+    <additional_attributes/>
+  </element>
+  <element>
+    <id>Relation</id>
+    <coordinates>
+      <x>340</x>
+      <y>310</y>
+      <w>60</w>
+      <h>100</h>
+    </coordinates>
+    <panel_attributes>lt=&lt;&lt;&lt;&lt;&lt;-</panel_attributes>
+    <additional_attributes>10.0;10.0;10.0;80.0;40.0;80.0</additional_attributes>
+  </element>
+</diagram>
diff --git a/pages/docs/img/swagger-ui.png b/pages/docs/img/swagger-ui.png
new file mode 100644
index 0000000000000000000000000000000000000000..f0f5fc77e8648341e092dbff465aa988a3f7805a
Binary files /dev/null and b/pages/docs/img/swagger-ui.png differ
diff --git a/pages/docs/index.md b/pages/docs/index.md
new file mode 100644
index 0000000000000000000000000000000000000000..a341cbda6a3c9c72aa825cc86ff4856bf86a412d
--- /dev/null
+++ b/pages/docs/index.md
@@ -0,0 +1,11 @@
+# Documentation of Eraser
+
+First, setup eraser following the README in the main repository: [dev](https://git-st.inf.tu-dresden.de/OpenLicht/eraser/blob/dev/README.md) | [master](https://git-st.inf.tu-dresden.de/OpenLicht/eraser/blob/master/README.md)
+To configure the system, read the [configuration page](config).
+
+For an overview of the model, check out the [Model description](Model-description).
+If you need more details, dive into the [inner workings](Inner-workings) (now with colorful images!), [insights for working with the model](working) the [description of machine learning](MachineLearning) (with code examples) or the [description of Learner implementation](Learner) (only in German).
+To be able to read in models, a [dedicated DSL](DSL) must be used.
+
+Further, the updated [configuration settings regarding MQTT 1.x and 2.x](mqtt) as well as the [Setup guide to connect to openHAB](openhab-binding) (only in German) are found in this wiki.
+For contributing, please see [contribution guideline](contributing).
diff --git a/pages/docs/mqtt.md b/pages/docs/mqtt.md
new file mode 100644
index 0000000000000000000000000000000000000000..70782f601d634e9c9439266c393b53de72b6305d
--- /dev/null
+++ b/pages/docs/mqtt.md
@@ -0,0 +1,89 @@
+# OpenHAB Bindings
+
+## openHAB 2.0-2.3 and MQTT 1.x
+
+In the old openHAB versions, there used to be the MQTT event bus, which publishes every change of the state of an item to a channel dedicated to this item, and receives updates for the state analogously.
+
+The configuration file needed is located in `/etc/openhab2/services/mqtt-eventbus.cfg` with the following content:
+
+```bash
+broker=mosquitto_local
+statePublishTopic=oh2/out/${item}/state
+commandSubscribeTopic=oh2/in/${item}/state
+```
+
+If you have an item named `iris1_item`, then every change (e.g., using the PaperUI) will be published to `oh2/out/iris1_item/state`.
+And whenever a message is published to `oh2/in/iris1_item/state`, its payload will be used to update the state of the item `iris1_item`.
+
+## openHAB 2.4+ and MQTT 2.x
+
+In the more recent versions of openHAB, the old MQTT binding was ported to the new architecture.
+However, the event bus feature [was dropped in favour of simple rules](https://community.openhab.org/t/roadmap-mqtt-binding/70657/12).
+
+Now the following setup is required, involving one new channel, one new group and two new rules.
+
+### A new MQTT channel to receive updates
+
+To enable a trigger for all new MQTT messages, a new channel has to be created in the Thing of the respective broker.
+Navigate to the Thing of the broker in the PaperUI, and click the "+" near "Channels" to create a new one using the following settings:
+
+- Channel type: "Publish trigger" (will change the editable fields)
+- Channel Id: Choose any appropriate name and stick to it. In the following, `receiveEverythingChannel` will be used.
+- Label: Pick a description, like "Receive everything".
+- MQTT Topic: This is the topic to subscribe to, and has to match the `outgoing` value in the MQTT settings of Eraser. The default in most examples is to use `oh2/in/#`.
+- Payload condition: Is left empty.
+- Separator character: The character to separate the last topic and the payload. In the following, "#" is used (not to be confused with the `#` used for the topic above, which matches any topic with the given prefix)
+
+### A new group for relevant items
+
+To enable a trigger to publish new states, a new group has to be created with all relevant items as children.
+Navigate to Configuration > Items in the PaperUI. If this is not visible, disable the "Simple Mode" found at Configuration > System > Item Linking. This enables the manual editing of items and their links to channels.
+
+Create a new group with the following settings:
+
+- Name: Choose any appropriate name and stick to it. In the following, `PublishAllToMqttGroup` will be used.
+- Label: Pick a description, like "Items whose state will be published to MQTT".
+- Category: Is left empty.
+- Type: `Group`
+- Base type: `None` (Other types would enable an aggregation function, which is not needed here)
+
+### A rule to process received updates
+
+Add the following rule to your rule file in `./etc/openhab2/rules/`:
+
+```java
+rule "Receive all"
+when
+	Channel "mqtt:systemBroker:embedded-mqtt-broker:receiveEverythingChannel" triggered
+then
+	// The receivedEvent String contains unneeded elements like the mqtt topic, we only need everything after the "/" as this is were item name an
+	// logInfo("one.rules", "receivedEvent: {}", receivedEvent.toString())
+	val payload = receivedEvent.toString.split(" ", 3).get(2)
+	val parts = payload.split("/")
+	// logInfo("one.rules", "parts: {}", parts)
+	val lastTopicPartAndRealPayload = parts.get(parts.length - 1)
+	// logInfo("one.rules", "lastTopicPartAndRealPayload: {}", lastTopicPartAndRealPayload)
+	val topicAndPayloadTokens = lastTopicPartAndRealPayload.split("#", 2)
+	// logInfo("one.rules", "topicAndPayloadTokens: {}", topicAndPayloadTokens)
+	sendCommand(topicAndPayloadTokens.get(0), topicAndPayloadTokens.get(1));
+end
+```
+
+Note the matching channel id for an system broker with the id `embedded-mqtt-broker`. If you use a normal broker with the id `myMQTTBroker`, it would be `mqtt:broker:myMQTTBroker:receiveEverythingChannel` instead.
+The rule processes the received information, which is a String containing the topic and payload, separated by the formerly chosen Separator character `#`.
+Lastly, it updates the item matching the last part of the topic with the payload.
+
+### A rule to publish updates
+
+```java
+rule "Publish all"
+when
+	Member of PublishAllToMqttGroup changed
+then
+	val actions = getActions("mqtt","mqtt:systemBroker:embedded-mqtt-broker")
+	actions.publishMQTT("oh2/out/" + triggeringItem.name, triggeringItem.state.toString);
+end
+```
+
+Note the matching group name `PublishAllToMqttGroup`, the matching name of the system broker `embedded-mqtt-broker` (see [above](#a-rule-to-process-received-updates) for normal broker), and the correct topic to publish to.
+The topic has to match the `incoming` value in the MQTT settings of Eraser. The default in most examples is to use `oh2/out/`.
diff --git a/pages/docs/openhab-binding.md b/pages/docs/openhab-binding.md
new file mode 100644
index 0000000000000000000000000000000000000000..7be215a07fc2c16486f3836862d67cdd6b0297f6
--- /dev/null
+++ b/pages/docs/openhab-binding.md
@@ -0,0 +1,157 @@
+# Setup für Knowledge-Base
+
+_This document is only available in German_
+
+## Eraser-Seite
+
+Grundlage zum Starten der Knowledge-Base ist die Datei `eraser.starter-1.0.0-SNAPSHOT.zip`, welche die eraser-Module, deren Abhängigkeiten sowie ein Start-Skript enthält.
+
+Zusätzlich ist eine Konfigurationsdatei im YAML-Format notwendig. Die Standard-Konfiguration ist folgende (mit den Standard-Werten in Kommentaren):
+
+```yaml
+# Settings for Eraser.
+
+# Start the feedback loop. Default: true.
+useMAPE: true
+
+rest:
+  # Start the REST server. Default: true.
+  use: true
+  # Port of the REST server. Default: 4567.
+  port: 4567
+  # Add some dummy data for activities and events. Only effective when using the REST server. Default: false.
+  createDummyMLData: false
+
+# Initialize the knowledge base with a file.
+# OpenHAB synchronization is done if MQTT url is set in the processed file
+load:
+  # File to read in. Expected format = eraser
+#  # Option 1: Use built-in file
+#  file: starter.eraser
+#  external: false
+  # Option 2: Use external file
+  file: starter.eraser
+  external: true
+
+# Model for activity recognition. If dummy is true, then the file parameter is ignored.
+activity:
+  # File to read in. Expected format = eg
+  file: activity.eg
+  # Use dummy model in which the current activity is directly editable. Default: false.
+  dummy: true
+  # Model id. Default: 1.
+  id: 1
+
+# Model for preference learning. If dummy is true, then the file parameter is ignored.
+preference:
+  # File to read in. Expected format = eg
+  file: preference.eg
+  # Use dummy model in which the current activity is directly editable. Default: false.
+  dummy: true
+  # Model id. Default: 1.
+  id: 1
+  # Items to connect to inputs
+  items:
+    - datetime_month
+    - datetime_day
+    - datetime_hour
+    - datetime_minute
+    - bias
+    - activity
+  # Item to change with classification result
+  affectedItem: iris1_item
+
+# Initialize the knowledge base by importing data from openHAB.
+openhab:
+  # The URL from which to import and at which openHAB is running
+  url: "127.0.0.1:8080"
+  # The metadata namespace for items
+  metadataNamespace: fuenf
+
+# Get updates from openHAB into the knowledge base. Default: true.
+mqttUpdate: true
+
+# Method to initialize model. Possible values: "load", "openhab". Default: "load".
+initModelWith: load
+```
+
+Anzupassen ist folgendes:
+
+- referenzierte Dateien (initiales Modell `load.file = starter.eraser`, ML-Modell für Aktivitätserkennung `activity.file = activity.eg` und ML-Modell für Präferenzen `preference.file = preference.eg`) 
+- referenzierte Items für die Präferenzen (`preference.items` und `preference.affectedItem`)
+- URL von openHAB, inklusive Port. Optional der Namespace für Metadaten.
+
+Die in der Konfigurations-Datei referenzierte Modell-Datei `starter.eraser` enthält das initiale Modell in der dafür vorgesehenen [DSL](https://git-st.inf.tu-dresden.de/OpenLicht/eraser/wikis/DSL). Ein Beispiel-Modell sieht wie folgt aus:
+
+```
+Color Item: id="iris1_item" label="Iris 1" state="121,88,68" topic="iris1_item";
+Number Item: id="datetime_month" label="Month" state="1" topic="datetime_month";
+Number Item: id="datetime_day" label="Day" state="31" topic="datetime_day";
+Number Item: id="datetime_hour" label="Hour" state="13" topic="datetime_hour";
+Number Item: id="datetime_minute" label="Minute" state="37" topic="datetime_minute";
+Number Item: id="bias" label="bias item" state="1" ;
+Activity Item: id="activity" ;
+
+Group: id="Lights" items=["iris1_item"];
+Group: id="Datetime" items=["datetime_month", "datetime_day", "datetime_hour", "datetime_minute"];
+
+Mqtt: incoming="oh2/out/" outgoing="oh2/in/" host="localhost:2883" ;
+
+Influx: host="172.22.1.152" ;
+
+ML: activities={
+  0: "Open door in empty room",
+  1: "Door closed in empty room",
+  2: "Open door with person in room",
+  3: "Door closed with person in room",
+  4: "Working",
+  5: "Watch TV",
+  6: "Reading",
+  7: "Listening to music",
+  8: "Going to sleep",
+  9: "Wake up"
+} ;
+```
+
+Im Statement zu `Mqtt` muss die Verbindung zum MQTT-Broker, der auch im openHAB verwendet wird, angegeben werden. Gegebenfalls muss eine Port-Weiterleitung eingerichtet werden.
+Das Statement zu Influx ist optional.
+
+Zum Starter der Knowledge-Base ist die Konfigurationsdatei anzugeben (hier im Beispiel `./starter-setting.yaml`):
+
+```bash
+./eraser.starter-1.0.0-SNAPSHOT/bin/eraser.starter -f starter-setting.yaml
+```
+
+Zum Beenden sollte (wie auch beim Starten im Log zu lesen) ein POST-Request auf `localhost:3467/system/exit` gesendet werden. Das ist auch über die [Swagger-UI](#swagger-ui-fur-die-rest-api-der-knowledge-base) möglich.
+
+## openHAB-Seite
+
+Grundlage auf der openHAB-Seite ist ein installiertes MQTT-Binding in Version 2, und das Eraser-Binding in Version `2.3.0.201904121612`.
+
+In der PaperUI muss ein MQTT-Broker-Thing angelegt werden, entweder ein SystemBroker oder ein lokaler Broker, wie im Beispiel gezeigt:
+
+![MQTT Binding Config](img/config-mqtt-binding.png)
+
+Zusätzlich muss ein Eraser-Thing angelegt werden, welches den Namen des oben genannten Brokers in den Einstellung gesetzt hat (hier im Beispiel `local-mqtt-broker`).
+Wahlweise können Updates von allen Items (`Publish All` aktiviert), oder nur von Items in einer Gruppe (`Publish All` deaktiviert und `Publish Group` ausgewählt) an Eraser gesendet werden.
+
+Weiterhin ist zu beachten, dass die MQTT-Topics hier und bei der Eraser-Konfiguration übereinstimmen, d.h.
+
+- `openhab.Base-Topic == eraser.outgoing` (im Beispiel `oh2/in`)
+- `openhab.Outgoing-Topic == eraser.incoming` (im Beispiel `oh2/out`)
+
+![Eraser Binding Config](img/config-eraser-binding.png)
+
+## Swagger-UI für die REST-API der Knowledge-Base
+
+Zur einfacheren Verwendung der REST-API wurde eine Swagger-UI in Python entwickelt, da das verwendete leichtgewichtige REST-Framework ([SparkJava](http://sparkjava.com/)) dies nicht unterstützt.
+Zum Starten wird das Python-Skript gestartet, welches auf `localhost:5000` läuft und nach `localhost:4567` (Standard-Einstellung in der Knowledge-Base unter `rest.port`) weiterleitet.
+
+```bash
+python forward.py
+```
+
+Abhängigkeiten sind `flask`, `flask_restplus` und `requests`.
+Nach Starten sieht die Oberfläche aktuell wie folgt aus:
+
+![Swagger-UI Startseite](img/swagger-ui.png)
diff --git a/pages/docs/setup.md b/pages/docs/setup.md
new file mode 100644
index 0000000000000000000000000000000000000000..7d293e437494ab5aef8b93b18f952b6a423495bd
--- /dev/null
+++ b/pages/docs/setup.md
@@ -0,0 +1,17 @@
+# Setup and Building eraser
+
+This project uses Gradle as the build tool. Please use the provided Gradle wrappers instead of an installed one.
+
+- Clone the repository, either using https (`https://git-st.inf.tu-dresden.de/OpenLicht/eraser.git`) or ssh (`git@git-st.inf.tu-dresden.de:OpenLicht/eraser.git`)
+- (Optional) Build all subprojects: `./gradlew build`
+
+## Troubleshooting
+
+### Lombok
+
+Some of the modules use [Lombok](https://projectlombok.org/). It has to be set up according to your platform, e.g., for IntelliJ the [plugin has to be installed](https://projectlombok.org/setup/intellij).
+Afterwards, the annotation processor has to be enabled for the project (which sould be warned about by IntelliJ).
+
+### Java Version
+
+All submodules use Java `1.8`. Please ensure using an appropriate compiler.
diff --git a/pages/docs/working.md b/pages/docs/working.md
new file mode 100644
index 0000000000000000000000000000000000000000..ec9110a2e1157adedac16177ef6cf45116ec850f
--- /dev/null
+++ b/pages/docs/working.md
@@ -0,0 +1,18 @@
+# Working with the model
+
+The root is mostly the entry point to all needed information, and can be obtained from any element in the model using `getRoot()`.
+From there, one has mostly "descend" into the relevant part of the model, e.g., if information is needed about items, then `getOpenHAB2Model()` yields this part of the model.
+
+There are various attributes to resolve model entities by their ID, e.g., `resolveThing(String thingName)`, `resolveItem(String itemName)`. Those return an `java.util.Optional` with the respective type, e.g., `Optional<Item>` to represent non-matched IDs.
+
+## OpenHAB specifics
+
+As described in the [description of the model](Model-description), item type is reified, so all items with a double state are of type `ItemWithDoubleState` and only this type has a `getState` returning its state (as a double value).
+There is a convenience way to get the state as a double, or String value using `getStateAsDouble` and `getStateAsString` defined on `Item` and implement in a meaningful way by the different subclasses.
+Analogously, state can be set from different type, e.g., from a String, or a boolean value.
+
+Synchronisation between eraser and openHAB itself currently includes only states of items. Therefore, any structural changes (e.g., addition or removal of an item) or change of other attributes such as description of items or things, is **not tracked nor supported**.
+
+## Documentation
+
+When working and especially when extending eraser, it is highly recommended to use the [API documentation](ragdoc/index.html) as a reference manual.
diff --git a/pages/mkdocs.yml b/pages/mkdocs.yml
new file mode 100644
index 0000000000000000000000000000000000000000..e4410b59ba5f3b4eb406b9cfbd0d9bfd8e8e5197
--- /dev/null
+++ b/pages/mkdocs.yml
@@ -0,0 +1,24 @@
+site_name: Documentation of Eraser
+nav:
+  - setup.md
+  - config.md
+  - Model-description.md
+  - Inner-workings.md
+  - working.md
+  - MachineLearning.md
+  - Learner.md
+  - DSL.md
+  - mqtt.md
+  - openhab-binding.md
+  - contributing.md
+  - API documentation: ragdoc/index.html
+theme:
+  name: readthedocs
+  custom_dir: custom_theme/
+plugins:
+  - search
+  - git-revision-date:
+      as_datetime: True
+  - macros
+repo_url: https://git-st.inf.tu-dresden.de/OpenLicht/eraser
+site_dir: ../public
diff --git a/ragdoc-view b/ragdoc-view
deleted file mode 160000
index 4bb8afb1bc3dc6b346e04e72c5896568b2e9b192..0000000000000000000000000000000000000000
--- a/ragdoc-view
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit 4bb8afb1bc3dc6b346e04e72c5896568b2e9b192