Frames and Data
Frames are used to send requests to the home power plant. The home power plant also responds in frames. Each frame consists of a series (at least one) of data blocks. The type of a block is determined by so-called tags.
Tags¶
Tags describe the type of a data block. They tell whether the contained value is a number or a text, and whether it is, for example, the current PV prodction or a load limit.
The tags I know are located as enum classes in the package de.jnkconsulting.e3dc.easyrscp.api.frame.tags
.
For each namespace defined by E3DC there is a separate enum class.
What exactly the namespaces mean is described in the RSCP section.
If a tag is needed, either as a request or as a response, which are not defined here in enum classes, an instance of UnknownTag
can be used.
The original byte value remains here and can be used accordingly.
Building frames¶
The easiest way to create frames is to use the FrameBuilder
and the DataBuilder
classes.
Know what you do
You must know what you are doing. Neither the FrameBuilder
nor the DataBuilder
check if the combination makes any sense!
Here is an example of how to put together a query frame that asks for some live data:
import de.jnkconsulting.e3dc.easyrscp.api.frame.tags.EMSTag
import de.jnkconsulting.e3dc.easyrscp.frame.DataBuilder
import de.jnkconsulting.e3dc.easyrscp.frame.FrameBuilder
import de.jnkconsulting.e3dc.easyrscp.service.converter.StringFrameConverter
fun main() {
val requestFrame = FrameBuilder()
.addData(
DataBuilder().tag(EMSTag.REQ_POWER_PV).build(),
DataBuilder().tag(EMSTag.REQ_POWER_BAT).build(),
DataBuilder().tag(EMSTag.REQ_POWER_GRID).build(),
DataBuilder().tag(EMSTag.REQ_POWER_HOME).build(),
DataBuilder().tag(EMSTag.REQ_BAT_SOC).build(),
).build()
println(StringFrameConverter().invoke(requestFrame))
}
import de.jnkconsulting.e3dc.easyrscp.api.frame.Frame;
import de.jnkconsulting.e3dc.easyrscp.api.frame.tags.EMSTag;
import de.jnkconsulting.e3dc.easyrscp.frame.DataBuilder;
import de.jnkconsulting.e3dc.easyrscp.frame.FrameBuilder;
import de.jnkconsulting.e3dc.easyrscp.service.converter.StringFrameConverter;
public class FrameExamples {
public static void main(String[] args) {
Frame requestFrame = new FrameBuilder()
.addData(
new DataBuilder().tag(EMSTag.REQ_POWER_PV).build(),
new DataBuilder().tag(EMSTag.REQ_POWER_BAT).build(),
new DataBuilder().tag(EMSTag.REQ_POWER_GRID).build(),
new DataBuilder().tag(EMSTag.REQ_POWER_HOME).build(),
new DataBuilder().tag(EMSTag.REQ_BAT_SOC).build()
).build();
System.out.println(new StringFrameConverter().invoke(requestFrame));
}
}
import {FrameBuilder, DataBuilder, StringFrameConverter, EMSTag} from 'easy-rscp';
const request = new FrameBuilder()
.addData(
new DataBuilder().tag(EMSTag.REQ_POWER_PV).build(),
new DataBuilder().tag(EMSTag.REQ_POWER_BAT).build(),
new DataBuilder().tag(EMSTag.REQ_POWER_GRID).build(),
new DataBuilder().tag(EMSTag.REQ_POWER_HOME).build(),
new DataBuilder().tag(EMSTag.REQ_BAT_SOC).build()
).build();
console.log(new StringFrameConverter().convert(requestFrame));
The output should look something like this:
Timestamp: 2023-09-19T20:32:43.305569Z
WithChecksum: true
Tag: EMS.REQ_POWER_PV - 01000001
Type: NONE - 00
Value: [NONE] -
Tag: EMS.REQ_POWER_BAT - 01000002
Type: NONE - 00
Value: [NONE] -
Tag: EMS.REQ_POWER_GRID - 01000004
Type: NONE - 00
Value: [NONE] -
Tag: EMS.REQ_POWER_HOME - 01000003
Type: NONE - 00
Value: [NONE] -
Tag: EMS.REQ_BAT_SOC - 01000008
Type: NONE - 00
Value: [NONE] -
Reading frames¶
Reading data from a frame can be complex. Theoretically, a frame can contain data blocks of type container
. So, blocks that contain other blocks.
To make it as comfortable as possible to access the individual values, the frame class provides various functions to access the contents in any depth.
For this purpose different xxxByTag
functions are available. The functions search for a specific data block with the given tag. There is an additional vararg parameter,
which maps the path through possibly existing containers.
Here is an example to read the house consumption of a certain day. For this, a request was made to the home power plant database. In response, a frame with a nested structure is provided. The searched value is in the following structure:
DBTag.HISTORY_DATA_DAY
and DBTag.SUM_CONTAINER
are data blocks of type container
. DBTag.CONSUMPTION
contains a float value indicating the total house consumption of the day.
This value can be accessed as follows:
The various xxxByTag
usually always return a value. If the corresponding tag is not found, a default value is returned (For numeric values 0, for string "" etc.).
The xxxByTag
methods have their limit when a container contains several data blocks of the same type. This happens quite rarely (in database queries for example). But if it does, then you have to access manually according to the content.