]> git.basschouten.com Git - openhab-addons.git/blob
d5ea05953febe5483fb305e68170cbc3c28786cc
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2022 Contributors to the openHAB project
3  *
4  * See the NOTICE file(s) distributed with this work for additional
5  * information.
6  *
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
10  *
11  * SPDX-License-Identifier: EPL-2.0
12  */
13 package org.openhab.binding.fronius.internal.handler;
14
15 import java.util.Map;
16
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;
30
31 /**
32  * The {@link FroniusSymoInverterHandler} is responsible for updating the data, which are
33  * sent to one of the channels.
34  *
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
38  */
39 public class FroniusSymoInverterHandler extends FroniusBaseThingHandler {
40
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";
45
46     private final Logger logger = LoggerFactory.getLogger(FroniusSymoInverterHandler.class);
47     private InverterRealtimeResponse inverterRealtimeResponse;
48     private PowerFlowRealtimeResponse powerFlowResponse;
49     private FroniusBaseDeviceConfiguration config;
50
51     public FroniusSymoInverterHandler(Thing thing) {
52         super(thing);
53     }
54
55     @Override
56     protected String getDescription() {
57         return "Fronius Symo Inverter";
58     }
59
60     @Override
61     protected void handleRefresh(FroniusBridgeConfiguration bridgeConfiguration) throws FroniusCommunicationException {
62         updateData(bridgeConfiguration, config);
63         updateChannels();
64     }
65
66     @Override
67     public void initialize() {
68         config = getConfigAs(FroniusBaseDeviceConfiguration.class);
69         super.initialize();
70     }
71
72     /**
73      * Update the channel from the last data retrieved
74      *
75      * @param channelId the id identifying the channel to be updated
76      * @return the last retrieved data
77      */
78     @Override
79     protected Object getValue(String channelId) {
80         final String[] fields = channelId.split("#");
81         if (fields.length < 1) {
82             return null;
83         }
84         final String fieldName = fields[0];
85
86         if (inverterRealtimeResponse != null) {
87             switch (fieldName) {
88                 case FroniusBindingConstants.INVERTER_DATA_CHANNEL_DAY_ENERGY:
89                     ValueUnit day = inverterRealtimeResponse.getBody().getData().getDayEnergy();
90                     if (day != null) {
91                         day.setUnit("kWh");
92                     }
93                     return day;
94                 case FroniusBindingConstants.INVERTER_DATA_CHANNEL_PAC:
95                     ValueUnit pac = inverterRealtimeResponse.getBody().getData().getPac();
96                     if (pac == null) {
97                         pac = new ValueUnit();
98                         pac.setValue(0);
99                     }
100                     return pac;
101                 case FroniusBindingConstants.INVERTER_DATA_CHANNEL_TOTAL:
102                     ValueUnit total = inverterRealtimeResponse.getBody().getData().getTotalEnergy();
103                     if (total != null) {
104                         total.setUnit("MWh");
105                     }
106                     return total;
107                 case FroniusBindingConstants.INVERTER_DATA_CHANNEL_YEAR:
108                     ValueUnit year = inverterRealtimeResponse.getBody().getData().getYearEnergy();
109                     if (year != null) {
110                         year.setUnit("MWh");
111                     }
112                     return year;
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();
127                 default:
128                     break;
129             }
130         }
131
132         if (powerFlowResponse != null) {
133             switch (fieldName) {
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");
146                 default:
147                     break;
148             }
149         }
150
151         return null;
152     }
153
154     /**
155      * get flow data for a specific inverter.
156      *
157      * @param fieldName
158      * @param number
159      * @return
160      */
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);
165             return null;
166         }
167         switch (fieldName) {
168             case INVERTER_POWER:
169                 return new QuantityType<>(inverters.get(number).getP(), Units.WATT);
170             case INVERTER_SOC:
171                 return new QuantityType<>(inverters.get(number).getSoc(), Units.PERCENT);
172             default:
173                 break;
174         }
175         return null;
176     }
177
178     /**
179      * Get new data
180      */
181     private void updateData(FroniusBridgeConfiguration bridgeConfiguration, FroniusBaseDeviceConfiguration config)
182             throws FroniusCommunicationException {
183         inverterRealtimeResponse = getRealtimeData(bridgeConfiguration.hostname, config.deviceId);
184         powerFlowResponse = getPowerFlowRealtime(bridgeConfiguration.hostname);
185     }
186
187     /**
188      * Make the PowerFlowRealtimeDataRequest
189      *
190      * @param ip address of the device
191      * @return {PowerFlowRealtimeResponse} the object representation of the json response
192      */
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);
197     }
198
199     /**
200      * Make the InverterRealtimeDataRequest
201      *
202      * @param ip address of the device
203      * @param deviceId of the device
204      * @return {InverterRealtimeResponse} the object representation of the json response
205      */
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);
211     }
212 }