]> git.basschouten.com Git - openhab-addons.git/blob
7edcfaf216cf25007d9bfa24a3979528924d2ccc
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2023 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.solax.internal;
14
15 import java.io.IOException;
16 import java.time.ZonedDateTime;
17 import java.util.concurrent.ScheduledFuture;
18 import java.util.concurrent.TimeUnit;
19
20 import org.eclipse.jdt.annotation.NonNullByDefault;
21 import org.eclipse.jdt.annotation.Nullable;
22 import org.openhab.binding.solax.internal.connectivity.LocalHttpConnector;
23 import org.openhab.binding.solax.internal.connectivity.rawdata.LocalConnectRawDataBean;
24 import org.openhab.binding.solax.internal.model.InverterData;
25 import org.openhab.core.library.types.DateTimeType;
26 import org.openhab.core.library.types.QuantityType;
27 import org.openhab.core.library.types.StringType;
28 import org.openhab.core.library.unit.SIUnits;
29 import org.openhab.core.library.unit.Units;
30 import org.openhab.core.thing.ChannelUID;
31 import org.openhab.core.thing.Thing;
32 import org.openhab.core.thing.ThingStatus;
33 import org.openhab.core.thing.ThingStatusDetail;
34 import org.openhab.core.thing.binding.BaseThingHandler;
35 import org.openhab.core.types.Command;
36 import org.slf4j.Logger;
37 import org.slf4j.LoggerFactory;
38
39 import com.google.gson.JsonParseException;
40
41 /**
42  * The {@link SolaxLocalAccessHandler} is responsible for handling commands, which are
43  * sent to one of the channels.
44  *
45  * @author Konstantin Polihronov - Initial contribution
46  */
47 @NonNullByDefault
48 public class SolaxLocalAccessHandler extends BaseThingHandler {
49
50     private final Logger logger = LoggerFactory.getLogger(SolaxLocalAccessHandler.class);
51
52     private static final int INITIAL_SCHEDULE_DELAY_SECONDS = 5;
53
54     private @NonNullByDefault({}) LocalHttpConnector localHttpConnector;
55
56     private @Nullable ScheduledFuture<?> schedule;
57
58     public SolaxLocalAccessHandler(Thing thing) {
59         super(thing);
60     }
61
62     @Override
63     public void initialize() {
64         updateStatus(ThingStatus.UNKNOWN);
65
66         SolaxConfiguration config = getConfigAs(SolaxConfiguration.class);
67         localHttpConnector = new LocalHttpConnector(config.password, config.hostname);
68         int refreshInterval = config.refreshInterval;
69         TimeUnit timeUnit = TimeUnit.SECONDS;
70
71         logger.debug("Scheduling regular interval retrieval every {} {}", refreshInterval, timeUnit);
72         schedule = scheduler.scheduleWithFixedDelay(this::retrieveData, INITIAL_SCHEDULE_DELAY_SECONDS, refreshInterval,
73                 timeUnit);
74     }
75
76     private void retrieveData() {
77         try {
78             String rawJsonData = localHttpConnector.retrieveData();
79             logger.debug("Raw data retrieved = {}", rawJsonData);
80
81             if (rawJsonData != null && !rawJsonData.isEmpty()) {
82                 updateData(rawJsonData);
83             } else {
84                 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
85                         SolaxBindingConstants.I18N_KEY_OFFLINE_COMMUNICATION_ERROR_JSON_CANNOT_BE_RETRIEVED);
86             }
87         } catch (IOException e) {
88             logger.debug("Exception received while attempting to retrieve data via HTTP", e);
89             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());
90         }
91     }
92
93     private void updateData(String rawJsonData) {
94         try {
95             LocalConnectRawDataBean inverterParsedData = parseJson(rawJsonData);
96             updateThing(inverterParsedData);
97         } catch (JsonParseException e) {
98             logger.debug("Unable to deserialize from JSON.", e);
99             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());
100         }
101     }
102
103     private void updateThing(LocalConnectRawDataBean inverterParsedData) {
104         transferInverterDataToChannels(inverterParsedData);
105
106         if (getThing().getStatus() != ThingStatus.ONLINE) {
107             updateStatus(ThingStatus.ONLINE);
108         }
109     }
110
111     private LocalConnectRawDataBean parseJson(String rawJsonData) {
112         LocalConnectRawDataBean inverterParsedData = LocalConnectRawDataBean.fromJson(rawJsonData);
113         logger.debug("Received a new inverter data object. Data = {}", inverterParsedData.toStringDetailed());
114         return inverterParsedData;
115     }
116
117     private void transferInverterDataToChannels(InverterData data) {
118         updateProperty(Thing.PROPERTY_SERIAL_NUMBER, data.getWifiSerial());
119         updateProperty(SolaxBindingConstants.PROPERTY_INVERTER_TYPE, data.getInverterType().name());
120
121         updateState(SolaxBindingConstants.INVERTER_OUTPUT_POWER,
122                 new QuantityType<>(data.getInverterOutputPower(), Units.WATT));
123         updateState(SolaxBindingConstants.INVERTER_OUTPUT_CURRENT,
124                 new QuantityType<>(data.getInverterCurrent(), Units.AMPERE));
125         updateState(SolaxBindingConstants.INVERTER_OUTPUT_VOLTAGE,
126                 new QuantityType<>(data.getInverterVoltage(), Units.VOLT));
127         updateState(SolaxBindingConstants.INVERTER_OUTPUT_FREQUENCY,
128                 new QuantityType<>(data.getInverterFrequency(), Units.HERTZ));
129
130         updateState(SolaxBindingConstants.INVERTER_PV1_POWER, new QuantityType<>(data.getPV1Power(), Units.WATT));
131         updateState(SolaxBindingConstants.INVERTER_PV1_CURRENT, new QuantityType<>(data.getPV1Current(), Units.AMPERE));
132         updateState(SolaxBindingConstants.INVERTER_PV1_VOLTAGE, new QuantityType<>(data.getPV1Voltage(), Units.VOLT));
133
134         updateState(SolaxBindingConstants.INVERTER_PV2_POWER, new QuantityType<>(data.getPV2Power(), Units.WATT));
135         updateState(SolaxBindingConstants.INVERTER_PV2_CURRENT, new QuantityType<>(data.getPV2Current(), Units.AMPERE));
136         updateState(SolaxBindingConstants.INVERTER_PV2_VOLTAGE, new QuantityType<>(data.getPV2Voltage(), Units.VOLT));
137
138         updateState(SolaxBindingConstants.INVERTER_PV_TOTAL_POWER,
139                 new QuantityType<>(data.getPVTotalPower(), Units.WATT));
140         updateState(SolaxBindingConstants.INVERTER_PV_TOTAL_CURRENT,
141                 new QuantityType<>(data.getPVTotalCurrent(), Units.AMPERE));
142
143         updateState(SolaxBindingConstants.BATTERY_POWER, new QuantityType<>(data.getBatteryPower(), Units.WATT));
144         updateState(SolaxBindingConstants.BATTERY_CURRENT, new QuantityType<>(data.getBatteryCurrent(), Units.AMPERE));
145         updateState(SolaxBindingConstants.BATTERY_VOLTAGE, new QuantityType<>(data.getBatteryVoltage(), Units.VOLT));
146         updateState(SolaxBindingConstants.BATTERY_TEMPERATURE,
147                 new QuantityType<>(data.getBatteryTemperature(), SIUnits.CELSIUS));
148         updateState(SolaxBindingConstants.BATTERY_STATE_OF_CHARGE,
149                 new QuantityType<>(data.getBatterySoC(), Units.PERCENT));
150
151         updateState(SolaxBindingConstants.FEED_IN_POWER, new QuantityType<>(data.getFeedInPower(), Units.WATT));
152
153         updateState(SolaxBindingConstants.TIMESTAMP, new DateTimeType(ZonedDateTime.now()));
154         updateState(SolaxBindingConstants.RAW_DATA, new StringType(data.getRawData()));
155     }
156
157     @Override
158     public void handleCommand(ChannelUID channelUID, Command command) {
159         // Nothing to do here as of now. Maybe implement a REFRESH command in the future.
160     }
161
162     @Override
163     public void dispose() {
164         super.dispose();
165         ScheduledFuture<?> schedule = this.schedule;
166         if (schedule != null) {
167             schedule.cancel(true);
168             this.schedule = null;
169         }
170     }
171 }