Skip to content

Commit c33a6c2

Browse files
authored
FEMS/OpenEMS: add modbus (#24586)
1 parent 98850e5 commit c33a6c2

File tree

3 files changed

+261
-5
lines changed

3 files changed

+261
-5
lines changed
Lines changed: 234 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,234 @@
1+
template: openems-modbus
2+
products:
3+
- brand: OpenEMS
4+
description:
5+
generic: Modbus-API
6+
- brand: FENECON
7+
description:
8+
generic: Modbus-API
9+
capabilities: ["battery-control"]
10+
requirements:
11+
description:
12+
de: |
13+
##### Lizenzhinweis:
14+
Für FENECON FEMS Systeme ist für die aktive Batteriesteuerung eine kommerzielle Lizenz *FEMS App Modbus/TCP Schreibzugriff* erforderlich.<br/><br/>
15+
##### FEMS-Dokumentation:
16+
- [FEMS App Modbus/TCP – Lesezugriff](https://docs.fenecon.de/de/fems/fems-app/App_ModbusTCP_Lesezugriff.html)
17+
- [FEMS App Modbus/TCP – Schreibzugriff](https://docs.fenecon.de/de/fems/fems-app/App_ModbusTCP_Schreibzugriff.html)
18+
##### OpenEMS-Dokumentation:
19+
- [OpenEMS Edge Api Modbus Controller](https://openems.github.io/openems.io/openems/latest/edge/controller.html#_api_modbus)
20+
en: |
21+
##### License notice:
22+
For active battery control on FENECON FEMS systems, a commercial license (*FEMS App Modbus/TCP Write Access*) is required.<br/><br/>
23+
##### FEMS documentation:
24+
- [FEMS App Modbus/TCP — Read Access](https://docs.fenecon.de/en/fems/fems-app/App_ModbusTCP_Lesezugriff.html)
25+
- [FEMS App Modbus/TCP — Write Access](https://docs.fenecon.de/en/fems/fems-app/App_ModbusTCP_Schreibzugriff.html)
26+
##### OpenEMS documentation:
27+
- [OpenEMS Edge Api Modbus Controller](https://openems.github.io/openems.io/openems/latest/edge/controller.html#_api_modbus)
28+
params:
29+
- name: usage
30+
choice: ["grid", "pv", "battery"]
31+
allinone: true
32+
- name: modbus
33+
choice: ["tcpip"]
34+
default: "tcpip"
35+
- name: grid_power_register
36+
type: int
37+
default: 315
38+
description:
39+
de: Modbus-Register für Netzleistung
40+
en: Modbus register for grid power
41+
help:
42+
generic: GridActivePower (W)
43+
usages: ["grid"]
44+
advanced: true
45+
- name: grid_energy_register
46+
type: int
47+
default: 359
48+
description:
49+
de: Modbus-Register für Netzbezug Energie
50+
en: Modbus register for grid import energy
51+
help:
52+
generic: GridBuyActiveEnergy (Wh)
53+
usages: ["grid"]
54+
advanced: true
55+
- name: pv_power_register
56+
type: int
57+
default: 327
58+
description:
59+
de: Modbus-Register für PV-Leistung
60+
en: Modbus register for PV power
61+
help:
62+
generic: ProductionActivePower (W)
63+
usages: ["pv"]
64+
advanced: true
65+
- name: pv_energy_register
66+
type: int
67+
default: 367
68+
description:
69+
de: Modbus-Register für PV-Energie
70+
en: Modbus register for PV energy
71+
help:
72+
generic: ProductionActiveEnergy (Wh)
73+
usages: ["pv"]
74+
advanced: true
75+
- name: battery_power_register
76+
type: int
77+
default: 415
78+
description:
79+
de: Modbus-Register für Batterie-Leistung
80+
en: Modbus register for battery power
81+
help:
82+
generic: EssDischargePower (W)
83+
usages: ["battery"]
84+
advanced: true
85+
- name: battery_soc_register
86+
type: int
87+
default: 302
88+
description:
89+
de: Modbus-Register für Batteriestand
90+
en: Modbus register for state of charge
91+
help:
92+
generic: SoC (%)
93+
usages: ["battery"]
94+
advanced: true
95+
- name: battery_set_register
96+
type: int
97+
default: 710
98+
description:
99+
de: Modbus-Register für Ladeleistung
100+
en: Modbus register for charge power
101+
help:
102+
generic: SetActivePowerLessOrEquals (W)
103+
usages: ["battery"]
104+
advanced: true
105+
- name: battery
106+
type: bool
107+
default: false
108+
description:
109+
de: steuert Batterie Komponente
110+
en: controls battery component
111+
help:
112+
de: aktive Batteriesteuerung (Modbus/TCP schreibend)
113+
en: active battery control (Modbus/TCP Write Access)
114+
usages: ["battery"]
115+
- name: watchdog
116+
type: duration
117+
default: 60s
118+
description:
119+
de: FEMS/OpenEMS Batteriesteuerung API-Timeout
120+
en: FEMS/OpenEMS battery control API timeout
121+
help:
122+
de: FEMS/OpenEMS Standard 60s
123+
en: FEMS/OpenEMS standard 60s
124+
usages: ["battery"]
125+
advanced: true
126+
- name: minsoc
127+
advanced: true
128+
- name: maxsoc
129+
advanced: true
130+
- name: capacity
131+
advanced: true
132+
- name: maxchargepower
133+
- name: maxdischargepower
134+
- name: maxacpower
135+
render: |
136+
type: custom
137+
{{- if eq .usage "grid" }}
138+
power:
139+
source: modbus
140+
{{- include "modbus" . | indent 2 }}
141+
register:
142+
address: {{ .grid_power_register }} # GridActivePower (W)
143+
type: input
144+
encoding: float32
145+
energy:
146+
source: modbus
147+
{{- include "modbus" . | indent 2 }}
148+
register:
149+
address: {{ .grid_energy_register }} # GridBuyActiveEnergy (Wh)
150+
type: holding
151+
encoding: float64
152+
scale: 0.001 # Wh -> kWh
153+
{{- end }}
154+
{{- if eq .usage "pv" }}
155+
power:
156+
source: modbus
157+
{{- include "modbus" . | indent 2 }}
158+
register:
159+
address: {{ .pv_power_register }} # ProductionActivePower (W)
160+
type: input
161+
encoding: float32
162+
energy:
163+
source: modbus
164+
{{- include "modbus" . | indent 2 }}
165+
register:
166+
address: {{ .pv_energy_register }} # ProductionActiveEnergy (Wh)
167+
type: holding
168+
encoding: float64
169+
scale: 0.001 # Wh -> kWh
170+
maxacpower: {{ .maxacpower }} # W
171+
{{- end }}
172+
{{- if eq .usage "battery" }}
173+
power:
174+
source: modbus
175+
{{- include "modbus" . | indent 2 }}
176+
register:
177+
address: {{ .battery_power_register }} # EssDischargePower (W)
178+
type: input
179+
encoding: float32
180+
soc:
181+
source: modbus
182+
{{- include "modbus" . | indent 2 }}
183+
register:
184+
address: {{ .battery_soc_register }} # EssSoc (%)
185+
type: input
186+
encoding: uint16
187+
{{- if .battery }}
188+
batterymode:
189+
source: watchdog
190+
timeout: {{ .watchdog }} # re-write at timeout/2
191+
reset: 1
192+
set:
193+
source: switch
194+
switch:
195+
- case: 1 # normal
196+
set:
197+
source: const
198+
value: 0
199+
set:
200+
source: modbus
201+
{{- include "modbus" . | indent 10 }}
202+
register:
203+
address: {{ .battery_set_register }} # SetActivePowerLessOrEquals (W)
204+
type: writemultiple
205+
encoding: float32
206+
- case: 2 # hold
207+
set:
208+
source: const
209+
value: 0
210+
set:
211+
source: modbus
212+
{{- include "modbus" . | indent 10 }}
213+
register:
214+
address: {{ .battery_set_register }}
215+
type: writemultiple
216+
encoding: float32
217+
- case: 3 # charge
218+
set:
219+
source: const
220+
value: {{ mul .maxchargepower -1 }} # charge power is negative
221+
set:
222+
source: modbus
223+
{{- include "modbus" . | indent 10 }}
224+
register:
225+
address: {{ .battery_set_register }}
226+
type: writemultiple
227+
encoding: float32
228+
{{- end }}
229+
minsoc: {{ .minsoc }} # %
230+
maxsoc: {{ .maxsoc }} # %
231+
maxchargepower: {{ .maxchargepower }} # W
232+
maxdischargepower: {{ .maxdischargepower }} # W
233+
capacity: {{ .capacity }} # kWh
234+
{{- end }}

templates/definition/meter/openems.yaml

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,30 @@
11
template: openems
22
products:
33
- brand: OpenEMS
4+
description:
5+
generic: REST-API
46
- brand: FENECON
7+
description:
8+
generic: REST-API
59
capabilities: ["battery-control"]
610
requirements:
711
description:
812
de: |
9-
Für FEMS FENECON-Systeme ist eine kommerzielle Lizenz für die aktive Batteriesteuerung erforderlich (REST-API).
13+
##### Lizenzhinweis:
14+
Für FENECON FEMS Systeme ist für die aktive Batteriesteuerung eine kommerzielle Lizenz *FEMS App REST/JSON Schreibzugriff* erforderlich.<br/><br/>
15+
##### FEMS-Dokumentation:
16+
- [FEMS App REST/JSON Lesezugriff](https://docs.fenecon.de/de/fems/fems-app/App_REST-JSON_Lesezugriff.html)
17+
- [FEMS App REST/JSON Schreibzugriff](https://docs.fenecon.de/de/fems/fems-app/App_REST-JSON_Schreibzugriff.html)
18+
##### OpenEMS-Dokumentation:
19+
- [OpenEMS Edge REST-Api Controller](https://openems.github.io/openems.io/openems/latest/edge/controller.html#_rest_api_controller)
1020
en: |
11-
A commercial license is required for FEMS FENECON systems for active battery control (REST-API).
21+
##### License notice:
22+
For active battery control on FENECON FEMS systems, a commercial license (*FEMS App REST/JSON Write Access*) is required.<br/><br/>
23+
##### FEMS documentation:
24+
- [FEMS App REST/JSON Read Access](https://docs.fenecon.de/en/fems/fems-app/App_REST-JSON_Lesezugriff.html)
25+
- [FEMS App REST/JSON Write Access](https://docs.fenecon.de/en/fems/fems-app/App_REST-JSON_Schreibzugriff.html)
26+
##### OpenEMS documentation:
27+
- [OpenEMS Edge REST-Api Controller](https://openems.github.io/openems.io/openems/latest/edge/controller.html#_rest_api_controller)
1228
params:
1329
- name: usage
1430
choice: ["grid", "pv", "battery"]
@@ -23,14 +39,20 @@ params:
2339
description:
2440
de: Steuerbare Batterie Komponente
2541
en: Controllable battery component
42+
help:
43+
de: aktive Batteriesteuerung (REST/JSON schreibend)
44+
en: active battery control (REST/JSON Write Access)
2645
usages: ["battery"]
2746
advanced: true
2847
- name: watchdog
2948
type: duration
3049
default: 60s
50+
description:
51+
de: FEMS/OpenEMS Batteriesteuerung API-Timeout
52+
en: FEMS/OpenEMS battery control API timeout
3153
help:
32-
de: abgestimmt auf das API-Timeout
33-
en: adjusted to the API timeout
54+
de: FEMS/OpenEMS Standard 60s
55+
en: FEMS/OpenEMS standard 60s
3456
usages: ["battery"]
3557
advanced: true
3658
- name: minsoc

tests/config-grid.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ test.describe("grid meter", async () => {
4747
await page.getByTestId("add-grid").click();
4848

4949
const meterModal = page.getByTestId("meter-modal");
50-
await meterModal.getByLabel("Manufacturer").selectOption("OpenEMS");
50+
await meterModal.getByLabel("Manufacturer").selectOption("OpenEMS REST-API");
5151
await meterModal.getByLabel("IP address or hostname").fill(simulatorHost());
5252
await expect(meterModal.getByRole("button", { name: "Validate & save" })).toBeVisible();
5353
await meterModal.getByRole("link", { name: "validate" }).click();

0 commit comments

Comments
 (0)