From: Konstantin Polihronov Date: Tue, 23 Jul 2024 07:23:03 +0000 (+0300) Subject: [solax] Support for Solax EV charger via direct(local) data retrieval (#17055) X-Git-Url: https://git.basschouten.com/?a=commitdiff_plain;h=104a1e537956809e7f777fc049914d8bcc5a93f0;p=openhab-addons.git [solax] Support for Solax EV charger via direct(local) data retrieval (#17055) * Implementation of Solax EV Charger support Signed-off-by: Konstantin Polihronov --- diff --git a/bundles/org.openhab.binding.solax/README.md b/bundles/org.openhab.binding.solax/README.md index 08b6cd8973..a928d872df 100644 --- a/bundles/org.openhab.binding.solax/README.md +++ b/bundles/org.openhab.binding.solax/README.md @@ -12,10 +12,11 @@ In case the parsed information that comes with the binding out of the box differ ## Supported Things -| Thing | Thing Type | Description | -|------------------------|------------|-------------------------------------------------------------------------------------| -| local-connect-inverter | Thing | An inverter representation with all the data available as a channels (directly retrieved from the wi-fi module | -| cloud-connect-inverter | Thing | An inverter representation with all the data available as a channels (retrieved from the Solax cloud API) | +| Thing | Thing Type | Description | +|------------------------|------------|---------------------------------------------------------------------------------------------------------------------------------| +| local-connect-inverter | Thing | An inverter representation with all the data available as a channels (directly retrieved from the wi-fi module) | +| local-connect-charger | Thing | An electric vehicle charger representation with all the data available as a channels (directly retrieved from the wi-fi module) | +| cloud-connect-inverter | Thing | An inverter representation with all the data available as a channels (retrieved from the Solax cloud API) | Note: Channels may vary depending on the inverter type and the availability of information for parsing the raw data. If you're missing a channel this means that it's not supported for your inverter type. @@ -113,6 +114,46 @@ If you're missing a channel this means that it's not supported for your inverter | inverterType | Inverter Type (for example X1_HYBRID_G4) | +### Local Connect EV Charger Configuration + +### Parameters + +| Parameter | Description | +|-------------------|----------------------------------------------------------------------------------------------------------------------------------------------------| +| refreshInterval | Defines the refresh interval when the binding polls from the inverter's Wi-Fi module (in seconds). Optional parameter. Default 10 seconds. | +| password | Password for accessing the Wi-Fi module (the serial number of the wifi). Mandatory parameter. | +| hostname | IP address or hostname of your Wi-Fi module. If hostname is used must be resolvable by OpenHAB. Mandatory parameter. | + +### Channels + +| Channel ID | Type | Description | +|------------------------------------------|-----------------------------|---------------------------------------------------------------| +| eq-single-session | Number:Energy | Energy charged for the current session. [kWh] | +| eq-total | Number:Energy | Total energy charged for all sessions. [kWh] | +| charger-output-power-phase1 | Number:Power | Power to/from the charger phase 1. [W] | +| charger-output-power-phase2 | Number:Power | Power to/from the charger phase 2. [W] | +| charger-output-power-phase3 | Number:Power | Power to/from the charger phase 3. [W] | +| charger-total-output-power | Number:Power | Power from the charger on all phases. [W] | +| charger-current-phase1 | Number:ElectricCurrent | Current from the charger phase 1. [A] | +| charger-current-phase2 | Number:ElectricCurrent | Current from the charger phase 2. [A] | +| charger-current-phase3 | Number:ElectricCurrent | Current from the charger phase 3. [A] | +| charger-voltage-phase1 | Number:ElectricPotential | Voltage of the charger's phase 1. [V] | +| charger-voltage-phase2 | Number:ElectricPotential | Voltage of the charger's phase 2. [V] | +| charger-voltage-phase3 | Number:ElectricPotential | Voltage of the charger's phase 3. [V] | +| charger-external-current-phase1 | Number:ElectricCurrent | Current from the provider phase 1. [A] | +| charger-external-current-phase2 | Number:ElectricCurrent | Current from the provider phase 2. [A] | +| charger-external-current-phase3 | Number:ElectricCurrent | Current from the provider phase 3. [A] | +| charger-external-power-phase1 | Number:Power | Power from the provider phase 1. [W] | +| charger-external-power-phase2 | Number:Power | Power from the provider phase 2. [W] | +| charger-external-power-phase3 | Number:Power | Power from the provider phase 3. [W] | +| charger-external-total-power | Number:Power | Total power from the provider. [W] | +| charger-plug-temperature | Number:Temperature | Temperature of the charger's plug. [°C] | +| charger-internal-temperature | Number:Temperature | Internal temperature on the board of the charger. [°C] | +| charger-mode | String | Charger Workmode. | +| charger-state | String | Charger State. | +| last-update-time | DateTime | Last time with a successful retrieval of data. | + + ### Cloud Connect Inverter Configuration | Parameter | Description | diff --git a/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/SolaxBindingConstants.java b/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/SolaxBindingConstants.java index 4d2f18fb49..16d2f2c4c5 100644 --- a/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/SolaxBindingConstants.java +++ b/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/SolaxBindingConstants.java @@ -28,16 +28,19 @@ public class SolaxBindingConstants { public static final String BINDING_ID = "solax"; private static final String THING_LOCAL_CONNECT_INVERTER_ID = "local-connect-inverter"; + private static final String THING_LOCAL_CONNECT_CHARGER_ID = "local-connect-charger"; 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_LOCAL_CONNECT_CHARGER = new ThingTypeUID(BINDING_ID, + THING_LOCAL_CONNECT_CHARGER_ID); public static final ThingTypeUID THING_TYPE_CLOUD_CONNECT_INVERTER = new ThingTypeUID(BINDING_ID, THING_CLOUD_CONNECT_INVERTER_ID); public static final Set SUPPORTED_THING_TYPES_UIDS = Set.of(THING_TYPE_LOCAL_CONNECT_INVERTER, - THING_TYPE_CLOUD_CONNECT_INVERTER); + THING_TYPE_LOCAL_CONNECT_CHARGER, THING_TYPE_CLOUD_CONNECT_INVERTER); // List of properties public static final String PROPERTY_INVERTER_TYPE = "inverterType"; @@ -116,6 +119,32 @@ public class SolaxBindingConstants { 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"; + // EV Charger channels + public static final String CHANNEL_CHARGER_MODE = "charger-mode"; + public static final String CHANNEL_CHARGER_STATE = "charger-state"; + public static final String CHANNEL_CHARGER_EQ_SINGLE_SESSION = "eq-single-session"; + public static final String CHANNEL_CHARGER_EQ_TOTAL = "eq-total"; + public static final String CHANNEL_CHARGER_OUTPUT_POWER_PHASE1 = "charger-output-power-phase1"; + public static final String CHANNEL_CHARGER_OUTPUT_POWER_PHASE2 = "charger-output-power-phase2"; + public static final String CHANNEL_CHARGER_OUTPUT_POWER_PHASE3 = "charger-output-power-phase3"; + public static final String CHANNEL_CHARGER_TOTAL_OUTPUT_POWER = "charger-total-output-power"; + public static final String CHANNEL_CHARGER_OUTPUT_CURRENT_PHASE1 = "charger-current-phase1"; + public static final String CHANNEL_CHARGER_OUTPUT_CURRENT_PHASE2 = "charger-current-phase2"; + public static final String CHANNEL_CHARGER_OUTPUT_CURRENT_PHASE3 = "charger-current-phase3"; + public static final String CHANNEL_CHARGER_OUTPUT_VOLTAGE_PHASE1 = "charger-voltage-phase1"; + public static final String CHANNEL_CHARGER_OUTPUT_VOLTAGE_PHASE2 = "charger-voltage-phase2"; + public static final String CHANNEL_CHARGER_OUTPUT_VOLTAGE_PHASE3 = "charger-voltage-phase3"; + public static final String CHANNEL_CHARGER_EXTERNAL_CURRENT_PHASE1 = "charger-external-current-phase1"; + public static final String CHANNEL_CHARGER_EXTERNAL_CURRENT_PHASE2 = "charger-external-current-phase2"; + public static final String CHANNEL_CHARGER_EXTERNAL_CURRENT_PHASE3 = "charger-external-current-phase3"; + public static final String CHANNEL_CHARGER_EXTERNAL_POWER_PHASE1 = "charger-external-power-phase1"; + public static final String CHANNEL_CHARGER_EXTERNAL_POWER_PHASE2 = "charger-external-power-phase2"; + public static final String CHANNEL_CHARGER_EXTERNAL_POWER_PHASE3 = "charger-external-power-phase3"; + public static final String CHANNEL_CHARGER_TOTAL_EXTERNAL_POWER = "charger-external-total-power"; + public static final String CHANNEL_CHARGER_PLUG_TEMPERATURE = "charger-plug-temperature"; + public static final String CHANNEL_CHARGER_INTERNAL_TEMPERATURE = "charger-internal-temperature"; + // I18N Keys public 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_CONFIGURATION_ERROR_JSON_CANNOT_BE_PARSED = "@text/offline.configuration-error.json-cannot-be-parsed"; } diff --git a/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/SolaxHandlerFactory.java b/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/SolaxHandlerFactory.java index c0c5a2b103..1a2fe28d4f 100644 --- a/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/SolaxHandlerFactory.java +++ b/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/SolaxHandlerFactory.java @@ -17,7 +17,8 @@ import static org.openhab.binding.solax.internal.SolaxBindingConstants.*; 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.binding.solax.internal.handlers.SolaxLocalAccessChargerHandler; +import org.openhab.binding.solax.internal.handlers.SolaxLocalAccessInverterHandler; import org.openhab.core.i18n.LocaleProvider; import org.openhab.core.i18n.TimeZoneProvider; import org.openhab.core.i18n.TranslationProvider; @@ -61,9 +62,11 @@ public class SolaxHandlerFactory extends BaseThingHandlerFactory { protected @Nullable ThingHandler createHandler(Thing thing) { ThingTypeUID thingTypeUID = thing.getThingTypeUID(); if (THING_TYPE_LOCAL_CONNECT_INVERTER.equals(thingTypeUID)) { - return new SolaxLocalAccessHandler(thing, i18nProvider, timeZoneProvider); + return new SolaxLocalAccessInverterHandler(thing, i18nProvider, timeZoneProvider); } else if (THING_TYPE_CLOUD_CONNECT_INVERTER.equals(thingTypeUID)) { return new SolaxCloudHandler(thing, i18nProvider, timeZoneProvider, localeProvider); + } else if (THING_TYPE_LOCAL_CONNECT_CHARGER.equals(thingTypeUID)) { + return new SolaxLocalAccessChargerHandler(thing, i18nProvider, timeZoneProvider); } return null; } diff --git a/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/connectivity/rawdata/local/LocalConnectRawDataBean.java b/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/connectivity/rawdata/local/LocalConnectRawDataBean.java index 876648493c..576853d321 100644 --- a/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/connectivity/rawdata/local/LocalConnectRawDataBean.java +++ b/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/connectivity/rawdata/local/LocalConnectRawDataBean.java @@ -30,6 +30,7 @@ import com.google.gson.annotations.SerializedName; @NonNullByDefault public class LocalConnectRawDataBean implements RawDataBean { + @SerializedName(value = "sn", alternate = { "SN" }) private @Nullable String sn; private @Nullable String ver; private int type; @@ -38,6 +39,10 @@ public class LocalConnectRawDataBean implements RawDataBean { @SerializedName("Information") private String @Nullable [] information; private @Nullable String rawData; + @SerializedName("OCPPServer") + private @Nullable String ocppServer; + @SerializedName("OCPPChargerId") + private @Nullable String ocppChargerId; @Override public String toString() { @@ -95,6 +100,22 @@ public class LocalConnectRawDataBean implements RawDataBean { this.rawData = rawData; } + public @Nullable String getOcppServer() { + return ocppServer; + } + + public void setOcppServer(@Nullable String ocppServer) { + this.ocppServer = ocppServer; + } + + public @Nullable String getOcppChargerId() { + return ocppChargerId; + } + + public void setOcppChargerId(String ocppChargerId) { + this.ocppChargerId = ocppChargerId; + } + public static LocalConnectRawDataBean fromJson(String json) { if (json.isEmpty()) { throw new IllegalArgumentException("JSON payload should not be empty"); diff --git a/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/handlers/AbstractSolaxHandler.java b/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/handlers/AbstractSolaxHandler.java index 037efa896b..cfcb9d8143 100644 --- a/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/handlers/AbstractSolaxHandler.java +++ b/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/handlers/AbstractSolaxHandler.java @@ -36,6 +36,8 @@ import org.openhab.core.types.RefreshType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.google.gson.JsonSyntaxException; + /** * The {@link SolaxCloudHandler} is responsible for handling commands, which are * sent to one of the channels. @@ -99,6 +101,10 @@ public abstract class AbstractSolaxHandler extends BaseThingHandler { updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage()); } catch (SolaxUpdateException e) { updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage()); + } catch (JsonSyntaxException jse) { + logger.debug("JsonSyntaxException received.", jse); + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, + SolaxBindingConstants.I18N_KEY_OFFLINE_CONFIGURATION_ERROR_JSON_CANNOT_BE_PARSED); } finally { retrieveDataCallLock.unlock(); } @@ -116,6 +122,14 @@ public abstract class AbstractSolaxHandler extends BaseThingHandler { } } + @Override + protected void updateStatus(ThingStatus status, ThingStatusDetail statusDetail, @Nullable String description) { + super.updateStatus(status, statusDetail, description); + if (status == ThingStatus.OFFLINE && statusDetail == ThingStatusDetail.CONFIGURATION_ERROR) { + cancelSchedule(); + } + } + @Override public void dispose() { super.dispose(); diff --git a/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/handlers/SolaxLocalAccessAbstractHandler.java b/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/handlers/SolaxLocalAccessAbstractHandler.java new file mode 100644 index 0000000000..39d55a5706 --- /dev/null +++ b/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/handlers/SolaxLocalAccessAbstractHandler.java @@ -0,0 +1,101 @@ +/** + * 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.handlers; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import javax.measure.Quantity; +import javax.measure.Unit; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.binding.solax.internal.SolaxConfiguration; +import org.openhab.binding.solax.internal.connectivity.LocalHttpConnector; +import org.openhab.binding.solax.internal.connectivity.SolaxConnector; +import org.openhab.binding.solax.internal.connectivity.rawdata.local.LocalConnectRawDataBean; +import org.openhab.core.i18n.TimeZoneProvider; +import org.openhab.core.i18n.TranslationProvider; +import org.openhab.core.library.types.QuantityType; +import org.openhab.core.thing.Channel; +import org.openhab.core.thing.Thing; +import org.openhab.core.types.UnDefType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The {@link SolaxLocalAccessAbstractHandler} abstract handler combining the common logic for an inverter and a charger + * + * @author Konstantin Polihronov - Initial contribution + */ +@NonNullByDefault +public abstract class SolaxLocalAccessAbstractHandler extends AbstractSolaxHandler { + private final Logger logger = LoggerFactory.getLogger(SolaxLocalAccessAbstractHandler.class); + + protected final Set unsupportedExistingChannels = new HashSet<>(); + protected boolean alreadyRemovedUnsupportedChannels; + + public SolaxLocalAccessAbstractHandler(Thing thing, TranslationProvider i18nProvider, + TimeZoneProvider timeZoneProvider) { + super(thing, i18nProvider, timeZoneProvider); + } + + @Override + protected SolaxConnector createConnector(SolaxConfiguration config) { + return new LocalHttpConnector(config.password, config.hostname); + } + + protected LocalConnectRawDataBean parseJson(String rawJsonData) { + LocalConnectRawDataBean fromJson = LocalConnectRawDataBean.fromJson(rawJsonData); + logger.debug("Received a new inverter JSON object. Data = {}", fromJson.toString()); + return fromJson; + } + + protected void removeUnsupportedChannels(Set supportedChannels) { + if (supportedChannels.isEmpty()) { + return; + } + List channels = getThing().getChannels(); + List channelsToRemove = channels.stream() + .filter(channel -> !supportedChannels.contains(channel.getUID().getId())).toList(); + + if (!channelsToRemove.isEmpty()) { + if (logger.isDebugEnabled()) { + logRemovedChannels(channelsToRemove); + } + updateThing(editThing().withoutChannels(channelsToRemove).build()); + } + } + + private void logRemovedChannels(List channelsToRemove) { + List channelsToRemoveForLog = channelsToRemove.stream().map(channel -> channel.getUID().getId()) + .toList(); + logger.debug("Detected unsupported channels for the current inverter. Channels to be removed: {}", + channelsToRemoveForLog); + } + + protected > void updateChannel(String channelID, double value, Unit unit, + Set supportedChannels) { + if (supportedChannels.contains(channelID)) { + if (value > Short.MIN_VALUE) { + updateState(channelID, new QuantityType<>(value, unit)); + } else if (!unsupportedExistingChannels.contains(channelID)) { + updateState(channelID, UnDefType.UNDEF); + unsupportedExistingChannels.add(channelID); + logger.warn( + "Channel {} is marked as supported, but its value is out of the defined range. Value = {}. This is unexpected behaviour. Please file a bug.", + channelID, value); + } + } + } +} diff --git a/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/handlers/SolaxLocalAccessChargerHandler.java b/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/handlers/SolaxLocalAccessChargerHandler.java new file mode 100644 index 0000000000..5609c4318a --- /dev/null +++ b/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/handlers/SolaxLocalAccessChargerHandler.java @@ -0,0 +1,129 @@ +/** + * 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.handlers; + +import java.time.ZonedDateTime; +import java.util.Set; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.binding.solax.internal.SolaxBindingConstants; +import org.openhab.binding.solax.internal.connectivity.rawdata.local.LocalConnectRawDataBean; +import org.openhab.binding.solax.internal.exceptions.SolaxUpdateException; +import org.openhab.binding.solax.internal.model.local.EvChargerData; +import org.openhab.binding.solax.internal.model.local.LocalData; +import org.openhab.binding.solax.internal.model.local.RawDataParser; +import org.openhab.binding.solax.internal.model.local.evchargers.EvChargerDataParser; +import org.openhab.core.i18n.TimeZoneProvider; +import org.openhab.core.i18n.TranslationProvider; +import org.openhab.core.library.types.DateTimeType; +import org.openhab.core.library.types.StringType; +import org.openhab.core.library.unit.SIUnits; +import org.openhab.core.library.unit.Units; +import org.openhab.core.thing.Thing; + +/** + * The {@link SolaxLocalAccessChargerHandler} the handler for the charger + * + * @author Konstantin Polihronov - Initial contribution + */ +@NonNullByDefault +public class SolaxLocalAccessChargerHandler extends SolaxLocalAccessAbstractHandler { + + private static final EvChargerDataParser parser = new EvChargerDataParser(); + + public SolaxLocalAccessChargerHandler(Thing thing, TranslationProvider i18nProvider, + TimeZoneProvider timeZoneProvider) { + super(thing, i18nProvider, timeZoneProvider); + } + + @Override + public void initialize() { + removeUnsupportedChannels(parser.getSupportedChannels()); + super.initialize(); + } + + @Override + protected void updateFromData(String rawJsonData) throws SolaxUpdateException { + LocalConnectRawDataBean rawDataBean = parseJson(rawJsonData); + EvChargerData data = parser.getData(rawDataBean); + updateChannels(parser, data); + updateProperties(data); + } + + private void updateProperties(LocalData data) { + } + + private void updateChannels(RawDataParser parser, EvChargerData data) { + Set supportedChannels = parser.getSupportedChannels(); + + // States/modes + updateState(SolaxBindingConstants.CHANNEL_CHARGER_MODE, new StringType(data.getDeviceMode())); + updateState(SolaxBindingConstants.CHANNEL_CHARGER_STATE, new StringType(data.getDeviceState())); + + // Energy + updateChannel(SolaxBindingConstants.CHANNEL_CHARGER_EQ_SINGLE_SESSION, data.getEqSingle(), Units.KILOWATT_HOUR, + supportedChannels); + updateChannel(SolaxBindingConstants.CHANNEL_CHARGER_EQ_TOTAL, data.getEqTotal(), Units.KILOWATT_HOUR, + supportedChannels); + + // Output data + updateChannel(SolaxBindingConstants.CHANNEL_CHARGER_OUTPUT_CURRENT_PHASE1, data.getCurrentPhase1(), + Units.AMPERE, supportedChannels); + updateChannel(SolaxBindingConstants.CHANNEL_CHARGER_OUTPUT_CURRENT_PHASE2, data.getCurrentPhase2(), + Units.AMPERE, supportedChannels); + updateChannel(SolaxBindingConstants.CHANNEL_CHARGER_OUTPUT_CURRENT_PHASE3, data.getCurrentPhase3(), + Units.AMPERE, supportedChannels); + + updateChannel(SolaxBindingConstants.CHANNEL_CHARGER_OUTPUT_VOLTAGE_PHASE1, data.getVoltagePhase1(), Units.VOLT, + supportedChannels); + updateChannel(SolaxBindingConstants.CHANNEL_CHARGER_OUTPUT_VOLTAGE_PHASE2, data.getVoltagePhase2(), Units.VOLT, + supportedChannels); + updateChannel(SolaxBindingConstants.CHANNEL_CHARGER_OUTPUT_VOLTAGE_PHASE3, data.getVoltagePhase3(), Units.VOLT, + supportedChannels); + + updateChannel(SolaxBindingConstants.CHANNEL_CHARGER_OUTPUT_POWER_PHASE1, data.getOutputPowerPhase1(), + Units.WATT, supportedChannels); + updateChannel(SolaxBindingConstants.CHANNEL_CHARGER_OUTPUT_POWER_PHASE2, data.getOutputPowerPhase2(), + Units.WATT, supportedChannels); + updateChannel(SolaxBindingConstants.CHANNEL_CHARGER_OUTPUT_POWER_PHASE3, data.getOutputPowerPhase3(), + Units.WATT, supportedChannels); + updateChannel(SolaxBindingConstants.CHANNEL_CHARGER_TOTAL_OUTPUT_POWER, data.getTotalChargePower(), Units.WATT, + supportedChannels); + + // Provider data + updateChannel(SolaxBindingConstants.CHANNEL_CHARGER_EXTERNAL_CURRENT_PHASE1, data.getExternalCurrentPhase1(), + Units.AMPERE, supportedChannels); + updateChannel(SolaxBindingConstants.CHANNEL_CHARGER_EXTERNAL_CURRENT_PHASE2, data.getExternalCurrentPhase2(), + Units.AMPERE, supportedChannels); + updateChannel(SolaxBindingConstants.CHANNEL_CHARGER_EXTERNAL_CURRENT_PHASE3, data.getExternalCurrentPhase3(), + Units.AMPERE, supportedChannels); + + updateChannel(SolaxBindingConstants.CHANNEL_CHARGER_EXTERNAL_POWER_PHASE1, data.getExternalPowerPhase1(), + Units.WATT, supportedChannels); + updateChannel(SolaxBindingConstants.CHANNEL_CHARGER_EXTERNAL_POWER_PHASE2, data.getExternalPowerPhase2(), + Units.WATT, supportedChannels); + updateChannel(SolaxBindingConstants.CHANNEL_CHARGER_EXTERNAL_POWER_PHASE3, data.getExternalPowerPhase3(), + Units.WATT, supportedChannels); + updateChannel(SolaxBindingConstants.CHANNEL_CHARGER_TOTAL_EXTERNAL_POWER, data.getExternalTotalPower(), + Units.WATT, supportedChannels); + + // Temperatures + updateChannel(SolaxBindingConstants.CHANNEL_CHARGER_PLUG_TEMPERATURE, data.getPlugTemperature(), + SIUnits.CELSIUS, supportedChannels); + updateChannel(SolaxBindingConstants.CHANNEL_CHARGER_INTERNAL_TEMPERATURE, data.getInternalTemperature(), + SIUnits.CELSIUS, supportedChannels); + + // Binding provided data + updateState(SolaxBindingConstants.CHANNEL_TIMESTAMP, new DateTimeType(ZonedDateTime.now())); + } +} diff --git a/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/handlers/SolaxLocalAccessHandler.java b/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/handlers/SolaxLocalAccessHandler.java deleted file mode 100644 index 60f59e74eb..0000000000 --- a/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/handlers/SolaxLocalAccessHandler.java +++ /dev/null @@ -1,263 +0,0 @@ -/** - * 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.handlers; - -import java.time.ZonedDateTime; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import javax.measure.Quantity; -import javax.measure.Unit; - -import org.eclipse.jdt.annotation.NonNullByDefault; -import org.openhab.binding.solax.internal.SolaxBindingConstants; -import org.openhab.binding.solax.internal.SolaxConfiguration; -import org.openhab.binding.solax.internal.connectivity.LocalHttpConnector; -import org.openhab.binding.solax.internal.connectivity.SolaxConnector; -import org.openhab.binding.solax.internal.connectivity.rawdata.local.LocalConnectRawDataBean; -import org.openhab.binding.solax.internal.model.InverterType; -import org.openhab.binding.solax.internal.model.local.LocalInverterData; -import org.openhab.binding.solax.internal.model.local.parsers.RawDataParser; -import org.openhab.core.i18n.TimeZoneProvider; -import org.openhab.core.i18n.TranslationProvider; -import org.openhab.core.library.types.DateTimeType; -import org.openhab.core.library.types.QuantityType; -import org.openhab.core.library.types.StringType; -import org.openhab.core.library.unit.SIUnits; -import org.openhab.core.library.unit.Units; -import org.openhab.core.thing.Channel; -import org.openhab.core.thing.Thing; -import org.openhab.core.thing.ThingStatus; -import org.openhab.core.thing.ThingStatusDetail; -import org.openhab.core.types.UnDefType; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.gson.JsonParseException; - -/** - * The {@link SolaxLocalAccessHandler} is responsible for handling commands, which are - * sent to one of the channels. - * - * @author Konstantin Polihronov - Initial contribution - */ -@NonNullByDefault -public class SolaxLocalAccessHandler extends AbstractSolaxHandler { - - private final Logger logger = LoggerFactory.getLogger(SolaxLocalAccessHandler.class); - - private boolean alreadyRemovedUnsupportedChannels; - - private final Set unsupportedExistingChannels = new HashSet<>(); - - public SolaxLocalAccessHandler(Thing thing, TranslationProvider i18nProvider, TimeZoneProvider timeZoneProvider) { - super(thing, i18nProvider, timeZoneProvider); - } - - @Override - protected SolaxConnector createConnector(SolaxConfiguration config) { - return new LocalHttpConnector(config.password, config.hostname); - } - - @Override - protected void updateFromData(String rawJsonData) { - try { - LocalConnectRawDataBean rawDataBean = parseJson(rawJsonData); - InverterType inverterType = calculateInverterType(rawDataBean); - RawDataParser parser = inverterType.getParser(); - if (parser != null) { - if (!alreadyRemovedUnsupportedChannels) { - removeUnsupportedChannels(inverterType.getSupportedChannels()); - alreadyRemovedUnsupportedChannels = true; - } - - LocalInverterData genericInverterData = parser.getData(rawDataBean); - updateChannels(parser, genericInverterData); - updateProperties(genericInverterData); - } else { - cancelSchedule(); - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, - "@text/offline.configuration-error.parser-not-implemented [\"" + inverterType.name() + "\"]"); - } - } catch (JsonParseException e) { - logger.debug("Unable to deserialize from JSON.", e); - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage()); - } - } - - private LocalConnectRawDataBean parseJson(String rawJsonData) { - LocalConnectRawDataBean fromJson = LocalConnectRawDataBean.fromJson(rawJsonData); - logger.debug("Received a new inverter JSON object. Data = {}", fromJson.toString()); - return fromJson; - } - - private InverterType calculateInverterType(LocalConnectRawDataBean rawDataBean) { - int type = rawDataBean.getType(); - return InverterType.fromIndex(type); - } - - private void updateProperties(LocalInverterData genericInverterData) { - updateProperty(Thing.PROPERTY_SERIAL_NUMBER, genericInverterData.getWifiSerial()); - updateProperty(SolaxBindingConstants.PROPERTY_INVERTER_TYPE, genericInverterData.getInverterType().name()); - } - - private void updateChannels(RawDataParser parser, LocalInverterData inverterData) { - updateState(SolaxBindingConstants.CHANNEL_RAW_DATA, new StringType(inverterData.getRawData())); - - Set supportedChannels = parser.getSupportedChannels(); - updateChannel(SolaxBindingConstants.CHANNEL_INVERTER_PV1_POWER, inverterData.getPV1Power(), Units.WATT, - supportedChannels); - updateChannel(SolaxBindingConstants.CHANNEL_INVERTER_PV1_CURRENT, inverterData.getPV1Current(), Units.AMPERE, - supportedChannels); - updateChannel(SolaxBindingConstants.CHANNEL_INVERTER_PV1_VOLTAGE, inverterData.getPV1Voltage(), Units.VOLT, - supportedChannels); - - updateChannel(SolaxBindingConstants.CHANNEL_INVERTER_PV2_POWER, inverterData.getPV2Power(), Units.WATT, - supportedChannels); - updateChannel(SolaxBindingConstants.CHANNEL_INVERTER_PV2_CURRENT, inverterData.getPV2Current(), Units.AMPERE, - supportedChannels); - updateChannel(SolaxBindingConstants.CHANNEL_INVERTER_PV2_VOLTAGE, inverterData.getPV2Voltage(), Units.VOLT, - supportedChannels); - - updateChannel(SolaxBindingConstants.CHANNEL_INVERTER_PV_TOTAL_POWER, inverterData.getPVTotalPower(), Units.WATT, - supportedChannels); - updateChannel(SolaxBindingConstants.CHANNEL_INVERTER_PV_TOTAL_CURRENT, inverterData.getPVTotalCurrent(), - Units.AMPERE, supportedChannels); - - updateChannel(SolaxBindingConstants.CHANNEL_BATTERY_POWER, inverterData.getBatteryPower(), Units.WATT, - supportedChannels); - updateChannel(SolaxBindingConstants.CHANNEL_BATTERY_CURRENT, inverterData.getBatteryCurrent(), Units.AMPERE, - supportedChannels); - updateChannel(SolaxBindingConstants.CHANNEL_BATTERY_VOLTAGE, inverterData.getBatteryVoltage(), Units.VOLT, - supportedChannels); - updateChannel(SolaxBindingConstants.CHANNEL_BATTERY_TEMPERATURE, inverterData.getBatteryTemperature(), - SIUnits.CELSIUS, supportedChannels); - updateChannel(SolaxBindingConstants.CHANNEL_BATTERY_STATE_OF_CHARGE, inverterData.getBatteryLevel(), - Units.PERCENT, supportedChannels); - updateChannel(SolaxBindingConstants.CHANNEL_FEED_IN_POWER, inverterData.getFeedInPower(), Units.WATT, - supportedChannels); - updateChannel(SolaxBindingConstants.CHANNEL_POWER_USAGE, inverterData.getPowerUsage(), Units.WATT, - supportedChannels); - updateState(SolaxBindingConstants.CHANNEL_INVERTER_WORKMODE, - new StringType(inverterData.getInverterWorkMode())); - - // Totals - updateChannel(SolaxBindingConstants.CHANNEL_TOTAL_ENERGY, inverterData.getTotalEnergy(), Units.KILOWATT_HOUR, - supportedChannels); - updateChannel(SolaxBindingConstants.CHANNEL_TOTAL_BATTERY_DISCHARGE_ENERGY, - inverterData.getTotalBatteryDischargeEnergy(), Units.KILOWATT_HOUR, supportedChannels); - updateChannel(SolaxBindingConstants.CHANNEL_TOTAL_BATTERY_CHARGE_ENERGY, - inverterData.getTotalBatteryChargeEnergy(), Units.KILOWATT_HOUR, supportedChannels); - updateChannel(SolaxBindingConstants.CHANNEL_TOTAL_PV_ENERGY, inverterData.getTotalPVEnergy(), - Units.KILOWATT_HOUR, supportedChannels); - updateChannel(SolaxBindingConstants.CHANNEL_TOTAL_FEED_IN_ENERGY, inverterData.getTotalFeedInEnergy(), - Units.KILOWATT_HOUR, supportedChannels); - updateChannel(SolaxBindingConstants.CHANNEL_TOTAL_CONSUMPTION, inverterData.getTotalConsumption(), - Units.KILOWATT_HOUR, supportedChannels); - - // Today's - updateChannel(SolaxBindingConstants.CHANNEL_TODAY_ENERGY, inverterData.getTodayEnergy(), Units.KILOWATT_HOUR, - supportedChannels); - updateChannel(SolaxBindingConstants.CHANNEL_TODAY_BATTERY_DISCHARGE_ENERGY, - inverterData.getTodayBatteryDischargeEnergy(), Units.KILOWATT_HOUR, supportedChannels); - updateChannel(SolaxBindingConstants.CHANNEL_TODAY_BATTERY_CHARGE_ENERGY, - inverterData.getTodayBatteryChargeEnergy(), Units.KILOWATT_HOUR, supportedChannels); - updateChannel(SolaxBindingConstants.CHANNEL_TODAY_FEED_IN_ENERGY, inverterData.getTodayFeedInEnergy(), - Units.KILOWATT_HOUR, supportedChannels); - updateChannel(SolaxBindingConstants.CHANNEL_TODAY_CONSUMPTION, inverterData.getTodayConsumption(), - Units.KILOWATT_HOUR, supportedChannels); - - // Single phase specific channels - updateChannel(SolaxBindingConstants.CHANNEL_INVERTER_OUTPUT_POWER, inverterData.getInverterOutputPower(), - Units.WATT, supportedChannels); - updateChannel(SolaxBindingConstants.CHANNEL_INVERTER_OUTPUT_CURRENT, inverterData.getInverterCurrent(), - Units.AMPERE, supportedChannels); - updateChannel(SolaxBindingConstants.CHANNEL_INVERTER_OUTPUT_VOLTAGE, inverterData.getInverterVoltage(), - Units.VOLT, supportedChannels); - updateChannel(SolaxBindingConstants.CHANNEL_INVERTER_OUTPUT_FREQUENCY, inverterData.getInverterFrequency(), - Units.HERTZ, supportedChannels); - - // Three phase specific channels - updateChannel(SolaxBindingConstants.CHANNEL_INVERTER_OUTPUT_POWER_PHASE1, inverterData.getOutputPowerPhase1(), - Units.WATT, supportedChannels); - updateChannel(SolaxBindingConstants.CHANNEL_INVERTER_OUTPUT_POWER_PHASE2, inverterData.getOutputPowerPhase2(), - Units.WATT, supportedChannels); - updateChannel(SolaxBindingConstants.CHANNEL_INVERTER_OUTPUT_POWER_PHASE3, inverterData.getOutputPowerPhase3(), - Units.WATT, supportedChannels); - updateChannel(SolaxBindingConstants.CHANNEL_INVERTER_TOTAL_OUTPUT_POWER, inverterData.getTotalOutputPower(), - Units.WATT, supportedChannels); - - updateChannel(SolaxBindingConstants.CHANNEL_INVERTER_OUTPUT_CURRENT_PHASE1, inverterData.getCurrentPhase1(), - Units.AMPERE, supportedChannels); - updateChannel(SolaxBindingConstants.CHANNEL_INVERTER_OUTPUT_CURRENT_PHASE2, inverterData.getCurrentPhase2(), - Units.AMPERE, supportedChannels); - updateChannel(SolaxBindingConstants.CHANNEL_INVERTER_OUTPUT_CURRENT_PHASE3, inverterData.getCurrentPhase3(), - Units.AMPERE, supportedChannels); - - updateChannel(SolaxBindingConstants.CHANNEL_INVERTER_OUTPUT_VOLTAGE_PHASE1, inverterData.getVoltagePhase1(), - Units.VOLT, supportedChannels); - updateChannel(SolaxBindingConstants.CHANNEL_INVERTER_OUTPUT_VOLTAGE_PHASE2, inverterData.getVoltagePhase2(), - Units.VOLT, supportedChannels); - updateChannel(SolaxBindingConstants.CHANNEL_INVERTER_OUTPUT_VOLTAGE_PHASE3, inverterData.getVoltagePhase3(), - Units.VOLT, supportedChannels); - - updateChannel(SolaxBindingConstants.CHANNEL_INVERTER_OUTPUT_FREQUENCY_PHASE1, inverterData.getFrequencyPhase1(), - Units.HERTZ, supportedChannels); - updateChannel(SolaxBindingConstants.CHANNEL_INVERTER_OUTPUT_FREQUENCY_PHASE2, inverterData.getFrequencyPhase2(), - Units.HERTZ, supportedChannels); - updateChannel(SolaxBindingConstants.CHANNEL_INVERTER_OUTPUT_FREQUENCY_PHASE3, inverterData.getFrequencyPhase3(), - Units.HERTZ, supportedChannels); - - // Binding provided data - updateState(SolaxBindingConstants.CHANNEL_TIMESTAMP, new DateTimeType(ZonedDateTime.now())); - } - - private void removeUnsupportedChannels(Set supportedChannels) { - if (supportedChannels.isEmpty()) { - return; - } - List channels = getThing().getChannels(); - List channelsToRemove = channels.stream() - .filter(channel -> !supportedChannels.contains(channel.getUID().getId())).toList(); - - if (!channelsToRemove.isEmpty()) { - if (logger.isDebugEnabled()) { - logRemovedChannels(channelsToRemove); - } - updateThing(editThing().withoutChannels(channelsToRemove).build()); - } - } - - private void logRemovedChannels(List channelsToRemove) { - List channelsToRemoveForLog = channelsToRemove.stream().map(channel -> channel.getUID().getId()) - .toList(); - logger.debug("Detected unsupported channels for the current inverter. Channels to be removed: {}", - channelsToRemoveForLog); - } - - private > void updateChannel(String channelID, double value, Unit unit, - Set supportedChannels) { - if (supportedChannels.contains(channelID)) { - if (value > Short.MIN_VALUE) { - updateState(channelID, new QuantityType<>(value, unit)); - } else if (!unsupportedExistingChannels.contains(channelID)) { - updateState(channelID, UnDefType.UNDEF); - unsupportedExistingChannels.add(channelID); - logger.warn( - "Channel {} is marked as supported, but its value is out of the defined range. Value = {}. This is unexpected behaviour. Please file a bug.", - channelID, value); - } - } - } -} diff --git a/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/handlers/SolaxLocalAccessInverterHandler.java b/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/handlers/SolaxLocalAccessInverterHandler.java new file mode 100644 index 0000000000..b496cc09a6 --- /dev/null +++ b/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/handlers/SolaxLocalAccessInverterHandler.java @@ -0,0 +1,199 @@ +/** + * 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.handlers; + +import java.time.ZonedDateTime; +import java.util.Set; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.binding.solax.internal.SolaxBindingConstants; +import org.openhab.binding.solax.internal.connectivity.rawdata.local.LocalConnectRawDataBean; +import org.openhab.binding.solax.internal.model.InverterType; +import org.openhab.binding.solax.internal.model.local.LocalData; +import org.openhab.binding.solax.internal.model.local.RawDataParser; +import org.openhab.core.i18n.TimeZoneProvider; +import org.openhab.core.i18n.TranslationProvider; +import org.openhab.core.library.types.DateTimeType; +import org.openhab.core.library.types.StringType; +import org.openhab.core.library.unit.SIUnits; +import org.openhab.core.library.unit.Units; +import org.openhab.core.thing.Thing; +import org.openhab.core.thing.ThingStatus; +import org.openhab.core.thing.ThingStatusDetail; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.gson.JsonParseException; + +/** + * The {@link SolaxLocalAccessInverterHandler} the handler for the inverter + * + * @author Konstantin Polihronov - Initial contribution + */ +@NonNullByDefault +public class SolaxLocalAccessInverterHandler extends SolaxLocalAccessAbstractHandler { + + private final Logger logger = LoggerFactory.getLogger(SolaxLocalAccessInverterHandler.class); + + public SolaxLocalAccessInverterHandler(Thing thing, TranslationProvider i18nProvider, + TimeZoneProvider timeZoneProvider) { + super(thing, i18nProvider, timeZoneProvider); + } + + @Override + protected void updateFromData(String rawJsonData) { + try { + LocalConnectRawDataBean rawDataBean = parseJson(rawJsonData); + InverterType inverterType = calculateInverterType(rawDataBean); + RawDataParser parser = inverterType.getParser(); + if (parser != null) { + if (!alreadyRemovedUnsupportedChannels) { + removeUnsupportedChannels(inverterType.getSupportedChannels()); + alreadyRemovedUnsupportedChannels = true; + } + + LocalData genericInverterData = parser.getData(rawDataBean); + updateChannels(parser, genericInverterData); + updateProperties(genericInverterData); + } else { + cancelSchedule(); + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, + "@text/offline.configuration-error.parser-not-implemented [\"" + inverterType.name() + "\"]"); + } + } catch (JsonParseException e) { + logger.debug("Unable to deserialize from JSON.", e); + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage()); + } + } + + private InverterType calculateInverterType(LocalConnectRawDataBean rawDataBean) { + int type = rawDataBean.getType(); + return InverterType.fromIndex(type); + } + + private void updateProperties(LocalData genericInverterData) { + updateProperty(Thing.PROPERTY_SERIAL_NUMBER, genericInverterData.getWifiSerial()); + updateProperty(SolaxBindingConstants.PROPERTY_INVERTER_TYPE, genericInverterData.getInverterType().name()); + } + + private void updateChannels(RawDataParser parser, LocalData inverterData) { + updateState(SolaxBindingConstants.CHANNEL_RAW_DATA, new StringType(inverterData.getRawData())); + + Set supportedChannels = parser.getSupportedChannels(); + updateChannel(SolaxBindingConstants.CHANNEL_INVERTER_PV1_POWER, inverterData.getPV1Power(), Units.WATT, + supportedChannels); + updateChannel(SolaxBindingConstants.CHANNEL_INVERTER_PV1_CURRENT, inverterData.getPV1Current(), Units.AMPERE, + supportedChannels); + updateChannel(SolaxBindingConstants.CHANNEL_INVERTER_PV1_VOLTAGE, inverterData.getPV1Voltage(), Units.VOLT, + supportedChannels); + + updateChannel(SolaxBindingConstants.CHANNEL_INVERTER_PV2_POWER, inverterData.getPV2Power(), Units.WATT, + supportedChannels); + updateChannel(SolaxBindingConstants.CHANNEL_INVERTER_PV2_CURRENT, inverterData.getPV2Current(), Units.AMPERE, + supportedChannels); + updateChannel(SolaxBindingConstants.CHANNEL_INVERTER_PV2_VOLTAGE, inverterData.getPV2Voltage(), Units.VOLT, + supportedChannels); + + updateChannel(SolaxBindingConstants.CHANNEL_INVERTER_PV_TOTAL_POWER, inverterData.getPVTotalPower(), Units.WATT, + supportedChannels); + updateChannel(SolaxBindingConstants.CHANNEL_INVERTER_PV_TOTAL_CURRENT, inverterData.getPVTotalCurrent(), + Units.AMPERE, supportedChannels); + + updateChannel(SolaxBindingConstants.CHANNEL_BATTERY_POWER, inverterData.getBatteryPower(), Units.WATT, + supportedChannels); + updateChannel(SolaxBindingConstants.CHANNEL_BATTERY_CURRENT, inverterData.getBatteryCurrent(), Units.AMPERE, + supportedChannels); + updateChannel(SolaxBindingConstants.CHANNEL_BATTERY_VOLTAGE, inverterData.getBatteryVoltage(), Units.VOLT, + supportedChannels); + updateChannel(SolaxBindingConstants.CHANNEL_BATTERY_TEMPERATURE, inverterData.getBatteryTemperature(), + SIUnits.CELSIUS, supportedChannels); + updateChannel(SolaxBindingConstants.CHANNEL_BATTERY_STATE_OF_CHARGE, inverterData.getBatteryLevel(), + Units.PERCENT, supportedChannels); + updateChannel(SolaxBindingConstants.CHANNEL_FEED_IN_POWER, inverterData.getFeedInPower(), Units.WATT, + supportedChannels); + updateChannel(SolaxBindingConstants.CHANNEL_POWER_USAGE, inverterData.getPowerUsage(), Units.WATT, + supportedChannels); + updateState(SolaxBindingConstants.CHANNEL_INVERTER_WORKMODE, + new StringType(inverterData.getInverterWorkMode())); + + // Totals + updateChannel(SolaxBindingConstants.CHANNEL_TOTAL_ENERGY, inverterData.getTotalEnergy(), Units.KILOWATT_HOUR, + supportedChannels); + updateChannel(SolaxBindingConstants.CHANNEL_TOTAL_BATTERY_DISCHARGE_ENERGY, + inverterData.getTotalBatteryDischargeEnergy(), Units.KILOWATT_HOUR, supportedChannels); + updateChannel(SolaxBindingConstants.CHANNEL_TOTAL_BATTERY_CHARGE_ENERGY, + inverterData.getTotalBatteryChargeEnergy(), Units.KILOWATT_HOUR, supportedChannels); + updateChannel(SolaxBindingConstants.CHANNEL_TOTAL_PV_ENERGY, inverterData.getTotalPVEnergy(), + Units.KILOWATT_HOUR, supportedChannels); + updateChannel(SolaxBindingConstants.CHANNEL_TOTAL_FEED_IN_ENERGY, inverterData.getTotalFeedInEnergy(), + Units.KILOWATT_HOUR, supportedChannels); + updateChannel(SolaxBindingConstants.CHANNEL_TOTAL_CONSUMPTION, inverterData.getTotalConsumption(), + Units.KILOWATT_HOUR, supportedChannels); + + // Today's + updateChannel(SolaxBindingConstants.CHANNEL_TODAY_ENERGY, inverterData.getTodayEnergy(), Units.KILOWATT_HOUR, + supportedChannels); + updateChannel(SolaxBindingConstants.CHANNEL_TODAY_BATTERY_DISCHARGE_ENERGY, + inverterData.getTodayBatteryDischargeEnergy(), Units.KILOWATT_HOUR, supportedChannels); + updateChannel(SolaxBindingConstants.CHANNEL_TODAY_BATTERY_CHARGE_ENERGY, + inverterData.getTodayBatteryChargeEnergy(), Units.KILOWATT_HOUR, supportedChannels); + updateChannel(SolaxBindingConstants.CHANNEL_TODAY_FEED_IN_ENERGY, inverterData.getTodayFeedInEnergy(), + Units.KILOWATT_HOUR, supportedChannels); + updateChannel(SolaxBindingConstants.CHANNEL_TODAY_CONSUMPTION, inverterData.getTodayConsumption(), + Units.KILOWATT_HOUR, supportedChannels); + + // Single phase specific channels + updateChannel(SolaxBindingConstants.CHANNEL_INVERTER_OUTPUT_POWER, inverterData.getInverterOutputPower(), + Units.WATT, supportedChannels); + updateChannel(SolaxBindingConstants.CHANNEL_INVERTER_OUTPUT_CURRENT, inverterData.getInverterCurrent(), + Units.AMPERE, supportedChannels); + updateChannel(SolaxBindingConstants.CHANNEL_INVERTER_OUTPUT_VOLTAGE, inverterData.getInverterVoltage(), + Units.VOLT, supportedChannels); + updateChannel(SolaxBindingConstants.CHANNEL_INVERTER_OUTPUT_FREQUENCY, inverterData.getInverterFrequency(), + Units.HERTZ, supportedChannels); + + // Three phase specific channels + updateChannel(SolaxBindingConstants.CHANNEL_INVERTER_OUTPUT_POWER_PHASE1, inverterData.getOutputPowerPhase1(), + Units.WATT, supportedChannels); + updateChannel(SolaxBindingConstants.CHANNEL_INVERTER_OUTPUT_POWER_PHASE2, inverterData.getOutputPowerPhase2(), + Units.WATT, supportedChannels); + updateChannel(SolaxBindingConstants.CHANNEL_INVERTER_OUTPUT_POWER_PHASE3, inverterData.getOutputPowerPhase3(), + Units.WATT, supportedChannels); + updateChannel(SolaxBindingConstants.CHANNEL_INVERTER_TOTAL_OUTPUT_POWER, inverterData.getTotalOutputPower(), + Units.WATT, supportedChannels); + + updateChannel(SolaxBindingConstants.CHANNEL_INVERTER_OUTPUT_CURRENT_PHASE1, inverterData.getCurrentPhase1(), + Units.AMPERE, supportedChannels); + updateChannel(SolaxBindingConstants.CHANNEL_INVERTER_OUTPUT_CURRENT_PHASE2, inverterData.getCurrentPhase2(), + Units.AMPERE, supportedChannels); + updateChannel(SolaxBindingConstants.CHANNEL_INVERTER_OUTPUT_CURRENT_PHASE3, inverterData.getCurrentPhase3(), + Units.AMPERE, supportedChannels); + + updateChannel(SolaxBindingConstants.CHANNEL_INVERTER_OUTPUT_VOLTAGE_PHASE1, inverterData.getVoltagePhase1(), + Units.VOLT, supportedChannels); + updateChannel(SolaxBindingConstants.CHANNEL_INVERTER_OUTPUT_VOLTAGE_PHASE2, inverterData.getVoltagePhase2(), + Units.VOLT, supportedChannels); + updateChannel(SolaxBindingConstants.CHANNEL_INVERTER_OUTPUT_VOLTAGE_PHASE3, inverterData.getVoltagePhase3(), + Units.VOLT, supportedChannels); + + updateChannel(SolaxBindingConstants.CHANNEL_INVERTER_OUTPUT_FREQUENCY_PHASE1, inverterData.getFrequencyPhase1(), + Units.HERTZ, supportedChannels); + updateChannel(SolaxBindingConstants.CHANNEL_INVERTER_OUTPUT_FREQUENCY_PHASE2, inverterData.getFrequencyPhase2(), + Units.HERTZ, supportedChannels); + updateChannel(SolaxBindingConstants.CHANNEL_INVERTER_OUTPUT_FREQUENCY_PHASE3, inverterData.getFrequencyPhase3(), + Units.HERTZ, supportedChannels); + + // Binding provided data + updateState(SolaxBindingConstants.CHANNEL_TIMESTAMP, new DateTimeType(ZonedDateTime.now())); + } +} diff --git a/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/model/InverterType.java b/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/model/InverterType.java index 17a88adecb..09996a0759 100644 --- a/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/model/InverterType.java +++ b/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/model/InverterType.java @@ -19,11 +19,11 @@ import java.util.stream.Stream; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; -import org.openhab.binding.solax.internal.model.local.parsers.RawDataParser; -import org.openhab.binding.solax.internal.model.local.parsers.X1BoostAirMiniDataParser; -import org.openhab.binding.solax.internal.model.local.parsers.X1HybridG4DataParser; -import org.openhab.binding.solax.internal.model.local.parsers.X3HybridG4DataParser; -import org.openhab.binding.solax.internal.model.local.parsers.X3MicOrProG2DataParser; +import org.openhab.binding.solax.internal.model.local.RawDataParser; +import org.openhab.binding.solax.internal.model.local.inverters.X1BoostAirMiniDataParser; +import org.openhab.binding.solax.internal.model.local.inverters.X1HybridG4DataParser; +import org.openhab.binding.solax.internal.model.local.inverters.X3HybridG4DataParser; +import org.openhab.binding.solax.internal.model.local.inverters.X3MicOrProG2DataParser; /** * The {@link InverterType} class is enum representing the different inverter types with a simple logic to convert from diff --git a/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/model/local/CommonLocalDeviceData.java b/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/model/local/CommonLocalDeviceData.java new file mode 100644 index 0000000000..4a6b16949c --- /dev/null +++ b/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/model/local/CommonLocalDeviceData.java @@ -0,0 +1,85 @@ +/** + * 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.model.local; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.openhab.binding.solax.internal.connectivity.rawdata.local.LocalConnectRawDataBean; +import org.openhab.binding.solax.internal.model.InverterType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The {@link CommonLocalDeviceData} is an abstract class that contains the common information, applicable for all + * devices. + * + * @author Konstantin Polihronov - Initial contribution + */ +@NonNullByDefault +public abstract class CommonLocalDeviceData implements LocalData { + + private final Logger logger = LoggerFactory.getLogger(CommonLocalDeviceData.class); + + private LocalConnectRawDataBean data; + + public CommonLocalDeviceData(LocalConnectRawDataBean data) { + this.data = data; + } + + @Override + public @Nullable String getRawData() { + return data.getRawData(); + } + + @Override + public @Nullable String getWifiSerial() { + return data.getSn(); + } + + @Override + public @Nullable String getWifiVersion() { + return data.getVer(); + } + + @Override + public InverterType getInverterType() { + return InverterType.fromIndex(data.getType()); + } + + protected Short getFromRawData(int index) { + try { + short[] dataArray = data.getData(); + if (dataArray != null) { + return dataArray[index]; + } + } catch (IndexOutOfBoundsException e) { + logger.debug("Tried to get data out of bounds of the raw data array.", e); + } + return 0; + } + + public long packU16(int indexMajor, int indexMinor) { + short major = getFromRawData(indexMajor); + short minor = getFromRawData(indexMinor); + if (major == 0) { + return minor; + } + + return Integer.toUnsignedLong(major << 16 | minor & 0xFFFF); + } + + @Override + public LocalConnectRawDataBean getData() { + return data; + } +} diff --git a/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/model/local/CommonLocalInverterData.java b/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/model/local/CommonLocalInverterData.java deleted file mode 100644 index 6d7f23f5ad..0000000000 --- a/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/model/local/CommonLocalInverterData.java +++ /dev/null @@ -1,80 +0,0 @@ -/** - * 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.model.local; - -import org.eclipse.jdt.annotation.NonNullByDefault; -import org.eclipse.jdt.annotation.Nullable; -import org.openhab.binding.solax.internal.connectivity.rawdata.local.LocalConnectRawDataBean; -import org.openhab.binding.solax.internal.model.InverterType; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * The {@link CommonLocalInverterData} is an abstract class that contains the common information, applicable for all - * inverters. - * - * @author Konstantin Polihronov - Initial contribution - */ -@NonNullByDefault -public abstract class CommonLocalInverterData implements LocalInverterData { - - private final Logger logger = LoggerFactory.getLogger(CommonLocalInverterData.class); - - private LocalConnectRawDataBean data; - - public CommonLocalInverterData(LocalConnectRawDataBean data) { - this.data = data; - } - - @Override - public @Nullable String getRawData() { - return data.getRawData(); - } - - @Override - public @Nullable String getWifiSerial() { - return data.getSn(); - } - - @Override - public @Nullable String getWifiVersion() { - return data.getVer(); - } - - @Override - public InverterType getInverterType() { - return InverterType.fromIndex(data.getType()); - } - - protected short getData(int index) { - try { - short[] dataArray = data.getData(); - if (dataArray != null) { - return dataArray[index]; - } - } catch (IndexOutOfBoundsException e) { - logger.debug("Tried to get data out of bounds of the raw data array.", e); - } - return 0; - } - - public long packU16(int indexMajor, int indexMinor) { - short major = getData(indexMajor); - short minor = getData(indexMinor); - if (major == 0) { - return minor; - } - - return Integer.toUnsignedLong(major << 16 | minor & 0xFFFF); - } -} diff --git a/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/model/local/EvChargerData.java b/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/model/local/EvChargerData.java new file mode 100644 index 0000000000..41962e662a --- /dev/null +++ b/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/model/local/EvChargerData.java @@ -0,0 +1,161 @@ +/** + * 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.model.local; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.binding.solax.internal.connectivity.rawdata.local.LocalConnectRawDataBean; +import org.openhab.binding.solax.internal.model.InverterType; +import org.openhab.binding.solax.internal.util.ByteUtil; + +/** + * The {@link EvChargerData} is the data representation of the EV charger, retrieved from the raw data array. + * + * @author Konstantin Polihronov - Initial contribution + */ +@NonNullByDefault +public class EvChargerData extends CommonLocalDeviceData { + + public EvChargerData(LocalConnectRawDataBean bean) { + super(bean); + } + + @Override + public InverterType getInverterType() { + return InverterType.UNKNOWN; + } + + public String getDeviceState() { + return String.valueOf(getFromRawData(0)); + } + + public String getDeviceMode() { + return String.valueOf(getFromRawData(1)); + } + + public double getEqSingle() { + return getFromRawData(12).doubleValue() / 10; + } + + public double getEqTotal() { + return ((double) ByteUtil.read32BitSigned(getFromRawData(14), getFromRawData(15))) / 10; + } + + public short getTotalChargePower() { + return getFromRawData(11); + } + + @Override + public double getVoltagePhase1() { + return getFromRawData(2).doubleValue() / 100; + } + + @Override + public double getVoltagePhase2() { + return getFromRawData(3).doubleValue() / 100; + } + + @Override + public double getVoltagePhase3() { + return getFromRawData(4).doubleValue() / 100; + } + + @Override + public double getCurrentPhase1() { + return getFromRawData(5).doubleValue() / 100; + } + + @Override + public double getCurrentPhase2() { + return getFromRawData(6).doubleValue() / 100; + } + + @Override + public double getCurrentPhase3() { + return getFromRawData(7).doubleValue() / 100; + } + + @Override + public short getOutputPowerPhase1() { + return getFromRawData(8); + } + + @Override + public short getOutputPowerPhase2() { + return getFromRawData(9); + } + + @Override + public short getOutputPowerPhase3() { + return getFromRawData(10); + } + + public double getExternalCurrentPhase1() { + return getFromRawData(16).doubleValue() / 100; + } + + public double getExternalCurrentPhase2() { + return getFromRawData(17).doubleValue() / 100; + } + + public double getExternalCurrentPhase3() { + return getFromRawData(18).doubleValue() / 100; + } + + public double getExternalPowerPhase1() { + return getFromRawData(19).intValue(); + } + + public double getExternalPowerPhase2() { + return getFromRawData(20).intValue(); + } + + public double getExternalPowerPhase3() { + return getFromRawData(21).intValue(); + } + + public double getExternalTotalPower() { + return getFromRawData(22).intValue(); + } + + public short getPlugTemperature() { + return getFromRawData(23); + } + + public short getInternalTemperature() { + return getFromRawData(24); + } + + public short getCPState() { + return getFromRawData(26); + } + + public int getChargingDuration() { + return ByteUtil.read32BitSigned(getFromRawData(80), getFromRawData(81)); + } + + public short getOccpOfflineMode() { + return getFromRawData(85); + } + + public short getTypePower() { + return getFromRawData(87); + } + + public short getTypePhase() { + return getFromRawData(88); + } + + public short getTypeCharger() { + return getFromRawData(89); + } +} diff --git a/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/model/local/LocalData.java b/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/model/local/LocalData.java new file mode 100644 index 0000000000..f9c6ac7b1e --- /dev/null +++ b/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/model/local/LocalData.java @@ -0,0 +1,241 @@ +/** + * 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.model.local; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.openhab.binding.solax.internal.connectivity.rawdata.local.LocalConnectRawDataBean; +import org.openhab.binding.solax.internal.model.InverterType; + +/** + * The {@link LocalData} Interface for the parsed inverter data in meaningful format + * + * @author Konstantin Polihronov - Initial contribution + */ +@NonNullByDefault +public interface LocalData { + + @Nullable + default String getWifiSerial() { + return getData().getSn(); + } + + @Nullable + default String getWifiVersion() { + return getData().getVer(); + } + + InverterType getInverterType(); + + @Nullable + default String getRawData() { + return getData().getRawData(); + } + + LocalConnectRawDataBean getData(); + + default double getPV1Voltage() { + return Short.MIN_VALUE; + } + + default double getPV1Current() { + return Short.MIN_VALUE; + } + + default short getPV1Power() { + return Short.MIN_VALUE; + } + + default double getPV2Voltage() { + return Short.MIN_VALUE; + } + + default double getPV2Current() { + return Short.MIN_VALUE; + } + + default short getPV2Power() { + return Short.MIN_VALUE; + } + + default double getPVTotalPower() { + return getPV1Power() + getPV2Power(); + } + + default double getPVTotalCurrent() { + return getPV1Current() + getPV2Current(); + } + + default double getBatteryVoltage() { + return Short.MIN_VALUE; + } + + default double getBatteryCurrent() { + return Short.MIN_VALUE; + } + + default short getBatteryPower() { + return Short.MIN_VALUE; + } + + default short getBatteryTemperature() { + return Short.MIN_VALUE; + } + + default short getInverterTemperature1() { + return Short.MIN_VALUE; + } + + default short getInverterTemperature2() { + return Short.MIN_VALUE; + } + + default short getBatteryLevel() { + return Short.MIN_VALUE; + } + + default short getFeedInPower() { + return Short.MIN_VALUE; + } + + default short getPowerUsage() { + return Short.MIN_VALUE; + } + + default double getTotalEnergy() { + return Short.MIN_VALUE; + } + + default short getTotalBatteryDischargeEnergy() { + return Short.MIN_VALUE; + } + + default short getTotalBatteryChargeEnergy() { + return Short.MIN_VALUE; + } + + default double getTotalPVEnergy() { + return Short.MIN_VALUE; + } + + default short getTotalFeedInEnergy() { + return Short.MIN_VALUE; + } + + default double getTotalConsumption() { + return Short.MIN_VALUE; + } + + default double getTodayEnergy() { + return Short.MIN_VALUE; + } + + default double getTodayFeedInEnergy() { + return Short.MIN_VALUE; + } + + default double getTodayConsumption() { + return Short.MIN_VALUE; + } + + default double getTodayBatteryDischargeEnergy() { + return Short.MIN_VALUE; + } + + default double getTodayBatteryChargeEnergy() { + return Short.MIN_VALUE; + } + + default double getInverterVoltage() { + return Short.MIN_VALUE; + } + + default double getInverterCurrent() { + return Short.MIN_VALUE; + } + + default short getInverterOutputPower() { + return Short.MIN_VALUE; + } + + default double getInverterFrequency() { + return Short.MIN_VALUE; + } + + default double getVoltagePhase1() { + return Short.MIN_VALUE; + } + + default double getVoltagePhase2() { + return Short.MIN_VALUE; + } + + default double getVoltagePhase3() { + return Short.MIN_VALUE; + } + + default double getCurrentPhase1() { + return Short.MIN_VALUE; + } + + default double getCurrentPhase2() { + return Short.MIN_VALUE; + } + + default double getCurrentPhase3() { + return Short.MIN_VALUE; + } + + default short getOutputPowerPhase1() { + return Short.MIN_VALUE; + } + + default short getOutputPowerPhase2() { + return Short.MIN_VALUE; + } + + default short getOutputPowerPhase3() { + return Short.MIN_VALUE; + } + + default short getTotalOutputPower() { + return Short.MIN_VALUE; + } + + default double getFrequencyPhase1() { + return Short.MIN_VALUE; + } + + default double getFrequencyPhase2() { + return Short.MIN_VALUE; + } + + default double getFrequencyPhase3() { + return Short.MIN_VALUE; + } + + default short getInverterWorkModeCode() { + return Short.MIN_VALUE; + } + + default String getInverterWorkMode() { + return String.valueOf(getInverterWorkModeCode()); + } + + default String toStringDetailed() { + return "WifiSerial = " + getWifiSerial() + ", WifiVersion = " + getWifiVersion() + ", InverterType = " + + getInverterType() + ", BatteryPower = " + getBatteryPower() + "W, Battery SoC = " + getBatteryLevel() + + "%, FeedIn Power = " + getFeedInPower() + "W, Total PV Power = " + (getPV1Power() + getPV2Power()) + + "W"; + } +} diff --git a/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/model/local/LocalInverterData.java b/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/model/local/LocalInverterData.java deleted file mode 100644 index 106aaee772..0000000000 --- a/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/model/local/LocalInverterData.java +++ /dev/null @@ -1,232 +0,0 @@ -/** - * 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.model.local; - -import org.eclipse.jdt.annotation.NonNullByDefault; -import org.eclipse.jdt.annotation.Nullable; -import org.openhab.binding.solax.internal.model.InverterType; - -/** - * The {@link LocalInverterData} Interface for the parsed inverter data in meaningful format - * - * @author Konstantin Polihronov - Initial contribution - */ -@NonNullByDefault -public interface LocalInverterData { - - @Nullable - String getWifiSerial(); - - @Nullable - String getWifiVersion(); - - InverterType getInverterType(); - - @Nullable - String getRawData(); - - default double getPV1Voltage() { - return Short.MIN_VALUE; - } - - default double getPV1Current() { - return Short.MIN_VALUE; - } - - default short getPV1Power() { - return Short.MIN_VALUE; - } - - default double getPV2Voltage() { - return Short.MIN_VALUE; - } - - default double getPV2Current() { - return Short.MIN_VALUE; - } - - default short getPV2Power() { - return Short.MIN_VALUE; - } - - default double getPVTotalPower() { - return getPV1Power() + getPV2Power(); - } - - default double getPVTotalCurrent() { - return getPV1Current() + getPV2Current(); - } - - default double getBatteryVoltage() { - return Short.MIN_VALUE; - } - - default double getBatteryCurrent() { - return Short.MIN_VALUE; - } - - default short getBatteryPower() { - return Short.MIN_VALUE; - } - - default short getBatteryTemperature() { - return Short.MIN_VALUE; - } - - default short getInverterTemperature1() { - return Short.MIN_VALUE; - } - - default short getInverterTemperature2() { - return Short.MIN_VALUE; - } - - default short getBatteryLevel() { - return Short.MIN_VALUE; - } - - default short getFeedInPower() { - return Short.MIN_VALUE; - } - - default short getPowerUsage() { - return Short.MIN_VALUE; - } - - default double getTotalEnergy() { - return Short.MIN_VALUE; - } - - default short getTotalBatteryDischargeEnergy() { - return Short.MIN_VALUE; - } - - default short getTotalBatteryChargeEnergy() { - return Short.MIN_VALUE; - } - - default double getTotalPVEnergy() { - return Short.MIN_VALUE; - } - - default short getTotalFeedInEnergy() { - return Short.MIN_VALUE; - } - - default double getTotalConsumption() { - return Short.MIN_VALUE; - } - - default double getTodayEnergy() { - return Short.MIN_VALUE; - } - - default double getTodayFeedInEnergy() { - return Short.MIN_VALUE; - } - - default double getTodayConsumption() { - return Short.MIN_VALUE; - } - - default double getTodayBatteryDischargeEnergy() { - return Short.MIN_VALUE; - } - - default double getTodayBatteryChargeEnergy() { - return Short.MIN_VALUE; - } - - default double getInverterVoltage() { - return Short.MIN_VALUE; - } - - default double getInverterCurrent() { - return Short.MIN_VALUE; - } - - default short getInverterOutputPower() { - return Short.MIN_VALUE; - } - - default double getInverterFrequency() { - return Short.MIN_VALUE; - } - - default double getVoltagePhase1() { - return Short.MIN_VALUE; - } - - default double getVoltagePhase2() { - return Short.MIN_VALUE; - } - - default double getVoltagePhase3() { - return Short.MIN_VALUE; - } - - default double getCurrentPhase1() { - return Short.MIN_VALUE; - } - - default double getCurrentPhase2() { - return Short.MIN_VALUE; - } - - default double getCurrentPhase3() { - return Short.MIN_VALUE; - } - - default short getOutputPowerPhase1() { - return Short.MIN_VALUE; - } - - default short getOutputPowerPhase2() { - return Short.MIN_VALUE; - } - - default short getOutputPowerPhase3() { - return Short.MIN_VALUE; - } - - default short getTotalOutputPower() { - return Short.MIN_VALUE; - } - - default double getFrequencyPhase1() { - return Short.MIN_VALUE; - } - - default double getFrequencyPhase2() { - return Short.MIN_VALUE; - } - - default double getFrequencyPhase3() { - return Short.MIN_VALUE; - } - - default short getInverterWorkModeCode() { - return Short.MIN_VALUE; - } - - default String getInverterWorkMode() { - return String.valueOf(getInverterWorkModeCode()); - } - - default String toStringDetailed() { - return "WifiSerial = " + getWifiSerial() + ", WifiVersion = " + getWifiVersion() + ", InverterType = " - + getInverterType() + ", BatteryPower = " + getBatteryPower() + "W, Battery SoC = " + getBatteryLevel() - + "%, FeedIn Power = " + getFeedInPower() + "W, Total PV Power = " + (getPV1Power() + getPV2Power()) - + "W"; - } -} diff --git a/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/model/local/RawDataParser.java b/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/model/local/RawDataParser.java new file mode 100644 index 0000000000..7214d30bf2 --- /dev/null +++ b/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/model/local/RawDataParser.java @@ -0,0 +1,32 @@ +/** + * 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.model.local; + +import java.util.Set; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.binding.solax.internal.connectivity.rawdata.local.LocalConnectRawDataBean; + +/** + * The {@link RawDataParser} declares generic parser implementation that parses raw data to generic inverter data which + * is common for all inverters. + * + * @author Konstantin Polihronov - Initial contribution + */ +@NonNullByDefault +public interface RawDataParser { + + LocalData getData(LocalConnectRawDataBean bean); + + Set getSupportedChannels(); +} diff --git a/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/model/local/X1BoostAirMiniData.java b/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/model/local/X1BoostAirMiniData.java new file mode 100644 index 0000000000..104ac87ec6 --- /dev/null +++ b/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/model/local/X1BoostAirMiniData.java @@ -0,0 +1,95 @@ +/** + * 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.model.local; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.binding.solax.internal.connectivity.rawdata.local.LocalConnectRawDataBean; + +/** + * The {@link X1BoostAirMiniData} is an implementation of the single phased inverter data interface for X1 Mini + * / X1 Air Mini or X1 Boost Mini inverter. + * + * @author Konstantin Polihronov - Initial contribution + */ +@NonNullByDefault +public class X1BoostAirMiniData extends CommonLocalDeviceData { + + public X1BoostAirMiniData(LocalConnectRawDataBean data) { + super(data); + } + + @Override + public double getInverterVoltage() { + return (double) getFromRawData(0) / 10; + } + + @Override + public double getInverterCurrent() { + return (double) getFromRawData(1) / 10; + } + + @Override + public short getInverterOutputPower() { + return getFromRawData(2); + } + + @Override + public double getPV1Voltage() { + return (double) getFromRawData(3) / 10; + } + + @Override + public double getPV2Voltage() { + return (double) getFromRawData(4) / 10; + } + + @Override + public double getPV1Current() { + return (double) getFromRawData(5) / 10; + } + + @Override + public double getPV2Current() { + return (double) getFromRawData(6) / 10; + } + + @Override + public short getPV1Power() { + return getFromRawData(7); + } + + @Override + public short getPV2Power() { + return getFromRawData(8); + } + + @Override + public double getInverterFrequency() { + return (double) getFromRawData(9) / 100; + } + + @Override + public double getTotalEnergy() { + return (double) getFromRawData(11) / 10; + } + + @Override + public double getTodayEnergy() { + return (double) getFromRawData(13) / 10; + } + + @Override + public short getPowerUsage() { + return (short) Math.round((double) getFromRawData(43) / 10); + } +} diff --git a/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/model/local/X1BoostAirMiniInverterData.java b/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/model/local/X1BoostAirMiniInverterData.java deleted file mode 100644 index 9c4e951180..0000000000 --- a/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/model/local/X1BoostAirMiniInverterData.java +++ /dev/null @@ -1,95 +0,0 @@ -/** - * 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.model.local; - -import org.eclipse.jdt.annotation.NonNullByDefault; -import org.openhab.binding.solax.internal.connectivity.rawdata.local.LocalConnectRawDataBean; - -/** - * The {@link X1BoostAirMiniInverterData} is an implementation of the single phased inverter data interface for X1 Mini - * / X1 Air Mini or X1 Boost Mini inverter. - * - * @author Konstantin Polihronov - Initial contribution - */ -@NonNullByDefault -public class X1BoostAirMiniInverterData extends CommonLocalInverterData { - - public X1BoostAirMiniInverterData(LocalConnectRawDataBean data) { - super(data); - } - - @Override - public double getInverterVoltage() { - return (double) getData(0) / 10; - } - - @Override - public double getInverterCurrent() { - return (double) getData(1) / 10; - } - - @Override - public short getInverterOutputPower() { - return getData(2); - } - - @Override - public double getPV1Voltage() { - return (double) getData(3) / 10; - } - - @Override - public double getPV2Voltage() { - return (double) getData(4) / 10; - } - - @Override - public double getPV1Current() { - return (double) getData(5) / 10; - } - - @Override - public double getPV2Current() { - return (double) getData(6) / 10; - } - - @Override - public short getPV1Power() { - return getData(7); - } - - @Override - public short getPV2Power() { - return getData(8); - } - - @Override - public double getInverterFrequency() { - return (double) getData(9) / 100; - } - - @Override - public double getTotalEnergy() { - return (double) getData(11) / 10; - } - - @Override - public double getTodayEnergy() { - return (double) getData(13) / 10; - } - - @Override - public short getPowerUsage() { - return (short) Math.round((double) getData(43) / 10); - } -} diff --git a/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/model/local/X1HybridG4Data.java b/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/model/local/X1HybridG4Data.java new file mode 100644 index 0000000000..ea59e4bb96 --- /dev/null +++ b/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/model/local/X1HybridG4Data.java @@ -0,0 +1,115 @@ +/** + * 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.model.local; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.binding.solax.internal.connectivity.rawdata.local.LocalConnectRawDataBean; + +/** + * The {@link X1HybridG4Data} is an implementation of the single phased inverter data interface for X1 Hybrid G4 + * inverter. + * + * @author Konstantin Polihronov - Initial contribution + */ +@NonNullByDefault +public class X1HybridG4Data extends CommonLocalDeviceData { + + public X1HybridG4Data(LocalConnectRawDataBean data) { + super(data); + } + + @Override + public double getInverterVoltage() { + return ((double) getFromRawData(0)) / 10; + } + + @Override + public double getInverterCurrent() { + return ((double) getFromRawData(1)) / 10; + } + + @Override + public short getInverterOutputPower() { + return getFromRawData(2); + } + + @Override + public double getInverterFrequency() { + return ((double) getFromRawData(3)) / 100; + } + + @Override + public short getFeedInPower() { + return getFromRawData(32); + } + + @Override + public double getPV1Voltage() { + return ((double) getFromRawData(4)) / 10; + } + + @Override + public double getPV2Voltage() { + return ((double) getFromRawData(5)) / 10; + } + + @Override + public double getPV1Current() { + return ((double) getFromRawData(6)) / 10; + } + + @Override + public double getPV2Current() { + return ((double) getFromRawData(7)) / 10; + } + + @Override + public short getPV1Power() { + return getFromRawData(8); + } + + @Override + public short getPV2Power() { + return getFromRawData(9); + } + + @Override + public double getBatteryVoltage() { + return ((double) getFromRawData(14)) / 100; + } + + @Override + public double getBatteryCurrent() { + return ((double) getFromRawData(15)) / 100; + } + + @Override + public short getBatteryPower() { + return getFromRawData(16); + } + + @Override + public short getBatteryTemperature() { + return getFromRawData(17); + } + + @Override + public short getBatteryLevel() { + return getFromRawData(18); + } + + @Override + public short getInverterWorkModeCode() { + return getFromRawData(10); + } +} diff --git a/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/model/local/X1HybridG4InverterData.java b/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/model/local/X1HybridG4InverterData.java deleted file mode 100644 index b5364595c2..0000000000 --- a/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/model/local/X1HybridG4InverterData.java +++ /dev/null @@ -1,115 +0,0 @@ -/** - * 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.model.local; - -import org.eclipse.jdt.annotation.NonNullByDefault; -import org.openhab.binding.solax.internal.connectivity.rawdata.local.LocalConnectRawDataBean; - -/** - * The {@link X1HybridG4InverterData} is an implementation of the single phased inverter data interface for X1 Hybrid G4 - * inverter. - * - * @author Konstantin Polihronov - Initial contribution - */ -@NonNullByDefault -public class X1HybridG4InverterData extends CommonLocalInverterData { - - public X1HybridG4InverterData(LocalConnectRawDataBean data) { - super(data); - } - - @Override - public double getInverterVoltage() { - return ((double) getData(0)) / 10; - } - - @Override - public double getInverterCurrent() { - return ((double) getData(1)) / 10; - } - - @Override - public short getInverterOutputPower() { - return getData(2); - } - - @Override - public double getInverterFrequency() { - return ((double) getData(3)) / 100; - } - - @Override - public short getFeedInPower() { - return getData(32); - } - - @Override - public double getPV1Voltage() { - return ((double) getData(4)) / 10; - } - - @Override - public double getPV2Voltage() { - return ((double) getData(5)) / 10; - } - - @Override - public double getPV1Current() { - return ((double) getData(6)) / 10; - } - - @Override - public double getPV2Current() { - return ((double) getData(7)) / 10; - } - - @Override - public short getPV1Power() { - return getData(8); - } - - @Override - public short getPV2Power() { - return getData(9); - } - - @Override - public double getBatteryVoltage() { - return ((double) getData(14)) / 100; - } - - @Override - public double getBatteryCurrent() { - return ((double) getData(15)) / 100; - } - - @Override - public short getBatteryPower() { - return getData(16); - } - - @Override - public short getBatteryTemperature() { - return getData(17); - } - - @Override - public short getBatteryLevel() { - return getData(18); - } - - @Override - public short getInverterWorkModeCode() { - return getData(10); - } -} diff --git a/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/model/local/X3HybridG4Data.java b/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/model/local/X3HybridG4Data.java new file mode 100644 index 0000000000..a1f1b16519 --- /dev/null +++ b/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/model/local/X3HybridG4Data.java @@ -0,0 +1,228 @@ +/** + * 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.model.local; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.binding.solax.internal.connectivity.rawdata.local.LocalConnectRawDataBean; + +/** + * The {@link X3HybridG4Data} is an implementation of the single phased inverter data interface for X3 Hybrid G4 + * inverter. + * + * @author Konstantin Polihronov - Initial contribution + */ +@NonNullByDefault +public class X3HybridG4Data extends CommonLocalDeviceData { + + public X3HybridG4Data(LocalConnectRawDataBean data) { + super(data); + } + + // Inverter data + + @Override + public double getVoltagePhase1() { + return ((double) getFromRawData(0)) / 10; + } + + @Override + public double getVoltagePhase2() { + return ((double) getFromRawData(1)) / 10; + } + + @Override + public double getVoltagePhase3() { + return ((double) getFromRawData(2)) / 10; + } + + @Override + public double getCurrentPhase1() { + return ((double) getFromRawData(3)) / 10; + } + + @Override + public double getCurrentPhase2() { + return ((double) getFromRawData(4)) / 10; + } + + @Override + public double getCurrentPhase3() { + return ((double) getFromRawData(5)) / 10; + } + + @Override + public short getOutputPowerPhase1() { + return getFromRawData(6); + } + + @Override + public short getOutputPowerPhase2() { + return getFromRawData(7); + } + + @Override + public short getOutputPowerPhase3() { + return getFromRawData(8); + } + + @Override + public short getTotalOutputPower() { + return getFromRawData(9); + } + + @Override + public double getPV1Voltage() { + return ((double) getFromRawData(10)) / 10; + } + + @Override + public double getPV2Voltage() { + return ((double) getFromRawData(11)) / 10; + } + + @Override + public double getPV1Current() { + return ((double) getFromRawData(12)) / 10; + } + + @Override + public double getPV2Current() { + return ((double) getFromRawData(13)) / 10; + } + + @Override + public short getPV1Power() { + return getFromRawData(14); + } + + @Override + public short getPV2Power() { + return getFromRawData(15); + } + + @Override + public double getFrequencyPhase1() { + return ((double) getFromRawData(16)) / 100; + } + + @Override + public double getFrequencyPhase2() { + return ((double) getFromRawData(17)) / 100; + } + + @Override + public double getFrequencyPhase3() { + return ((double) getFromRawData(18)) / 100; + } + + // Battery + + @Override + public double getBatteryVoltage() { + return ((double) getFromRawData(39)) / 100; + } + + @Override + public double getBatteryCurrent() { + return ((double) getFromRawData(40)) / 100; + } + + @Override + public short getBatteryPower() { + return getFromRawData(41); + } + + @Override + public short getBatteryTemperature() { + return getFromRawData(105); + } + + @Override + public short getBatteryLevel() { + return getFromRawData(103); + } + + // Feed in power + + @Override + public short getFeedInPower() { + return (short) (getFromRawData(34) - getFromRawData(35)); + } + + // Totals + + @Override + public short getPowerUsage() { + return getFromRawData(47); + } + + @Override + public double getTotalEnergy() { + return ((double) getFromRawData(68)) / 10; + } + + @Override + public short getTotalBatteryDischargeEnergy() { + return getFromRawData(74); + } + + @Override + public short getTotalBatteryChargeEnergy() { + return getFromRawData(76); + } + + @Override + public double getTotalPVEnergy() { + return ((double) getFromRawData(80)) / 10; + } + + @Override + public short getTotalFeedInEnergy() { + return getFromRawData(86); + } + + @Override + public double getTotalConsumption() { + return ((double) getFromRawData(88)) / 10; + } + + @Override + public double getTodayEnergy() { + return ((double) getFromRawData(82)) / 10; + } + + @Override + public double getTodayFeedInEnergy() { + return ((double) getFromRawData(90)) / 100; + } + + @Override + public double getTodayConsumption() { + return ((double) getFromRawData(92)) / 100; + } + + @Override + public double getTodayBatteryDischargeEnergy() { + return ((double) getFromRawData(78)) / 10; + } + + @Override + public double getTodayBatteryChargeEnergy() { + return ((double) getFromRawData(79)) / 10; + } + + @Override + public short getInverterWorkModeCode() { + return getFromRawData(19); + } +} diff --git a/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/model/local/X3HybridG4InverterData.java b/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/model/local/X3HybridG4InverterData.java deleted file mode 100644 index b613fb4487..0000000000 --- a/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/model/local/X3HybridG4InverterData.java +++ /dev/null @@ -1,228 +0,0 @@ -/** - * 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.model.local; - -import org.eclipse.jdt.annotation.NonNullByDefault; -import org.openhab.binding.solax.internal.connectivity.rawdata.local.LocalConnectRawDataBean; - -/** - * The {@link X3HybridG4InverterData} is responsible for handling commands, which are - * sent to one of the channels. - * - * @author Konstantin Polihronov - Initial contribution - */ -@NonNullByDefault -public class X3HybridG4InverterData extends CommonLocalInverterData { - - public X3HybridG4InverterData(LocalConnectRawDataBean data) { - super(data); - } - - // Inverter data - - @Override - public double getVoltagePhase1() { - return ((double) getData(0)) / 10; - } - - @Override - public double getVoltagePhase2() { - return ((double) getData(1)) / 10; - } - - @Override - public double getVoltagePhase3() { - return ((double) getData(2)) / 10; - } - - @Override - public double getCurrentPhase1() { - return ((double) getData(3)) / 10; - } - - @Override - public double getCurrentPhase2() { - return ((double) getData(4)) / 10; - } - - @Override - public double getCurrentPhase3() { - return ((double) getData(5)) / 10; - } - - @Override - public short getOutputPowerPhase1() { - return getData(6); - } - - @Override - public short getOutputPowerPhase2() { - return getData(7); - } - - @Override - public short getOutputPowerPhase3() { - return getData(8); - } - - @Override - public short getTotalOutputPower() { - return getData(9); - } - - @Override - public double getPV1Voltage() { - return ((double) getData(10)) / 10; - } - - @Override - public double getPV2Voltage() { - return ((double) getData(11)) / 10; - } - - @Override - public double getPV1Current() { - return ((double) getData(12)) / 10; - } - - @Override - public double getPV2Current() { - return ((double) getData(13)) / 10; - } - - @Override - public short getPV1Power() { - return getData(14); - } - - @Override - public short getPV2Power() { - return getData(15); - } - - @Override - public double getFrequencyPhase1() { - return ((double) getData(16)) / 100; - } - - @Override - public double getFrequencyPhase2() { - return ((double) getData(17)) / 100; - } - - @Override - public double getFrequencyPhase3() { - return ((double) getData(18)) / 100; - } - - // Battery - - @Override - public double getBatteryVoltage() { - return ((double) getData(39)) / 100; - } - - @Override - public double getBatteryCurrent() { - return ((double) getData(40)) / 100; - } - - @Override - public short getBatteryPower() { - return getData(41); - } - - @Override - public short getBatteryTemperature() { - return getData(105); - } - - @Override - public short getBatteryLevel() { - return getData(103); - } - - // Feed in power - - @Override - public short getFeedInPower() { - return (short) (getData(34) - getData(35)); - } - - // Totals - - @Override - public short getPowerUsage() { - return getData(47); - } - - @Override - public double getTotalEnergy() { - return ((double) getData(68)) / 10; - } - - @Override - public short getTotalBatteryDischargeEnergy() { - return getData(74); - } - - @Override - public short getTotalBatteryChargeEnergy() { - return getData(76); - } - - @Override - public double getTotalPVEnergy() { - return ((double) getData(80)) / 10; - } - - @Override - public short getTotalFeedInEnergy() { - return getData(86); - } - - @Override - public double getTotalConsumption() { - return ((double) getData(88)) / 10; - } - - @Override - public double getTodayEnergy() { - return ((double) getData(82)) / 10; - } - - @Override - public double getTodayFeedInEnergy() { - return ((double) getData(90)) / 100; - } - - @Override - public double getTodayConsumption() { - return ((double) getData(92)) / 100; - } - - @Override - public double getTodayBatteryDischargeEnergy() { - return ((double) getData(78)) / 10; - } - - @Override - public double getTodayBatteryChargeEnergy() { - return ((double) getData(79)) / 10; - } - - @Override - public short getInverterWorkModeCode() { - return getData(19); - } -} diff --git a/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/model/local/X3MicOrProG2Data.java b/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/model/local/X3MicOrProG2Data.java new file mode 100644 index 0000000000..b56fba937a --- /dev/null +++ b/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/model/local/X3MicOrProG2Data.java @@ -0,0 +1,153 @@ +/** + * 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.model.local; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.binding.solax.internal.connectivity.rawdata.local.LocalConnectRawDataBean; + +/** + * The {@link X3HybridG4Data} is responsible for handling commands, which are + * sent to one of the channels. + * + * @author Henrik Tóth - Initial contribution + * (based on X1/X3 G4 parser from Konstantin Polihronov) + */ +@NonNullByDefault +public class X3MicOrProG2Data extends CommonLocalDeviceData { + + public X3MicOrProG2Data(LocalConnectRawDataBean data) { + super(data); + } + + // Inverter data + + @Override + public double getVoltagePhase1() { + return ((double) getFromRawData(0)) / 10; + } + + @Override + public double getVoltagePhase2() { + return ((double) getFromRawData(1)) / 10; + } + + @Override + public double getVoltagePhase3() { + return ((double) getFromRawData(2)) / 10; + } + + @Override + public double getCurrentPhase1() { + return ((double) getFromRawData(3)) / 10; + } + + @Override + public double getCurrentPhase2() { + return ((double) getFromRawData(4)) / 10; + } + + @Override + public double getCurrentPhase3() { + return ((double) getFromRawData(5)) / 10; + } + + @Override + public short getOutputPowerPhase1() { + return getFromRawData(6); + } + + @Override + public short getOutputPowerPhase2() { + return getFromRawData(7); + } + + @Override + public short getOutputPowerPhase3() { + return getFromRawData(8); + } + + @Override + public double getPV1Voltage() { + return ((double) getFromRawData(9)) / 10; + } + + @Override + public double getPV2Voltage() { + return ((double) getFromRawData(10)) / 10; + } + + @Override + public double getPV1Current() { + return ((double) getFromRawData(12)) / 10; + } + + @Override + public double getPV2Current() { + return ((double) getFromRawData(13)) / 10; + } + + @Override + public short getPV1Power() { + return getFromRawData(15); + } + + @Override + public short getPV2Power() { + return getFromRawData(16); + } + + @Override + public double getFrequencyPhase1() { + return ((double) getFromRawData(18)) / 100; + } + + @Override + public double getFrequencyPhase2() { + return ((double) getFromRawData(19)) / 100; + } + + @Override + public double getFrequencyPhase3() { + return ((double) getFromRawData(20)) / 100; + } + + @Override + public short getInverterWorkModeCode() { + return getFromRawData(21); + } + + @Override + public double getTotalEnergy() { + return ((double) getFromRawData(22)) / 10; + } + + @Override + public double getTodayEnergy() { + return ((double) getFromRawData(24)) / 10; + } + + @Override + public short getInverterTemperature1() { + return getFromRawData(26); + } + + @Override + public short getInverterTemperature2() { + return getFromRawData(27); + } + + @Override + public short getTotalOutputPower() { + return getFromRawData(78); + } +} diff --git a/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/model/local/X3MicOrProG2InverterData.java b/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/model/local/X3MicOrProG2InverterData.java deleted file mode 100644 index bd0e03c7a4..0000000000 --- a/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/model/local/X3MicOrProG2InverterData.java +++ /dev/null @@ -1,153 +0,0 @@ -/** - * 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.model.local; - -import org.eclipse.jdt.annotation.NonNullByDefault; -import org.openhab.binding.solax.internal.connectivity.rawdata.local.LocalConnectRawDataBean; - -/** - * The {@link X3HybridG4InverterData} is responsible for handling commands, which are - * sent to one of the channels. - * - * @author Henrik Tóth - Initial contribution - * (based on X1/X3 G4 parser from Konstantin Polihronov) - */ -@NonNullByDefault -public class X3MicOrProG2InverterData extends CommonLocalInverterData { - - public X3MicOrProG2InverterData(LocalConnectRawDataBean data) { - super(data); - } - - // Inverter data - - @Override - public double getVoltagePhase1() { - return ((double) getData(0)) / 10; - } - - @Override - public double getVoltagePhase2() { - return ((double) getData(1)) / 10; - } - - @Override - public double getVoltagePhase3() { - return ((double) getData(2)) / 10; - } - - @Override - public double getCurrentPhase1() { - return ((double) getData(3)) / 10; - } - - @Override - public double getCurrentPhase2() { - return ((double) getData(4)) / 10; - } - - @Override - public double getCurrentPhase3() { - return ((double) getData(5)) / 10; - } - - @Override - public short getOutputPowerPhase1() { - return getData(6); - } - - @Override - public short getOutputPowerPhase2() { - return getData(7); - } - - @Override - public short getOutputPowerPhase3() { - return getData(8); - } - - @Override - public double getPV1Voltage() { - return ((double) getData(9)) / 10; - } - - @Override - public double getPV2Voltage() { - return ((double) getData(10)) / 10; - } - - @Override - public double getPV1Current() { - return ((double) getData(12)) / 10; - } - - @Override - public double getPV2Current() { - return ((double) getData(13)) / 10; - } - - @Override - public short getPV1Power() { - return getData(15); - } - - @Override - public short getPV2Power() { - return getData(16); - } - - @Override - public double getFrequencyPhase1() { - return ((double) getData(18)) / 100; - } - - @Override - public double getFrequencyPhase2() { - return ((double) getData(19)) / 100; - } - - @Override - public double getFrequencyPhase3() { - return ((double) getData(20)) / 100; - } - - @Override - public short getInverterWorkModeCode() { - return getData(21); - } - - @Override - public double getTotalEnergy() { - return ((double) getData(22)) / 10; - } - - @Override - public double getTodayEnergy() { - return ((double) getData(24)) / 10; - } - - @Override - public short getInverterTemperature1() { - return getData(26); - } - - @Override - public short getInverterTemperature2() { - return getData(27); - } - - @Override - public short getTotalOutputPower() { - return getData(78); - } -} diff --git a/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/model/local/evchargers/EvChargerDataParser.java b/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/model/local/evchargers/EvChargerDataParser.java new file mode 100644 index 0000000000..bd08d99224 --- /dev/null +++ b/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/model/local/evchargers/EvChargerDataParser.java @@ -0,0 +1,53 @@ +/** + * 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.model.local.evchargers; + +import static org.openhab.binding.solax.internal.SolaxBindingConstants.*; + +import java.util.Set; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.binding.solax.internal.connectivity.rawdata.local.LocalConnectRawDataBean; +import org.openhab.binding.solax.internal.model.local.EvChargerData; +import org.openhab.binding.solax.internal.model.local.RawDataParser; + +/** + * The {@link EvChargerDataParser} is the implementation that parses raw data into a EvChargerData for the EV charger. + * + * @author Konstantin Polihronov - Initial contribution + */ +@NonNullByDefault +public class EvChargerDataParser implements RawDataParser { + + private static final Set EV_CHARGER_SUPPORTED_CHANNELS = Set.of(CHANNEL_CHARGER_MODE, CHANNEL_CHARGER_STATE, + CHANNEL_CHARGER_EQ_SINGLE_SESSION, CHANNEL_CHARGER_EQ_TOTAL, CHANNEL_CHARGER_OUTPUT_POWER_PHASE1, + CHANNEL_CHARGER_OUTPUT_POWER_PHASE2, CHANNEL_CHARGER_OUTPUT_POWER_PHASE3, + CHANNEL_CHARGER_TOTAL_OUTPUT_POWER, CHANNEL_CHARGER_OUTPUT_CURRENT_PHASE1, + CHANNEL_CHARGER_OUTPUT_CURRENT_PHASE2, CHANNEL_CHARGER_OUTPUT_CURRENT_PHASE3, + CHANNEL_CHARGER_OUTPUT_VOLTAGE_PHASE1, CHANNEL_CHARGER_OUTPUT_VOLTAGE_PHASE2, + CHANNEL_CHARGER_OUTPUT_VOLTAGE_PHASE3, CHANNEL_CHARGER_EXTERNAL_CURRENT_PHASE1, + CHANNEL_CHARGER_EXTERNAL_CURRENT_PHASE2, CHANNEL_CHARGER_EXTERNAL_CURRENT_PHASE3, + CHANNEL_CHARGER_EXTERNAL_POWER_PHASE1, CHANNEL_CHARGER_EXTERNAL_POWER_PHASE2, + CHANNEL_CHARGER_EXTERNAL_POWER_PHASE3, CHANNEL_CHARGER_TOTAL_EXTERNAL_POWER, + CHANNEL_CHARGER_PLUG_TEMPERATURE, CHANNEL_CHARGER_INTERNAL_TEMPERATURE); + + @Override + public EvChargerData getData(LocalConnectRawDataBean bean) { + return new EvChargerData(bean); + } + + @Override + public Set getSupportedChannels() { + return EV_CHARGER_SUPPORTED_CHANNELS; + } +} diff --git a/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/model/local/inverters/X1BoostAirMiniDataParser.java b/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/model/local/inverters/X1BoostAirMiniDataParser.java new file mode 100644 index 0000000000..d79bb23cda --- /dev/null +++ b/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/model/local/inverters/X1BoostAirMiniDataParser.java @@ -0,0 +1,50 @@ +/** + * 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.model.local.inverters; + +import static org.openhab.binding.solax.internal.SolaxBindingConstants.*; + +import java.util.Set; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.binding.solax.internal.connectivity.rawdata.local.LocalConnectRawDataBean; +import org.openhab.binding.solax.internal.model.local.LocalData; +import org.openhab.binding.solax.internal.model.local.RawDataParser; +import org.openhab.binding.solax.internal.model.local.X1BoostAirMiniData; + +/** + * The {@link X1BoostAirMiniDataParser} is the implementation that parses raw data into a {@link LocalData} for the + * X1 Mini / X1 Air Mini or X1 Boost Mini inverter. + * + * @author Konstantin Polihronov - Initial contribution + */ +@NonNullByDefault +public class X1BoostAirMiniDataParser implements RawDataParser { + + private static final Set X1_BOOST_AIR_MINI_SUPPORTED_CHANNELS = Set.of(CHANNEL_INVERTER_PV1_POWER, + CHANNEL_INVERTER_PV1_VOLTAGE, CHANNEL_INVERTER_PV1_CURRENT, CHANNEL_INVERTER_PV2_POWER, + CHANNEL_INVERTER_PV2_VOLTAGE, CHANNEL_INVERTER_PV2_CURRENT, CHANNEL_INVERTER_PV_TOTAL_POWER, + CHANNEL_INVERTER_PV_TOTAL_CURRENT, CHANNEL_TIMESTAMP, CHANNEL_RAW_DATA, CHANNEL_INVERTER_OUTPUT_POWER, + CHANNEL_INVERTER_OUTPUT_CURRENT, CHANNEL_INVERTER_OUTPUT_VOLTAGE, CHANNEL_INVERTER_OUTPUT_FREQUENCY, + CHANNEL_TOTAL_ENERGY, CHANNEL_TODAY_ENERGY, CHANNEL_POWER_USAGE); + + @Override + public LocalData getData(LocalConnectRawDataBean bean) { + return new X1BoostAirMiniData(bean); + } + + @Override + public Set getSupportedChannels() { + return X1_BOOST_AIR_MINI_SUPPORTED_CHANNELS; + } +} diff --git a/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/model/local/inverters/X1HybridG4DataParser.java b/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/model/local/inverters/X1HybridG4DataParser.java new file mode 100644 index 0000000000..59abad6a4a --- /dev/null +++ b/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/model/local/inverters/X1HybridG4DataParser.java @@ -0,0 +1,51 @@ +/** + * 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.model.local.inverters; + +import static org.openhab.binding.solax.internal.SolaxBindingConstants.*; + +import java.util.Set; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.binding.solax.internal.connectivity.rawdata.local.LocalConnectRawDataBean; +import org.openhab.binding.solax.internal.model.local.LocalData; +import org.openhab.binding.solax.internal.model.local.RawDataParser; +import org.openhab.binding.solax.internal.model.local.X1HybridG4Data; + +/** + * The {@link X1HybridG4DataParser} is the implementation that parses raw data into a {@link LocalData} for the + * X1 Hybrid G4 inverter. + * + * @author Konstantin Polihronov - Initial contribution + */ +@NonNullByDefault +public class X1HybridG4DataParser implements RawDataParser { + + private static final Set X1_HYBRID_G4_SUPPORTED_CHANNELS = Set.of(CHANNEL_INVERTER_PV1_POWER, + CHANNEL_INVERTER_PV1_VOLTAGE, CHANNEL_INVERTER_PV1_CURRENT, CHANNEL_INVERTER_PV2_POWER, + CHANNEL_INVERTER_PV2_VOLTAGE, CHANNEL_INVERTER_PV2_CURRENT, CHANNEL_INVERTER_PV_TOTAL_POWER, + CHANNEL_INVERTER_PV_TOTAL_CURRENT, CHANNEL_BATTERY_POWER, CHANNEL_BATTERY_VOLTAGE, CHANNEL_BATTERY_CURRENT, + CHANNEL_BATTERY_TEMPERATURE, CHANNEL_BATTERY_STATE_OF_CHARGE, CHANNEL_FEED_IN_POWER, CHANNEL_TIMESTAMP, + CHANNEL_RAW_DATA, CHANNEL_INVERTER_OUTPUT_POWER, CHANNEL_INVERTER_OUTPUT_CURRENT, + CHANNEL_INVERTER_OUTPUT_VOLTAGE, CHANNEL_INVERTER_OUTPUT_FREQUENCY, CHANNEL_INVERTER_WORKMODE); + + @Override + public LocalData getData(LocalConnectRawDataBean rawData) { + return new X1HybridG4Data(rawData); + } + + @Override + public Set getSupportedChannels() { + return X1_HYBRID_G4_SUPPORTED_CHANNELS; + } +} diff --git a/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/model/local/inverters/X3HybridG4DataParser.java b/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/model/local/inverters/X3HybridG4DataParser.java new file mode 100644 index 0000000000..d023596593 --- /dev/null +++ b/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/model/local/inverters/X3HybridG4DataParser.java @@ -0,0 +1,59 @@ +/** + * 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.model.local.inverters; + +import static org.openhab.binding.solax.internal.SolaxBindingConstants.*; + +import java.util.Set; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.binding.solax.internal.connectivity.rawdata.local.LocalConnectRawDataBean; +import org.openhab.binding.solax.internal.model.local.LocalData; +import org.openhab.binding.solax.internal.model.local.RawDataParser; +import org.openhab.binding.solax.internal.model.local.X3HybridG4Data; + +/** + * The {@link X3HybridG4DataParser} is the implementation that parses raw data into a {@link LocalData} for the + * X3 Hybrid G4 inverter. + * + * @author Konstantin Polihronov - Initial contribution + */ +@NonNullByDefault +public class X3HybridG4DataParser implements RawDataParser { + + private static final Set X3_HYBRID_G4_SUPPORTED_CHANNELS = Set.of(CHANNEL_INVERTER_PV1_POWER, + CHANNEL_INVERTER_PV1_VOLTAGE, CHANNEL_INVERTER_PV1_CURRENT, CHANNEL_INVERTER_PV2_POWER, + CHANNEL_INVERTER_PV2_VOLTAGE, CHANNEL_INVERTER_PV2_CURRENT, CHANNEL_INVERTER_PV_TOTAL_POWER, + CHANNEL_INVERTER_PV_TOTAL_CURRENT, CHANNEL_BATTERY_POWER, CHANNEL_BATTERY_VOLTAGE, CHANNEL_BATTERY_CURRENT, + CHANNEL_BATTERY_TEMPERATURE, CHANNEL_BATTERY_STATE_OF_CHARGE, CHANNEL_FEED_IN_POWER, CHANNEL_TIMESTAMP, + CHANNEL_RAW_DATA, CHANNEL_INVERTER_OUTPUT_POWER_PHASE1, CHANNEL_INVERTER_OUTPUT_POWER_PHASE2, + CHANNEL_INVERTER_OUTPUT_POWER_PHASE3, CHANNEL_INVERTER_TOTAL_OUTPUT_POWER, + CHANNEL_INVERTER_OUTPUT_CURRENT_PHASE1, CHANNEL_INVERTER_OUTPUT_CURRENT_PHASE2, + CHANNEL_INVERTER_OUTPUT_CURRENT_PHASE3, CHANNEL_INVERTER_OUTPUT_VOLTAGE_PHASE1, + CHANNEL_INVERTER_OUTPUT_VOLTAGE_PHASE2, CHANNEL_INVERTER_OUTPUT_VOLTAGE_PHASE3, + CHANNEL_INVERTER_OUTPUT_FREQUENCY_PHASE1, CHANNEL_INVERTER_OUTPUT_FREQUENCY_PHASE2, + CHANNEL_INVERTER_OUTPUT_FREQUENCY_PHASE3, CHANNEL_POWER_USAGE, CHANNEL_TOTAL_ENERGY, + CHANNEL_TOTAL_BATTERY_CHARGE_ENERGY, CHANNEL_TOTAL_PV_ENERGY, CHANNEL_TOTAL_CONSUMPTION, + CHANNEL_TODAY_ENERGY, CHANNEL_TODAY_FEED_IN_ENERGY, CHANNEL_TODAY_CONSUMPTION, + CHANNEL_TODAY_BATTERY_CHARGE_ENERGY, CHANNEL_TODAY_BATTERY_DISCHARGE_ENERGY, CHANNEL_INVERTER_WORKMODE); + + @Override + public LocalData getData(LocalConnectRawDataBean rawData) { + return new X3HybridG4Data(rawData); + } + + @Override + public Set getSupportedChannels() { + return X3_HYBRID_G4_SUPPORTED_CHANNELS; + } +} diff --git a/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/model/local/inverters/X3MicOrProG2DataParser.java b/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/model/local/inverters/X3MicOrProG2DataParser.java new file mode 100644 index 0000000000..f63c70c23c --- /dev/null +++ b/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/model/local/inverters/X3MicOrProG2DataParser.java @@ -0,0 +1,56 @@ +/** + * 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.model.local.inverters; + +import static org.openhab.binding.solax.internal.SolaxBindingConstants.*; + +import java.util.Set; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.binding.solax.internal.connectivity.rawdata.local.LocalConnectRawDataBean; +import org.openhab.binding.solax.internal.model.local.LocalData; +import org.openhab.binding.solax.internal.model.local.RawDataParser; +import org.openhab.binding.solax.internal.model.local.X3MicOrProG2Data; + +/** + * The {@link X3MicOrProG2DataParser} is the implementation that parses raw data into a SinglePhaseInverterData for the + * X3 Mic / Pro G2 inverter. + * + * @author Henrik Tóth - Initial contribution + * (based on X1/X3 G4 parser from Konstantin Polihronov) + */ +@NonNullByDefault +public class X3MicOrProG2DataParser implements RawDataParser { + + private static final Set X3_MIC_OR_PRO_G2_SUPPORTED_CHANNELS = Set.of( + CHANNEL_INVERTER_OUTPUT_VOLTAGE_PHASE1, CHANNEL_INVERTER_OUTPUT_FREQUENCY_PHASE2, + CHANNEL_INVERTER_OUTPUT_VOLTAGE_PHASE3, CHANNEL_INVERTER_OUTPUT_CURRENT_PHASE1, + CHANNEL_INVERTER_OUTPUT_CURRENT_PHASE2, CHANNEL_INVERTER_OUTPUT_CURRENT_PHASE3, + CHANNEL_INVERTER_OUTPUT_POWER_PHASE1, CHANNEL_INVERTER_OUTPUT_POWER_PHASE2, + CHANNEL_INVERTER_OUTPUT_POWER_PHASE3, CHANNEL_INVERTER_PV1_VOLTAGE, CHANNEL_INVERTER_PV2_VOLTAGE, + CHANNEL_INVERTER_PV1_CURRENT, CHANNEL_INVERTER_PV2_CURRENT, CHANNEL_INVERTER_PV1_POWER, + CHANNEL_INVERTER_PV2_POWER, CHANNEL_INVERTER_OUTPUT_FREQUENCY_PHASE1, + CHANNEL_INVERTER_OUTPUT_VOLTAGE_PHASE2, CHANNEL_INVERTER_OUTPUT_FREQUENCY_PHASE3, CHANNEL_TOTAL_ENERGY, + CHANNEL_TODAY_ENERGY, CHANNEL_INVERTER_TOTAL_OUTPUT_POWER, CHANNEL_INVERTER_TEMPERATURE1, + CHANNEL_INVERTER_TEMPERATURE2, CHANNEL_INVERTER_WORKMODE, CHANNEL_RAW_DATA); + + @Override + public LocalData getData(LocalConnectRawDataBean rawData) { + return new X3MicOrProG2Data(rawData); + } + + @Override + public Set getSupportedChannels() { + return X3_MIC_OR_PRO_G2_SUPPORTED_CHANNELS; + } +} diff --git a/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/model/local/parsers/RawDataParser.java b/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/model/local/parsers/RawDataParser.java deleted file mode 100644 index d45cc088eb..0000000000 --- a/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/model/local/parsers/RawDataParser.java +++ /dev/null @@ -1,33 +0,0 @@ -/** - * 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.model.local.parsers; - -import java.util.Set; - -import org.eclipse.jdt.annotation.NonNullByDefault; -import org.openhab.binding.solax.internal.connectivity.rawdata.local.LocalConnectRawDataBean; -import org.openhab.binding.solax.internal.model.local.LocalInverterData; - -/** - * The {@link RawDataParser} declares generic parser implementation that parses raw data to generic inverter data which - * is common for all inverters. - * - * @author Konstantin Polihronov - Initial contribution - */ -@NonNullByDefault -public interface RawDataParser { - - LocalInverterData getData(LocalConnectRawDataBean bean); - - Set getSupportedChannels(); -} diff --git a/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/model/local/parsers/X1BoostAirMiniDataParser.java b/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/model/local/parsers/X1BoostAirMiniDataParser.java deleted file mode 100644 index 4b680b609f..0000000000 --- a/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/model/local/parsers/X1BoostAirMiniDataParser.java +++ /dev/null @@ -1,49 +0,0 @@ -/** - * 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.model.local.parsers; - -import static org.openhab.binding.solax.internal.SolaxBindingConstants.*; - -import java.util.Set; - -import org.eclipse.jdt.annotation.NonNullByDefault; -import org.openhab.binding.solax.internal.connectivity.rawdata.local.LocalConnectRawDataBean; -import org.openhab.binding.solax.internal.model.local.LocalInverterData; -import org.openhab.binding.solax.internal.model.local.X1BoostAirMiniInverterData; - -/** - * The {@link X1BoostAirMiniDataParser} is the implementation that parses raw data into a LocalInverterData for the - * X1 Mini / X1 Air Mini or X1 Boost Mini inverter. - * - * @author Konstantin Polihronov - Initial contribution - */ -@NonNullByDefault -public class X1BoostAirMiniDataParser implements RawDataParser { - - private static final Set X1_BOOST_AIR_MINI_SUPPORTED_CHANNELS = Set.of(CHANNEL_INVERTER_PV1_POWER, - CHANNEL_INVERTER_PV1_VOLTAGE, CHANNEL_INVERTER_PV1_CURRENT, CHANNEL_INVERTER_PV2_POWER, - CHANNEL_INVERTER_PV2_VOLTAGE, CHANNEL_INVERTER_PV2_CURRENT, CHANNEL_INVERTER_PV_TOTAL_POWER, - CHANNEL_INVERTER_PV_TOTAL_CURRENT, CHANNEL_TIMESTAMP, CHANNEL_RAW_DATA, CHANNEL_INVERTER_OUTPUT_POWER, - CHANNEL_INVERTER_OUTPUT_CURRENT, CHANNEL_INVERTER_OUTPUT_VOLTAGE, CHANNEL_INVERTER_OUTPUT_FREQUENCY, - CHANNEL_TOTAL_ENERGY, CHANNEL_TODAY_ENERGY, CHANNEL_POWER_USAGE); - - @Override - public LocalInverterData getData(LocalConnectRawDataBean bean) { - return new X1BoostAirMiniInverterData(bean); - } - - @Override - public Set getSupportedChannels() { - return X1_BOOST_AIR_MINI_SUPPORTED_CHANNELS; - } -} diff --git a/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/model/local/parsers/X1HybridG4DataParser.java b/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/model/local/parsers/X1HybridG4DataParser.java deleted file mode 100644 index 2804f1dbbf..0000000000 --- a/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/model/local/parsers/X1HybridG4DataParser.java +++ /dev/null @@ -1,50 +0,0 @@ -/** - * 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.model.local.parsers; - -import static org.openhab.binding.solax.internal.SolaxBindingConstants.*; - -import java.util.Set; - -import org.eclipse.jdt.annotation.NonNullByDefault; -import org.openhab.binding.solax.internal.connectivity.rawdata.local.LocalConnectRawDataBean; -import org.openhab.binding.solax.internal.model.local.LocalInverterData; -import org.openhab.binding.solax.internal.model.local.X1HybridG4InverterData; - -/** - * The {@link X1HybridG4DataParser} is the implementation that parses raw data into a LocalInverterData for the - * X1 Hybrid G4 inverter. - * - * @author Konstantin Polihronov - Initial contribution - */ -@NonNullByDefault -public class X1HybridG4DataParser implements RawDataParser { - - private static final Set X1_HYBRID_G4_SUPPORTED_CHANNELS = Set.of(CHANNEL_INVERTER_PV1_POWER, - CHANNEL_INVERTER_PV1_VOLTAGE, CHANNEL_INVERTER_PV1_CURRENT, CHANNEL_INVERTER_PV2_POWER, - CHANNEL_INVERTER_PV2_VOLTAGE, CHANNEL_INVERTER_PV2_CURRENT, CHANNEL_INVERTER_PV_TOTAL_POWER, - CHANNEL_INVERTER_PV_TOTAL_CURRENT, CHANNEL_BATTERY_POWER, CHANNEL_BATTERY_VOLTAGE, CHANNEL_BATTERY_CURRENT, - CHANNEL_BATTERY_TEMPERATURE, CHANNEL_BATTERY_STATE_OF_CHARGE, CHANNEL_FEED_IN_POWER, CHANNEL_TIMESTAMP, - CHANNEL_RAW_DATA, CHANNEL_INVERTER_OUTPUT_POWER, CHANNEL_INVERTER_OUTPUT_CURRENT, - CHANNEL_INVERTER_OUTPUT_VOLTAGE, CHANNEL_INVERTER_OUTPUT_FREQUENCY, CHANNEL_INVERTER_WORKMODE); - - @Override - public LocalInverterData getData(LocalConnectRawDataBean rawData) { - return new X1HybridG4InverterData(rawData); - } - - @Override - public Set getSupportedChannels() { - return X1_HYBRID_G4_SUPPORTED_CHANNELS; - } -} diff --git a/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/model/local/parsers/X3HybridG4DataParser.java b/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/model/local/parsers/X3HybridG4DataParser.java deleted file mode 100644 index 3cc4f11f5e..0000000000 --- a/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/model/local/parsers/X3HybridG4DataParser.java +++ /dev/null @@ -1,58 +0,0 @@ -/** - * 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.model.local.parsers; - -import static org.openhab.binding.solax.internal.SolaxBindingConstants.*; - -import java.util.Set; - -import org.eclipse.jdt.annotation.NonNullByDefault; -import org.openhab.binding.solax.internal.connectivity.rawdata.local.LocalConnectRawDataBean; -import org.openhab.binding.solax.internal.model.local.LocalInverterData; -import org.openhab.binding.solax.internal.model.local.X3HybridG4InverterData; - -/** - * The {@link X3HybridG4DataParser} is the implementation that parses raw data into a LocalInverterData for the - * X3 Hybrid G4 inverter. - * - * @author Konstantin Polihronov - Initial contribution - */ -@NonNullByDefault -public class X3HybridG4DataParser implements RawDataParser { - - private static final Set X3_HYBRID_G4_SUPPORTED_CHANNELS = Set.of(CHANNEL_INVERTER_PV1_POWER, - CHANNEL_INVERTER_PV1_VOLTAGE, CHANNEL_INVERTER_PV1_CURRENT, CHANNEL_INVERTER_PV2_POWER, - CHANNEL_INVERTER_PV2_VOLTAGE, CHANNEL_INVERTER_PV2_CURRENT, CHANNEL_INVERTER_PV_TOTAL_POWER, - CHANNEL_INVERTER_PV_TOTAL_CURRENT, CHANNEL_BATTERY_POWER, CHANNEL_BATTERY_VOLTAGE, CHANNEL_BATTERY_CURRENT, - CHANNEL_BATTERY_TEMPERATURE, CHANNEL_BATTERY_STATE_OF_CHARGE, CHANNEL_FEED_IN_POWER, CHANNEL_TIMESTAMP, - CHANNEL_RAW_DATA, CHANNEL_INVERTER_OUTPUT_POWER_PHASE1, CHANNEL_INVERTER_OUTPUT_POWER_PHASE2, - CHANNEL_INVERTER_OUTPUT_POWER_PHASE3, CHANNEL_INVERTER_TOTAL_OUTPUT_POWER, - CHANNEL_INVERTER_OUTPUT_CURRENT_PHASE1, CHANNEL_INVERTER_OUTPUT_CURRENT_PHASE2, - CHANNEL_INVERTER_OUTPUT_CURRENT_PHASE3, CHANNEL_INVERTER_OUTPUT_VOLTAGE_PHASE1, - CHANNEL_INVERTER_OUTPUT_VOLTAGE_PHASE2, CHANNEL_INVERTER_OUTPUT_VOLTAGE_PHASE3, - CHANNEL_INVERTER_OUTPUT_FREQUENCY_PHASE1, CHANNEL_INVERTER_OUTPUT_FREQUENCY_PHASE2, - CHANNEL_INVERTER_OUTPUT_FREQUENCY_PHASE3, CHANNEL_POWER_USAGE, CHANNEL_TOTAL_ENERGY, - CHANNEL_TOTAL_BATTERY_CHARGE_ENERGY, CHANNEL_TOTAL_PV_ENERGY, CHANNEL_TOTAL_CONSUMPTION, - CHANNEL_TODAY_ENERGY, CHANNEL_TODAY_FEED_IN_ENERGY, CHANNEL_TODAY_CONSUMPTION, - CHANNEL_TODAY_BATTERY_CHARGE_ENERGY, CHANNEL_TODAY_BATTERY_DISCHARGE_ENERGY, CHANNEL_INVERTER_WORKMODE); - - @Override - public LocalInverterData getData(LocalConnectRawDataBean rawData) { - return new X3HybridG4InverterData(rawData); - } - - @Override - public Set getSupportedChannels() { - return X3_HYBRID_G4_SUPPORTED_CHANNELS; - } -} diff --git a/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/model/local/parsers/X3MicOrProG2DataParser.java b/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/model/local/parsers/X3MicOrProG2DataParser.java deleted file mode 100644 index 4dec8566be..0000000000 --- a/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/model/local/parsers/X3MicOrProG2DataParser.java +++ /dev/null @@ -1,55 +0,0 @@ -/** - * 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.model.local.parsers; - -import static org.openhab.binding.solax.internal.SolaxBindingConstants.*; - -import java.util.Set; - -import org.eclipse.jdt.annotation.NonNullByDefault; -import org.openhab.binding.solax.internal.connectivity.rawdata.local.LocalConnectRawDataBean; -import org.openhab.binding.solax.internal.model.local.LocalInverterData; -import org.openhab.binding.solax.internal.model.local.X3MicOrProG2InverterData; - -/** - * The {@link X3MicOrProG2DataParser} is the implementation that parses raw data into a SinglePhaseInverterData for the - * X3 Mic / Pro G2 inverter. - * - * @author Henrik Tóth - Initial contribution - * (based on X1/X3 G4 parser from Konstantin Polihronov) - */ -@NonNullByDefault -public class X3MicOrProG2DataParser implements RawDataParser { - - private static final Set X3_MIC_OR_PRO_G2_SUPPORTED_CHANNELS = Set.of( - CHANNEL_INVERTER_OUTPUT_VOLTAGE_PHASE1, CHANNEL_INVERTER_OUTPUT_FREQUENCY_PHASE2, - CHANNEL_INVERTER_OUTPUT_VOLTAGE_PHASE3, CHANNEL_INVERTER_OUTPUT_CURRENT_PHASE1, - CHANNEL_INVERTER_OUTPUT_CURRENT_PHASE2, CHANNEL_INVERTER_OUTPUT_CURRENT_PHASE3, - CHANNEL_INVERTER_OUTPUT_POWER_PHASE1, CHANNEL_INVERTER_OUTPUT_POWER_PHASE2, - CHANNEL_INVERTER_OUTPUT_POWER_PHASE3, CHANNEL_INVERTER_PV1_VOLTAGE, CHANNEL_INVERTER_PV2_VOLTAGE, - CHANNEL_INVERTER_PV1_CURRENT, CHANNEL_INVERTER_PV2_CURRENT, CHANNEL_INVERTER_PV1_POWER, - CHANNEL_INVERTER_PV2_POWER, CHANNEL_INVERTER_OUTPUT_FREQUENCY_PHASE1, - CHANNEL_INVERTER_OUTPUT_VOLTAGE_PHASE2, CHANNEL_INVERTER_OUTPUT_FREQUENCY_PHASE3, CHANNEL_TOTAL_ENERGY, - CHANNEL_TODAY_ENERGY, CHANNEL_INVERTER_TOTAL_OUTPUT_POWER, CHANNEL_INVERTER_TEMPERATURE1, - CHANNEL_INVERTER_TEMPERATURE2, CHANNEL_INVERTER_WORKMODE, CHANNEL_RAW_DATA); - - @Override - public LocalInverterData getData(LocalConnectRawDataBean rawData) { - return new X3MicOrProG2InverterData(rawData); - } - - @Override - public Set getSupportedChannels() { - return X3_MIC_OR_PRO_G2_SUPPORTED_CHANNELS; - } -} diff --git a/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/util/ByteUtil.java b/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/util/ByteUtil.java new file mode 100644 index 0000000000..dc5b5981d3 --- /dev/null +++ b/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/util/ByteUtil.java @@ -0,0 +1,31 @@ +/** + * 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.util; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * The {@link ByteUtil} Utility method for manipulating byte-level data + * + * @author Konstantin Polihronov - Initial contribution + */ +@NonNullByDefault +public class ByteUtil { + + public static final int MASK = 0xFFFF; + public static final int SHIFT_VALUE = 16; + + public static int read32BitSigned(short low, short high) { + return (high << SHIFT_VALUE) | (low & MASK); + } +} diff --git a/bundles/org.openhab.binding.solax/src/main/resources/OH-INF/i18n/solax.properties b/bundles/org.openhab.binding.solax/src/main/resources/OH-INF/i18n/solax.properties index e5f3ee6b0c..bd1c910650 100644 --- a/bundles/org.openhab.binding.solax/src/main/resources/OH-INF/i18n/solax.properties +++ b/bundles/org.openhab.binding.solax/src/main/resources/OH-INF/i18n/solax.properties @@ -23,6 +23,8 @@ thing-type.solax.cloud-connect-inverter.channel.inverter-meter2-power.label = Me thing-type.solax.cloud-connect-inverter.channel.inverter-meter2-power.description = Inverter power on meter2. thing-type.solax.cloud-connect-inverter.channel.inverter-output-power.label = Inverter Input/Output Power thing-type.solax.cloud-connect-inverter.channel.inverter-output-power.description = Power to/from the inverter +thing-type.solax.cloud-connect-inverter.channel.inverter-workmode.label = Inverter Workmode +thing-type.solax.cloud-connect-inverter.channel.inverter-workmode.description = Inverter Workmode thing-type.solax.cloud-connect-inverter.channel.pv-total-power.label = PV Total Power thing-type.solax.cloud-connect-inverter.channel.pv-total-power.description = The sum of PV powers from all PV strings thing-type.solax.cloud-connect-inverter.channel.pv1-power.label = PV 1 Power @@ -41,6 +43,54 @@ thing-type.solax.cloud-connect-inverter.channel.total-energy.label = Yield total thing-type.solax.cloud-connect-inverter.channel.total-energy.description = Total inverter output energy thing-type.solax.cloud-connect-inverter.channel.total-feed-in-energy.label = Total Feed-In Energy thing-type.solax.cloud-connect-inverter.channel.total-feed-in-energy.description = Total energy feed-in to the electricity network. +thing-type.solax.local-connect-charger.label = Local Connect Charger +thing-type.solax.local-connect-charger.description = The charger representation that supports local connections via HTTP +thing-type.solax.local-connect-charger.channel.charger-current-phase1.label = Charger Output Current Phase 1 +thing-type.solax.local-connect-charger.channel.charger-current-phase1.description = Current from the charger phase 1 +thing-type.solax.local-connect-charger.channel.charger-current-phase2.label = Charger Output Current Phase 2 +thing-type.solax.local-connect-charger.channel.charger-current-phase2.description = Current from the charger phase 2 +thing-type.solax.local-connect-charger.channel.charger-current-phase3.label = Charger Output Current Phase 3 +thing-type.solax.local-connect-charger.channel.charger-current-phase3.description = Current from the charger phase 3 +thing-type.solax.local-connect-charger.channel.charger-external-current-phase1.label = Charger External Current Phase 1 +thing-type.solax.local-connect-charger.channel.charger-external-current-phase1.description = Current from the provider phase 1 +thing-type.solax.local-connect-charger.channel.charger-external-current-phase2.label = Charger External Current Phase 2 +thing-type.solax.local-connect-charger.channel.charger-external-current-phase2.description = Current from the provider phase 2 +thing-type.solax.local-connect-charger.channel.charger-external-current-phase3.label = Charger External Current Phase 3 +thing-type.solax.local-connect-charger.channel.charger-external-current-phase3.description = Current from the provider phase 3 +thing-type.solax.local-connect-charger.channel.charger-external-power-phase1.label = Charger External Power Phase 1 +thing-type.solax.local-connect-charger.channel.charger-external-power-phase1.description = Power from the provider phase 1 +thing-type.solax.local-connect-charger.channel.charger-external-power-phase2.label = Charger External Power Phase 2 +thing-type.solax.local-connect-charger.channel.charger-external-power-phase2.description = Power from the provider phase 2 +thing-type.solax.local-connect-charger.channel.charger-external-power-phase3.label = Charger External Power Phase 3 +thing-type.solax.local-connect-charger.channel.charger-external-power-phase3.description = Power from the provider phase 3 +thing-type.solax.local-connect-charger.channel.charger-external-total-power.label = Charger External Total Power +thing-type.solax.local-connect-charger.channel.charger-external-total-power.description = Total power from the provider +thing-type.solax.local-connect-charger.channel.charger-internal-temperature.label = Charger Internal Temperature +thing-type.solax.local-connect-charger.channel.charger-internal-temperature.description = Internal temperature on the board of the charger +thing-type.solax.local-connect-charger.channel.charger-mode.label = Charger Workmode +thing-type.solax.local-connect-charger.channel.charger-mode.description = Charger Workmode +thing-type.solax.local-connect-charger.channel.charger-output-power-phase1.label = Charger Output Power Phase 1 +thing-type.solax.local-connect-charger.channel.charger-output-power-phase1.description = Power to/from the charger phase 1 +thing-type.solax.local-connect-charger.channel.charger-output-power-phase2.label = Charger Output Power Phase 2 +thing-type.solax.local-connect-charger.channel.charger-output-power-phase2.description = Power to/from the charger phase 2 +thing-type.solax.local-connect-charger.channel.charger-output-power-phase3.label = Charger Output Power Phase 3 +thing-type.solax.local-connect-charger.channel.charger-output-power-phase3.description = Power to/from the charger phase 3 +thing-type.solax.local-connect-charger.channel.charger-plug-temperature.label = Charger Plug Temperature +thing-type.solax.local-connect-charger.channel.charger-plug-temperature.description = Temperature of the charger's plug +thing-type.solax.local-connect-charger.channel.charger-state.label = Charger State +thing-type.solax.local-connect-charger.channel.charger-state.description = Charger State +thing-type.solax.local-connect-charger.channel.charger-total-output-power.label = Charger Output Total Power +thing-type.solax.local-connect-charger.channel.charger-total-output-power.description = Power from the charger on all phases +thing-type.solax.local-connect-charger.channel.charger-voltage-phase1.label = Charger Voltage Phase 1 +thing-type.solax.local-connect-charger.channel.charger-voltage-phase1.description = Voltage of the charger's phase 1 +thing-type.solax.local-connect-charger.channel.charger-voltage-phase2.label = Charger Voltage Phase 2 +thing-type.solax.local-connect-charger.channel.charger-voltage-phase2.description = Voltage of the charger's phase 2 +thing-type.solax.local-connect-charger.channel.charger-voltage-phase3.label = Charger Voltage Phase 3 +thing-type.solax.local-connect-charger.channel.charger-voltage-phase3.description = Voltage of the charger's phase 3 +thing-type.solax.local-connect-charger.channel.eq-single-session.label = Energy charged this session +thing-type.solax.local-connect-charger.channel.eq-single-session.description = The energy charged for the current session +thing-type.solax.local-connect-charger.channel.eq-total.label = Total energy charged +thing-type.solax.local-connect-charger.channel.eq-total.description = The total energy charged for all sessions thing-type.solax.local-connect-inverter.label = Local Connect Inverter thing-type.solax.local-connect-inverter.description = The inverter representation that supports local connections via HTTP thing-type.solax.local-connect-inverter.channel.battery-current.label = Battery Current @@ -142,6 +192,12 @@ thing-type.config.solax.cloud-connect-inverter.refreshInterval.label = Refresh I thing-type.config.solax.cloud-connect-inverter.refreshInterval.description = Refresh interval in seconds. (Cloud API is limited to max 10 calls per minute and 10000 times per day) thing-type.config.solax.cloud-connect-inverter.token.label = Token thing-type.config.solax.cloud-connect-inverter.token.description = Token to access the Solax cloud API +thing-type.config.solax.local-connect-charger.hostname.label = Network Address +thing-type.config.solax.local-connect-charger.hostname.description = IP address or the host name of the Wi-Fi module +thing-type.config.solax.local-connect-charger.password.label = Password +thing-type.config.solax.local-connect-charger.password.description = Password for accessing the Wi-Fi module (the serial number of the Wi-Fi module) +thing-type.config.solax.local-connect-charger.refreshInterval.label = Refresh Interval +thing-type.config.solax.local-connect-charger.refreshInterval.description = Specifies the refresh interval in seconds. thing-type.config.solax.local-connect-inverter.hostname.label = Network Address thing-type.config.solax.local-connect-inverter.hostname.description = IP address or the host name of the Wi-Fi module thing-type.config.solax.local-connect-inverter.password.label = Password @@ -153,12 +209,45 @@ thing-type.config.solax.local-connect-inverter.refreshInterval.description = Spe channel-type.solax.battery-temperature.label = Battery Temperature channel-type.solax.battery-temperature.description = Battery Temperature +channel-type.solax.charger-mode.label = Charger Mode +channel-type.solax.charger-mode.description = Charger Mode +channel-type.solax.charger-mode.state.option.0 = Stop +channel-type.solax.charger-mode.state.option.1 = Fast +channel-type.solax.charger-mode.state.option.2 = Eco +channel-type.solax.charger-mode.state.option.3 = Green +channel-type.solax.charger-state.label = Charger State +channel-type.solax.charger-state.description = Charger State +channel-type.solax.charger-state.state.option.0 = Preparing +channel-type.solax.charger-state.state.option.1 = Preparing +channel-type.solax.charger-state.state.option.2 = Charging +channel-type.solax.charger-state.state.option.3 = Finishing +channel-type.solax.charger-state.state.option.4 = Fault +channel-type.solax.charger-state.state.option.5 = Unavailable +channel-type.solax.charger-state.state.option.6 = Reserved +channel-type.solax.charger-state.state.option.7 = Suspended EV +channel-type.solax.charger-state.state.option.8 = Suspended EV SE +channel-type.solax.charger-temperature.label = Charger Temperature +channel-type.solax.charger-temperature.description = Charger Temperature channel-type.solax.frequency.label = Electric Frequency channel-type.solax.frequency.description = Frequency of the electricity to/from the inverter -channel-type.solax.inverter-status-type.label = Inverter Status -channel-type.solax.inverter-status-type.description = The status of the inverter. channel-type.solax.inverter-temperature.label = Inverter Temperature channel-type.solax.inverter-temperature.description = Inverter Temperature +channel-type.solax.inverter-workmode-cloud.label = Inverter Workmode +channel-type.solax.inverter-workmode-cloud.description = Inverter Workmode +channel-type.solax.inverter-workmode-cloud.state.option.100 = Waiting +channel-type.solax.inverter-workmode-cloud.state.option.101 = Checking +channel-type.solax.inverter-workmode-cloud.state.option.102 = Normal +channel-type.solax.inverter-workmode-cloud.state.option.103 = Fault +channel-type.solax.inverter-workmode-cloud.state.option.104 = Permanent Fault +channel-type.solax.inverter-workmode-cloud.state.option.105 = Updating +channel-type.solax.inverter-workmode-cloud.state.option.106 = EPS Check +channel-type.solax.inverter-workmode-cloud.state.option.107 = EPS Normal +channel-type.solax.inverter-workmode-cloud.state.option.108 = Self Test +channel-type.solax.inverter-workmode-cloud.state.option.109 = Idle +channel-type.solax.inverter-workmode-cloud.state.option.110 = Standby +channel-type.solax.inverter-workmode-cloud.state.option.111 = PV Wake-up Battery +channel-type.solax.inverter-workmode-cloud.state.option.112 = GEN Check +channel-type.solax.inverter-workmode-cloud.state.option.113 = GEN Run channel-type.solax.inverter-workmode.label = Inverter Workmode channel-type.solax.inverter-workmode.description = Inverter Workmode channel-type.solax.inverter-workmode.state.option.0 = Waiting @@ -180,6 +269,11 @@ channel-type.solax.last-retrieve-time-stamp.description = Last time with a succe channel-type.solax.raw-data-type.label = Raw Data channel-type.solax.raw-data-type.description = The raw JSON data retrieved from the inverter's Wi-Fi module. +# channel types + +channel-type.solax.inverter-status-type.label = Inverter Status +channel-type.solax.inverter-status-type.description = The status of the inverter. + # thing status descriptions cloud.inverter.status.wait = Wait @@ -198,3 +292,4 @@ cloud.inverter.status.gen-run = Gen Run cloud.inverter.status.unknown = Unknown offline.communication-error.json-cannot-be-retrieved = JSON data could not be retrieved. offline.configuration-error.parser-not-implemented = Parser for inverter of type {0} is not implemented. +offline.configuration-error.json-cannot-be-parsed = Json cannot be parsed. Check your connection configuration for a wrong password. diff --git a/bundles/org.openhab.binding.solax/src/main/resources/OH-INF/thing/channel_types.xml b/bundles/org.openhab.binding.solax/src/main/resources/OH-INF/thing/channel_types.xml index 2267461b2e..20af98eb43 100644 --- a/bundles/org.openhab.binding.solax/src/main/resources/OH-INF/thing/channel_types.xml +++ b/bundles/org.openhab.binding.solax/src/main/resources/OH-INF/thing/channel_types.xml @@ -93,5 +93,46 @@ The raw JSON data retrieved from the inverter's Wi-Fi module. + + String + + Charger State + + + + + + + + + + + + + + + + String + + Charger Mode + + + + + + + + + + + Number:Temperature + + Charger Temperature + + Measurement + Temperature + + + diff --git a/bundles/org.openhab.binding.solax/src/main/resources/OH-INF/thing/localConnectEVCharger.xml b/bundles/org.openhab.binding.solax/src/main/resources/OH-INF/thing/localConnectEVCharger.xml new file mode 100644 index 0000000000..51325c97d4 --- /dev/null +++ b/bundles/org.openhab.binding.solax/src/main/resources/OH-INF/thing/localConnectEVCharger.xml @@ -0,0 +1,129 @@ + + + + + + + The charger representation that supports local connections via HTTP + + + + + The energy charged for the current session + + + + The total energy charged for all sessions + + + + Power to/from the charger phase 1 + + + + Power to/from the charger phase 2 + + + + Power to/from the charger phase 3 + + + + Power from the charger on all phases + + + + Current from the charger phase 1 + + + + Current from the charger phase 2 + + + + Current from the charger phase 3 + + + + Voltage of the charger's phase 1 + + + + Voltage of the charger's phase 2 + + + + Voltage of the charger's phase 3 + + + + + Current from the provider phase 1 + + + + Current from the provider phase 2 + + + + Current from the provider phase 3 + + + + Power from the provider phase 1 + + + + Power from the provider phase 2 + + + + Power from the provider phase 3 + + + + Total power from the provider + + + + + Temperature of the charger's plug + + + + Internal temperature on the board of the charger + + + + Charger Workmode + + + + Charger State + + + + + + + + + Specifies the refresh interval in seconds. + 10 + + + + Password for accessing the Wi-Fi module (the serial number of the Wi-Fi module) + password + + + + IP address or the host name of the Wi-Fi module + network-address + + + + diff --git a/bundles/org.openhab.binding.solax/src/test/java/org/openhab/binding/solax/internal/local/AbstractParserTest.java b/bundles/org.openhab.binding.solax/src/test/java/org/openhab/binding/solax/internal/local/AbstractParserTest.java index 791e304ba4..3b840a8972 100644 --- a/bundles/org.openhab.binding.solax/src/test/java/org/openhab/binding/solax/internal/local/AbstractParserTest.java +++ b/bundles/org.openhab.binding.solax/src/test/java/org/openhab/binding/solax/internal/local/AbstractParserTest.java @@ -20,8 +20,8 @@ import org.eclipse.jdt.annotation.NonNullByDefault; import org.junit.jupiter.api.Test; import org.openhab.binding.solax.internal.connectivity.rawdata.local.LocalConnectRawDataBean; import org.openhab.binding.solax.internal.model.InverterType; -import org.openhab.binding.solax.internal.model.local.LocalInverterData; -import org.openhab.binding.solax.internal.model.local.parsers.RawDataParser; +import org.openhab.binding.solax.internal.model.local.LocalData; +import org.openhab.binding.solax.internal.model.local.RawDataParser; /** * The {@link AbstractParserTest} Abstract class defining the common logic for testing local connections to the various @@ -44,7 +44,7 @@ public abstract class AbstractParserTest { Set supportedChannels = parser.getSupportedChannels(); assertFalse(supportedChannels.isEmpty()); - LocalInverterData data = parser.getData(bean); + LocalData data = parser.getData(bean); assertParserSpecific(data); } @@ -52,5 +52,5 @@ public abstract class AbstractParserTest { protected abstract String getRawData(); - protected abstract void assertParserSpecific(LocalInverterData data); + protected abstract void assertParserSpecific(LocalData data); } diff --git a/bundles/org.openhab.binding.solax/src/test/java/org/openhab/binding/solax/internal/local/TestX1BoostAirMiniDataParser.java b/bundles/org.openhab.binding.solax/src/test/java/org/openhab/binding/solax/internal/local/TestX1BoostAirMiniDataParser.java deleted file mode 100644 index 66f6f4bcff..0000000000 --- a/bundles/org.openhab.binding.solax/src/test/java/org/openhab/binding/solax/internal/local/TestX1BoostAirMiniDataParser.java +++ /dev/null @@ -1,79 +0,0 @@ -/** - * 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.local; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -import org.eclipse.jdt.annotation.NonNullByDefault; -import org.openhab.binding.solax.internal.model.InverterType; -import org.openhab.binding.solax.internal.model.local.LocalInverterData; - -/** - * The {@link TestX1BoostAirMiniDataParser} Simple test that tests for proper parsing against a real data from the - * inverter - * - * @author Konstantin Polihronov - Initial contribution - */ -@NonNullByDefault -public class TestX1BoostAirMiniDataParser extends AbstractParserTest { - - private static final String RAW_DATA = """ - { - sn:SR***, - ver:3.006.04, - type:4, - Data:[ - 2263,7,128,1519,0,9,0,138,0,5000, - 2,15569,0,7,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,13, - 0,4071,0,3456,0,0,0,0,0,0, - 0,0,0,0,0,23,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 - ], - Information:[1.500,4,XM3A15IA669518,8,2.27,0.00,1.43,0.00,0.00,1]} - """; - - @Override - protected String getRawData() { - return RAW_DATA; - } - - @Override - protected void assertParserSpecific(LocalInverterData data) { - assertEquals("SR***", data.getWifiSerial()); - assertEquals("3.006.04", data.getWifiVersion()); - - assertEquals(226.3, data.getInverterVoltage()); // [0] - assertEquals(0.7, data.getInverterCurrent()); // [1] - assertEquals(128, data.getInverterOutputPower()); // [2] - - assertEquals(151.9, data.getPV1Voltage()); // [3] - assertEquals(0, data.getPV2Voltage()); // [4] - assertEquals(0.9, data.getPV1Current()); // [5] - assertEquals(0, data.getPV2Current()); // [6] - assertEquals(138, data.getPV1Power()); // [7] - assertEquals(0, data.getPV2Power()); // [8] - - assertEquals(50, data.getInverterFrequency()); // [9] - - assertEquals(1556.9, data.getTotalEnergy()); // [11] - assertEquals(0.7, data.getTodayEnergy()); // [13] - - assertEquals(346, data.getPowerUsage()); // [43] - } - - @Override - protected InverterType getInverterType() { - return InverterType.X1_BOOST_AIR_MINI; - } -} diff --git a/bundles/org.openhab.binding.solax/src/test/java/org/openhab/binding/solax/internal/local/TestX1HybridG4Parser.java b/bundles/org.openhab.binding.solax/src/test/java/org/openhab/binding/solax/internal/local/TestX1HybridG4Parser.java deleted file mode 100644 index f2d2032469..0000000000 --- a/bundles/org.openhab.binding.solax/src/test/java/org/openhab/binding/solax/internal/local/TestX1HybridG4Parser.java +++ /dev/null @@ -1,105 +0,0 @@ -/** - * 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.local; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -import org.eclipse.jdt.annotation.NonNullByDefault; -import org.openhab.binding.solax.internal.model.InverterType; -import org.openhab.binding.solax.internal.model.local.LocalInverterData; - -/** - * The {@link TestX1HybridG4Parser} Simple test that tests for proper parsing against a real data from the inverter - * - * @author Konstantin Polihronov - Initial contribution - */ -@NonNullByDefault -public class TestX1HybridG4Parser extends AbstractParserTest { - - private static final String RAW_DATA = """ - { - sn:SOME_SERIAL_NUMBER, - ver:3.008.10, - type:15, - Data:[ - 2388,21,460,4998,4483,4483,10,1,487,65, - 2,59781,0,70,12180,500,605,33,99,12000, - 0,23159,0,57,100,0,39,4501,0,0, - 0,0,12,0,13240,0,63348,2,448,43, - 256,1314,900,0,350,311,279,33,33,279,1,1,652,0,708,1,65077,65535,65386,65535,0,0,0,0,0,0,0,0,0,0,0,0,65068,65535,4500,0,61036,65535,10,0,90,0,0,12,0,116,7,57,0,0,2320,0,110,0,0,0,0,0,0,12544,7440,5896,594,521,9252,0,0,0,0,0,1,1201,0,0,3342,3336,7296,54,21302,14389,18753,12852,16692,12355,13618,21302,14389,18753,12852,16692,12355,13618,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1025,4609,1026,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], - Information:[7.500,15,H4752TI1063020,8,1.24,0.00,1.21,1.03,0.00,1]} - """; - - @Override - protected InverterType getInverterType() { - return InverterType.X1_HYBRID_G4; - } - - @Override - protected void assertParserSpecific(LocalInverterData data) { - assertEquals("SOME_SERIAL_NUMBER", data.getWifiSerial()); - assertEquals("3.008.10", data.getWifiVersion()); - - assertEquals(238.8, data.getInverterVoltage()); // [0] - assertEquals(2.1, data.getInverterCurrent()); // [1] - assertEquals(460, data.getInverterOutputPower()); // [2] - assertEquals(49.98, data.getInverterFrequency()); // [3] - - assertEquals(448.3, data.getPV1Voltage()); // [4] - assertEquals(448.3, data.getPV2Voltage()); // [5] - assertEquals(1, data.getPV1Current()); // [6] - assertEquals(0.1, data.getPV2Current()); // [7] - assertEquals(487, data.getPV1Power()); // [8] - assertEquals(65, data.getPV2Power()); // [9] - - assertEquals(2, data.getInverterWorkModeCode()); // [10] - assertEquals("2", data.getInverterWorkMode()); // [10] - - assertEquals(121.8, data.getBatteryVoltage()); // [14] - assertEquals(5, data.getBatteryCurrent()); // [15] - assertEquals(605, data.getBatteryPower()); // [16] - assertEquals(33, data.getBatteryTemperature()); // [17] - assertEquals(99, data.getBatteryLevel()); // [18] - - assertEquals(12, data.getFeedInPower()); // [32] - } - - @Override - protected String getRawData() { - return RAW_DATA; - } - - // Yield_Today: Data[13] / 10, - // Yield_Total: read32BitUnsigned(Data[11], Data[12]) / 10, - // PowerDc1: Data[8], - // PowerDc2: Data[9], - // BAT_Power: read16BitSigned(Data[16]), - // feedInPower: read32BitSigned(Data[32], Data[33]), - // GridAPower: read16BitSigned(Data[2]), - // FeedInEnergy: read32BitUnsigned(Data[34], Data[35]) / 100, - // ConsumeEnergy: read32BitUnsigned(Data[36], Data[37]) / 100, - // RunMode: Data[10], - // EPSAPower: read16BitSigned(Data[28]), - // Vdc1: Data[4] / 10, - // Vdc2: Data[5] / 10, - // Idc1: Data[6] / 10, - // Idc2: Data[7] / 10, - // EPSAVoltage: Data[29] / 10, - // EPSACurrent: read16BitSigned(Data[30]) / 10, - // BatteryCapacity: Data[18], - // BatteryVoltage: Data[14] / 100, - // BatteryTemperature: read16BitSigned(Data[17]), - // GridAVoltage: Data[0] / 10, - // GridACurrent: read16BitSigned(Data[1]) / 10, - // FreqacA: Data[3] / 100, -} diff --git a/bundles/org.openhab.binding.solax/src/test/java/org/openhab/binding/solax/internal/local/TestX3HybridG4Parser.java b/bundles/org.openhab.binding.solax/src/test/java/org/openhab/binding/solax/internal/local/TestX3HybridG4Parser.java deleted file mode 100644 index a30172c981..0000000000 --- a/bundles/org.openhab.binding.solax/src/test/java/org/openhab/binding/solax/internal/local/TestX3HybridG4Parser.java +++ /dev/null @@ -1,115 +0,0 @@ -/** - * 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.local; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -import org.eclipse.jdt.annotation.NonNullByDefault; -import org.openhab.binding.solax.internal.model.InverterType; -import org.openhab.binding.solax.internal.model.local.LocalInverterData; - -/** - * The {@link TestX3HybridG4Parser} simple test that tests for proper parsing against a real data from the inverter - * - * @author Konstantin Polihronov - Initial contribution - */ -@NonNullByDefault -public class TestX3HybridG4Parser extends AbstractParserTest { - - private static final String RAW_DATA = """ - { - sn:XYZ, - ver:3.005.01, - type:14,Data:[ - 2316,2329,2315,18,18,18,372,363,365,1100, - 12,23,34,45,56,67,4996,4996,4996,2, - 0,0,0,0,0,0,0,0,0,0, - 0,0,0,1,65494,65535,0,0,0,31330, - 320,1034,3078,1,44,1100,256,1294,0,0, - 7445,5895,100,0,38,0,0,0,0,0, - 0,0,0,0,0,0,0,0,505,0, - 396,0,0,0,102,0,142,0,62,110, - 570,0,463,0,0,0,1925,0,369,0, - 506,1925,304,309,0,0,0,0,0,0, - 0,0,0,45,1,59,1,34,54,256, - 3504,2400,300,300,295,276,33,33,2,1620,779,15163,15163,14906,0,0,0,3270,3264,45581,0,20564,12339,18753,12353,18742,12356,13625,20564,12339,18754,12866,18743,14151,13104,20564,12339,18754,12866,18743,14151,12592,20564,12339,18754,12865,18738,12871,13620,0,0,0,0,0,0,0,1025,8195,769,259,0,31460,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], - Information:[12.000,14,XY,8,1.23,0.00,1.24,1.09,0.00,1] - } - """; - - @Override - protected InverterType getInverterType() { - return InverterType.X3_HYBRID_G4; - } - - @Override - protected void assertParserSpecific(LocalInverterData data) { - assertEquals("XYZ", data.getWifiSerial()); - assertEquals("3.005.01", data.getWifiVersion()); - - assertEquals(231.6, data.getVoltagePhase1()); // [0] - assertEquals(232.9, data.getVoltagePhase2()); // [1] - assertEquals(231.5, data.getVoltagePhase3()); // [2] - - assertEquals(1.8, data.getCurrentPhase1()); // [3] - assertEquals(1.8, data.getCurrentPhase2()); // [4] - assertEquals(1.8, data.getCurrentPhase3()); // [5] - - assertEquals(372, data.getOutputPowerPhase1()); // [6] - assertEquals(363, data.getOutputPowerPhase2()); // [7] - assertEquals(365, data.getOutputPowerPhase3()); // [8] - - assertEquals(1100, data.getTotalOutputPower()); // [9] - - assertEquals(1.2, data.getPV1Voltage()); // [10] - assertEquals(2.3, data.getPV2Voltage()); // [11] - assertEquals(3.4, data.getPV1Current()); // [12] - assertEquals(4.5, data.getPV2Current()); // [13] - assertEquals(56, data.getPV1Power()); // [14] - assertEquals(67, data.getPV2Power()); // [15] - - assertEquals(49.96, data.getFrequencyPhase1()); // [16] - assertEquals(49.96, data.getFrequencyPhase2()); // [17] - assertEquals(49.96, data.getFrequencyPhase3()); // [18] - - assertEquals(2, data.getInverterWorkModeCode()); // [19] - assertEquals("2", data.getInverterWorkMode()); // [19] - - assertEquals(-41, data.getFeedInPower()); // [34] - [35] - - assertEquals(313.3, data.getBatteryVoltage()); // [39] - assertEquals(3.2, data.getBatteryCurrent()); // [40] - assertEquals(1034, data.getBatteryPower()); // [41] - assertEquals(45, data.getBatteryLevel()); // [103] - assertEquals(59, data.getBatteryTemperature()); // [105] - - // Totals - assertEquals(1294, data.getPowerUsage()); // [47] - assertEquals(50.5, data.getTotalEnergy()); // [68] - assertEquals(102, data.getTotalBatteryDischargeEnergy()); // [74] - assertEquals(142, data.getTotalBatteryChargeEnergy()); // [76] - assertEquals(57, data.getTotalPVEnergy()); // [80] - assertEquals(1925, data.getTotalFeedInEnergy()); // [86] - assertEquals(36.9, data.getTotalConsumption()); // [88] - assertEquals(46.3, data.getTodayEnergy()); // [82] / 10 - assertEquals(5.06, data.getTodayFeedInEnergy()); // [90] / 100 - assertEquals(3.04, data.getTodayConsumption()); // [92] / 100 - assertEquals(6.2, data.getTodayBatteryDischargeEnergy()); // [78] / 100 - assertEquals(11, data.getTodayBatteryChargeEnergy()); // [79] / 100 - } - - @Override - protected String getRawData() { - return RAW_DATA; - } -} diff --git a/bundles/org.openhab.binding.solax/src/test/java/org/openhab/binding/solax/internal/local/TestX3MicOrProG2Parser.java b/bundles/org.openhab.binding.solax/src/test/java/org/openhab/binding/solax/internal/local/TestX3MicOrProG2Parser.java deleted file mode 100644 index 29846be0de..0000000000 --- a/bundles/org.openhab.binding.solax/src/test/java/org/openhab/binding/solax/internal/local/TestX3MicOrProG2Parser.java +++ /dev/null @@ -1,97 +0,0 @@ -/** - * 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.local; - -import static org.junit.jupiter.api.Assertions.*; - -import org.eclipse.jdt.annotation.NonNullByDefault; -import org.junit.jupiter.api.Test; -import org.openhab.binding.solax.internal.connectivity.rawdata.local.LocalConnectRawDataBean; -import org.openhab.binding.solax.internal.model.InverterType; -import org.openhab.binding.solax.internal.model.local.LocalInverterData; -import org.openhab.binding.solax.internal.model.local.parsers.RawDataParser; - -/** - * The {@link TestX3HybridG4Parser} simple test that tests for proper parsing against a real data from the inverter - * - * @author Konstantin Polihronov - Initial contribution - */ -@NonNullByDefault -public class TestX3MicOrProG2Parser { - - String rawData = """ - { - sn:XYZ, - ver:3.003.02, - type:16,Data:[ - 2515,2449,2484,5,5,9,54,44,20,4080,4340, - 0,1,2,0,67,102,0,4999,4999,4999,2,19035, - 0,50,8000,5,9, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0, - 0,0,0,0,0,0,0,0,120,40,1,6,5,0,6772,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0 - ], - Information:[8.000,16,XY,8,1.15,0.00,1.11,1.01,0.00,1] - } - """; - - @Test - public void testParser() { - LocalConnectRawDataBean bean = LocalConnectRawDataBean.fromJson(rawData); - int type = bean.getType(); - InverterType inverterType = InverterType.fromIndex(type); - assertEquals(InverterType.X3_MIC_OR_PRO_G2, inverterType, "Inverter type not recognized properly"); - - RawDataParser parser = inverterType.getParser(); - assertNotNull(parser); - - LocalInverterData data = parser.getData(bean); - assertEquals("XYZ", data.getWifiSerial()); - assertEquals("3.003.02", data.getWifiVersion()); - - assertEquals(251.5, data.getVoltagePhase1()); // [0] - assertEquals(244.9, data.getVoltagePhase2()); // [1] - assertEquals(248.4, data.getVoltagePhase3()); // [2] - - assertEquals(0.5, data.getCurrentPhase1()); // [3] - assertEquals(0.5, data.getCurrentPhase2()); // [4] - assertEquals(0.9, data.getCurrentPhase3()); // [5] - - assertEquals(54, data.getOutputPowerPhase1()); // [6] - assertEquals(44, data.getOutputPowerPhase2()); // [7] - assertEquals(20, data.getOutputPowerPhase3()); // [8] - - assertEquals(408, data.getPV1Voltage()); // [9] - assertEquals(434, data.getPV2Voltage()); // [10] - assertEquals(0.1, data.getPV1Current()); // [12] - assertEquals(0.2, data.getPV2Current()); // [13] - assertEquals(67, data.getPV1Power()); // [15] - assertEquals(102, data.getPV2Power()); // [16] - - assertEquals(49.99, data.getFrequencyPhase1()); // [18] - assertEquals(49.99, data.getFrequencyPhase2()); // [19] - assertEquals(49.99, data.getFrequencyPhase3()); // [20] - - assertEquals(2, data.getInverterWorkModeCode()); // [21] - assertEquals("2", data.getInverterWorkMode()); // [21] - - assertEquals(5, data.getInverterTemperature1()); // [26] - assertEquals(9, data.getInverterTemperature2()); // [27] - - assertEquals(120, data.getTotalOutputPower()); // [78] - - assertEquals(1903.5, data.getTotalEnergy()); // [22] - assertEquals(5.0, data.getTodayEnergy()); // [24] - } -} diff --git a/bundles/org.openhab.binding.solax/src/test/java/org/openhab/binding/solax/internal/local/parsers/TestEVChargerParser.java b/bundles/org.openhab.binding.solax/src/test/java/org/openhab/binding/solax/internal/local/parsers/TestEVChargerParser.java new file mode 100644 index 0000000000..6bbce4ec52 --- /dev/null +++ b/bundles/org.openhab.binding.solax/src/test/java/org/openhab/binding/solax/internal/local/parsers/TestEVChargerParser.java @@ -0,0 +1,101 @@ +/** + * 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.local.parsers; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.junit.jupiter.api.Test; +import org.openhab.binding.solax.internal.connectivity.rawdata.local.LocalConnectRawDataBean; +import org.openhab.binding.solax.internal.model.local.EvChargerData; + +/** + * The {@link TestEVChargerParser} Simple test that tests for proper parsing against a real data from the inverter + * + * @author Konstantin Polihronov - Initial contribution + */ +@NonNullByDefault +public class TestEVChargerParser { + + private static final String RAW_DATA = """ + { + "SN":"SQBLABLA", + "ver":"3.004.11", + "type":1, + "Data":[ + 2,2,23914,23991,23895,1517,1513,1519,3654,3657, + 3656,10968,44,0,346,0,65434,35463,65459,65508, + 65513,27,402,0,43,0,2,15,0,0, + 0,0,0,5004,5000,4996,10518,1547,6150,4, + 0,0,0,0,0,0,0,0,1,100, + 0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, + 1717,0,3114,1547,6150,0,1,1,1,0, + 0,121,584,266,0,50,0,0,1,1,0], + "Information":[11.000,1,"CXXXXXXXXXX",1,1.13,1.01,0.00,0.00,0.00,1], + "OCPPServer":"", + "OCPPChargerId":"" + } + """; + + @Test + public void testParser() { + LocalConnectRawDataBean bean = LocalConnectRawDataBean.fromJson(RAW_DATA); + assertNotNull(bean); + + EvChargerData data = new EvChargerData(bean); + assertEquals("SQBLABLA", data.getWifiSerial()); // 0 + assertEquals("3.004.11", data.getWifiVersion()); // 1 + + assertEquals(239.14, data.getVoltagePhase1()); // 2 + assertEquals(239.91, data.getVoltagePhase2()); // 3 + assertEquals(238.95, data.getVoltagePhase3()); // 4 + + assertEquals(15.17, data.getCurrentPhase1()); // 5 + assertEquals(15.13, data.getCurrentPhase2()); // 6 + assertEquals(15.19, data.getCurrentPhase3()); // 7 + + assertEquals(3654, data.getOutputPowerPhase1()); // 8 + assertEquals(3657, data.getOutputPowerPhase2()); // 9 + assertEquals(3656, data.getOutputPowerPhase3()); // 10 + + assertEquals(10968, data.getTotalChargePower()); // 11 + + assertEquals(4.4, data.getEqSingle()); // 12 + assertEquals(34.6, data.getEqTotal()); // 14 and 15 + + assertEquals(-1.02, data.getExternalCurrentPhase1()); // 16 + assertEquals(-300.73, data.getExternalCurrentPhase2()); // 17 + assertEquals(-0.77, data.getExternalCurrentPhase3()); // 18 + + assertEquals(-28, data.getExternalPowerPhase1()); // 19 + assertEquals(-23, data.getExternalPowerPhase2()); // 20 + assertEquals(27, data.getExternalPowerPhase3()); // 21 + assertEquals(402, data.getExternalTotalPower()); // 22 + + assertEquals(0, data.getPlugTemperature()); // 23 + assertEquals(43, data.getInternalTemperature()); // 24 + + assertEquals(2, data.getCPState()); // 26 + + assertEquals(1717, data.getChargingDuration()); // 80 and 81 + + assertEquals(0, data.getOccpOfflineMode()); // 85 + + assertEquals(1, data.getTypePower()); // 87 + assertEquals(1, data.getTypePhase()); // 88 + assertEquals(0, data.getTypeCharger()); // 89 + } +} diff --git a/bundles/org.openhab.binding.solax/src/test/java/org/openhab/binding/solax/internal/local/parsers/TestX1BoostAirMiniDataParser.java b/bundles/org.openhab.binding.solax/src/test/java/org/openhab/binding/solax/internal/local/parsers/TestX1BoostAirMiniDataParser.java new file mode 100644 index 0000000000..395085d3e0 --- /dev/null +++ b/bundles/org.openhab.binding.solax/src/test/java/org/openhab/binding/solax/internal/local/parsers/TestX1BoostAirMiniDataParser.java @@ -0,0 +1,80 @@ +/** + * 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.local.parsers; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.binding.solax.internal.local.AbstractParserTest; +import org.openhab.binding.solax.internal.model.InverterType; +import org.openhab.binding.solax.internal.model.local.LocalData; + +/** + * The {@link TestX1BoostAirMiniDataParser} Simple test that tests for proper parsing against a real data from the + * inverter + * + * @author Konstantin Polihronov - Initial contribution + */ +@NonNullByDefault +public class TestX1BoostAirMiniDataParser extends AbstractParserTest { + + private static final String RAW_DATA = """ + { + sn:SR***, + ver:3.006.04, + type:4, + Data:[ + 2263,7,128,1519,0,9,0,138,0,5000, + 2,15569,0,7,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,13, + 0,4071,0,3456,0,0,0,0,0,0, + 0,0,0,0,0,23,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + ], + Information:[1.500,4,XM3A15IA669518,8,2.27,0.00,1.43,0.00,0.00,1]} + """; + + @Override + protected String getRawData() { + return RAW_DATA; + } + + @Override + protected void assertParserSpecific(LocalData data) { + assertEquals("SR***", data.getWifiSerial()); + assertEquals("3.006.04", data.getWifiVersion()); + + assertEquals(226.3, data.getInverterVoltage()); // [0] + assertEquals(0.7, data.getInverterCurrent()); // [1] + assertEquals(128, data.getInverterOutputPower()); // [2] + + assertEquals(151.9, data.getPV1Voltage()); // [3] + assertEquals(0, data.getPV2Voltage()); // [4] + assertEquals(0.9, data.getPV1Current()); // [5] + assertEquals(0, data.getPV2Current()); // [6] + assertEquals(138, data.getPV1Power()); // [7] + assertEquals(0, data.getPV2Power()); // [8] + + assertEquals(50, data.getInverterFrequency()); // [9] + + assertEquals(1556.9, data.getTotalEnergy()); // [11] + assertEquals(0.7, data.getTodayEnergy()); // [13] + + assertEquals(346, data.getPowerUsage()); // [43] + } + + @Override + protected InverterType getInverterType() { + return InverterType.X1_BOOST_AIR_MINI; + } +} diff --git a/bundles/org.openhab.binding.solax/src/test/java/org/openhab/binding/solax/internal/local/parsers/TestX1HybridG4Parser.java b/bundles/org.openhab.binding.solax/src/test/java/org/openhab/binding/solax/internal/local/parsers/TestX1HybridG4Parser.java new file mode 100644 index 0000000000..90ea895246 --- /dev/null +++ b/bundles/org.openhab.binding.solax/src/test/java/org/openhab/binding/solax/internal/local/parsers/TestX1HybridG4Parser.java @@ -0,0 +1,106 @@ +/** + * 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.local.parsers; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.binding.solax.internal.local.AbstractParserTest; +import org.openhab.binding.solax.internal.model.InverterType; +import org.openhab.binding.solax.internal.model.local.LocalData; + +/** + * The {@link TestX1HybridG4Parser} Simple test that tests for proper parsing against a real data from the inverter + * + * @author Konstantin Polihronov - Initial contribution + */ +@NonNullByDefault +public class TestX1HybridG4Parser extends AbstractParserTest { + + private static final String RAW_DATA = """ + { + sn:SOME_SERIAL_NUMBER, + ver:3.008.10, + type:15, + Data:[ + 2388,21,460,4998,4483,4483,10,1,487,65, + 2,59781,0,70,12180,500,605,33,99,12000, + 0,23159,0,57,100,0,39,4501,0,0, + 0,0,12,0,13240,0,63348,2,448,43, + 256,1314,900,0,350,311,279,33,33,279,1,1,652,0,708,1,65077,65535,65386,65535,0,0,0,0,0,0,0,0,0,0,0,0,65068,65535,4500,0,61036,65535,10,0,90,0,0,12,0,116,7,57,0,0,2320,0,110,0,0,0,0,0,0,12544,7440,5896,594,521,9252,0,0,0,0,0,1,1201,0,0,3342,3336,7296,54,21302,14389,18753,12852,16692,12355,13618,21302,14389,18753,12852,16692,12355,13618,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1025,4609,1026,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + Information:[7.500,15,H4752TI1063020,8,1.24,0.00,1.21,1.03,0.00,1]} + """; + + @Override + protected InverterType getInverterType() { + return InverterType.X1_HYBRID_G4; + } + + @Override + protected void assertParserSpecific(LocalData data) { + assertEquals("SOME_SERIAL_NUMBER", data.getWifiSerial()); + assertEquals("3.008.10", data.getWifiVersion()); + + assertEquals(238.8, data.getInverterVoltage()); // [0] + assertEquals(2.1, data.getInverterCurrent()); // [1] + assertEquals(460, data.getInverterOutputPower()); // [2] + assertEquals(49.98, data.getInverterFrequency()); // [3] + + assertEquals(448.3, data.getPV1Voltage()); // [4] + assertEquals(448.3, data.getPV2Voltage()); // [5] + assertEquals(1, data.getPV1Current()); // [6] + assertEquals(0.1, data.getPV2Current()); // [7] + assertEquals(487, data.getPV1Power()); // [8] + assertEquals(65, data.getPV2Power()); // [9] + + assertEquals(2, data.getInverterWorkModeCode()); // [10] + assertEquals("2", data.getInverterWorkMode()); // [10] + + assertEquals(121.8, data.getBatteryVoltage()); // [14] + assertEquals(5, data.getBatteryCurrent()); // [15] + assertEquals(605, data.getBatteryPower()); // [16] + assertEquals(33, data.getBatteryTemperature()); // [17] + assertEquals(99, data.getBatteryLevel()); // [18] + + assertEquals(12, data.getFeedInPower()); // [32] + } + + @Override + protected String getRawData() { + return RAW_DATA; + } + + // Yield_Today: Data[13] / 10, + // Yield_Total: read32BitUnsigned(Data[11], Data[12]) / 10, + // PowerDc1: Data[8], + // PowerDc2: Data[9], + // BAT_Power: read16BitSigned(Data[16]), + // feedInPower: read32BitSigned(Data[32], Data[33]), + // GridAPower: read16BitSigned(Data[2]), + // FeedInEnergy: read32BitUnsigned(Data[34], Data[35]) / 100, + // ConsumeEnergy: read32BitUnsigned(Data[36], Data[37]) / 100, + // RunMode: Data[10], + // EPSAPower: read16BitSigned(Data[28]), + // Vdc1: Data[4] / 10, + // Vdc2: Data[5] / 10, + // Idc1: Data[6] / 10, + // Idc2: Data[7] / 10, + // EPSAVoltage: Data[29] / 10, + // EPSACurrent: read16BitSigned(Data[30]) / 10, + // BatteryCapacity: Data[18], + // BatteryVoltage: Data[14] / 100, + // BatteryTemperature: read16BitSigned(Data[17]), + // GridAVoltage: Data[0] / 10, + // GridACurrent: read16BitSigned(Data[1]) / 10, + // FreqacA: Data[3] / 100, +} diff --git a/bundles/org.openhab.binding.solax/src/test/java/org/openhab/binding/solax/internal/local/parsers/TestX3HybridG4Parser.java b/bundles/org.openhab.binding.solax/src/test/java/org/openhab/binding/solax/internal/local/parsers/TestX3HybridG4Parser.java new file mode 100644 index 0000000000..056d2bc64b --- /dev/null +++ b/bundles/org.openhab.binding.solax/src/test/java/org/openhab/binding/solax/internal/local/parsers/TestX3HybridG4Parser.java @@ -0,0 +1,116 @@ +/** + * 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.local.parsers; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.binding.solax.internal.local.AbstractParserTest; +import org.openhab.binding.solax.internal.model.InverterType; +import org.openhab.binding.solax.internal.model.local.LocalData; + +/** + * The {@link TestX3HybridG4Parser} simple test that tests for proper parsing against a real data from the inverter + * + * @author Konstantin Polihronov - Initial contribution + */ +@NonNullByDefault +public class TestX3HybridG4Parser extends AbstractParserTest { + + private static final String RAW_DATA = """ + { + sn:XYZ, + ver:3.005.01, + type:14,Data:[ + 2316,2329,2315,18,18,18,372,363,365,1100, + 12,23,34,45,56,67,4996,4996,4996,2, + 0,0,0,0,0,0,0,0,0,0, + 0,0,0,1,65494,65535,0,0,0,31330, + 320,1034,3078,1,44,1100,256,1294,0,0, + 7445,5895,100,0,38,0,0,0,0,0, + 0,0,0,0,0,0,0,0,505,0, + 396,0,0,0,102,0,142,0,62,110, + 570,0,463,0,0,0,1925,0,369,0, + 506,1925,304,309,0,0,0,0,0,0, + 0,0,0,45,1,59,1,34,54,256, + 3504,2400,300,300,295,276,33,33,2,1620,779,15163,15163,14906,0,0,0,3270,3264,45581,0,20564,12339,18753,12353,18742,12356,13625,20564,12339,18754,12866,18743,14151,13104,20564,12339,18754,12866,18743,14151,12592,20564,12339,18754,12865,18738,12871,13620,0,0,0,0,0,0,0,1025,8195,769,259,0,31460,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + Information:[12.000,14,XY,8,1.23,0.00,1.24,1.09,0.00,1] + } + """; + + @Override + protected InverterType getInverterType() { + return InverterType.X3_HYBRID_G4; + } + + @Override + protected void assertParserSpecific(LocalData data) { + assertEquals("XYZ", data.getWifiSerial()); + assertEquals("3.005.01", data.getWifiVersion()); + + assertEquals(231.6, data.getVoltagePhase1()); // [0] + assertEquals(232.9, data.getVoltagePhase2()); // [1] + assertEquals(231.5, data.getVoltagePhase3()); // [2] + + assertEquals(1.8, data.getCurrentPhase1()); // [3] + assertEquals(1.8, data.getCurrentPhase2()); // [4] + assertEquals(1.8, data.getCurrentPhase3()); // [5] + + assertEquals(372, data.getOutputPowerPhase1()); // [6] + assertEquals(363, data.getOutputPowerPhase2()); // [7] + assertEquals(365, data.getOutputPowerPhase3()); // [8] + + assertEquals(1100, data.getTotalOutputPower()); // [9] + + assertEquals(1.2, data.getPV1Voltage()); // [10] + assertEquals(2.3, data.getPV2Voltage()); // [11] + assertEquals(3.4, data.getPV1Current()); // [12] + assertEquals(4.5, data.getPV2Current()); // [13] + assertEquals(56, data.getPV1Power()); // [14] + assertEquals(67, data.getPV2Power()); // [15] + + assertEquals(49.96, data.getFrequencyPhase1()); // [16] + assertEquals(49.96, data.getFrequencyPhase2()); // [17] + assertEquals(49.96, data.getFrequencyPhase3()); // [18] + + assertEquals(2, data.getInverterWorkModeCode()); // [19] + assertEquals("2", data.getInverterWorkMode()); // [19] + + assertEquals(-41, data.getFeedInPower()); // [34] - [35] + + assertEquals(313.3, data.getBatteryVoltage()); // [39] + assertEquals(3.2, data.getBatteryCurrent()); // [40] + assertEquals(1034, data.getBatteryPower()); // [41] + assertEquals(45, data.getBatteryLevel()); // [103] + assertEquals(59, data.getBatteryTemperature()); // [105] + + // Totals + assertEquals(1294, data.getPowerUsage()); // [47] + assertEquals(50.5, data.getTotalEnergy()); // [68] + assertEquals(102, data.getTotalBatteryDischargeEnergy()); // [74] + assertEquals(142, data.getTotalBatteryChargeEnergy()); // [76] + assertEquals(57, data.getTotalPVEnergy()); // [80] + assertEquals(1925, data.getTotalFeedInEnergy()); // [86] + assertEquals(36.9, data.getTotalConsumption()); // [88] + assertEquals(46.3, data.getTodayEnergy()); // [82] / 10 + assertEquals(5.06, data.getTodayFeedInEnergy()); // [90] / 100 + assertEquals(3.04, data.getTodayConsumption()); // [92] / 100 + assertEquals(6.2, data.getTodayBatteryDischargeEnergy()); // [78] / 100 + assertEquals(11, data.getTodayBatteryChargeEnergy()); // [79] / 100 + } + + @Override + protected String getRawData() { + return RAW_DATA; + } +} diff --git a/bundles/org.openhab.binding.solax/src/test/java/org/openhab/binding/solax/internal/local/parsers/TestX3MicOrProG2Parser.java b/bundles/org.openhab.binding.solax/src/test/java/org/openhab/binding/solax/internal/local/parsers/TestX3MicOrProG2Parser.java new file mode 100644 index 0000000000..f983227abf --- /dev/null +++ b/bundles/org.openhab.binding.solax/src/test/java/org/openhab/binding/solax/internal/local/parsers/TestX3MicOrProG2Parser.java @@ -0,0 +1,97 @@ +/** + * 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.local.parsers; + +import static org.junit.jupiter.api.Assertions.*; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.junit.jupiter.api.Test; +import org.openhab.binding.solax.internal.connectivity.rawdata.local.LocalConnectRawDataBean; +import org.openhab.binding.solax.internal.model.InverterType; +import org.openhab.binding.solax.internal.model.local.LocalData; +import org.openhab.binding.solax.internal.model.local.RawDataParser; + +/** + * The {@link TestX3HybridG4Parser} simple test that tests for proper parsing against a real data from the inverter + * + * @author Konstantin Polihronov - Initial contribution + */ +@NonNullByDefault +public class TestX3MicOrProG2Parser { + + String rawData = """ + { + sn:XYZ, + ver:3.003.02, + type:16,Data:[ + 2515,2449,2484,5,5,9,54,44,20,4080,4340, + 0,1,2,0,67,102,0,4999,4999,4999,2,19035, + 0,50,8000,5,9, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0, + 0,0,0,0,0,0,0,0,120,40,1,6,5,0,6772,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0 + ], + Information:[8.000,16,XY,8,1.15,0.00,1.11,1.01,0.00,1] + } + """; + + @Test + public void testParser() { + LocalConnectRawDataBean bean = LocalConnectRawDataBean.fromJson(rawData); + int type = bean.getType(); + InverterType inverterType = InverterType.fromIndex(type); + assertEquals(InverterType.X3_MIC_OR_PRO_G2, inverterType, "Inverter type not recognized properly"); + + RawDataParser parser = inverterType.getParser(); + assertNotNull(parser); + + LocalData data = parser.getData(bean); + assertEquals("XYZ", data.getWifiSerial()); + assertEquals("3.003.02", data.getWifiVersion()); + + assertEquals(251.5, data.getVoltagePhase1()); // [0] + assertEquals(244.9, data.getVoltagePhase2()); // [1] + assertEquals(248.4, data.getVoltagePhase3()); // [2] + + assertEquals(0.5, data.getCurrentPhase1()); // [3] + assertEquals(0.5, data.getCurrentPhase2()); // [4] + assertEquals(0.9, data.getCurrentPhase3()); // [5] + + assertEquals(54, data.getOutputPowerPhase1()); // [6] + assertEquals(44, data.getOutputPowerPhase2()); // [7] + assertEquals(20, data.getOutputPowerPhase3()); // [8] + + assertEquals(408, data.getPV1Voltage()); // [9] + assertEquals(434, data.getPV2Voltage()); // [10] + assertEquals(0.1, data.getPV1Current()); // [12] + assertEquals(0.2, data.getPV2Current()); // [13] + assertEquals(67, data.getPV1Power()); // [15] + assertEquals(102, data.getPV2Power()); // [16] + + assertEquals(49.99, data.getFrequencyPhase1()); // [18] + assertEquals(49.99, data.getFrequencyPhase2()); // [19] + assertEquals(49.99, data.getFrequencyPhase3()); // [20] + + assertEquals(2, data.getInverterWorkModeCode()); // [21] + assertEquals("2", data.getInverterWorkMode()); // [21] + + assertEquals(5, data.getInverterTemperature1()); // [26] + assertEquals(9, data.getInverterTemperature2()); // [27] + + assertEquals(120, data.getTotalOutputPower()); // [78] + + assertEquals(1903.5, data.getTotalEnergy()); // [22] + assertEquals(5.0, data.getTodayEnergy()); // [24] + } +} diff --git a/bundles/org.openhab.binding.solax/src/test/java/org/openhab/binding/solax/internal/util/TestByteUtil.java b/bundles/org.openhab.binding.solax/src/test/java/org/openhab/binding/solax/internal/util/TestByteUtil.java new file mode 100644 index 0000000000..a66a4bddce --- /dev/null +++ b/bundles/org.openhab.binding.solax/src/test/java/org/openhab/binding/solax/internal/util/TestByteUtil.java @@ -0,0 +1,52 @@ +/** + * 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.util; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.junit.jupiter.api.Test; + +/** + * The {@link TestByteUtil} Simple test that tests the methods of the ByteUtil + * + * @author Konstantin Polihronov - Initial contribution + */ +@NonNullByDefault +public class TestByteUtil { + + @Test + public void testRead32BitSignedWithNegativeInputs() { + assertEquals(-65536, ByteUtil.read32BitSigned((short) 0, (short) -1)); + assertEquals(-1, ByteUtil.read32BitSigned((short) -1, (short) -1)); + assertEquals(-2, ByteUtil.read32BitSigned((short) -2, (short) -1)); + } + + @Test + public void testRead32BitSignedWithBoundaryValues() { + assertEquals(Short.MAX_VALUE, ByteUtil.read32BitSigned((short) Short.MAX_VALUE, (short) 0)); + assertEquals((Short.MIN_VALUE & 0xFFFF) | (Short.MAX_VALUE << 16), + ByteUtil.read32BitSigned((short) Short.MIN_VALUE, (short) Short.MAX_VALUE)); + assertEquals(Integer.MIN_VALUE, ByteUtil.read32BitSigned((short) 0, (short) (Integer.MIN_VALUE >> 16))); + } + + @Test + public void testRead32BitSignedResultingInNegative() { + assertEquals(-131072, ByteUtil.read32BitSigned((short) 0, (short) -2)); + } + + @Test + public void testRead32BitSignedResultingInMaxInteger() { + assertEquals(Integer.MAX_VALUE, ByteUtil.read32BitSigned((short) 0xFFFF, (short) 0x7FFF)); + } +}