]> git.basschouten.com Git - openhab-addons.git/blob
1cada21e3cbf4218dc46cbb209d95f6dc3465dd2
[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.Optional;
16
17 import javax.measure.Unit;
18
19 import org.openhab.binding.fronius.internal.FroniusBaseDeviceConfiguration;
20 import org.openhab.binding.fronius.internal.FroniusBindingConstants;
21 import org.openhab.binding.fronius.internal.FroniusBridgeConfiguration;
22 import org.openhab.binding.fronius.internal.FroniusCommunicationException;
23 import org.openhab.binding.fronius.internal.api.InverterRealtimeBodyData;
24 import org.openhab.binding.fronius.internal.api.InverterRealtimeResponse;
25 import org.openhab.binding.fronius.internal.api.PowerFlowRealtimeInverter;
26 import org.openhab.binding.fronius.internal.api.PowerFlowRealtimeResponse;
27 import org.openhab.binding.fronius.internal.api.PowerFlowRealtimeSite;
28 import org.openhab.binding.fronius.internal.api.ValueUnit;
29 import org.openhab.core.library.types.DecimalType;
30 import org.openhab.core.library.types.QuantityType;
31 import org.openhab.core.library.unit.Units;
32 import org.openhab.core.thing.Thing;
33 import org.openhab.core.types.State;
34 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory;
36
37 /**
38  * The {@link FroniusSymoInverterHandler} is responsible for updating the data, which are
39  * sent to one of the channels.
40  *
41  * @author Thomas Rokohl - Initial contribution
42  * @author Peter Schraffl - Added device status and error status channels
43  * @author Thomas Kordelle - Added inverter power, battery state of charge and PV solar yield
44  * @author Jimmy Tanagra - Add powerflow autonomy, self consumption channels
45  */
46 public class FroniusSymoInverterHandler extends FroniusBaseThingHandler {
47
48     private final Logger logger = LoggerFactory.getLogger(FroniusSymoInverterHandler.class);
49     private InverterRealtimeResponse inverterRealtimeResponse;
50     private PowerFlowRealtimeResponse powerFlowResponse;
51     private FroniusBaseDeviceConfiguration config;
52
53     public FroniusSymoInverterHandler(Thing thing) {
54         super(thing);
55     }
56
57     @Override
58     protected String getDescription() {
59         return "Fronius Symo Inverter";
60     }
61
62     @Override
63     protected void handleRefresh(FroniusBridgeConfiguration bridgeConfiguration) throws FroniusCommunicationException {
64         updateData(bridgeConfiguration, config);
65         updateChannels();
66     }
67
68     @Override
69     public void initialize() {
70         config = getConfigAs(FroniusBaseDeviceConfiguration.class);
71         super.initialize();
72     }
73
74     /**
75      * Update the channel from the last data retrieved
76      *
77      * @param channelId the id identifying the channel to be updated
78      * @return the last retrieved data
79      */
80     @Override
81     protected State getValue(String channelId) {
82         final String[] fields = channelId.split("#");
83         if (fields.length < 1) {
84             return null;
85         }
86         final String fieldName = fields[0];
87
88         if (inverterRealtimeResponse != null) {
89             InverterRealtimeBodyData inverterData = inverterRealtimeResponse.getBody().getData();
90             switch (fieldName) {
91                 case FroniusBindingConstants.INVERTER_DATA_CHANNEL_PAC:
92                     return getQuantityOrZero(inverterData.getPac(), Units.WATT);
93                 case FroniusBindingConstants.INVERTER_DATA_CHANNEL_FAC:
94                     return getQuantityOrZero(inverterData.getFac(), Units.HERTZ);
95                 case FroniusBindingConstants.INVERTER_DATA_CHANNEL_IAC:
96                     return getQuantityOrZero(inverterData.getIac(), Units.AMPERE);
97                 case FroniusBindingConstants.INVERTER_DATA_CHANNEL_IDC:
98                     return getQuantityOrZero(inverterData.getIdc(), Units.AMPERE);
99                 case FroniusBindingConstants.INVERTER_DATA_CHANNEL_UAC:
100                     return getQuantityOrZero(inverterData.getUac(), Units.VOLT);
101                 case FroniusBindingConstants.INVERTER_DATA_CHANNEL_UDC:
102                     return getQuantityOrZero(inverterData.getUdc(), Units.VOLT);
103                 case FroniusBindingConstants.INVERTER_DATA_CHANNEL_DAY_ENERGY:
104                     // Convert the unit to kWh for backwards compatibility with non-quantity type
105                     return getQuantityOrZero(inverterData.getDayEnergy(), Units.KILOWATT_HOUR).toUnit("kWh");
106                 case FroniusBindingConstants.INVERTER_DATA_CHANNEL_TOTAL:
107                     // Convert the unit to MWh for backwards compatibility with non-quantity type
108                     return getQuantityOrZero(inverterData.getTotalEnergy(), Units.MEGAWATT_HOUR).toUnit("MWh");
109                 case FroniusBindingConstants.INVERTER_DATA_CHANNEL_YEAR:
110                     // Convert the unit to MWh for backwards compatibility with non-quantity type
111                     return getQuantityOrZero(inverterData.getYearEnergy(), Units.MEGAWATT_HOUR).toUnit("MWh");
112                 case FroniusBindingConstants.INVERTER_DATA_CHANNEL_DEVICE_STATUS_ERROR_CODE:
113                     return new DecimalType(inverterData.getDeviceStatus().getErrorCode());
114                 case FroniusBindingConstants.INVERTER_DATA_CHANNEL_DEVICE_STATUS_STATUS_CODE:
115                     return new DecimalType(inverterData.getDeviceStatus().getStatusCode());
116                 default:
117                     break;
118             }
119         }
120
121         if (powerFlowResponse != null) {
122             PowerFlowRealtimeSite site = powerFlowResponse.getBody().getData().getSite();
123             switch (fieldName) {
124                 case FroniusBindingConstants.POWER_FLOW_P_GRID:
125                     return new QuantityType<>(site.getPgrid(), Units.WATT);
126                 case FroniusBindingConstants.POWER_FLOW_P_LOAD:
127                     return new QuantityType<>(site.getPload(), Units.WATT);
128                 case FroniusBindingConstants.POWER_FLOW_P_AKKU:
129                     return new QuantityType<>(site.getPakku(), Units.WATT);
130                 case FroniusBindingConstants.POWER_FLOW_P_PV:
131                     return new QuantityType<>(site.getPpv(), Units.WATT);
132                 case FroniusBindingConstants.POWER_FLOW_AUTONOMY:
133                     return new QuantityType<>(site.getRelAutonomy(), Units.PERCENT);
134                 case FroniusBindingConstants.POWER_FLOW_SELF_CONSUMPTION:
135                     return new QuantityType<>(site.getRelSelfConsumption(), Units.PERCENT);
136                 case FroniusBindingConstants.POWER_FLOW_INVERTER_1_POWER:
137                     return new QuantityType<>(getInverter("1").getP(), Units.WATT);
138                 case FroniusBindingConstants.POWER_FLOW_INVERTER_1_SOC:
139                     return new QuantityType<>(getInverter("1").getSoc(), Units.PERCENT);
140                 default:
141                     break;
142             }
143         }
144
145         return null;
146     }
147
148     /**
149      * get flow data for a specific inverter.
150      *
151      * @param number The inverter object of the given index
152      * @return an PowerFlowRealtimeInverter object.
153      */
154     private PowerFlowRealtimeInverter getInverter(final String number) {
155         return powerFlowResponse.getBody().getData().getInverters().get(number);
156     }
157
158     /**
159      * Return the value as QuantityType with the unit extracted from ValueUnit
160      * or a zero QuantityType with the given unit argument when value is null
161      * 
162      * @param value The ValueUnit data
163      * @param unit The default unit to use when value is null
164      * @return a QuantityType from the given value
165      */
166     private QuantityType<?> getQuantityOrZero(ValueUnit value, Unit unit) {
167         return Optional.ofNullable(value).map(val -> val.asQuantityType().toUnit(unit))
168                 .orElse(new QuantityType<>(0, unit));
169     }
170
171     /**
172      * Get new data
173      */
174     private void updateData(FroniusBridgeConfiguration bridgeConfiguration, FroniusBaseDeviceConfiguration config)
175             throws FroniusCommunicationException {
176         inverterRealtimeResponse = getRealtimeData(bridgeConfiguration.hostname, config.deviceId);
177         powerFlowResponse = getPowerFlowRealtime(bridgeConfiguration.hostname);
178     }
179
180     /**
181      * Make the PowerFlowRealtimeDataRequest
182      *
183      * @param ip address of the device
184      * @return {PowerFlowRealtimeResponse} the object representation of the json response
185      */
186     private PowerFlowRealtimeResponse getPowerFlowRealtime(String ip) throws FroniusCommunicationException {
187         String location = FroniusBindingConstants.getPowerFlowDataUrl(ip);
188         return collectDataFromUrl(PowerFlowRealtimeResponse.class, location);
189     }
190
191     /**
192      * Make the InverterRealtimeDataRequest
193      *
194      * @param ip address of the device
195      * @param deviceId of the device
196      * @return {InverterRealtimeResponse} the object representation of the json response
197      */
198     private InverterRealtimeResponse getRealtimeData(String ip, int deviceId) throws FroniusCommunicationException {
199         String location = FroniusBindingConstants.getInverterDataUrl(ip, deviceId);
200         return collectDataFromUrl(InverterRealtimeResponse.class, location);
201     }
202 }