Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[solax] Add cloud connection support #16124

Merged
merged 4 commits into from
Feb 14, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
224 changes: 177 additions & 47 deletions bundles/org.openhab.binding.solax/README.md

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,18 @@
@NonNullByDefault
public class SolaxBindingConstants {

protected static final String BINDING_ID = "solax";
public static final String BINDING_ID = "solax";
private static final String THING_LOCAL_CONNECT_INVERTER_ID = "local-connect-inverter";
private static final String THING_CLOUD_CONNECT_INVERTER_ID = "cloud-connect-inverter";

// List of all Thing Type UIDs
public static final ThingTypeUID THING_TYPE_LOCAL_CONNECT_INVERTER = new ThingTypeUID(BINDING_ID,
THING_LOCAL_CONNECT_INVERTER_ID);
public static final ThingTypeUID THING_TYPE_CLOUD_CONNECT_INVERTER = new ThingTypeUID(BINDING_ID,
THING_CLOUD_CONNECT_INVERTER_ID);

public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Set.of(THING_TYPE_LOCAL_CONNECT_INVERTER);
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Set.of(THING_TYPE_LOCAL_CONNECT_INVERTER,
THING_TYPE_CLOUD_CONNECT_INVERTER);

// List of properties
public static final String PROPERTY_INVERTER_TYPE = "inverterType";
Expand Down Expand Up @@ -104,6 +108,14 @@ public class SolaxBindingConstants {
public static final String CHANNEL_TODAY_FEED_IN_ENERGY = "today-feed-in-energy";
public static final String CHANNEL_TODAY_CONSUMPTION = "today-consumption";

// Cloud specific channels
public static final String CHANNEL_INVERTER_PV3_POWER = "pv3-power";
public static final String CHANNEL_INVERTER_PV4_POWER = "pv4-power";
public static final String CHANNEL_INVERTER_OUTPUT_POWER_METER2 = "inverter-meter2-power";
public static final String CHANNEL_INVERTER_EPS_POWER_R = "inverter-eps-power-r";
public static final String CHANNEL_INVERTER_EPS_POWER_S = "inverter-eps-power-s";
public static final String CHANNEL_INVERTER_EPS_POWER_T = "inverter-eps-power-t";

// I18N Keys
protected static final String I18N_KEY_OFFLINE_COMMUNICATION_ERROR_JSON_CANNOT_BE_RETRIEVED = "@text/offline.communication-error.json-cannot-be-retrieved";
public static final String I18N_KEY_OFFLINE_COMMUNICATION_ERROR_JSON_CANNOT_BE_RETRIEVED = "@text/offline.communication-error.json-cannot-be-retrieved";
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,5 @@ public class SolaxConfiguration {
public String hostname = "";
public String password = "";
public int refreshInterval = 10;
public String token = "";
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,19 @@

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.solax.internal.handlers.SolaxCloudHandler;
import org.openhab.binding.solax.internal.handlers.SolaxLocalAccessHandler;
import org.openhab.core.i18n.LocaleProvider;
import org.openhab.core.i18n.TimeZoneProvider;
import org.openhab.core.i18n.TranslationProvider;
import org.openhab.core.thing.Thing;
import org.openhab.core.thing.ThingTypeUID;
import org.openhab.core.thing.binding.BaseThingHandlerFactory;
import org.openhab.core.thing.binding.ThingHandler;
import org.openhab.core.thing.binding.ThingHandlerFactory;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;

/**
* The {@link SolaxHandlerFactory} is responsible for creating things and thing
Expand All @@ -33,6 +40,18 @@
@Component(configurationPid = "binding.solax", service = ThingHandlerFactory.class)
public class SolaxHandlerFactory extends BaseThingHandlerFactory {

private TranslationProvider i18nProvider;
private TimeZoneProvider timeZoneProvider;
private LocaleProvider localeProvider;

@Activate
public SolaxHandlerFactory(final @Reference TranslationProvider i18nProvider,
final @Reference TimeZoneProvider timeZoneProvider, final @Reference LocaleProvider localeProvider) {
this.i18nProvider = i18nProvider;
this.timeZoneProvider = timeZoneProvider;
this.localeProvider = localeProvider;
}

@Override
public boolean supportsThingType(ThingTypeUID thingTypeUID) {
return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID);
Expand All @@ -42,7 +61,9 @@ public boolean supportsThingType(ThingTypeUID thingTypeUID) {
protected @Nullable ThingHandler createHandler(Thing thing) {
ThingTypeUID thingTypeUID = thing.getThingTypeUID();
if (THING_TYPE_LOCAL_CONNECT_INVERTER.equals(thingTypeUID)) {
return new SolaxLocalAccessHandler(thing);
return new SolaxLocalAccessHandler(thing, i18nProvider, timeZoneProvider);
} else if (THING_TYPE_CLOUD_CONNECT_INVERTER.equals(thingTypeUID)) {
return new SolaxCloudHandler(thing, i18nProvider, timeZoneProvider, localeProvider);
}
return null;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/**
* Copyright (c) 2010-2024 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.solax.internal.connectivity;

import java.io.IOException;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.jetty.http.HttpMethod;
import org.openhab.core.io.net.http.HttpUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* The {@link CloudHttpConnector} class uses HttpUtil to retrieve the raw JSON data from Inverter's Wi-Fi module.
*
* @author Konstantin Polihronov - Initial contribution
*/
@NonNullByDefault
public class CloudHttpConnector implements SolaxConnector {

private static final int HTTP_REQUEST_TIME_OUT = 5000;

// private static final String CONTENT_TYPE = "text/html; charset=utf-8";
theater marked this conversation as resolved.
Show resolved Hide resolved
private static final String CONTENT_TYPE = "application/json; charset=utf-8";

private final Logger logger = LoggerFactory.getLogger(CloudHttpConnector.class);

private static final String TOKEN_ID_REPLACEMENT_PATTERN = "{tokenId}";
lsiepel marked this conversation as resolved.
Show resolved Hide resolved
// The serial number of the Wifi dongle is the password for the connection (default)
private static final String SERIAL_NUMBER_REPLACEMENT_PATTERN = "{serialNumber}";
private static final String URI = """
https://www.solaxcloud.com/proxyApp/proxy/api/getRealtimeInfo.do?tokenId={tokenId}&sn={serialNumber}
""";

private String uri;

public CloudHttpConnector(String tokenId, String serialNumber) {
this(URI, tokenId, serialNumber);
}

public CloudHttpConnector(String uri, String tokenId, String serialNumber) {
this.uri = uri.replace(TOKEN_ID_REPLACEMENT_PATTERN, tokenId)
.replace(SERIAL_NUMBER_REPLACEMENT_PATTERN, serialNumber).trim();
}

@Override
public @Nullable String retrieveData() throws IOException {
logger.trace("Uri: {}", uri);
lsiepel marked this conversation as resolved.
Show resolved Hide resolved
String result = HttpUtil.executeUrl(HttpMethod.GET.name(), uri, null, CONTENT_TYPE, HTTP_REQUEST_TIME_OUT);
logger.trace("Retrieved content = {}", result);
return result;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,6 @@
public interface RawDataBean {
@Nullable
String getRawData();

public void setRawData(String rawData);
}