2 * Copyright (c) 2010-2022 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
7 * This program and the accompanying materials are made available under the
8 * terms of the Eclipse Public License 2.0 which is available at
9 * http://www.eclipse.org/legal/epl-2.0
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.fronius.internal.handler;
17 import org.openhab.binding.fronius.internal.FroniusBaseDeviceConfiguration;
18 import org.openhab.binding.fronius.internal.FroniusBindingConstants;
19 import org.openhab.binding.fronius.internal.FroniusBridgeConfiguration;
20 import org.openhab.binding.fronius.internal.FroniusCommunicationException;
21 import org.openhab.binding.fronius.internal.api.InverterRealtimeResponse;
22 import org.openhab.binding.fronius.internal.api.PowerFlowRealtimeInverter;
23 import org.openhab.binding.fronius.internal.api.PowerFlowRealtimeResponse;
24 import org.openhab.binding.fronius.internal.api.ValueUnit;
25 import org.openhab.core.library.types.QuantityType;
26 import org.openhab.core.library.unit.Units;
27 import org.openhab.core.thing.Thing;
28 import org.slf4j.Logger;
29 import org.slf4j.LoggerFactory;
32 * The {@link FroniusSymoInverterHandler} is responsible for updating the data, which are
33 * sent to one of the channels.
35 * @author Thomas Rokohl - Initial contribution
36 * @author Peter Schraffl - Added device status and error status channels
37 * @author Thomas Kordelle - Added inverter power, battery state of charge and PV solar yield
39 public class FroniusSymoInverterHandler extends FroniusBaseThingHandler {
41 /* power produced/handled by the inverter. */
42 public static final String INVERTER_POWER = "power";
43 /* state of charge of the battery or other storage device */
44 public static final String INVERTER_SOC = "soc";
46 private final Logger logger = LoggerFactory.getLogger(FroniusSymoInverterHandler.class);
47 private InverterRealtimeResponse inverterRealtimeResponse;
48 private PowerFlowRealtimeResponse powerFlowResponse;
49 private FroniusBaseDeviceConfiguration config;
51 public FroniusSymoInverterHandler(Thing thing) {
56 protected String getDescription() {
57 return "Fronius Symo Inverter";
61 protected void handleRefresh(FroniusBridgeConfiguration bridgeConfiguration) throws FroniusCommunicationException {
62 updateData(bridgeConfiguration, config);
67 public void initialize() {
68 config = getConfigAs(FroniusBaseDeviceConfiguration.class);
73 * Update the channel from the last data retrieved
75 * @param channelId the id identifying the channel to be updated
76 * @return the last retrieved data
79 protected Object getValue(String channelId) {
80 final String[] fields = channelId.split("#");
81 if (fields.length < 1) {
84 final String fieldName = fields[0];
86 if (inverterRealtimeResponse != null) {
88 case FroniusBindingConstants.INVERTER_DATA_CHANNEL_DAY_ENERGY:
89 ValueUnit day = inverterRealtimeResponse.getBody().getData().getDayEnergy();
94 case FroniusBindingConstants.INVERTER_DATA_CHANNEL_PAC:
95 ValueUnit pac = inverterRealtimeResponse.getBody().getData().getPac();
97 pac = new ValueUnit();
101 case FroniusBindingConstants.INVERTER_DATA_CHANNEL_TOTAL:
102 ValueUnit total = inverterRealtimeResponse.getBody().getData().getTotalEnergy();
104 total.setUnit("MWh");
107 case FroniusBindingConstants.INVERTER_DATA_CHANNEL_YEAR:
108 ValueUnit year = inverterRealtimeResponse.getBody().getData().getYearEnergy();
113 case FroniusBindingConstants.INVERTER_DATA_CHANNEL_FAC:
114 return inverterRealtimeResponse.getBody().getData().getFac();
115 case FroniusBindingConstants.INVERTER_DATA_CHANNEL_IAC:
116 return inverterRealtimeResponse.getBody().getData().getIac();
117 case FroniusBindingConstants.INVERTER_DATA_CHANNEL_IDC:
118 return inverterRealtimeResponse.getBody().getData().getIdc();
119 case FroniusBindingConstants.INVERTER_DATA_CHANNEL_UAC:
120 return inverterRealtimeResponse.getBody().getData().getUac();
121 case FroniusBindingConstants.INVERTER_DATA_CHANNEL_UDC:
122 return inverterRealtimeResponse.getBody().getData().getUdc();
123 case FroniusBindingConstants.INVERTER_DATA_CHANNEL_DEVICE_STATUS_ERROR_CODE:
124 return inverterRealtimeResponse.getBody().getData().getDeviceStatus().getErrorCode();
125 case FroniusBindingConstants.INVERTER_DATA_CHANNEL_DEVICE_STATUS_STATUS_CODE:
126 return inverterRealtimeResponse.getBody().getData().getDeviceStatus().getStatusCode();
132 if (powerFlowResponse != null) {
134 case FroniusBindingConstants.POWER_FLOW_P_GRID:
135 return new QuantityType<>(powerFlowResponse.getBody().getData().getSite().getPgrid(), Units.WATT);
136 case FroniusBindingConstants.POWER_FLOW_P_LOAD:
137 return new QuantityType<>(powerFlowResponse.getBody().getData().getSite().getPload(), Units.WATT);
138 case FroniusBindingConstants.POWER_FLOW_P_AKKU:
139 return new QuantityType<>(powerFlowResponse.getBody().getData().getSite().getPakku(), Units.WATT);
140 case FroniusBindingConstants.POWER_FLOW_P_PV:
141 return new QuantityType<>(powerFlowResponse.getBody().getData().getSite().getPpv(), Units.WATT);
142 case FroniusBindingConstants.POWER_FLOW_INVERTER_1_POWER:
143 return getInverterFlowValue(INVERTER_POWER, "1");
144 case FroniusBindingConstants.POWER_FLOW_INVERTER_1_SOC:
145 return getInverterFlowValue(INVERTER_SOC, "1");
155 * get flow data for a specific inverter.
161 private Object getInverterFlowValue(final String fieldName, final String number) {
162 final Map<String, PowerFlowRealtimeInverter> inverters = powerFlowResponse.getBody().getData().getInverters();
163 if ((inverters == null) || (inverters.get(number) == null)) {
164 logger.debug("No data for inverter '{}' found.", number);
169 return new QuantityType<>(inverters.get(number).getP(), Units.WATT);
171 return new QuantityType<>(inverters.get(number).getSoc(), Units.PERCENT);
181 private void updateData(FroniusBridgeConfiguration bridgeConfiguration, FroniusBaseDeviceConfiguration config)
182 throws FroniusCommunicationException {
183 inverterRealtimeResponse = getRealtimeData(bridgeConfiguration.hostname, config.deviceId);
184 powerFlowResponse = getPowerFlowRealtime(bridgeConfiguration.hostname);
188 * Make the PowerFlowRealtimeDataRequest
190 * @param ip address of the device
191 * @return {PowerFlowRealtimeResponse} the object representation of the json response
193 private PowerFlowRealtimeResponse getPowerFlowRealtime(String ip) throws FroniusCommunicationException {
194 String location = FroniusBindingConstants.POWERFLOW_REALTIME_DATA.replace("%IP%",
195 (ip != null ? ip.trim() : ""));
196 return collectDataFromUrl(PowerFlowRealtimeResponse.class, location);
200 * Make the InverterRealtimeDataRequest
202 * @param ip address of the device
203 * @param deviceId of the device
204 * @return {InverterRealtimeResponse} the object representation of the json response
206 private InverterRealtimeResponse getRealtimeData(String ip, int deviceId) throws FroniusCommunicationException {
207 String location = FroniusBindingConstants.INVERTER_REALTIME_DATA_URL.replace("%IP%",
208 (ip != null ? ip.trim() : ""));
209 location = location.replace("%DEVICEID%", Integer.toString(deviceId));
210 return collectDataFromUrl(InverterRealtimeResponse.class, location);