Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

[solax] Add support for Solax X3MIC / G2 inverter and workmode channel #16248

Merged
merged 6 commits into from
Feb 10, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ 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";
theater marked this conversation as resolved.
Show resolved Hide resolved
public static final String CHANNEL_INVERTER_TEMPERATURE2 = "inverter-temperature2";
public static final String CHANNEL_INVERTER_WORKMODE_CODE = "inverter-workmode-code";
public static final String CHANNEL_INVERTER_WORKMODE = "inverter-workmode";

// Generic
public static final String CHANNEL_INVERTER_PV1_POWER = "pv1-power";
Expand Down Expand Up @@ -101,6 +105,14 @@ public class SolaxBindingConstants {
public static final String CHANNEL_TODAY_FEED_IN_ENERGY = "today-feed-in-energy";
public static final String CHANNEL_TODAY_CONSUMPTION = "today-consumption";

// Workmodes
public static final String WORKMODE_WAITING = "Waiting";
theater marked this conversation as resolved.
Show resolved Hide resolved
public static final String WORKMODE_CHECKING = "Checking";
public static final String WORKMODE_NORMAL = "Normal";
public static final String WORKMODE_FAULT = "Fault";
public static final String WORKMODE_PERMANENT_FAULT = "Permanent fault";
public static final String WORKMODE_UPGRADING = "Upgrading";

// I18N Keys
protected static final String I18N_KEY_OFFLINE_COMMUNICATION_ERROR_JSON_CANNOT_BE_RETRIEVED = "@text/offline.communication-error.json-cannot-be-retrieved";
}
Original file line number Diff line number Diff line change
Expand Up @@ -190,12 +190,20 @@ 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);
updateChannel(SolaxBindingConstants.CHANNEL_INVERTER_WORKMODE_CODE, inverterData.getInverterWorkModeCode(),
Units.ONE, supportedChannels);
lsiepel marked this conversation as resolved.
Show resolved Hide resolved
updateState(SolaxBindingConstants.CHANNEL_INVERTER_WORKMODE,
new StringType(inverterData.getInverterWorkMode()));

// Totals
updateChannel(SolaxBindingConstants.CHANNEL_TOTAL_ENERGY, inverterData.getTotalEnergy(), Units.KILOWATT_HOUR,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
*/
package org.openhab.binding.solax.internal.model;

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

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;

Expand Down Expand Up @@ -82,6 +84,37 @@ 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;
}

@Nullable
default String getInverterWorkMode() {
theater marked this conversation as resolved.
Show resolved Hide resolved
switch (getInverterWorkModeCode()) {
theater marked this conversation as resolved.
Show resolved Hide resolved
case 0:
return WORKMODE_WAITING;
case 1:
return WORKMODE_CHECKING;
case 2:
return WORKMODE_NORMAL;
case 3:
return WORKMODE_FAULT;
case 4:
return WORKMODE_PERMANENT_FAULT;
case 5:
return WORKMODE_UPGRADING;
}
theater marked this conversation as resolved.
Show resolved Hide resolved
return null;
}

default short getBatteryLevel() {
return Short.MIN_VALUE;
}
Expand Down
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
@@ -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);
}
}
Original file line number Diff line number Diff line change
@@ -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_INVERTER_WORKMODE_CODE, 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;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,10 @@ thing-type.solax.local-connect-inverter.channel.total-feed-in-energy.label = Tot
thing-type.solax.local-connect-inverter.channel.total-feed-in-energy.description = Total energy consumed from the electricity provider
thing-type.solax.local-connect-inverter.channel.total-pv-energy.label = Total PV Energy
thing-type.solax.local-connect-inverter.channel.total-pv-energy.description = Total energy produced by the PV
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 types config

Expand All @@ -111,6 +115,10 @@ 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
channel-type.solax.raw-data-type.description = The raw JSON data retrieved from the inverter's Wi-Fi module.
channel-type.solax.inverter-temperature.label = Inverter Temperature
channel-type.solax.inverter-temperature.description = Inverter Temperature
channel-type.solax.inverter-workmode-code.label = Inverter Workmode Code
theater marked this conversation as resolved.
Show resolved Hide resolved
channel-type.solax.inverter-workmode-code.description = Inverter Workmode Code (0=Waiting, 1=Checking, 2=Normal, 3=Off, 4=Fault, 5=Permanent fault, 6=Upgrading)

# thing status descriptions

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,28 @@
</tags>
<state pattern="%d %unit%" readOnly="true"/>
</channel-type>
<channel-type id="inverter-temperature">
<item-type>Number:Temperature</item-type>
<label>Inverter Temperature</label>
<description>Inverter Temperature</description>
<tags>
<tag>Measurement</tag>
<tag>Temperature</tag>
</tags>
<state pattern="%d %unit%" readOnly="true"/>
</channel-type>
<channel-type id="inverter-workmode-code">
<item-type>Number</item-type>
<label>Inverter Workmode Code</label>
<description>Inverter Workmode Code</description>
<state pattern="%d" readOnly="true"/>
</channel-type>
<channel-type id="inverter-workmode">
theater marked this conversation as resolved.
Show resolved Hide resolved
<item-type>String</item-type>
<label>Inverter Workmode</label>
<description>Inverter Workmode</description>
<state pattern="%s" readOnly="true"/>
</channel-type>
<channel-type id="last-retrieve-time-stamp">
<item-type>DateTime</item-type>
<label>Last Retrieve Time Stamp</label>
Expand Down