]> git.basschouten.com Git - openhab-addons.git/blob
037efa896bb4cf20069749c1ac9a1171d1b3b287
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2024 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.handlers;
14
15 import java.io.IOException;
16 import java.time.ZoneId;
17 import java.util.concurrent.ScheduledFuture;
18 import java.util.concurrent.TimeUnit;
19 import java.util.concurrent.locks.ReentrantLock;
20
21 import org.eclipse.jdt.annotation.NonNullByDefault;
22 import org.eclipse.jdt.annotation.Nullable;
23 import org.openhab.binding.solax.internal.SolaxBindingConstants;
24 import org.openhab.binding.solax.internal.SolaxConfiguration;
25 import org.openhab.binding.solax.internal.connectivity.SolaxConnector;
26 import org.openhab.binding.solax.internal.exceptions.SolaxUpdateException;
27 import org.openhab.core.i18n.TimeZoneProvider;
28 import org.openhab.core.i18n.TranslationProvider;
29 import org.openhab.core.thing.ChannelUID;
30 import org.openhab.core.thing.Thing;
31 import org.openhab.core.thing.ThingStatus;
32 import org.openhab.core.thing.ThingStatusDetail;
33 import org.openhab.core.thing.binding.BaseThingHandler;
34 import org.openhab.core.types.Command;
35 import org.openhab.core.types.RefreshType;
36 import org.slf4j.Logger;
37 import org.slf4j.LoggerFactory;
38
39 /**
40  * The {@link SolaxCloudHandler} is responsible for handling commands, which are
41  * sent to one of the channels.
42  *
43  * @author Konstantin Polihronov - Initial contribution
44  */
45 @NonNullByDefault
46 public abstract class AbstractSolaxHandler extends BaseThingHandler {
47
48     private final Logger logger = LoggerFactory.getLogger(AbstractSolaxHandler.class);
49
50     private static final int INITIAL_SCHEDULE_DELAY_SECONDS = 0;
51
52     private @NonNullByDefault({}) SolaxConnector connector;
53
54     private @Nullable ScheduledFuture<?> schedule;
55
56     private final ReentrantLock retrieveDataCallLock = new ReentrantLock();
57
58     protected final TranslationProvider i18nProvider;
59
60     protected final ZoneId timeZone;
61
62     public AbstractSolaxHandler(Thing thing, TranslationProvider i18nProvider, TimeZoneProvider timeZoneProvider) {
63         super(thing);
64         this.i18nProvider = i18nProvider;
65         this.timeZone = timeZoneProvider.getTimeZone();
66     }
67
68     @Override
69     public void initialize() {
70         updateStatus(ThingStatus.UNKNOWN);
71
72         SolaxConfiguration config = getConfigAs(SolaxConfiguration.class);
73         connector = createConnector(config);
74         int refreshInterval = config.refreshInterval;
75         TimeUnit timeUnit = TimeUnit.SECONDS;
76
77         logger.debug("Scheduling regular interval retrieval every {} {}", refreshInterval, timeUnit);
78         schedule = scheduler.scheduleWithFixedDelay(this::retrieveData, INITIAL_SCHEDULE_DELAY_SECONDS, refreshInterval,
79                 timeUnit);
80     }
81
82     private void retrieveData() {
83         if (retrieveDataCallLock.tryLock()) {
84             try {
85                 String rawJsonData = connector.retrieveData();
86                 logger.debug("Raw data retrieved = {}", rawJsonData);
87
88                 if (rawJsonData != null && !rawJsonData.isEmpty()) {
89                     updateFromData(rawJsonData);
90                     if (getThing().getStatus() != ThingStatus.ONLINE) {
91                         updateStatus(ThingStatus.ONLINE);
92                     }
93                 } else {
94                     updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
95                             SolaxBindingConstants.I18N_KEY_OFFLINE_COMMUNICATION_ERROR_JSON_CANNOT_BE_RETRIEVED);
96                 }
97             } catch (IOException e) {
98                 logger.debug("Exception received while attempting to retrieve data via HTTP", e);
99                 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());
100             } catch (SolaxUpdateException e) {
101                 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());
102             } finally {
103                 retrieveDataCallLock.unlock();
104             }
105         } else {
106             logger.debug("Unable to retrieve data because a request is already in progress.");
107         }
108     }
109
110     @Override
111     public void handleCommand(ChannelUID channelUID, Command command) {
112         if (command instanceof RefreshType) {
113             scheduler.execute(this::retrieveData);
114         } else {
115             logger.debug("Binding {} only supports refresh command", SolaxBindingConstants.BINDING_ID);
116         }
117     }
118
119     @Override
120     public void dispose() {
121         super.dispose();
122         cancelSchedule();
123     }
124
125     protected void cancelSchedule() {
126         ScheduledFuture<?> schedule = this.schedule;
127         if (schedule != null) {
128             logger.debug("Cancelling schedule {}", schedule);
129             schedule.cancel(true);
130             this.schedule = null;
131         }
132     }
133
134     protected abstract SolaxConnector createConnector(SolaxConfiguration config);
135
136     protected abstract void updateFromData(String rawJsonData) throws SolaxUpdateException;
137 }