]> git.basschouten.com Git - openhab-addons.git/blob
3483766077083d99d31dadf9515bfae2bf573ac7
[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                 return inverterRealtimeResponse.getBody().getData().getPac();
97             case FroniusBindingConstants.InverterDataChannelTotal:
98                 ValueUnit total = inverterRealtimeResponse.getBody().getData().getTotalEnergy();
99                 if (total != null) {
100                     total.setUnit("MWh");
101                 }
102                 return total;
103             case FroniusBindingConstants.InverterDataChannelYear:
104                 ValueUnit year = inverterRealtimeResponse.getBody().getData().getYearEnergy();
105                 if (year != null) {
106                     year.setUnit("MWh");
107                 }
108                 return year;
109             case FroniusBindingConstants.InverterDataChannelFac:
110                 return inverterRealtimeResponse.getBody().getData().getFac();
111             case FroniusBindingConstants.InverterDataChannelIac:
112                 return inverterRealtimeResponse.getBody().getData().getIac();
113             case FroniusBindingConstants.InverterDataChannelIdc:
114                 return inverterRealtimeResponse.getBody().getData().getIdc();
115             case FroniusBindingConstants.InverterDataChannelUac:
116                 return inverterRealtimeResponse.getBody().getData().getUac();
117             case FroniusBindingConstants.InverterDataChannelUdc:
118                 return inverterRealtimeResponse.getBody().getData().getUdc();
119             case FroniusBindingConstants.InverterDataChannelDeviceStatusErrorCode:
120                 return inverterRealtimeResponse.getBody().getData().getDeviceStatus().getErrorCode();
121             case FroniusBindingConstants.InverterDataChannelDeviceStatusStatusCode:
122                 return inverterRealtimeResponse.getBody().getData().getDeviceStatus().getStatusCode();
123         }
124         if (powerFlowResponse == null) {
125             return null;
126         }
127         switch (fieldName) {
128             case FroniusBindingConstants.PowerFlowpGrid:
129                 return powerFlowResponse.getBody().getData().getSite().getPgrid();
130             case FroniusBindingConstants.PowerFlowpLoad:
131                 return powerFlowResponse.getBody().getData().getSite().getPload();
132             case FroniusBindingConstants.PowerFlowpAkku:
133                 return powerFlowResponse.getBody().getData().getSite().getPakku();
134         }
135
136         return null;
137     }
138
139     /**
140      * Get new data
141      */
142     private void updateData(FroniusBridgeConfiguration bridgeConfiguration, FroniusBaseDeviceConfiguration config) {
143         inverterRealtimeResponse = getRealtimeData(bridgeConfiguration.hostname, config.deviceId);
144         powerFlowResponse = getPowerFlowRealtime(bridgeConfiguration.hostname);
145     }
146
147     /**
148      *
149      * @param type response class type
150      * @param url to request
151      * @return the object representation of the json response
152      */
153     private <T extends BaseFroniusResponse> T collectDataFormUrl(Class<T> type, String url) {
154         T result = null;
155         boolean resultOk = false;
156         String errorMsg = null;
157
158         try {
159             logger.debug("URL = {}", url);
160             String response = HttpUtil.executeUrl("GET", url, API_TIMEOUT);
161
162             if (response != null) {
163                 logger.debug("aqiResponse = {}", response);
164                 result = gson.fromJson(response, type);
165             }
166
167             if (result == null) {
168                 errorMsg = "no data returned";
169             } else {
170                 if (result.getHead().getStatus().getCode() == 0) {
171                     resultOk = true;
172                 } else {
173                     errorMsg = result.getHead().getStatus().getReason();
174                 }
175             }
176             if (!resultOk) {
177                 logger.debug("Error in fronius response: {}", errorMsg);
178             }
179         } catch (JsonSyntaxException e) {
180             errorMsg = "Configuration is incorrect";
181             logger.debug("Error running fronius request: {}", errorMsg);
182         } catch (IOException | IllegalStateException e) {
183             logger.debug("Error running fronius request: {}", e.getMessage());
184         }
185
186         // Update the thing status
187         if (resultOk) {
188             updateStatus(ThingStatus.ONLINE);
189         } else {
190             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR, errorMsg);
191         }
192         return resultOk ? result : null;
193     }
194
195     /**
196      * Make the PowerFlowRealtimeDataRequest
197      *
198      * @param ip address of the device
199      * @return {PowerFlowRealtimeResponse} the object representation of the json response
200      */
201     private PowerFlowRealtimeResponse getPowerFlowRealtime(String ip) {
202         String location = FroniusBindingConstants.POWERFLOW_REALTIME_DATA.replace("%IP%", StringUtils.trimToEmpty(ip));
203         return collectDataFormUrl(PowerFlowRealtimeResponse.class, location);
204     }
205
206     /**
207      * Make the InverterRealtimeDataRequest
208      *
209      * @param ip address of the device
210      * @param deviceId of the device
211      * @return {InverterRealtimeResponse} the object representation of the json response
212      */
213     private InverterRealtimeResponse getRealtimeData(String ip, int deviceId) {
214         String location = FroniusBindingConstants.INVERTER_REALTIME_DATA_URL.replace("%IP%",
215                 StringUtils.trimToEmpty(ip));
216         location = location.replace("%DEVICEID%", Integer.toString(deviceId));
217         return collectDataFormUrl(InverterRealtimeResponse.class, location);
218     }
219 }