Skip to content

Commit

Permalink
Merge branch 'release/v1.2'
Browse files Browse the repository at this point in the history
  • Loading branch information
sfeilmeier committed Sep 7, 2017
2 parents 5c79ef9 + 38c5965 commit 4aca6f4
Show file tree
Hide file tree
Showing 331 changed files with 28,399 additions and 23,794 deletions.
89 changes: 88 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ A number of devices, protocols and services are already implemented in OpenEMS:

### Inbound protocols

* JSON/REST
* [JSON/REST](doc/rest-api.md)
* JSON/Websocket
* [Modbus/TCP (in development)](/OpenEMS/openems/issues/2)

Expand Down Expand Up @@ -127,6 +127,93 @@ The target of this short guide is to quickly setup a development environment on

8. Open a browser at http://localhost:4200

### How to configure OpenEMS

The configuration of OpenEMS is placed in the json file /etc/openems.d/config.json.
To parameterize a Bridge,Device,DeviceNature, Scheduler, Controller or Persistance you have to use ConfigChannels. A ConfigChannel represents one parameter the Thing needs. The value of the ConfigChannel will be automatically parsed by OpenEMS on the configuration read. Each thing will be instantiated by reflection so you have to define a "class" property, which is the qualified name of the desired class.
The file is split into three sections:
1. `things`:
In the things section you need to set all devices to communicate with.
Therefore you have to use a so called "Bridge". A Bridge connects several devices(Hardware) with the same protocol to openems. For example you want to read the data of a Socomec Meter and FeneconPro which are connected to the same RS485 Bus, you have to use a ModbusRtu bridge and set the Socomec Meter and FeneconPro as devices for this bridge. Each bridge/device has ConfigChannels to provide the paremters to establish the connection. The required parameters can be found in the according class. A device has DeviceNatures, where each nature requires a unique id. This id is used as reference by the controllers.
2. `scheduler`: The Scheduler executes the controllers according to the programmed behaviour. For example the SimpleScheduler orders and executes the Controller by the configured priority. Controllers are the smallest divisible logical control unit. Each Controller needs at least one device reference to do the work.
3. `persistance`:

Example configuration:
```
{
"things": [
{
"class": "io.openems.impl.protocol.modbus.ModbusRtu",
"serialinterface": "/dev/ttyUSB0",
"baudrate": 9600,
"databits": 8,
"parity": "none",
"stopbits": 1,
"devices": [
{
"class": "io.openems.impl.device.pro.FeneconPro",
"modbusUnitId": 4,
"ess": {
"id": "ess0",
"minSoc": 15
},
"meter": {
"id": "meter1"
}
},
{
"class": "io.openems.impl.device.socomec.Socomec",
"modbusUnitId": 5,
"meter": {
"id": "meter0",
"type": "grid"
}
}
]
}
],
"scheduler": {
"class": "io.openems.impl.scheduler.SimpleScheduler",
"controllers": [
{
"priority": 150,
"class": "io.openems.impl.controller.debuglog.DebugLogController",
"esss": [ "ess0" ],
"meters": [ "meter0", "meter1" ],
"rtc": "ess0"
},
{
"priority": 100,
"class": "io.openems.impl.controller.asymmetric.avoidtotaldischarge.AvoidTotalDischargeController",
"esss": "ess0"
},
{
"priority": 50,
"class": "io.openems.impl.controller.asymmetric.balancing.BalancingController",
"esss": "ess0",
"meter": "meter0"
},
{
"priority": 1,
"class": "io.openems.impl.controller.clocksync.ClockSyncController",
"rtc": "ess0"
},
{
"priority": 0,
"class": "io.openems.impl.controller.feneconprosetup.FeneconProSetupController",
"esss": "ess0"
}
]
},
"persistence": [
{
"class": "io.openems.impl.persistence.influxdb.InfluxdbPersistence",
"ip": "127.0.0.1",
"fems": 0
}
]
}
```

## Professional services and support

Expand Down
1 change: 1 addition & 0 deletions backend/.classpath
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,6 @@
</attributes>
</classpathentry>
<classpathentry kind="src" path="resources"/>
<classpathentry combineaccessrules="false" kind="src" path="/common"/>
<classpathentry kind="output" path="target/classes"/>
</classpath>
2 changes: 1 addition & 1 deletion backend/.project
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>femsserver</name>
<name>backend</name>
<comment></comment>
<projects>
</projects>
Expand Down
25 changes: 25 additions & 0 deletions backend/OpenEMS-Backend (Dummy).launch
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<launchConfiguration type="org.eclipse.jdt.launching.localJavaApplication">
<setAttribute key="name.schedenig.eclipse.grepconsole.DisabledIds"/>
<setAttribute key="name.schedenig.eclipse.grepconsole.EnabledIds"/>
<setAttribute key="name.schedenig.eclipse.grepconsole.FilterDisabledIds"/>
<setAttribute key="name.schedenig.eclipse.grepconsole.FilterEnabledIds"/>
<setAttribute key="name.schedenig.eclipse.grepconsole.StatisticsDisabledIds"/>
<setAttribute key="name.schedenig.eclipse.grepconsole.StatisticsEnabledIds"/>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
<listEntry value="/backend/src/main/java/io/openems/backend/App.java"/>
</listAttribute>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
<listEntry value="1"/>
</listAttribute>
<mapAttribute key="org.eclipse.debug.core.environmentVariables">
<mapEntry key="BROWSER_WEBSOCKET_PORT" value="8078"/>
<mapEntry key="METADATA" value="DUMMY"/>
<mapEntry key="OPENEMS_WEBSOCKET_PORT" value="8077"/>
<mapEntry key="TIMEDATA" value="DUMMY"/>
</mapAttribute>
<stringAttribute key="org.eclipse.jdt.launching.CLASSPATH_PROVIDER" value="org.eclipse.m2e.launchconfig.classpathProvider"/>
<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="io.openems.backend.App"/>
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="backend"/>
<stringAttribute key="org.eclipse.jdt.launching.SOURCE_PATH_PROVIDER" value="org.eclipse.m2e.launchconfig.sourcepathProvider"/>
</launchConfiguration>
36 changes: 36 additions & 0 deletions backend/OpenEMS-Backend.launch
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<launchConfiguration type="org.eclipse.jdt.launching.localJavaApplication">
<setAttribute key="name.schedenig.eclipse.grepconsole.DisabledIds"/>
<setAttribute key="name.schedenig.eclipse.grepconsole.EnabledIds"/>
<setAttribute key="name.schedenig.eclipse.grepconsole.FilterDisabledIds"/>
<setAttribute key="name.schedenig.eclipse.grepconsole.FilterEnabledIds"/>
<setAttribute key="name.schedenig.eclipse.grepconsole.StatisticsDisabledIds"/>
<setAttribute key="name.schedenig.eclipse.grepconsole.StatisticsEnabledIds"/>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
<listEntry value="/backend/src/main/java/io/openems/backend/App.java"/>
</listAttribute>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
<listEntry value="1"/>
</listAttribute>
<mapAttribute key="org.eclipse.debug.core.environmentVariables">
<mapEntry key="BROWSER_WEBSOCKET_PORT" value="8078"/>
<mapEntry key="INFLUX_DATABASE" value="db"/>
<mapEntry key="INFLUX_PASSWORD" value="admin"/>
<mapEntry key="INFLUX_PORT" value="8086"/>
<mapEntry key="INFLUX_URL" value="localhost"/>
<mapEntry key="INFLUX_USERNAME" value="admin"/>
<mapEntry key="METADATA" value="DUMMY"/>
<mapEntry key="ODOO_DATABASE" value=""/>
<mapEntry key="ODOO_PASSWORD" value=""/>
<mapEntry key="ODOO_PORT" value="8069"/>
<mapEntry key="ODOO_URL" value=""/>
<mapEntry key="ODOO_USERNAME" value=""/>
<mapEntry key="OPENEMS_WEBSOCKET_PORT" value="8077"/>
</mapAttribute>
<stringAttribute key="org.eclipse.debug.core.source_locator_id" value="org.eclipse.jdt.launching.sourceLocator.JavaSourceLookupDirector"/>
<stringAttribute key="org.eclipse.debug.core.source_locator_memento" value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;sourceLookupDirector&gt;&#13;&#10;&lt;sourceContainers duplicates=&quot;false&quot;&gt;&#13;&#10;&lt;container memento=&quot;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot; standalone=&amp;quot;no&amp;quot;?&amp;gt;&amp;#13;&amp;#10;&amp;lt;javaProject name=&amp;quot;common&amp;quot;/&amp;gt;&amp;#13;&amp;#10;&quot; typeId=&quot;org.eclipse.jdt.launching.sourceContainer.javaProject&quot;/&gt;&#13;&#10;&lt;container memento=&quot;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot; standalone=&amp;quot;no&amp;quot;?&amp;gt;&amp;#13;&amp;#10;&amp;lt;default/&amp;gt;&amp;#13;&amp;#10;&quot; typeId=&quot;org.eclipse.debug.core.containerType.default&quot;/&gt;&#13;&#10;&lt;/sourceContainers&gt;&#13;&#10;&lt;/sourceLookupDirector&gt;&#13;&#10;"/>
<stringAttribute key="org.eclipse.jdt.launching.CLASSPATH_PROVIDER" value="org.eclipse.m2e.launchconfig.classpathProvider"/>
<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="io.openems.backend.App"/>
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="backend"/>
<stringAttribute key="org.eclipse.jdt.launching.SOURCE_PATH_PROVIDER" value="org.eclipse.m2e.launchconfig.sourcepathProvider"/>
</launchConfiguration>
10 changes: 9 additions & 1 deletion backend/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,14 @@
<name>femsserver</name>
<url>http://maven.apache.org</url>

<!-- TODO check all maven dependencies of all projects -->
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<slf4j.version>1.6.4</slf4j.version>
<openems-common.version>1.0.0</openems-common.version>
<slf4j.version>1.7.15</slf4j.version>
<logback.version>1.0.1</logback.version>
<gson.version>2.6.2</gson.version>
<guava.version>23.0</guava.version>
</properties>

<repositories>
Expand Down Expand Up @@ -62,5 +65,10 @@
<artifactId>java-websocket</artifactId>
<version>1.3.3</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>${guava.version}</version>
</dependency>
</dependencies>
</project>
1 change: 0 additions & 1 deletion backend/resources/logback.xml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
<pattern>[%-8.8thread] [%-5level] [%-20.20logger{36}:%-3line] %msg%ex{10}%n</pattern>
</encoder>
</appender>
<!-- <logger name="io.openems" level="DEBUG" additivity="false"> -->
<logger name="io.openems" level="INFO" additivity="false">
<appender-ref ref="STDOUT" />
</logger>
Expand Down
78 changes: 78 additions & 0 deletions backend/src/main/java/io/openems/backend/App.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package io.openems.backend;

import java.util.Optional;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import io.openems.backend.browserwebsocket.BrowserWebsocket;
import io.openems.backend.metadata.Metadata;
import io.openems.backend.openemswebsocket.OpenemsWebsocket;
import io.openems.backend.timedata.Timedata;
import io.openems.common.utils.EnvUtils;

public class App {
private static Logger log = LoggerFactory.getLogger(App.class);

public static void main(String[] args) throws Exception {
log.info("OpenEMS-Backend starting...");

// Configure everything
initMetadataProvider();
initTimedataProvider();
initOpenemsWebsocket();
initBrowserWebsocket();

log.info("OpenEMS Backend started.");
log.info("================================================================================");
}

/**
* Configures a metadata provider. It uses either Odoo as backend or a simple Dummy provider.
*
* @throws Exception
*/
private static void initMetadataProvider() throws Exception {
Optional<String> metadataOpt = EnvUtils.getAsOptionalString("METADATA");
if (metadataOpt.isPresent() && metadataOpt.get().equals("DUMMY")) {
log.info("Start Dummy Metadata provider");
Metadata.initializeDummy();
} else {
int port = EnvUtils.getAsInt("ODOO_PORT");
String url = EnvUtils.getAsString("ODOO_URL");
String database = EnvUtils.getAsString("ODOO_DATABASE");
log.info("Connect to Odoo. Url [" + url + ":" + port + "] Database [" + database + "]");
String username = EnvUtils.getAsString("ODOO_USERNAME");
String password = EnvUtils.getAsString("ODOO_PASSWORD");
Metadata.initializeOdoo(url, port, database, username, password);
}
}

private static void initTimedataProvider() throws Exception {
Optional<String> timedataOpt = EnvUtils.getAsOptionalString("TIMEDATA");
if (timedataOpt.isPresent() && timedataOpt.get().equals("DUMMY")) {
log.info("Start Dummy Timedata provider");
Timedata.initializeDummy();
} else {
int port = Integer.valueOf(System.getenv("INFLUX_PORT"));
String url = EnvUtils.getAsString("INFLUX_URL");
String database = EnvUtils.getAsString("INFLUX_DATABASE");
log.info("Connect to InfluxDB. Url [" + url + ":" + port + "], Database [" + database + "]");
String username = EnvUtils.getAsString("INFLUX_USERNAME");
String password = EnvUtils.getAsString("INFLUX_PASSWORD");
Timedata.initializeInfluxdb(database, url, port, username, password);
}
}

private static void initOpenemsWebsocket() throws Exception {
int port = EnvUtils.getAsInt("OPENEMS_WEBSOCKET_PORT");
log.info("Start OpenEMS Websocket server on port [" + port + "]");
OpenemsWebsocket.initialize(port);
}

private static void initBrowserWebsocket() throws Exception {
int port = EnvUtils.getAsInt("BROWSER_WEBSOCKET_PORT");
log.info("Start Browser Websocket server on port [" + port + "]");
BrowserWebsocket.initialize(port);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package io.openems.backend.browserwebsocket;

/**
* Provider for OpenemsWebsocketServer singleton
*
* @author stefan.feilmeier
*
*/
public class BrowserWebsocket {

private static BrowserWebsocketSingleton instance;

/**
* Initialize and start the Websocketserver
*
* @param port
* @throws Exception
*/
public static synchronized void initialize(int port) throws Exception {
BrowserWebsocket.instance = new BrowserWebsocketSingleton(port);
BrowserWebsocket.instance.start();
}

/**
* Returns the singleton instance
*
* @return
*/
public static synchronized BrowserWebsocketSingleton instance() {
return BrowserWebsocket.instance;
}
}
Loading

0 comments on commit 4aca6f4

Please sign in to comment.