mirror of
https://github.com/openhab/openhab-addons.git
synced 2025-01-10 15:11:59 +01:00
[solax] Support for Solax EV charger via direct(local) data retrieval (#17055)
* Implementation of Solax EV Charger support Signed-off-by: Konstantin Polihronov <polychronov@gmail.com> Signed-off-by: Ciprian Pascu <contact@ciprianpascu.ro>
This commit is contained in:
parent
665729437f
commit
3f35cb3e20
@ -13,8 +13,9 @@ 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 |
|
||||
|------------------------|------------|---------------------------------------------------------------------------------------------------------------------------------|
|
||||
| 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.
|
||||
@ -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 |
|
||||
|
@ -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<ThingTypeUID> 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";
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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");
|
||||
|
@ -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();
|
||||
|
@ -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<String> 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<String> supportedChannels) {
|
||||
if (supportedChannels.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
List<Channel> channels = getThing().getChannels();
|
||||
List<Channel> 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<Channel> channelsToRemove) {
|
||||
List<String> channelsToRemoveForLog = channelsToRemove.stream().map(channel -> channel.getUID().getId())
|
||||
.toList();
|
||||
logger.debug("Detected unsupported channels for the current inverter. Channels to be removed: {}",
|
||||
channelsToRemoveForLog);
|
||||
}
|
||||
|
||||
protected <T extends Quantity<T>> void updateChannel(String channelID, double value, Unit<T> unit,
|
||||
Set<String> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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<String> 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()));
|
||||
}
|
||||
}
|
@ -13,63 +13,43 @@
|
||||
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.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.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.
|
||||
* The {@link SolaxLocalAccessInverterHandler} the handler for the inverter
|
||||
*
|
||||
* @author Konstantin Polihronov - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class SolaxLocalAccessHandler extends AbstractSolaxHandler {
|
||||
public class SolaxLocalAccessInverterHandler extends SolaxLocalAccessAbstractHandler {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(SolaxLocalAccessHandler.class);
|
||||
private final Logger logger = LoggerFactory.getLogger(SolaxLocalAccessInverterHandler.class);
|
||||
|
||||
private boolean alreadyRemovedUnsupportedChannels;
|
||||
|
||||
private final Set<String> unsupportedExistingChannels = new HashSet<>();
|
||||
|
||||
public SolaxLocalAccessHandler(Thing thing, TranslationProvider i18nProvider, TimeZoneProvider timeZoneProvider) {
|
||||
public SolaxLocalAccessInverterHandler(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 {
|
||||
@ -82,7 +62,7 @@ public class SolaxLocalAccessHandler extends AbstractSolaxHandler {
|
||||
alreadyRemovedUnsupportedChannels = true;
|
||||
}
|
||||
|
||||
LocalInverterData genericInverterData = parser.getData(rawDataBean);
|
||||
LocalData genericInverterData = parser.getData(rawDataBean);
|
||||
updateChannels(parser, genericInverterData);
|
||||
updateProperties(genericInverterData);
|
||||
} else {
|
||||
@ -96,23 +76,17 @@ public class SolaxLocalAccessHandler extends AbstractSolaxHandler {
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
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, LocalInverterData inverterData) {
|
||||
private void updateChannels(RawDataParser parser, LocalData inverterData) {
|
||||
updateState(SolaxBindingConstants.CHANNEL_RAW_DATA, new StringType(inverterData.getRawData()));
|
||||
|
||||
Set<String> supportedChannels = parser.getSupportedChannels();
|
||||
@ -222,42 +196,4 @@ public class SolaxLocalAccessHandler extends AbstractSolaxHandler {
|
||||
// Binding provided data
|
||||
updateState(SolaxBindingConstants.CHANNEL_TIMESTAMP, new DateTimeType(ZonedDateTime.now()));
|
||||
}
|
||||
|
||||
private void removeUnsupportedChannels(Set<String> supportedChannels) {
|
||||
if (supportedChannels.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
List<Channel> channels = getThing().getChannels();
|
||||
List<Channel> 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<Channel> channelsToRemove) {
|
||||
List<String> channelsToRemoveForLog = channelsToRemove.stream().map(channel -> channel.getUID().getId())
|
||||
.toList();
|
||||
logger.debug("Detected unsupported channels for the current inverter. Channels to be removed: {}",
|
||||
channelsToRemoveForLog);
|
||||
}
|
||||
|
||||
private <T extends Quantity<T>> void updateChannel(String channelID, double value, Unit<T> unit,
|
||||
Set<String> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
||||
|
@ -20,19 +20,19 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link CommonLocalInverterData} is an abstract class that contains the common information, applicable for all
|
||||
* inverters.
|
||||
* 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 CommonLocalInverterData implements LocalInverterData {
|
||||
public abstract class CommonLocalDeviceData implements LocalData {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(CommonLocalInverterData.class);
|
||||
private final Logger logger = LoggerFactory.getLogger(CommonLocalDeviceData.class);
|
||||
|
||||
private LocalConnectRawDataBean data;
|
||||
|
||||
public CommonLocalInverterData(LocalConnectRawDataBean data) {
|
||||
public CommonLocalDeviceData(LocalConnectRawDataBean data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
@ -56,7 +56,7 @@ public abstract class CommonLocalInverterData implements LocalInverterData {
|
||||
return InverterType.fromIndex(data.getType());
|
||||
}
|
||||
|
||||
protected short getData(int index) {
|
||||
protected Short getFromRawData(int index) {
|
||||
try {
|
||||
short[] dataArray = data.getData();
|
||||
if (dataArray != null) {
|
||||
@ -69,12 +69,17 @@ public abstract class CommonLocalInverterData implements LocalInverterData {
|
||||
}
|
||||
|
||||
public long packU16(int indexMajor, int indexMinor) {
|
||||
short major = getData(indexMajor);
|
||||
short minor = getData(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;
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -14,26 +14,35 @@ 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 LocalInverterData} Interface for the parsed inverter data in meaningful format
|
||||
* The {@link LocalData} Interface for the parsed inverter data in meaningful format
|
||||
*
|
||||
* @author Konstantin Polihronov - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public interface LocalInverterData {
|
||||
public interface LocalData {
|
||||
|
||||
@Nullable
|
||||
String getWifiSerial();
|
||||
default String getWifiSerial() {
|
||||
return getData().getSn();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
String getWifiVersion();
|
||||
default String getWifiVersion() {
|
||||
return getData().getVer();
|
||||
}
|
||||
|
||||
InverterType getInverterType();
|
||||
|
||||
@Nullable
|
||||
String getRawData();
|
||||
default String getRawData() {
|
||||
return getData().getRawData();
|
||||
}
|
||||
|
||||
LocalConnectRawDataBean getData();
|
||||
|
||||
default double getPV1Voltage() {
|
||||
return Short.MIN_VALUE;
|
@ -10,13 +10,12 @@
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.solax.internal.model.local.parsers;
|
||||
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;
|
||||
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
|
||||
@ -27,7 +26,7 @@ import org.openhab.binding.solax.internal.model.local.LocalInverterData;
|
||||
@NonNullByDefault
|
||||
public interface RawDataParser {
|
||||
|
||||
LocalInverterData getData(LocalConnectRawDataBean bean);
|
||||
LocalData getData(LocalConnectRawDataBean bean);
|
||||
|
||||
Set<String> getSupportedChannels();
|
||||
}
|
@ -16,80 +16,80 @@ 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
|
||||
* 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 X1BoostAirMiniInverterData extends CommonLocalInverterData {
|
||||
public class X1BoostAirMiniData extends CommonLocalDeviceData {
|
||||
|
||||
public X1BoostAirMiniInverterData(LocalConnectRawDataBean data) {
|
||||
public X1BoostAirMiniData(LocalConnectRawDataBean data) {
|
||||
super(data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getInverterVoltage() {
|
||||
return (double) getData(0) / 10;
|
||||
return (double) getFromRawData(0) / 10;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getInverterCurrent() {
|
||||
return (double) getData(1) / 10;
|
||||
return (double) getFromRawData(1) / 10;
|
||||
}
|
||||
|
||||
@Override
|
||||
public short getInverterOutputPower() {
|
||||
return getData(2);
|
||||
return getFromRawData(2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getPV1Voltage() {
|
||||
return (double) getData(3) / 10;
|
||||
return (double) getFromRawData(3) / 10;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getPV2Voltage() {
|
||||
return (double) getData(4) / 10;
|
||||
return (double) getFromRawData(4) / 10;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getPV1Current() {
|
||||
return (double) getData(5) / 10;
|
||||
return (double) getFromRawData(5) / 10;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getPV2Current() {
|
||||
return (double) getData(6) / 10;
|
||||
return (double) getFromRawData(6) / 10;
|
||||
}
|
||||
|
||||
@Override
|
||||
public short getPV1Power() {
|
||||
return getData(7);
|
||||
return getFromRawData(7);
|
||||
}
|
||||
|
||||
@Override
|
||||
public short getPV2Power() {
|
||||
return getData(8);
|
||||
return getFromRawData(8);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getInverterFrequency() {
|
||||
return (double) getData(9) / 100;
|
||||
return (double) getFromRawData(9) / 100;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getTotalEnergy() {
|
||||
return (double) getData(11) / 10;
|
||||
return (double) getFromRawData(11) / 10;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getTodayEnergy() {
|
||||
return (double) getData(13) / 10;
|
||||
return (double) getFromRawData(13) / 10;
|
||||
}
|
||||
|
||||
@Override
|
||||
public short getPowerUsage() {
|
||||
return (short) Math.round((double) getData(43) / 10);
|
||||
return (short) Math.round((double) getFromRawData(43) / 10);
|
||||
}
|
||||
}
|
@ -16,100 +16,100 @@ 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
|
||||
* 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 X1HybridG4InverterData extends CommonLocalInverterData {
|
||||
public class X1HybridG4Data extends CommonLocalDeviceData {
|
||||
|
||||
public X1HybridG4InverterData(LocalConnectRawDataBean data) {
|
||||
public X1HybridG4Data(LocalConnectRawDataBean data) {
|
||||
super(data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getInverterVoltage() {
|
||||
return ((double) getData(0)) / 10;
|
||||
return ((double) getFromRawData(0)) / 10;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getInverterCurrent() {
|
||||
return ((double) getData(1)) / 10;
|
||||
return ((double) getFromRawData(1)) / 10;
|
||||
}
|
||||
|
||||
@Override
|
||||
public short getInverterOutputPower() {
|
||||
return getData(2);
|
||||
return getFromRawData(2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getInverterFrequency() {
|
||||
return ((double) getData(3)) / 100;
|
||||
return ((double) getFromRawData(3)) / 100;
|
||||
}
|
||||
|
||||
@Override
|
||||
public short getFeedInPower() {
|
||||
return getData(32);
|
||||
return getFromRawData(32);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getPV1Voltage() {
|
||||
return ((double) getData(4)) / 10;
|
||||
return ((double) getFromRawData(4)) / 10;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getPV2Voltage() {
|
||||
return ((double) getData(5)) / 10;
|
||||
return ((double) getFromRawData(5)) / 10;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getPV1Current() {
|
||||
return ((double) getData(6)) / 10;
|
||||
return ((double) getFromRawData(6)) / 10;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getPV2Current() {
|
||||
return ((double) getData(7)) / 10;
|
||||
return ((double) getFromRawData(7)) / 10;
|
||||
}
|
||||
|
||||
@Override
|
||||
public short getPV1Power() {
|
||||
return getData(8);
|
||||
return getFromRawData(8);
|
||||
}
|
||||
|
||||
@Override
|
||||
public short getPV2Power() {
|
||||
return getData(9);
|
||||
return getFromRawData(9);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getBatteryVoltage() {
|
||||
return ((double) getData(14)) / 100;
|
||||
return ((double) getFromRawData(14)) / 100;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getBatteryCurrent() {
|
||||
return ((double) getData(15)) / 100;
|
||||
return ((double) getFromRawData(15)) / 100;
|
||||
}
|
||||
|
||||
@Override
|
||||
public short getBatteryPower() {
|
||||
return getData(16);
|
||||
return getFromRawData(16);
|
||||
}
|
||||
|
||||
@Override
|
||||
public short getBatteryTemperature() {
|
||||
return getData(17);
|
||||
return getFromRawData(17);
|
||||
}
|
||||
|
||||
@Override
|
||||
public short getBatteryLevel() {
|
||||
return getData(18);
|
||||
return getFromRawData(18);
|
||||
}
|
||||
|
||||
@Override
|
||||
public short getInverterWorkModeCode() {
|
||||
return getData(10);
|
||||
return getFromRawData(10);
|
||||
}
|
||||
}
|
@ -16,15 +16,15 @@ 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.
|
||||
* 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 X3HybridG4InverterData extends CommonLocalInverterData {
|
||||
public class X3HybridG4Data extends CommonLocalDeviceData {
|
||||
|
||||
public X3HybridG4InverterData(LocalConnectRawDataBean data) {
|
||||
public X3HybridG4Data(LocalConnectRawDataBean data) {
|
||||
super(data);
|
||||
}
|
||||
|
||||
@ -32,197 +32,197 @@ public class X3HybridG4InverterData extends CommonLocalInverterData {
|
||||
|
||||
@Override
|
||||
public double getVoltagePhase1() {
|
||||
return ((double) getData(0)) / 10;
|
||||
return ((double) getFromRawData(0)) / 10;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getVoltagePhase2() {
|
||||
return ((double) getData(1)) / 10;
|
||||
return ((double) getFromRawData(1)) / 10;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getVoltagePhase3() {
|
||||
return ((double) getData(2)) / 10;
|
||||
return ((double) getFromRawData(2)) / 10;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getCurrentPhase1() {
|
||||
return ((double) getData(3)) / 10;
|
||||
return ((double) getFromRawData(3)) / 10;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getCurrentPhase2() {
|
||||
return ((double) getData(4)) / 10;
|
||||
return ((double) getFromRawData(4)) / 10;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getCurrentPhase3() {
|
||||
return ((double) getData(5)) / 10;
|
||||
return ((double) getFromRawData(5)) / 10;
|
||||
}
|
||||
|
||||
@Override
|
||||
public short getOutputPowerPhase1() {
|
||||
return getData(6);
|
||||
return getFromRawData(6);
|
||||
}
|
||||
|
||||
@Override
|
||||
public short getOutputPowerPhase2() {
|
||||
return getData(7);
|
||||
return getFromRawData(7);
|
||||
}
|
||||
|
||||
@Override
|
||||
public short getOutputPowerPhase3() {
|
||||
return getData(8);
|
||||
return getFromRawData(8);
|
||||
}
|
||||
|
||||
@Override
|
||||
public short getTotalOutputPower() {
|
||||
return getData(9);
|
||||
return getFromRawData(9);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getPV1Voltage() {
|
||||
return ((double) getData(10)) / 10;
|
||||
return ((double) getFromRawData(10)) / 10;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getPV2Voltage() {
|
||||
return ((double) getData(11)) / 10;
|
||||
return ((double) getFromRawData(11)) / 10;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getPV1Current() {
|
||||
return ((double) getData(12)) / 10;
|
||||
return ((double) getFromRawData(12)) / 10;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getPV2Current() {
|
||||
return ((double) getData(13)) / 10;
|
||||
return ((double) getFromRawData(13)) / 10;
|
||||
}
|
||||
|
||||
@Override
|
||||
public short getPV1Power() {
|
||||
return getData(14);
|
||||
return getFromRawData(14);
|
||||
}
|
||||
|
||||
@Override
|
||||
public short getPV2Power() {
|
||||
return getData(15);
|
||||
return getFromRawData(15);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getFrequencyPhase1() {
|
||||
return ((double) getData(16)) / 100;
|
||||
return ((double) getFromRawData(16)) / 100;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getFrequencyPhase2() {
|
||||
return ((double) getData(17)) / 100;
|
||||
return ((double) getFromRawData(17)) / 100;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getFrequencyPhase3() {
|
||||
return ((double) getData(18)) / 100;
|
||||
return ((double) getFromRawData(18)) / 100;
|
||||
}
|
||||
|
||||
// Battery
|
||||
|
||||
@Override
|
||||
public double getBatteryVoltage() {
|
||||
return ((double) getData(39)) / 100;
|
||||
return ((double) getFromRawData(39)) / 100;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getBatteryCurrent() {
|
||||
return ((double) getData(40)) / 100;
|
||||
return ((double) getFromRawData(40)) / 100;
|
||||
}
|
||||
|
||||
@Override
|
||||
public short getBatteryPower() {
|
||||
return getData(41);
|
||||
return getFromRawData(41);
|
||||
}
|
||||
|
||||
@Override
|
||||
public short getBatteryTemperature() {
|
||||
return getData(105);
|
||||
return getFromRawData(105);
|
||||
}
|
||||
|
||||
@Override
|
||||
public short getBatteryLevel() {
|
||||
return getData(103);
|
||||
return getFromRawData(103);
|
||||
}
|
||||
|
||||
// Feed in power
|
||||
|
||||
@Override
|
||||
public short getFeedInPower() {
|
||||
return (short) (getData(34) - getData(35));
|
||||
return (short) (getFromRawData(34) - getFromRawData(35));
|
||||
}
|
||||
|
||||
// Totals
|
||||
|
||||
@Override
|
||||
public short getPowerUsage() {
|
||||
return getData(47);
|
||||
return getFromRawData(47);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getTotalEnergy() {
|
||||
return ((double) getData(68)) / 10;
|
||||
return ((double) getFromRawData(68)) / 10;
|
||||
}
|
||||
|
||||
@Override
|
||||
public short getTotalBatteryDischargeEnergy() {
|
||||
return getData(74);
|
||||
return getFromRawData(74);
|
||||
}
|
||||
|
||||
@Override
|
||||
public short getTotalBatteryChargeEnergy() {
|
||||
return getData(76);
|
||||
return getFromRawData(76);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getTotalPVEnergy() {
|
||||
return ((double) getData(80)) / 10;
|
||||
return ((double) getFromRawData(80)) / 10;
|
||||
}
|
||||
|
||||
@Override
|
||||
public short getTotalFeedInEnergy() {
|
||||
return getData(86);
|
||||
return getFromRawData(86);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getTotalConsumption() {
|
||||
return ((double) getData(88)) / 10;
|
||||
return ((double) getFromRawData(88)) / 10;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getTodayEnergy() {
|
||||
return ((double) getData(82)) / 10;
|
||||
return ((double) getFromRawData(82)) / 10;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getTodayFeedInEnergy() {
|
||||
return ((double) getData(90)) / 100;
|
||||
return ((double) getFromRawData(90)) / 100;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getTodayConsumption() {
|
||||
return ((double) getData(92)) / 100;
|
||||
return ((double) getFromRawData(92)) / 100;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getTodayBatteryDischargeEnergy() {
|
||||
return ((double) getData(78)) / 10;
|
||||
return ((double) getFromRawData(78)) / 10;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getTodayBatteryChargeEnergy() {
|
||||
return ((double) getData(79)) / 10;
|
||||
return ((double) getFromRawData(79)) / 10;
|
||||
}
|
||||
|
||||
@Override
|
||||
public short getInverterWorkModeCode() {
|
||||
return getData(19);
|
||||
return getFromRawData(19);
|
||||
}
|
||||
}
|
@ -16,16 +16,16 @@ 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
|
||||
* 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 X3MicOrProG2InverterData extends CommonLocalInverterData {
|
||||
public class X3MicOrProG2Data extends CommonLocalDeviceData {
|
||||
|
||||
public X3MicOrProG2InverterData(LocalConnectRawDataBean data) {
|
||||
public X3MicOrProG2Data(LocalConnectRawDataBean data) {
|
||||
super(data);
|
||||
}
|
||||
|
||||
@ -33,121 +33,121 @@ public class X3MicOrProG2InverterData extends CommonLocalInverterData {
|
||||
|
||||
@Override
|
||||
public double getVoltagePhase1() {
|
||||
return ((double) getData(0)) / 10;
|
||||
return ((double) getFromRawData(0)) / 10;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getVoltagePhase2() {
|
||||
return ((double) getData(1)) / 10;
|
||||
return ((double) getFromRawData(1)) / 10;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getVoltagePhase3() {
|
||||
return ((double) getData(2)) / 10;
|
||||
return ((double) getFromRawData(2)) / 10;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getCurrentPhase1() {
|
||||
return ((double) getData(3)) / 10;
|
||||
return ((double) getFromRawData(3)) / 10;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getCurrentPhase2() {
|
||||
return ((double) getData(4)) / 10;
|
||||
return ((double) getFromRawData(4)) / 10;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getCurrentPhase3() {
|
||||
return ((double) getData(5)) / 10;
|
||||
return ((double) getFromRawData(5)) / 10;
|
||||
}
|
||||
|
||||
@Override
|
||||
public short getOutputPowerPhase1() {
|
||||
return getData(6);
|
||||
return getFromRawData(6);
|
||||
}
|
||||
|
||||
@Override
|
||||
public short getOutputPowerPhase2() {
|
||||
return getData(7);
|
||||
return getFromRawData(7);
|
||||
}
|
||||
|
||||
@Override
|
||||
public short getOutputPowerPhase3() {
|
||||
return getData(8);
|
||||
return getFromRawData(8);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getPV1Voltage() {
|
||||
return ((double) getData(9)) / 10;
|
||||
return ((double) getFromRawData(9)) / 10;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getPV2Voltage() {
|
||||
return ((double) getData(10)) / 10;
|
||||
return ((double) getFromRawData(10)) / 10;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getPV1Current() {
|
||||
return ((double) getData(12)) / 10;
|
||||
return ((double) getFromRawData(12)) / 10;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getPV2Current() {
|
||||
return ((double) getData(13)) / 10;
|
||||
return ((double) getFromRawData(13)) / 10;
|
||||
}
|
||||
|
||||
@Override
|
||||
public short getPV1Power() {
|
||||
return getData(15);
|
||||
return getFromRawData(15);
|
||||
}
|
||||
|
||||
@Override
|
||||
public short getPV2Power() {
|
||||
return getData(16);
|
||||
return getFromRawData(16);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getFrequencyPhase1() {
|
||||
return ((double) getData(18)) / 100;
|
||||
return ((double) getFromRawData(18)) / 100;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getFrequencyPhase2() {
|
||||
return ((double) getData(19)) / 100;
|
||||
return ((double) getFromRawData(19)) / 100;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getFrequencyPhase3() {
|
||||
return ((double) getData(20)) / 100;
|
||||
return ((double) getFromRawData(20)) / 100;
|
||||
}
|
||||
|
||||
@Override
|
||||
public short getInverterWorkModeCode() {
|
||||
return getData(21);
|
||||
return getFromRawData(21);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getTotalEnergy() {
|
||||
return ((double) getData(22)) / 10;
|
||||
return ((double) getFromRawData(22)) / 10;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getTodayEnergy() {
|
||||
return ((double) getData(24)) / 10;
|
||||
return ((double) getFromRawData(24)) / 10;
|
||||
}
|
||||
|
||||
@Override
|
||||
public short getInverterTemperature1() {
|
||||
return getData(26);
|
||||
return getFromRawData(26);
|
||||
}
|
||||
|
||||
@Override
|
||||
public short getInverterTemperature2() {
|
||||
return getData(27);
|
||||
return getFromRawData(27);
|
||||
}
|
||||
|
||||
@Override
|
||||
public short getTotalOutputPower() {
|
||||
return getData(78);
|
||||
return getFromRawData(78);
|
||||
}
|
||||
}
|
@ -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<String> 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<String> getSupportedChannels() {
|
||||
return EV_CHARGER_SUPPORTED_CHANNELS;
|
||||
}
|
||||
}
|
@ -10,7 +10,7 @@
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.solax.internal.model.local.parsers;
|
||||
package org.openhab.binding.solax.internal.model.local.inverters;
|
||||
|
||||
import static org.openhab.binding.solax.internal.SolaxBindingConstants.*;
|
||||
|
||||
@ -18,11 +18,12 @@ 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;
|
||||
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 LocalInverterData for the
|
||||
* 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
|
||||
@ -38,8 +39,8 @@ public class X1BoostAirMiniDataParser implements RawDataParser {
|
||||
CHANNEL_TOTAL_ENERGY, CHANNEL_TODAY_ENERGY, CHANNEL_POWER_USAGE);
|
||||
|
||||
@Override
|
||||
public LocalInverterData getData(LocalConnectRawDataBean bean) {
|
||||
return new X1BoostAirMiniInverterData(bean);
|
||||
public LocalData getData(LocalConnectRawDataBean bean) {
|
||||
return new X1BoostAirMiniData(bean);
|
||||
}
|
||||
|
||||
@Override
|
@ -10,7 +10,7 @@
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.solax.internal.model.local.parsers;
|
||||
package org.openhab.binding.solax.internal.model.local.inverters;
|
||||
|
||||
import static org.openhab.binding.solax.internal.SolaxBindingConstants.*;
|
||||
|
||||
@ -18,11 +18,12 @@ 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;
|
||||
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 LocalInverterData for the
|
||||
* 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
|
||||
@ -39,8 +40,8 @@ public class X1HybridG4DataParser implements RawDataParser {
|
||||
CHANNEL_INVERTER_OUTPUT_VOLTAGE, CHANNEL_INVERTER_OUTPUT_FREQUENCY, CHANNEL_INVERTER_WORKMODE);
|
||||
|
||||
@Override
|
||||
public LocalInverterData getData(LocalConnectRawDataBean rawData) {
|
||||
return new X1HybridG4InverterData(rawData);
|
||||
public LocalData getData(LocalConnectRawDataBean rawData) {
|
||||
return new X1HybridG4Data(rawData);
|
||||
}
|
||||
|
||||
@Override
|
@ -10,7 +10,7 @@
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.solax.internal.model.local.parsers;
|
||||
package org.openhab.binding.solax.internal.model.local.inverters;
|
||||
|
||||
import static org.openhab.binding.solax.internal.SolaxBindingConstants.*;
|
||||
|
||||
@ -18,11 +18,12 @@ 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;
|
||||
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 LocalInverterData for the
|
||||
* 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
|
||||
@ -47,8 +48,8 @@ public class X3HybridG4DataParser implements RawDataParser {
|
||||
CHANNEL_TODAY_BATTERY_CHARGE_ENERGY, CHANNEL_TODAY_BATTERY_DISCHARGE_ENERGY, CHANNEL_INVERTER_WORKMODE);
|
||||
|
||||
@Override
|
||||
public LocalInverterData getData(LocalConnectRawDataBean rawData) {
|
||||
return new X3HybridG4InverterData(rawData);
|
||||
public LocalData getData(LocalConnectRawDataBean rawData) {
|
||||
return new X3HybridG4Data(rawData);
|
||||
}
|
||||
|
||||
@Override
|
@ -10,7 +10,7 @@
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.solax.internal.model.local.parsers;
|
||||
package org.openhab.binding.solax.internal.model.local.inverters;
|
||||
|
||||
import static org.openhab.binding.solax.internal.SolaxBindingConstants.*;
|
||||
|
||||
@ -18,8 +18,9 @@ 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;
|
||||
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
|
||||
@ -44,8 +45,8 @@ public class X3MicOrProG2DataParser implements RawDataParser {
|
||||
CHANNEL_INVERTER_TEMPERATURE2, CHANNEL_INVERTER_WORKMODE, CHANNEL_RAW_DATA);
|
||||
|
||||
@Override
|
||||
public LocalInverterData getData(LocalConnectRawDataBean rawData) {
|
||||
return new X3MicOrProG2InverterData(rawData);
|
||||
public LocalData getData(LocalConnectRawDataBean rawData) {
|
||||
return new X3MicOrProG2Data(rawData);
|
||||
}
|
||||
|
||||
@Override
|
@ -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);
|
||||
}
|
||||
}
|
@ -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.
|
||||
|
@ -93,5 +93,46 @@
|
||||
<description>The raw JSON data retrieved from the inverter's Wi-Fi module.</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="charger-state">
|
||||
<item-type>String</item-type>
|
||||
<label>Charger State</label>
|
||||
<description>Charger State</description>
|
||||
<state pattern="%s" readOnly="true">
|
||||
<options>
|
||||
<option value="0">Preparing</option>
|
||||
<option value="1">Preparing</option>
|
||||
<option value="2">Charging</option>
|
||||
<option value="3">Finishing</option>
|
||||
<option value="4">Fault</option>
|
||||
<option value="5">Unavailable</option>
|
||||
<option value="6">Reserved</option>
|
||||
<option value="7">Suspended EV</option>
|
||||
<option value="8">Suspended EV SE</option>
|
||||
</options>
|
||||
</state>
|
||||
</channel-type>
|
||||
<channel-type id="charger-mode">
|
||||
<item-type>String</item-type>
|
||||
<label>Charger Mode</label>
|
||||
<description>Charger Mode</description>
|
||||
<state pattern="%s" readOnly="true">
|
||||
<options>
|
||||
<option value="0">Stop</option>
|
||||
<option value="1">Fast</option>
|
||||
<option value="2">Eco</option>
|
||||
<option value="3">Green</option>
|
||||
</options>
|
||||
</state>
|
||||
</channel-type>
|
||||
<channel-type id="charger-temperature">
|
||||
<item-type>Number:Temperature</item-type>
|
||||
<label>Charger Temperature</label>
|
||||
<description>Charger Temperature</description>
|
||||
<tags>
|
||||
<tag>Measurement</tag>
|
||||
<tag>Temperature</tag>
|
||||
</tags>
|
||||
<state pattern="%d %unit%" readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
</thing:thing-descriptions>
|
||||
|
@ -0,0 +1,129 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<thing:thing-descriptions bindingId="solax"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
|
||||
|
||||
<thing-type id="local-connect-charger">
|
||||
|
||||
<label>Local Connect Charger</label>
|
||||
<description>The charger representation that supports local connections via HTTP</description>
|
||||
|
||||
<channels>
|
||||
<channel id="eq-single-session" typeId="system.electric-energy">
|
||||
<label>Energy This Session</label>
|
||||
<description>The energy charged for the current session</description>
|
||||
</channel>
|
||||
<channel id="eq-total" typeId="system.electric-energy">
|
||||
<label>Total Energy Charged</label>
|
||||
<description>The total energy charged for all sessions</description>
|
||||
</channel>
|
||||
<channel id="charger-output-power-phase1" typeId="system.electric-power">
|
||||
<label>Output Power Phase1</label>
|
||||
<description>Power to/from the charger phase 1</description>
|
||||
</channel>
|
||||
<channel id="charger-output-power-phase2" typeId="system.electric-power">
|
||||
<label>Output Power Phase2</label>
|
||||
<description>Power to/from the charger phase 2</description>
|
||||
</channel>
|
||||
<channel id="charger-output-power-phase3" typeId="system.electric-power">
|
||||
<label>Output Power Phase3</label>
|
||||
<description>Power to/from the charger phase 3</description>
|
||||
</channel>
|
||||
<channel id="charger-total-output-power" typeId="system.electric-power">
|
||||
<label>Output Total Power</label>
|
||||
<description>Power from the charger on all phases</description>
|
||||
</channel>
|
||||
<channel id="charger-current-phase1" typeId="system.electric-current">
|
||||
<label>Output Current Phase1</label>
|
||||
<description>Current from the charger phase 1</description>
|
||||
</channel>
|
||||
<channel id="charger-current-phase2" typeId="system.electric-current">
|
||||
<label>Output Current Phase2</label>
|
||||
<description>Current from the charger phase 2</description>
|
||||
</channel>
|
||||
<channel id="charger-current-phase3" typeId="system.electric-current">
|
||||
<label>Output Current Phase3</label>
|
||||
<description>Current from the charger phase 3</description>
|
||||
</channel>
|
||||
<channel id="charger-voltage-phase1" typeId="system.electric-voltage">
|
||||
<label>Voltage Phase1</label>
|
||||
<description>Voltage of the charger's phase 1</description>
|
||||
</channel>
|
||||
<channel id="charger-voltage-phase2" typeId="system.electric-voltage">
|
||||
<label>Voltage Phase2</label>
|
||||
<description>Voltage of the charger's phase 2</description>
|
||||
</channel>
|
||||
<channel id="charger-voltage-phase3" typeId="system.electric-voltage">
|
||||
<label>Voltage Phase3</label>
|
||||
<description>Voltage of the charger's phase 3</description>
|
||||
</channel>
|
||||
|
||||
<channel id="charger-external-current-phase1" typeId="system.electric-current">
|
||||
<label>External Current Phase1</label>
|
||||
<description>Current from the provider phase 1</description>
|
||||
</channel>
|
||||
<channel id="charger-external-current-phase2" typeId="system.electric-current">
|
||||
<label>External Current Phase2</label>
|
||||
<description>Current from the provider phase 2</description>
|
||||
</channel>
|
||||
<channel id="charger-external-current-phase3" typeId="system.electric-current">
|
||||
<label>External Current Phase3</label>
|
||||
<description>Current from the provider phase 3</description>
|
||||
</channel>
|
||||
<channel id="charger-external-power-phase1" typeId="system.electric-power">
|
||||
<label>External Power Phase1</label>
|
||||
<description>Power from the provider phase 1</description>
|
||||
</channel>
|
||||
<channel id="charger-external-power-phase2" typeId="system.electric-power">
|
||||
<label>External Power Phase2</label>
|
||||
<description>Power from the provider phase 2</description>
|
||||
</channel>
|
||||
<channel id="charger-external-power-phase3" typeId="system.electric-power">
|
||||
<label>External Power Phase3</label>
|
||||
<description>Power from the provider phase 3</description>
|
||||
</channel>
|
||||
<channel id="charger-external-total-power" typeId="system.electric-power">
|
||||
<label>External Total Power</label>
|
||||
<description>Total power from the provider</description>
|
||||
</channel>
|
||||
|
||||
<channel id="charger-plug-temperature" typeId="charger-temperature">
|
||||
<label>Plug Temperature</label>
|
||||
<description>Temperature of the charger's plug</description>
|
||||
</channel>
|
||||
<channel id="charger-internal-temperature" typeId="charger-temperature">
|
||||
<label>Internal Temperature</label>
|
||||
<description>Internal temperature on the board of the charger</description>
|
||||
</channel>
|
||||
<channel id="charger-mode" typeId="charger-mode">
|
||||
<label>Workmode</label>
|
||||
<description>Charger Workmode</description>
|
||||
</channel>
|
||||
<channel id="charger-state" typeId="charger-state">
|
||||
<label>State</label>
|
||||
<description>Charger State</description>
|
||||
</channel>
|
||||
|
||||
<channel id="last-update-time" typeId="last-retrieve-time-stamp"/>
|
||||
</channels>
|
||||
|
||||
<config-description>
|
||||
<parameter name="refreshInterval" type="integer" min="1" max="600">
|
||||
<label>Refresh Interval</label>
|
||||
<description>Specifies the refresh interval in seconds.</description>
|
||||
<default>10</default>
|
||||
</parameter>
|
||||
<parameter name="password" type="text" required="true">
|
||||
<label>Password</label>
|
||||
<description>Password for accessing the Wi-Fi module (the serial number of the Wi-Fi module)</description>
|
||||
<context>password</context>
|
||||
</parameter>
|
||||
<parameter name="hostname" type="text" required="true">
|
||||
<label>Network Address</label>
|
||||
<description>IP address or the host name of the Wi-Fi module</description>
|
||||
<context>network-address</context>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</thing-type>
|
||||
</thing:thing-descriptions>
|
@ -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<String> 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);
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
}
|
@ -10,13 +10,14 @@
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.solax.internal.local;
|
||||
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.LocalInverterData;
|
||||
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
|
||||
@ -49,7 +50,7 @@ public class TestX1BoostAirMiniDataParser extends AbstractParserTest {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void assertParserSpecific(LocalInverterData data) {
|
||||
protected void assertParserSpecific(LocalData data) {
|
||||
assertEquals("SR***", data.getWifiSerial());
|
||||
assertEquals("3.006.04", data.getWifiVersion());
|
||||
|
@ -10,13 +10,14 @@
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.solax.internal.local;
|
||||
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.LocalInverterData;
|
||||
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
|
||||
@ -46,7 +47,7 @@ public class TestX1HybridG4Parser extends AbstractParserTest {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void assertParserSpecific(LocalInverterData data) {
|
||||
protected void assertParserSpecific(LocalData data) {
|
||||
assertEquals("SOME_SERIAL_NUMBER", data.getWifiSerial());
|
||||
assertEquals("3.008.10", data.getWifiVersion());
|
||||
|
@ -10,13 +10,14 @@
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.solax.internal.local;
|
||||
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.LocalInverterData;
|
||||
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
|
||||
@ -53,7 +54,7 @@ public class TestX3HybridG4Parser extends AbstractParserTest {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void assertParserSpecific(LocalInverterData data) {
|
||||
protected void assertParserSpecific(LocalData data) {
|
||||
assertEquals("XYZ", data.getWifiSerial());
|
||||
assertEquals("3.005.01", data.getWifiVersion());
|
||||
|
@ -10,7 +10,7 @@
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.solax.internal.local;
|
||||
package org.openhab.binding.solax.internal.local.parsers;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
@ -18,8 +18,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 TestX3HybridG4Parser} simple test that tests for proper parsing against a real data from the inverter
|
||||
@ -56,7 +56,7 @@ public class TestX3MicOrProG2Parser {
|
||||
RawDataParser parser = inverterType.getParser();
|
||||
assertNotNull(parser);
|
||||
|
||||
LocalInverterData data = parser.getData(bean);
|
||||
LocalData data = parser.getData(bean);
|
||||
assertEquals("XYZ", data.getWifiSerial());
|
||||
assertEquals("3.003.02", data.getWifiVersion());
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user