]> git.basschouten.com Git - openhab-addons.git/blob
0590b21d6bd6f34f344f785f419d049d37bea49a
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2020 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.io.IOException;
16
17 import org.apache.commons.lang.StringUtils;
18 import org.openhab.binding.fronius.internal.FroniusBaseDeviceConfiguration;
19 import org.openhab.binding.fronius.internal.FroniusBindingConstants;
20 import org.openhab.binding.fronius.internal.FroniusBridgeConfiguration;
21 import org.openhab.binding.fronius.internal.api.BaseFroniusResponse;
22 import org.openhab.binding.fronius.internal.api.InverterRealtimeResponse;
23 import org.openhab.binding.fronius.internal.api.PowerFlowRealtimeResponse;
24 import org.openhab.binding.fronius.internal.api.ValueUnit;
25 import org.openhab.core.io.net.http.HttpUtil;
26 import org.openhab.core.thing.Thing;
27 import org.openhab.core.thing.ThingStatus;
28 import org.openhab.core.thing.ThingStatusDetail;
29 import org.slf4j.Logger;
30 import org.slf4j.LoggerFactory;
31
32 import com.google.gson.Gson;
33 import com.google.gson.JsonSyntaxException;
34
35 /**
36  * The {@link FroniusSymoInverterHandler} is responsible for updating the data, which are
37  * sent to one of the channels.
38  *
39  * @author Thomas Rokohl - Initial contribution
40  * @author Peter Schraffl - Added device status and error status channels
41  */
42 public class FroniusSymoInverterHandler extends FroniusBaseThingHandler {
43
44     private static final int API_TIMEOUT = 5000;
45     private final Logger logger = LoggerFactory.getLogger(FroniusSymoInverterHandler.class);
46     private InverterRealtimeResponse inverterRealtimeResponse;
47     private PowerFlowRealtimeResponse powerFlowResponse;
48     private FroniusBaseDeviceConfiguration config;
49     private final Gson gson;
50
51     public FroniusSymoInverterHandler(Thing thing) {
52         super(thing);
53         gson = new Gson();
54     }
55
56     @Override
57     protected String getDescription() {
58         return "Fronius Symo Inverter";
59     }
60
61     @Override
62     public void refresh(FroniusBridgeConfiguration bridgeConfiguration) {
63         updateData(bridgeConfiguration, config);
64         updateChannels();
65     }
66
67     @Override
68     public void initialize() {
69         config = getConfigAs(FroniusBaseDeviceConfiguration.class);
70         super.initialize();
71     }
72
73     /**
74      * Update the channel from the last data retrieved
75      *
76      * @param channelId the id identifying the channel to be updated
77      * @return the last retrieved data
78      */
79     @Override
80     protected Object getValue(String channelId) {
81         String[] fields = StringUtils.split(channelId, "#");
82
83         String fieldName = fields[0];
84
85         if (inverterRealtimeResponse == null) {
86             return null;
87         }
88         switch (fieldName) {
89             case FroniusBindingConstants.InverterDataChannelDayEnergy:
90                 ValueUnit day = inverterRealtimeResponse.getBody().getData().getDayEnergy();
91                 if (day != null) {
92                     day.setUnit("kWh");
93                 }
94                 return day;
95             case FroniusBindingConstants.InverterDataChannelPac:
96                 ValueUnit pac = inverterRealtimeResponse.getBody().getData().getPac();
97                 if (pac == null) {
98                     pac = new ValueUnit();
99                     pac.setValue(0);
100                 }
101                 return pac;
102             case FroniusBindingConstants.InverterDataChannelTotal:
103                 ValueUnit total = inverterRealtimeResponse.getBody().getData().getTotalEnergy();
104                 if (total != null) {
105                     total.setUnit("MWh");
106                 }
107                 return total;
108             case FroniusBindingConstants.InverterDataChannelYear:
109                 ValueUnit year = inverterRealtimeResponse.getBody().getData().getYearEnergy();
110                 if (year != null) {
111                     year.setUnit("MWh");
112                 }
113                 return year;
114             case FroniusBindingConstants.InverterDataChannelFac:
115                 return inverterRealtimeResponse.getBody().getData().getFac();
116             case FroniusBindingConstants.InverterDataChannelIac:
117                 return inverterRealtimeResponse.getBody().getData().getIac();
118             case FroniusBindingConstants.InverterDataChannelIdc:
119                 return inverterRealtimeResponse.getBody().getData().getIdc();
120             case FroniusBindingConstants.InverterDataChannelUac:
121                 return inverterRealtimeResponse.getBody().getData().getUac();
122             case FroniusBindingConstants.InverterDataChannelUdc:
123                 return inverterRealtimeResponse.getBody().getData().getUdc();
124             case FroniusBindingConstants.InverterDataChannelDeviceStatusErrorCode:
125                 return inverterRealtimeResponse.getBody().getData().getDeviceStatus().getErrorCode();
126             case FroniusBindingConstants.InverterDataChannelDeviceStatusStatusCode:
127                 return inverterRealtimeResponse.getBody().getData().getDeviceStatus().getStatusCode();
128         }
129         if (powerFlowResponse == null) {
130             return null;
131         }
132         switch (fieldName) {
133             case FroniusBindingConstants.PowerFlowpGrid:
134                 return powerFlowResponse.getBody().getData().getSite().getPgrid();
135             case FroniusBindingConstants.PowerFlowpLoad:
136                 return powerFlowResponse.getBody().getData().getSite().getPload();
137             case FroniusBindingConstants.PowerFlowpAkku:
138                 return powerFlowResponse.getBody().getData().getSite().getPakku();
139         }
140
141         return null;
142     }
143
144     /**
145      * Get new data
146      */
147     private void updateData(FroniusBridgeConfiguration bridgeConfiguration, FroniusBaseDeviceConfiguration config) {
148         inverterRealtimeResponse = getRealtimeData(bridgeConfiguration.hostname, config.deviceId);
149         powerFlowResponse = getPowerFlowRealtime(bridgeConfiguration.hostname);
150     }
151
152     /**
153      *
154      * @param type response class type
155      * @param url to request
156      * @return the object representation of the json response
157      */
158     private <T extends BaseFroniusResponse> T collectDataFormUrl(Class<T> type, String url) {
159         T result = null;
160         boolean resultOk = false;
161         String errorMsg = null;
162
163         try {
164             logger.debug("URL = {}", url);
165             String response = HttpUtil.executeUrl("GET", url, API_TIMEOUT);
166
167             if (response != null) {
168                 logger.debug("aqiResponse = {}", response);
169                 result = gson.fromJson(response, type);
170             }
171
172             if (result == null) {
173                 errorMsg = "no data returned";
174             } else {
175                 if (result.getHead().getStatus().getCode() == 0) {
176                     resultOk = true;
177                 } else {
178                     errorMsg = result.getHead().getStatus().getReason();
179                 }
180             }
181             if (!resultOk) {
182                 logger.debug("Error in fronius response: {}", errorMsg);
183             }
184         } catch (JsonSyntaxException e) {
185             errorMsg = "Configuration is incorrect";
186             logger.debug("Error running fronius request: {}", errorMsg);
187         } catch (IOException | IllegalStateException e) {
188             logger.debug("Error running fronius request: {}", e.getMessage());
189         }
190
191         // Update the thing status
192         if (resultOk) {
193             updateStatus(ThingStatus.ONLINE);
194         } else {
195             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR, errorMsg);
196         }
197         return resultOk ? result : null;
198     }
199
200     /**
201      * Make the PowerFlowRealtimeDataRequest
202      *
203      * @param ip address of the device
204      * @return {PowerFlowRealtimeResponse} the object representation of the json response
205      */
206     private PowerFlowRealtimeResponse getPowerFlowRealtime(String ip) {
207         String location = FroniusBindingConstants.POWERFLOW_REALTIME_DATA.replace("%IP%", StringUtils.trimToEmpty(ip));
208         return collectDataFormUrl(PowerFlowRealtimeResponse.class, location);
209     }
210
211     /**
212      * Make the InverterRealtimeDataRequest
213      *
214      * @param ip address of the device
215      * @param deviceId of the device
216      * @return {InverterRealtimeResponse} the object representation of the json response
217      */
218     private InverterRealtimeResponse getRealtimeData(String ip, int deviceId) {
219         String location = FroniusBindingConstants.INVERTER_REALTIME_DATA_URL.replace("%IP%",
220                 StringUtils.trimToEmpty(ip));
221         location = location.replace("%DEVICEID%", Integer.toString(deviceId));
222         return collectDataFormUrl(InverterRealtimeResponse.class, location);
223     }
224 }