Skip to content

Commit

Permalink
[solax] Add support for Solax X3MIC / G2 inverter and workmode channel (
Browse files Browse the repository at this point in the history
openhab#16248)

* Support for Solax X3MIC / G2 inverter, and workmode channel for the existing X1, X3 also
* Add update instructions and make raise the target version to 1
* Refactor the workmode to be enum instead of string constants

Signed-off-by: Henrik Tóth <realthk@gmail.com>
Signed-off-by: Konstantin Polihronov <polychronov@gmail.com>
Signed-off-by: Leo Siepel <leosiepel@gmail.com>
Signed-off-by: Jørgen Austvik <jaustvik@acm.org>
  • Loading branch information
realthk authored and austvik committed Mar 27, 2024
1 parent 662cfd7 commit d8e5690
Show file tree
Hide file tree
Showing 17 changed files with 452 additions and 16 deletions.
Expand Up @@ -61,6 +61,9 @@ public class SolaxBindingConstants {
public static final String CHANNEL_INVERTER_OUTPUT_FREQUENCY_PHASE1 = "inverter-frequency-phase1";
public static final String CHANNEL_INVERTER_OUTPUT_FREQUENCY_PHASE2 = "inverter-frequency-phase2";
public static final String CHANNEL_INVERTER_OUTPUT_FREQUENCY_PHASE3 = "inverter-frequency-phase3";
public static final String CHANNEL_INVERTER_TEMPERATURE1 = "inverter-temperature1";
public static final String CHANNEL_INVERTER_TEMPERATURE2 = "inverter-temperature2";
public static final String CHANNEL_INVERTER_WORKMODE = "inverter-workmode";

// Generic
public static final String CHANNEL_INVERTER_PV1_POWER = "pv1-power";
Expand Down
Expand Up @@ -190,12 +190,18 @@ private void updateChannels(RawDataParser parser, InverterData inverterData) {
supportedChannels);
updateChannel(SolaxBindingConstants.CHANNEL_BATTERY_TEMPERATURE, inverterData.getBatteryTemperature(),
SIUnits.CELSIUS, supportedChannels);
updateChannel(SolaxBindingConstants.CHANNEL_INVERTER_TEMPERATURE1, inverterData.getInverterTemperature1(),
SIUnits.CELSIUS, supportedChannels);
updateChannel(SolaxBindingConstants.CHANNEL_INVERTER_TEMPERATURE2, inverterData.getInverterTemperature2(),
SIUnits.CELSIUS, supportedChannels);
updateChannel(SolaxBindingConstants.CHANNEL_BATTERY_STATE_OF_CHARGE, inverterData.getBatteryLevel(),
Units.PERCENT, supportedChannels);
updateChannel(SolaxBindingConstants.CHANNEL_FEED_IN_POWER, inverterData.getFeedInPower(), Units.WATT,
supportedChannels);
updateChannel(SolaxBindingConstants.CHANNEL_POWER_USAGE, inverterData.getPowerUsage(), Units.WATT,
supportedChannels);
updateState(SolaxBindingConstants.CHANNEL_INVERTER_WORKMODE,
new StringType(inverterData.getInverterWorkMode()));

// Totals
updateChannel(SolaxBindingConstants.CHANNEL_TOTAL_ENERGY, inverterData.getTotalEnergy(), Units.KILOWATT_HOUR,
Expand Down
Expand Up @@ -82,6 +82,22 @@ default short getBatteryTemperature() {
return Short.MIN_VALUE;
}

default short getInverterTemperature1() {
return Short.MIN_VALUE;
}

default short getInverterTemperature2() {
return Short.MIN_VALUE;
}

default short getInverterWorkModeCode() {
return Short.MIN_VALUE;
}

default String getInverterWorkMode() {
return String.valueOf(getInverterWorkModeCode());
}

default short getBatteryLevel() {
return Short.MIN_VALUE;
}
Expand Down
Expand Up @@ -21,6 +21,7 @@
import org.openhab.binding.solax.internal.model.parsers.RawDataParser;
import org.openhab.binding.solax.internal.model.parsers.X1HybridG4DataParser;
import org.openhab.binding.solax.internal.model.parsers.X3HybridG4DataParser;
import org.openhab.binding.solax.internal.model.parsers.X3MicOrProG2DataParser;

/**
* The {@link InverterType} class is enum representing the different inverter types with a simple logic to convert from
Expand All @@ -46,7 +47,7 @@ public enum InverterType {
J1_ESS(13),
X3_HYBRID_G4(14, new X3HybridG4DataParser()),
X1_HYBRID_G4(15, new X1HybridG4DataParser()),
X3_MIC_OR_PRO_G2(16),
X3_MIC_OR_PRO_G2(16, new X3MicOrProG2DataParser()),
X1_SPT(17),
X1_BOOST_OR_MINI_G4(18),
A1_HYB_G2(19),
Expand Down
Expand Up @@ -83,6 +83,11 @@ public short getPV2Power() {
return getData(9);
}

@Override
public short getInverterWorkModeCode() {
return getData(10);
}

@Override
public double getBatteryVoltage() {
return ((double) getData(14)) / 100;
Expand Down
Expand Up @@ -125,6 +125,11 @@ public double getFrequencyPhase3() {
return ((double) getData(18)) / 100;
}

@Override
public short getInverterWorkModeCode() {
return getData(19);
}

// Battery

@Override
Expand Down
@@ -0,0 +1,153 @@
/**
* Copyright (c) 2010-2024 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.solax.internal.model.impl;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.binding.solax.internal.connectivity.rawdata.LocalConnectRawDataBean;

/**
* The {@link X3HybridG4InverterData} is responsible for handling commands, which are
* sent to one of the channels.
*
* @author Henrik Tóth - Initial contribution
* (based on X1/X3 G4 parser from Konstantin Polihronov)
*/
@NonNullByDefault
public class X3MicOrProG2InverterData extends CommonInverterData {

public X3MicOrProG2InverterData(LocalConnectRawDataBean data) {
super(data);
}

// Inverter data

@Override
public double getVoltagePhase1() {
return ((double) getData(0)) / 10;
}

@Override
public double getVoltagePhase2() {
return ((double) getData(1)) / 10;
}

@Override
public double getVoltagePhase3() {
return ((double) getData(2)) / 10;
}

@Override
public double getCurrentPhase1() {
return ((double) getData(3)) / 10;
}

@Override
public double getCurrentPhase2() {
return ((double) getData(4)) / 10;
}

@Override
public double getCurrentPhase3() {
return ((double) getData(5)) / 10;
}

@Override
public short getOutputPowerPhase1() {
return getData(6);
}

@Override
public short getOutputPowerPhase2() {
return getData(7);
}

@Override
public short getOutputPowerPhase3() {
return getData(8);
}

@Override
public double getPV1Voltage() {
return ((double) getData(9)) / 10;
}

@Override
public double getPV2Voltage() {
return ((double) getData(10)) / 10;
}

@Override
public double getPV1Current() {
return ((double) getData(12)) / 10;
}

@Override
public double getPV2Current() {
return ((double) getData(13)) / 10;
}

@Override
public short getPV1Power() {
return getData(15);
}

@Override
public short getPV2Power() {
return getData(16);
}

@Override
public double getFrequencyPhase1() {
return ((double) getData(18)) / 100;
}

@Override
public double getFrequencyPhase2() {
return ((double) getData(19)) / 100;
}

@Override
public double getFrequencyPhase3() {
return ((double) getData(20)) / 100;
}

@Override
public short getInverterWorkModeCode() {
return getData(21);
}

@Override
public double getTotalEnergy() {
return ((double) getData(22)) / 10;
}

@Override
public double getTodayEnergy() {
return ((double) getData(24)) / 10;
}

@Override
public short getInverterTemperature1() {
return getData(26);
}

@Override
public short getInverterTemperature2() {
return getData(27);
}

@Override
public short getTotalOutputPower() {
return getData(78);
}
}
Expand Up @@ -36,7 +36,7 @@ public class X1HybridG4DataParser implements RawDataParser {
CHANNEL_INVERTER_PV_TOTAL_CURRENT, CHANNEL_BATTERY_POWER, CHANNEL_BATTERY_VOLTAGE, CHANNEL_BATTERY_CURRENT,
CHANNEL_BATTERY_TEMPERATURE, CHANNEL_BATTERY_STATE_OF_CHARGE, CHANNEL_FEED_IN_POWER, CHANNEL_TIMESTAMP,
CHANNEL_RAW_DATA, CHANNEL_INVERTER_OUTPUT_POWER, CHANNEL_INVERTER_OUTPUT_CURRENT,
CHANNEL_INVERTER_OUTPUT_VOLTAGE, CHANNEL_INVERTER_OUTPUT_FREQUENCY);
CHANNEL_INVERTER_OUTPUT_VOLTAGE, CHANNEL_INVERTER_OUTPUT_FREQUENCY, CHANNEL_INVERTER_WORKMODE);

@Override
public InverterData getData(LocalConnectRawDataBean rawData) {
Expand Down
Expand Up @@ -44,7 +44,7 @@ public class X3HybridG4DataParser implements RawDataParser {
CHANNEL_INVERTER_OUTPUT_FREQUENCY_PHASE3, CHANNEL_POWER_USAGE, CHANNEL_TOTAL_ENERGY,
CHANNEL_TOTAL_BATTERY_CHARGE_ENERGY, CHANNEL_TOTAL_PV_ENERGY, CHANNEL_TOTAL_CONSUMPTION,
CHANNEL_TODAY_ENERGY, CHANNEL_TODAY_FEED_IN_ENERGY, CHANNEL_TODAY_CONSUMPTION,
CHANNEL_TODAY_BATTERY_CHARGE_ENERGY, CHANNEL_TODAY_BATTERY_DISCHARGE_ENERGY);
CHANNEL_TODAY_BATTERY_CHARGE_ENERGY, CHANNEL_TODAY_BATTERY_DISCHARGE_ENERGY, CHANNEL_INVERTER_WORKMODE);

@Override
public InverterData getData(LocalConnectRawDataBean rawData) {
Expand Down
@@ -0,0 +1,55 @@
/**
* 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.parsers;

import static org.openhab.binding.solax.internal.SolaxBindingConstants.*;

import java.util.Set;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.binding.solax.internal.connectivity.rawdata.LocalConnectRawDataBean;
import org.openhab.binding.solax.internal.model.InverterData;
import org.openhab.binding.solax.internal.model.impl.X3MicOrProG2InverterData;

/**
* The {@link X3MicOrProG2DataParser} is the implementation that parses raw data into a SinglePhaseInverterData for the
* X3 Mic / Pro G2 inverter.
*
* @author Henrik Tóth - Initial contribution
* (based on X1/X3 G4 parser from Konstantin Polihronov)
*/
@NonNullByDefault
public class X3MicOrProG2DataParser implements RawDataParser {

private static final Set<String> X3_MIC_OR_PRO_G2_SUPPORTED_CHANNELS = Set.of(
CHANNEL_INVERTER_OUTPUT_VOLTAGE_PHASE1, CHANNEL_INVERTER_OUTPUT_FREQUENCY_PHASE2,
CHANNEL_INVERTER_OUTPUT_VOLTAGE_PHASE3, CHANNEL_INVERTER_OUTPUT_CURRENT_PHASE1,
CHANNEL_INVERTER_OUTPUT_CURRENT_PHASE2, CHANNEL_INVERTER_OUTPUT_CURRENT_PHASE3,
CHANNEL_INVERTER_OUTPUT_POWER_PHASE1, CHANNEL_INVERTER_OUTPUT_POWER_PHASE2,
CHANNEL_INVERTER_OUTPUT_POWER_PHASE3, CHANNEL_INVERTER_PV1_VOLTAGE, CHANNEL_INVERTER_PV2_VOLTAGE,
CHANNEL_INVERTER_PV1_CURRENT, CHANNEL_INVERTER_PV2_CURRENT, CHANNEL_INVERTER_PV1_POWER,
CHANNEL_INVERTER_PV2_POWER, CHANNEL_INVERTER_OUTPUT_FREQUENCY_PHASE1,
CHANNEL_INVERTER_OUTPUT_VOLTAGE_PHASE2, CHANNEL_INVERTER_OUTPUT_FREQUENCY_PHASE3, CHANNEL_TOTAL_ENERGY,
CHANNEL_TODAY_ENERGY, CHANNEL_INVERTER_TOTAL_OUTPUT_POWER, CHANNEL_INVERTER_TEMPERATURE1,
CHANNEL_INVERTER_TEMPERATURE2, CHANNEL_INVERTER_WORKMODE, CHANNEL_RAW_DATA);

@Override
public InverterData getData(LocalConnectRawDataBean rawData) {
return new X3MicOrProG2InverterData(rawData);
}

@Override
public Set<String> getSupportedChannels() {
return X3_MIC_OR_PRO_G2_SUPPORTED_CHANNELS;
}
}
Expand Up @@ -27,12 +27,12 @@ thing-type.solax.local-connect-inverter.channel.inverter-current-phase2.label =
thing-type.solax.local-connect-inverter.channel.inverter-current-phase2.description = Current to/from the inverter phase 2
thing-type.solax.local-connect-inverter.channel.inverter-current-phase3.label = Inverter Input/Output Current Phase 3
thing-type.solax.local-connect-inverter.channel.inverter-current-phase3.description = Current to/from the inverter phase 3
thing-type.solax.local-connect-inverter.channel.inverter-frequency-phase1.label = Inverter Voltage Phase 3
thing-type.solax.local-connect-inverter.channel.inverter-frequency-phase1.description = Voltage of the inverter's phase 3
thing-type.solax.local-connect-inverter.channel.inverter-frequency-phase2.label = Inverter Voltage Phase 2
thing-type.solax.local-connect-inverter.channel.inverter-frequency-phase2.description = Voltage of the inverter's phase 3
thing-type.solax.local-connect-inverter.channel.inverter-frequency-phase3.label = Inverter Voltage Phase 3
thing-type.solax.local-connect-inverter.channel.inverter-frequency-phase3.description = Voltage of the inverter's phase 3
thing-type.solax.local-connect-inverter.channel.inverter-frequency-phase1.label = Inverter Frequency Phase 1
thing-type.solax.local-connect-inverter.channel.inverter-frequency-phase1.description = Frequency of the inverter's phase 1
thing-type.solax.local-connect-inverter.channel.inverter-frequency-phase2.label = Inverter Frequency Phase 2
thing-type.solax.local-connect-inverter.channel.inverter-frequency-phase2.description = Frequency of the inverter's phase 2
thing-type.solax.local-connect-inverter.channel.inverter-frequency-phase3.label = Inverter Frequency Phase 3
thing-type.solax.local-connect-inverter.channel.inverter-frequency-phase3.description = Frequency of the inverter's phase 3
thing-type.solax.local-connect-inverter.channel.inverter-output-power.label = Inverter Input/Output Power
thing-type.solax.local-connect-inverter.channel.inverter-output-power.description = Power to/from the inverter
thing-type.solax.local-connect-inverter.channel.inverter-output-power-phase1.label = Inverter Input/Output Power Phase 1
Expand All @@ -41,6 +41,10 @@ thing-type.solax.local-connect-inverter.channel.inverter-output-power-phase2.lab
thing-type.solax.local-connect-inverter.channel.inverter-output-power-phase2.description = Power to/from the inverter phase 2
thing-type.solax.local-connect-inverter.channel.inverter-output-power-phase3.label = Inverter Input/Output Power Phase 3
thing-type.solax.local-connect-inverter.channel.inverter-output-power-phase3.description = Power to/from the inverter phase 3
thing-type.solax.local-connect-inverter.channel.inverter-temperature1.label = Inverter Temperature 1
thing-type.solax.local-connect-inverter.channel.inverter-temperature1.description = Temperature 1 of the inverter
thing-type.solax.local-connect-inverter.channel.inverter-temperature2.label = Inverter Temperature 2
thing-type.solax.local-connect-inverter.channel.inverter-temperature2.description = Temperature 2 of the inverter
thing-type.solax.local-connect-inverter.channel.inverter-total-output-power.label = Inverter Input/Output Total Power
thing-type.solax.local-connect-inverter.channel.inverter-total-output-power.description = Power to/from the inverter on all phases
thing-type.solax.local-connect-inverter.channel.inverter-voltage.label = Inverter Voltage
Expand All @@ -51,6 +55,8 @@ thing-type.solax.local-connect-inverter.channel.inverter-voltage-phase2.label =
thing-type.solax.local-connect-inverter.channel.inverter-voltage-phase2.description = Voltage of the inverter's phase 2
thing-type.solax.local-connect-inverter.channel.inverter-voltage-phase3.label = Inverter Voltage Phase 3
thing-type.solax.local-connect-inverter.channel.inverter-voltage-phase3.description = Voltage of the inverter's phase 3
thing-type.solax.local-connect-inverter.channel.inverter-workmode.label = Inverter Workmode
thing-type.solax.local-connect-inverter.channel.inverter-workmode.description = Inverter Workmode
thing-type.solax.local-connect-inverter.channel.power-usage.label = Power Usage
thing-type.solax.local-connect-inverter.channel.power-usage.description = Current power consumption of the building
thing-type.solax.local-connect-inverter.channel.pv-total-current.label = PV Total Current
Expand Down Expand Up @@ -107,6 +113,24 @@ channel-type.solax.battery-temperature.label = Battery Temperature
channel-type.solax.battery-temperature.description = Battery 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-temperature.label = Inverter Temperature
channel-type.solax.inverter-temperature.description = Inverter Temperature
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
channel-type.solax.inverter-workmode.state.option.1 = Checking
channel-type.solax.inverter-workmode.state.option.2 = Normal
channel-type.solax.inverter-workmode.state.option.3 = Fault
channel-type.solax.inverter-workmode.state.option.4 = Permanent Fault
channel-type.solax.inverter-workmode.state.option.5 = Updating
channel-type.solax.inverter-workmode.state.option.6 = EPS Check
channel-type.solax.inverter-workmode.state.option.7 = EPS Normal
channel-type.solax.inverter-workmode.state.option.8 = Self Test
channel-type.solax.inverter-workmode.state.option.9 = Idle
channel-type.solax.inverter-workmode.state.option.10 = Standby
channel-type.solax.inverter-workmode.state.option.11 = PV Wake-up Battery
channel-type.solax.inverter-workmode.state.option.12 = GEN Check
channel-type.solax.inverter-workmode.state.option.13 = GEN Run
channel-type.solax.last-retrieve-time-stamp.label = Last Retrieve Time Stamp
channel-type.solax.last-retrieve-time-stamp.description = Last time with a successful retrieval of data
channel-type.solax.raw-data-type.label = Raw Data
Expand Down

0 comments on commit d8e5690

Please sign in to comment.