Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 19 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,39 +1,39 @@
# SGr-JavaSamples

# SmartGridready Java Samples

## Index

[Summary](#summary)<br>
[Installation](#installation)<br>
[Architecture](#architecture)<br>
[Code description](#code-description-for-the-samplecommunicator)<br>


## Summary
SGr-JavaSamples provides sample projects that demonstrate the use of the SGr Communication Handler Library. The goal is to set up a test environment that allows to connect SGr components and different 'products' (heat pump, charging station, inverter, battery, electricity meter etc.) through the SGr communication interface.

SGr-JavaSamples provides sample projects that demonstrate the use of the SGr Communication Handler Library. The goal is to set up a test environment that allows to connect SGr components and different 'products' (heat pump, charging station, inverter, battery, electricity meter etc.) through the SGr communication interface.

## Installation

### Requirements / Prerequisites

- Java JDK version >= Java 11

### Clone

- Create a new folder for the project (eg. 'SGrJavaSamples').
- Clone the following project to a new folder: https://github.com/SmartgridReady/SGrJavaSamples.git

Rem: The folder [your-local-project-folder]/SampleCommunicator/src/main/resources contains the device description XML-files used by the SGrJavaSamples.

### Build

- Open the [your-local-project-folder]/SampleCommunicator with your IDE.
- Run the Gradle 'build' target in your IDE
- You can also run Gradle from the command line. Change to the directory [your-local-project-folder]/SampleCommunicator and run: `gradlew clean build`


## Architecture

![SGr Architecture Overview](doc/img/SGr-Architecture-Overview.png "SGr Architecture Overview")


### Component: Communicator

<table valign="top">
Expand All @@ -52,7 +52,7 @@ Rem: The folder [your-local-project-folder]/SampleCommunicator/src/main/resource
<li>The Communicator loads a device driver for the communication interface of the product (e.g. Modbus RTU/TCP, REST...).</li>
<li>The communicator reads or sets (analyses and/or controls) the data points.</li>
</ul></td>
</tr>
</tr>
<tr>
<td><b>SGrProject:</b></td>
<td><p><a href="https://github.com/SmartgridReady/SGrJavaSamples/tree/master/SampleCommunicator">SGrJavaSamples/SampleCommunicator</a></p></td>
Expand All @@ -72,13 +72,13 @@ Rem: The folder [your-local-project-folder]/SampleCommunicator/src/main/resource
</tr>
<tr>
<td valign="top"><b>Responsibilities:</b></td>
<td><p>The Generic Interface is used by the Communicator to communicate with the products in the SGr network.</p></td>
</tr>
<td><p>The Generic Interface is used by the Communicator to communicate with the products in the SGr network.</p></td>
</tr>
<tr>
<td><b>SGrProject:</b></td>
<td><p><a href="https://github.com/SmartgridReady/SGrSpecifications/tree/master/SchemaDatabase/SGr/Generic">SmartgridReady/SGrSpecifications/SchemaDatabase/SGr/Generic</a></p></td>
</tr>
</table>
</table>

### Component: Communication Handler

Expand All @@ -94,7 +94,7 @@ Rem: The folder [your-local-project-folder]/SampleCommunicator/src/main/resource
</tr>
<tr>
<td valign="top"><b>Responsibilities:</b></td>
<td><p>Responsibilities are:</p>
<td><p>Responsibilities are:</p>
<ul>
<li>Reading the XML device profiles</li>
<li>Processing commands of the Generic Interface</li>
Expand All @@ -110,7 +110,7 @@ Rem: The folder [your-local-project-folder]/SampleCommunicator/src/main/resource
<td><b>SGrProject:</b></td>
<td><p><a href="https://github.com/SmartgridReady/SGrJava/tree/master/CommHandler">SmartgridReady/SGrJava/CommHandler</a></p></td>
</tr>
</table>
</table>

### Component: XML (XML-Profile)

Expand All @@ -121,20 +121,20 @@ Rem: The folder [your-local-project-folder]/SampleCommunicator/src/main/resource
</tr>
<tr>
<td><b>Description:</b></td>
<td><p>The XML file describes the ''function profiles', data points and attributes that can be addressed over the SGr interface. The XML file also provides general information about the 'Product'.</p></td>
<td><p>The XML file describes the ''function profiles', data points and attributes that can be addressed over the SGr interface. The XML file also provides general information about the 'Product'.</p></td>
</tr>
<tr>
<td valign="top"><b>Responsibilities:</b></td>
<td><ul>
<li>Providing general data on the Product.</li>
<li>Provide the data necessary for mapping the SGr Generic Interface with the External Interface.</li>
</ul></td>
</tr>
</tr>
<tr>
<td><b>SGrProject:</b></td>
<td><p><a href="https://github.com/SmartgridReady/SGrSpecifications/tree/master/XMLInstances/ExtInterfaces">SmartgridReady/SGrSpecifications/XMLInstances/ExtInterfaces</a></p></td>
</tr>
</table>
</table>

### Component: Transport Layer (Transport Service)

Expand All @@ -152,10 +152,10 @@ Rem: The folder [your-local-project-folder]/SampleCommunicator/src/main/resource
</tr>
<tr>
<td valign="top"><b>Responsibilities:</b></td>
<td><p>The SGr Transport Service supports the following communication technologies to provide the following transport services:</p>
<td><p>The SGr Transport Service supports the following communication technologies to provide the following transport services:</p>
<ul>
<li>Modbus, REST/JSON, Sunspec</li>
<li>Support is planned for: OCPP 2.0, IEC-61968-9, IEC-608070-5-104</li>
<li>Modbus, REST/JSON, Sunspec</li>
<li>Support is planned for: OCPP 2.0, IEC-61968-9, IEC-608070-5-104</li>
</ul>
</td>
</tr>
Expand All @@ -174,7 +174,7 @@ Rem: The folder [your-local-project-folder]/SampleCommunicator/src/main/resource
<p>für MQTT: <a href="https://github.com/SmartGridready/SGrJavaDrivers/tree/master/HiveMq">SmartgridReady/SGrJavaDrivers/HiveMq</a></p>
</td>
</tr>
</table>
</table>

### Component: External Interface (EI)

Expand Down Expand Up @@ -263,7 +263,6 @@ If you are happy owner of a WAGO Smart-Meter you can read the read values from t

You find the sample code on [github](SampleCommunicator/src/main/java/com/smartgridready/communicator/example/WagoSmartMeterCommunicator.java)


## Further information / contact information

Webssite: [https://smartgridready.ch/](https://smartgridready.ch/)
Expand Down
56 changes: 47 additions & 9 deletions SampleCommunicator/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@ repositories {
mavenCentral()

maven {
url "https://nexus.library.smartgridready.ch/repository/maven-releases/"
url = "https://nexus.library.smartgridready.ch/repository/maven-releases/"
mavenContent {
releasesOnly()
}
}
maven {
url "https://nexus.library.smartgridready.ch/repository/maven-snapshots/"
url = "https://nexus.library.smartgridready.ch/repository/maven-snapshots/"
mavenContent {
snapshotsOnly()
}
Expand All @@ -43,27 +43,65 @@ java {
dependencies {

// SGr dependencies
implementation group: 'com.smartgridready', name: 'sgr-commhandler', version: '2.4.1'
implementation group: 'com.smartgridready', name: 'sgr-commhandler', version: '2.4.2'
runtimeOnly group: 'com.smartgridready', name: 'sgr-driver-j2mod', version: '1.0.0'
runtimeOnly group: 'com.smartgridready', name: 'sgr-driver-apachehttp', version: '2.1.1'
runtimeOnly group: 'com.smartgridready', name: 'sgr-driver-hivemq', version: '2.0.1'

// Logging
implementation group: 'org.slf4j', name: 'slf4j-api', version: '2.0.10'
implementation group: 'org.slf4j', name: 'slf4j-api', version: '2.0.17'
implementation group: 'org.apache.logging.log4j', name: 'log4j-core', version: '2.19.0'
implementation group: 'org.apache.logging.log4j', name: 'log4j-slf4j2-impl', version: '2.19.0'

// Use JUnit test framework
implementation group: 'org.junit.jupiter', name: 'junit-jupiter-api', version: '5.10.2'
runtimeOnly group: 'org.junit.jupiter', name: 'junit-jupiter-engine', version: '5.10.2'
implementation 'org.junit.jupiter:junit-jupiter:5.13.4'
runtimeOnly 'org.junit.platform:junit-platform-launcher'

implementation group: 'org.mockito', name: 'mockito-core', version: '5.12.0'
implementation group: 'org.mockito', name: 'mockito-junit-jupiter', version: '5.12.0'
implementation group: 'org.mockito', name: 'mockito-core', version: '5.18.0'
implementation group: 'org.mockito', name: 'mockito-junit-jupiter', version: '5.18.0'
implementation group: 'org.mockito', name: 'mockito-inline', version: '5.2.0'

implementation group: 'org.awaitility', name: 'awaitility', version: '4.2.0'
implementation group: 'org.awaitility', name: 'awaitility', version: '4.2.2'
}

test {
useJUnitPlatform() // needed to run JUnit 5 test with gradle
}

// can run the examples from project root

tasks.register("runBasicSampleCommunicator", JavaExec) {
group = ApplicationPlugin.APPLICATION_GROUP
classpath = sourceSets.main.runtimeClasspath
mainClass = 'com.smartgridready.communicator.example.BasicSampleCommunicator'
}

tasks.register("runBasicSampleCommunicatorClassic", JavaExec) {
group = ApplicationPlugin.APPLICATION_GROUP
classpath = sourceSets.main.runtimeClasspath
mainClass = 'com.smartgridready.communicator.example.BasicSampleCommunicatorClassic'
}

tasks.register("runEnumAndBitmapSampleCommunicator", JavaExec) {
group = ApplicationPlugin.APPLICATION_GROUP
classpath = sourceSets.main.runtimeClasspath
mainClass = 'com.smartgridready.communicator.example.EnumAndBitmapSampleCommunicator'
}

tasks.register("runMqttSampleCommunicator", JavaExec) {
group = ApplicationPlugin.APPLICATION_GROUP
classpath = sourceSets.main.runtimeClasspath
mainClass = 'com.smartgridready.communicator.example.MqttSampleCommunicator'
}

tasks.register("runRestSampleCommunicator", JavaExec) {
group = ApplicationPlugin.APPLICATION_GROUP
classpath = sourceSets.main.runtimeClasspath
mainClass = 'com.smartgridready.communicator.example.RestSampleCommunicator'
}

tasks.register("runWagoSmartMeterCommunicator", JavaExec) {
group = ApplicationPlugin.APPLICATION_GROUP
classpath = sourceSets.main.runtimeClasspath
mainClass = 'com.smartgridready.communicator.example.WagoSmartMeterCommunicator'
}
Binary file modified SampleCommunicator/gradle/wrapper/gradle-wrapper.jar
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
Expand Down
9 changes: 4 additions & 5 deletions SampleCommunicator/gradlew
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,7 @@ done
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s
' "$PWD" ) || exit
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit

# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
Expand Down Expand Up @@ -115,7 +114,7 @@ case "$( uname )" in #(
NONSTOP* ) nonstop=true ;;
esac

CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
CLASSPATH="\\\"\\\""


# Determine the Java command to use to start the JVM.
Expand Down Expand Up @@ -206,15 +205,15 @@ fi
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'

# Collect all arguments for the java command:
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
# and any embedded shellness will be escaped.
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
# treated as '${Hostname}' itself on the command line.

set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \
org.gradle.wrapper.GradleWrapperMain \
-jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \
"$@"

# Stop when "xargs" is not available.
Expand Down
4 changes: 2 additions & 2 deletions SampleCommunicator/gradlew.bat
Original file line number Diff line number Diff line change
Expand Up @@ -70,11 +70,11 @@ goto fail
:execute
@rem Setup the command line

set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
set CLASSPATH=


@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*

:end
@rem End local scope for the variables with windows NT shell
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,9 +116,9 @@ private void doBuildAndRunDatastructureTest() {
//
// Just define the return type of getVal() (Value), the functional-profile name, the data point name and the getter method of the
// commhandler API to be called. When ReadExec is executed it will call the callable and save the result within an AsyncResult member.
ReadExec<Value> wagoVoltageACL1 = new ReadExec<>("VoltageAC", "VoltageL1", wagoModbusDevice::getVal);
ReadExec<Value> wagoVoltageACL2 = new ReadExec<>("VoltageAC", "VoltageL2", wagoModbusDevice::getVal);
ReadExec<Value> wagoVoltageACL3 = new ReadExec<>("VoltageAC", "VoltageL3", wagoModbusDevice::getVal);
ReadExec<Value> wagoVoltageACL1 = new ReadExec<>("VoltageAC", "VoltageACL1_N", wagoModbusDevice::getVal);
ReadExec<Value> wagoVoltageACL2 = new ReadExec<>("VoltageAC", "VoltageACL2_N", wagoModbusDevice::getVal);
ReadExec<Value> wagoVoltageACL3 = new ReadExec<>("VoltageAC", "VoltageACL3_N", wagoModbusDevice::getVal);
ReadExec<Value> clemapActPowerACtot1 = new ReadExec<>("ActivePowerAC", "ActivePowerACtot", clemapRestApiDevice1::getVal);
ReadExec<Value> clemapActPowerACtot2 = new ReadExec<>("ActivePowerAC", "ActivePowerACtot", clemapRestApiDevice2::getVal);

Expand All @@ -128,7 +128,7 @@ private void doBuildAndRunDatastructureTest() {
WriteExec<Value> garoWallboxBHemsCurrLim = new WriteExec<>("Curtailment", "HemsCurrentLimit", garoModbusDeviceB::setVal);

// 3. Wire the tasks to define which tasks can be executed in parallel and which ones must be executed in sequence
// (example: The executables access the same device via modbus and therefore cannot be executed in parallel).
// (example: The executables access the same device via Modbus and therefore cannot be executed in parallel).
// Do create a new Parallel() or a new Sequence() and add ReadExec and WriteExec instances to them.
// To achieve this, you can create either a new 'Parallel()' or 'Sequence()' processing chain and add 'ReadExec'
// and 'WriteExec' instances to them as needed. Additionally, you have the flexibility to nest 'Parallel()' and 'Sequence()'
Expand Down
Loading