2 * Copyright (c) 2010-2023 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
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
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.enphase.internal.handler;
15 import org.eclipse.jdt.annotation.NonNullByDefault;
16 import org.eclipse.jdt.annotation.Nullable;
17 import org.eclipse.jetty.client.HttpClient;
18 import org.openhab.binding.enphase.internal.EnvoyConfiguration;
19 import org.openhab.binding.enphase.internal.exception.EnphaseException;
20 import org.openhab.binding.enphase.internal.exception.EnvoyConnectionException;
21 import org.openhab.binding.enphase.internal.exception.EnvoyNoHostnameException;
22 import org.slf4j.Logger;
23 import org.slf4j.LoggerFactory;
26 * Wraps around the specific Envoy connector and provides methods to determine which connector to use.
28 * @author Hilbrand Bouwkamp - Initial contribution
31 public class EnvoyConnectorWrapper {
33 private final Logger logger = LoggerFactory.getLogger(EnvoyConnectorWrapper.class);
34 private final HttpClient httpClient;
35 private @Nullable EnvoyConnector connector;
36 private @Nullable String version;
38 public EnvoyConnectorWrapper(final HttpClient httpClient) {
39 this.httpClient = httpClient;
42 public @Nullable String getVersion() {
47 * Sets the Envoy software version as retreived from the Envoy data.
49 * @param version Envoy software version.
51 public void setVersion(final @Nullable String version) {
52 if (version == null) {
55 logger.debug("Set Envoy version found in the Envoy data: {}", version);
56 this.version = version;
60 * Set the connector given the configuration.
62 * @param configuration configuration to use to set the connector.
63 * @return Returns configuration error message or empty string if no configuration errors present
64 * @throws EnphaseException
66 public synchronized String setConnector(final EnvoyConfiguration configuration) throws EnphaseException {
67 final EnvoyConnector connector = determineConnector(configuration.hostname);
68 final String message = connector.setConfiguration(configuration);
70 // Only set connector if no error messages.
71 if (message.isEmpty()) {
72 this.connector = connector;
78 * @return Returns true if a connection with the Envoy has been established.
80 public boolean hasConnection() {
81 return connector != null;
85 * @return Returns the connector when present. This method should only be called when a connector is present as
86 * returned by the {@link #hasConnection()} method.
88 public EnvoyConnector getConnector() throws EnvoyConnectionException {
89 final EnvoyConnector connector = this.connector;
91 if (connector == null) {
92 throw new EnvoyConnectionException("No connection to the Envoy. Check your configuration.");
97 private EnvoyConnector determineConnector(final String hostname) throws EnphaseException {
98 final EnvoyConnector connectorByVersion = determineConnectorOnVersion();
100 if (connectorByVersion != null) {
101 return connectorByVersion;
104 if (hostname.isBlank()) {
105 throw new EnvoyNoHostnameException("No hostname available.");
107 final EnvoyConnector envoyConnector = new EnvoyConnector(httpClient);
108 final String version = envoyConnector.checkConnection(hostname);
110 if (version != null) {
111 this.version = version;
112 final int majorVersionNumber = determineMajorVersionNumber();
114 if (majorVersionNumber > 0 && majorVersionNumber < 7) {
116 "Connection to Envoy determined by getting a reply from the Envoy using the prior to version 7 method.");
117 return envoyConnector;
119 if (majorVersionNumber >= 7) {
121 "Connection to Envoy determined by getting a reply from the Envoy using version 7 connection method.");
122 return new EnvoyEntrezConnector(httpClient);
125 final EnvoyEntrezConnector envoyEntrezConnector = new EnvoyEntrezConnector(httpClient);
126 final String entrezVersion = envoyEntrezConnector.checkConnection(hostname);
128 if (entrezVersion != null) {
129 this.version = entrezVersion;
130 final int majorVersionNumber = determineMajorVersionNumber();
132 if (majorVersionNumber >= 7) {
134 "Connection to Envoy determined by getting a reply from the Envoy using version 7 connection method.");
135 return envoyEntrezConnector;
138 throw new EnphaseException("No connection could be made with the Envoy. Check your connection/hostname.");
141 private @Nullable EnvoyConnector determineConnectorOnVersion() {
142 final int majorVersionNumber = determineMajorVersionNumber();
144 if (majorVersionNumber < 0) {
146 } else if (majorVersionNumber < 7) {
147 logger.debug("Connect to Envoy based on version number {} using standard connector", version);
148 return new EnvoyConnector(httpClient);
150 logger.debug("Connect to Envoy based on version number {} using entrez connector", version);
151 return new EnvoyEntrezConnector(httpClient);
155 private int determineMajorVersionNumber() {
156 final String version = this.version;
158 if (version == null) {
161 logger.debug("Envoy version information used to determine actual version: {}", version);
162 final int marjorVersionIndex = version.indexOf('.');
164 if (marjorVersionIndex < 0) {
168 return Integer.parseInt(version.substring(0, marjorVersionIndex));
169 } catch (final NumberFormatException e) {
170 logger.trace("Could not parse major version number in {}, error message: {}", version, e.getMessage());