]> git.basschouten.com Git - openhab-addons.git/blob
323a765eff56cd9d9630235be9302e400dd28158
[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.siemenshvac.internal.handler;
14
15 import java.net.URL;
16 import java.net.URLConnection;
17 import java.text.DateFormat;
18 import java.text.MessageFormat;
19 import java.text.SimpleDateFormat;
20 import java.time.LocalDate;
21 import java.util.Collection;
22 import java.util.Locale;
23 import java.util.Set;
24 import java.util.concurrent.TimeUnit;
25
26 import org.eclipse.jdt.annotation.NonNullByDefault;
27 import org.eclipse.jdt.annotation.Nullable;
28 import org.openhab.binding.siemenshvac.internal.discovery.SiemensHvacDeviceDiscoveryService;
29 import org.openhab.binding.siemenshvac.internal.metadata.SiemensHvacMetadataRegistry;
30 import org.openhab.binding.siemenshvac.internal.network.SiemensHvacConnector;
31 import org.openhab.binding.siemenshvac.internal.type.SiemensHvacException;
32 import org.openhab.core.i18n.TranslationProvider;
33 import org.openhab.core.io.net.http.HttpClientFactory;
34 import org.openhab.core.net.NetworkAddressService;
35 import org.openhab.core.thing.Bridge;
36 import org.openhab.core.thing.ChannelUID;
37 import org.openhab.core.thing.ThingStatus;
38 import org.openhab.core.thing.ThingStatusDetail;
39 import org.openhab.core.thing.binding.BaseBridgeHandler;
40 import org.openhab.core.thing.binding.ThingHandlerService;
41 import org.openhab.core.types.Command;
42 import org.osgi.framework.BundleContext;
43 import org.osgi.framework.FrameworkUtil;
44 import org.slf4j.Logger;
45 import org.slf4j.LoggerFactory;
46
47 /**
48  * The {@link SiemensHvacBridgeBaseThingHandler} is responsible for handling commands, which are
49  * sent to one of the channels.
50  *
51  * @author Laurent Arnal - Initial contribution and API
52  */
53 @NonNullByDefault
54 public class SiemensHvacBridgeThingHandler extends BaseBridgeHandler {
55
56     private final Logger logger = LoggerFactory.getLogger(SiemensHvacBridgeThingHandler.class);
57     private @Nullable SiemensHvacDeviceDiscoveryService discoveryService;
58     private final @Nullable HttpClientFactory httpClientFactory;
59     private final SiemensHvacMetadataRegistry metaDataRegistry;
60     private @Nullable SiemensHvacBridgeConfig config;
61     private final TranslationProvider translationProvider;
62
63     public SiemensHvacBridgeThingHandler(Bridge bridge, @Nullable NetworkAddressService networkAddressService,
64             @Nullable HttpClientFactory httpClientFactory, SiemensHvacMetadataRegistry metaDataRegistry,
65             TranslationProvider translationProvider) {
66         super(bridge);
67         SiemensHvacConnector lcConnector = null;
68         this.httpClientFactory = httpClientFactory;
69         this.metaDataRegistry = metaDataRegistry;
70         this.translationProvider = translationProvider;
71
72         lcConnector = this.metaDataRegistry.getSiemensHvacConnector();
73         if (lcConnector != null) {
74             lcConnector.setSiemensHvacBridgeBaseThingHandler(this);
75         }
76     }
77
78     @Override
79     public void handleCommand(ChannelUID channelUID, Command command) {
80     }
81
82     @Override
83     public void dispose() {
84         metaDataRegistry.invalidate();
85     }
86
87     @Override
88     public void initialize() {
89         SiemensHvacBridgeConfig lcConfig = getConfigAs(SiemensHvacBridgeConfig.class);
90         String baseUrl = null;
91
92         if (logger.isDebugEnabled()) {
93             logger.debug("Initialize() bridge: {}", getBuildDate());
94         }
95
96         baseUrl = lcConfig.baseUrl;
97
98         if (baseUrl.isEmpty()) {
99             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.CONFIGURATION_ERROR,
100                     "@text/offline.error-gateway-init");
101             return;
102         }
103
104         if (!baseUrl.startsWith("http://") && !baseUrl.startsWith("https://")) {
105             baseUrl = "http://" + baseUrl;
106         }
107
108         if (!baseUrl.endsWith("/")) {
109             baseUrl = baseUrl + "/";
110         }
111
112         config = lcConfig;
113
114         updateStatus(ThingStatus.UNKNOWN, ThingStatusDetail.NONE, "@text/offline.waiting-bridge-initialization");
115
116         // Will read metadata in background to not block initialize for a long period !
117         scheduler.schedule(this::initializeCode, 1, TimeUnit.SECONDS);
118     }
119
120     protected String getBuildDate() {
121         try {
122             ClassLoader cl = getClass().getClassLoader();
123             if (cl != null) {
124                 URL res = cl.getResource(getClass().getCanonicalName().replace('.', '/') + ".class");
125                 if (res != null) {
126                     URLConnection cnx = res.openConnection();
127                     LocalDate dt = LocalDate.ofEpochDay(cnx.getLastModified());
128                     DateFormat df = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
129                     return df.format(dt);
130                 }
131             }
132
133         } catch (Exception ex) {
134         }
135         return "unknown";
136     }
137
138     public static String getStackTrace(final Throwable throwable) {
139         StringBuffer sb = new StringBuffer();
140
141         Throwable current = throwable;
142         while (current != null) {
143             sb.append(current.getLocalizedMessage());
144             sb.append(",\r\n");
145
146             Throwable cause = throwable.getCause();
147             if (cause != null) {
148                 if (!cause.equals(throwable)) {
149                     current = current.getCause();
150                 } else {
151                     current = null;
152                 }
153             } else {
154                 current = null;
155             }
156         }
157         return sb.toString();
158     }
159
160     private void initializeCode() {
161         try {
162             metaDataRegistry.readMeta();
163             updateStatus(ThingStatus.ONLINE);
164         } catch (SiemensHvacException ex) {
165             Locale local = metaDataRegistry.getUserLocale();
166             BundleContext bundleContext = FrameworkUtil.getBundle(this.getClass()).getBundleContext();
167             String text = translationProvider.getText(bundleContext.getBundle(), "offline.error-gateway-init",
168                     "DefaultValue", local);
169
170             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
171                     MessageFormat.format(text, ex.getMessage()));
172         }
173     }
174
175     public @Nullable SiemensHvacBridgeConfig getBridgeConfiguration() {
176         return config;
177     }
178
179     @Override
180     public void updateStatus(ThingStatus status, ThingStatusDetail statusDetail, @Nullable String description) {
181         super.updateStatus(status, statusDetail, description);
182     }
183
184     public boolean registerDiscoveryListener(SiemensHvacDeviceDiscoveryService listener) {
185         SiemensHvacDeviceDiscoveryService lcDiscoveryService = discoveryService;
186         if (lcDiscoveryService == null) {
187             lcDiscoveryService = listener;
188             lcDiscoveryService.setSiemensHvacMetadataRegistry(metaDataRegistry);
189             return true;
190         }
191
192         return false;
193     }
194
195     public boolean unregisterDiscoveryListener() {
196         SiemensHvacDeviceDiscoveryService lcDiscoveryService = discoveryService;
197         if (lcDiscoveryService != null) {
198             discoveryService = null;
199             return true;
200         }
201
202         return false;
203     }
204
205     public @Nullable HttpClientFactory getHttpClientFactory() {
206         return this.httpClientFactory;
207     }
208
209     @Override
210     public Collection<Class<? extends ThingHandlerService>> getServices() {
211         return Set.of(SiemensHvacDeviceDiscoveryService.class);
212     }
213 }