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

preparing for master/main update

- also add version to eraser.starter
parent e96e61b6
Branches
No related tags found
1 merge request!19dev to master
Pipeline #10041 failed
......@@ -119,7 +119,7 @@ pages:
- cd pages && mkdocs build
only:
- dev
- master
- main
artifacts:
paths:
- "public"
......@@ -5,7 +5,7 @@
There are the following subprojects in this repository:
- Base
- **eraser-base**: The core part of the framework containing the [grammar](/../../blob/master/eraser-base/src/main/jastadd/main.relast), various attributes, the [parser](/../../blob/master/eraser-base/src/main/jastadd/eraser.parser) for model specification files, and Java classes for the [openHAB communication](/../../tree/master/eraser-base/src/main/java/de/tudresden/inf/st/eraser/openhab2) via [MQTT](/../../blob/master/eraser-base/src/main/java/de/tudresden/inf/st/eraser/openhab2/mqtt/MQTTUpdater.java)
- **eraser-base**: The core part of the framework containing the [grammar](/../../blob/main/eraser-base/src/main/jastadd/main.relast), various attributes, the [parser](/../../blob/main/eraser-base/src/main/jastadd/eraser.parser) for model specification files, and Java classes for the [openHAB communication](/../../tree/main/eraser-base/src/main/java/de/tudresden/inf/st/eraser/openhab2) via [MQTT](/../../blob/main/eraser-base/src/main/java/de/tudresden/inf/st/eraser/openhab2/mqtt/MQTTUpdater.java)
- Utility
- **commons.color**: Utilities for converting color spaces (XYZ, RGB, HSB)
- **eraser.rest** and **eraser.spark**: REST-API to communicate with the framework
......@@ -25,15 +25,6 @@ There are the following subprojects in this repository:
This project uses Gradle as the build tool. For detailed information, see [setup guidelines](/../../wikis/setup)
## Running the demo
There is a demo project, as explained [above](#overview) to showcase the framework.
To start it, run `./gradlew :skywriter-hue-integration:run`
This demo is intended to run with a pre-configured openHAB instance and has some hard-coded settings.
It will first try to connect to an MQTT broker (with a hard-coded IP) to listen on changes of item states.
There is one rule implemented, namely to listen on changes of the item `skywriter_xyz` expecting MQTT messages of the form `XVALUE,YVALUE,ZVALUE`, and to change to state of another item `iris1_item` representing the HSB value of a Hue Iris.
## Trivia
The name *Eraser* is a small pun on the term *eRACR*, which is an extension of *RACR* for event recognition. It was chosen to ease the search for a good repository image as it is based on a [film](https://en.wikipedia.org/wiki/Eraser_(film)).
......@@ -19,6 +19,31 @@ dependencies {
}
def versionFile = 'src/main/resources/eraser.properties'
def oldProps = new Properties()
try {
file(versionFile).withInputStream { stream -> oldProps.load(stream) }
version = oldProps['version']
} catch (e) {
// this happens, if either the properties file is not present, or cannot be read from
throw new GradleException("File ${versionFile} not found or unreadable. Aborting.", e)
}
task printVersion() {
doLast {
println(version)
}
}
task newVersion() {
doFirst {
def props = new Properties()
props['version'] = value
props.store(file(versionFile).newWriter(), null)
}
}
application.mainClass = 'de.tudresden.inf.st.eraser.starter.EraserStarter'
import io.github.httpbuilderng.http.HttpTask
......
......@@ -24,8 +24,11 @@ import org.apache.logging.log4j.Logger;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
......@@ -52,8 +55,12 @@ public class EraserStarter {
private static final Logger logger = LogManager.getLogger(EraserStarter.class);
@SuppressWarnings("ResultOfMethodCallIgnored")
public static void main(String[] args) {
EraserStarter starter = new EraserStarter();
starter.run(args);
}
public void run(String[] args) {
ArgumentParser parser = ArgumentParsers.newFor("eraser").build()
.defaultHelp(true)
.description("Starts the knowledge-base of OpenLicht");
......@@ -79,7 +86,7 @@ public class EraserStarter {
System.exit(1);
return;
}
logger.info("Starting ERASER");
logger.info("Starting ERASER " + readVersion());
boolean startRest = settings.rest.use;
Root root;
......@@ -102,7 +109,7 @@ public class EraserStarter {
default:
try {
root = ParserUtils.load(settings.load.realURL());
model = root.getSmartHomeEntityModel();
root.getSmartHomeEntityModel();
} catch (IOException | Parser.Exception e) {
logger.error("Problems parsing the given file {}", settings.load.file);
logger.catching(e);
......@@ -194,6 +201,7 @@ public class EraserStarter {
logger.info("No REST server this time");
System.out.println("Hit [Enter] to exit");
try {
//noinspection ResultOfMethodCallIgnored
System.in.read();
} catch (IOException e) {
e.printStackTrace();
......@@ -222,7 +230,7 @@ public class EraserStarter {
logger.info("I'm done here.");
}
private static MachineLearningHandlerFactory createFactory(MachineLearningHandlerFactory.MachineLearningHandlerFactoryTarget target, Setting.MLContainer config, Root root) {
private MachineLearningHandlerFactory createFactory(MachineLearningHandlerFactory.MachineLearningHandlerFactoryTarget target, Setting.MLContainer config, Root root) {
MachineLearningHandlerFactory factory;
String niceTargetName = target.toString().toLowerCase().replace("_", " ");
if (config.dummy || config.factory == null) {
......@@ -232,10 +240,11 @@ public class EraserStarter {
try {
Class<? extends MachineLearningHandlerFactory> clazz = Class.forName(config.factory)
.asSubclass(MachineLearningHandlerFactory.class);
factory = clazz.newInstance();
factory = clazz.getDeclaredConstructor().newInstance();
factory.setKnowledgeBaseRoot(root);
factory.initializeFor(target, config.realURL());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | IOException e) {
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | IOException |
NoSuchMethodException | InvocationTargetException e) {
logger.error("Could not instantiate machine learning factory for {} with class '{}'.",
niceTargetName, config);
logger.catching(e);
......@@ -250,4 +259,14 @@ public class EraserStarter {
}
return factory;
}
private String readVersion() {
try {
ResourceBundle resources = ResourceBundle.getBundle("eraser");
return resources.getString("version");
} catch (MissingResourceException e) {
return "version ?";
}
}
}
#Sun Jun 20 11:43:25 CEST 2021
version=1.0.0
/docs/ragdoc/
__pycache__
......@@ -4,8 +4,8 @@
{% 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>
{% if page and page.meta and page.meta.git_revision_date_localized %}
<small><br><i>Last updated {{ page.meta.git_revision_date_localized }}</i></small>
{% endif %}
</p>
{% endblock %}
# 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)).
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), [main](https://git-st.inf.tu-dresden.de/OpenLicht/eraser/blob/main/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), [main](https://git-st.inf.tu-dresden.de/OpenLicht/eraser/blob/main/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):
The following elements can be described (in the main branch if not otherwise noted):
## ChannelType
......@@ -15,7 +15,7 @@ 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))
- 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), [main](https://git-st.inf.tu-dresden.de/OpenLicht/eraser/blob/main/eraser-base/src/main/jastadd/enums.jadd))
- The flag `readOnly` is currently without any effect
## Channel
......
# 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):
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) | [main](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
......
# 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)
The latest version of the model: [main](https://git-st.inf.tu-dresden.de/rschoene/eraser/blob/main/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* ;
`Root ::= SmartHomeEntityModel User* MqttRoot InfluxRoot MachineLearningRoot Rule* Location* ;`
- `OpenHAB2Model`: Content from openHAB
- `SmartHomeEntityModel`: Smart home entities
- `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)
......@@ -16,16 +16,16 @@ Root ::= OpenHAB2Model User* MqttRoot InfluxRoot MachineLearningRoot Rule* Locat
- `Rule*`: Self-made ECA rules
- `Location*`: Locations associated with users, activities, preferences (work in progress)
## openHAB
## Smart Home Entity Model
> OpenHAB2Model ::= Thing* Group* ThingType* ChannelType* ChannelCategory* ItemCategory* /ActivityItem:Item/
`SmartHomeEntityModel ::= Thing* Group* ThingType* Parameter* ChannelType* Channel* ItemCategory* /ActivityItem:Item/ FrequencySetting* ;`
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
- Links are not modelled explicitly, 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:
Explanations 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.
......@@ -46,13 +46,22 @@ Basically, here are just some tokens containing information for connection to In
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 is a distinction between internal and external models, both implement an 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.
Decision tree are modelled straight-forward, there are inner nodes and leaves. 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.
### StateSyncGroup
#### What does it do?
Item states can be synchronized through StateSyncGroups. Once an item belongs to such a group, all of its state changes will be applied and then sent to other items in that group.
The behavior of the other items in the group following the order to change the state is up to the item type. This is how state transfers between different item types can be managed. For example if a ColorItem (currently at `1%` brightness) and a SwitchItem (currently at value `false`) are in a StateSyncGroup and the SwitchItem is changing to `true` then the ColorItem won't change to 100%. Instead, it keeps its old value (`1%`).
#### How does it work?
The StateSyncGroup as an entity does only exist while parsing. After resolving all references, it is rewritten (using JastAdd rewrites). As a result, an ECA rule emerges that has conditions and actions whose functionality correspond to the explained behavior in the previous paragraph.
# 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)
First, setup eraser following the README in the main repository: [dev](https://git-st.inf.tu-dresden.de/OpenLicht/eraser/blob/dev/README.md) | [main](https://git-st.inf.tu-dresden.de/OpenLicht/eraser/blob/main/README.md)
To configure the system, read the [configuration page](config).
For an overview of the model, check out the [Model description](Model-description).
......
eraserVersionFileName = '../eraser.starter/src/main/resources/eraser.properties'
def get_version():
with open(eraserVersionFileName) as eraserVersionFile:
versionFileContent = eraserVersionFile.read()
return versionFileContent[versionFileContent.rindex('version=') + 8:].strip()
def define_env(env):
"""
This is the hook for defining variables, macros and filters
- variables: the dictionary that contains the environment variables
- macro: a decorator function, to declare a macro.
"""
env.conf['site_name'] = 'Documentation of Eraser ' + get_version()
@env.macro
def eraser_version():
return get_version()
if __name__ == '__main__':
print(get_version())
......@@ -17,8 +17,11 @@ theme:
custom_dir: custom_theme/
plugins:
- search
- git-revision-date:
as_datetime: True
- git-revision-date-localized:
type: datetime
timezone: Europe/Berlin
locale: en
fallback_to_build_date: True
- macros
repo_url: https://git-st.inf.tu-dresden.de/OpenLicht/eraser
site_dir: ../public
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment