mirror of
https://github.com/openhab/openhab-addons.git
synced 2025-01-25 14:55:55 +01:00
[solax] Support for x1 mini inverter local connection (#16412)
Skeleton of the required classes for supporting X1 mini Add the parser data Signed-off-by: Konstantin Polihronov <polychronov@gmail.com> Signed-off-by: Ciprian Pascu <contact@ciprianpascu.ro>
This commit is contained in:
parent
087dedb4c6
commit
a1c783dd9b
@ -19,6 +19,7 @@ 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;
|
||||
@ -35,7 +36,7 @@ public enum InverterType {
|
||||
X1_LX(1),
|
||||
X_HYBRID(2),
|
||||
X1_HYBRID_FIT(3),
|
||||
X1_BOOST_AIR_MINI(4),
|
||||
X1_BOOST_AIR_MINI(4, new X1BoostAirMiniDataParser()),
|
||||
X3_HYBRID_FIT(5),
|
||||
X3_20K_30K(6),
|
||||
X3_MIC_PRO(7),
|
||||
|
@ -0,0 +1,95 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2024 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.solax.internal.model.local;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.solax.internal.connectivity.rawdata.local.LocalConnectRawDataBean;
|
||||
|
||||
/**
|
||||
* The {@link X1BoostAirMiniInverterData} is an implementation of the single phased inverter data interface for X1 Mini
|
||||
* / X1 Air Mini or X1 Boost Mini inverter.
|
||||
*
|
||||
* @author Konstantin Polihronov - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class X1BoostAirMiniInverterData extends CommonLocalInverterData {
|
||||
|
||||
public X1BoostAirMiniInverterData(LocalConnectRawDataBean data) {
|
||||
super(data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getInverterVoltage() {
|
||||
return (double) getData(0) / 10;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getInverterCurrent() {
|
||||
return (double) getData(1) / 10;
|
||||
}
|
||||
|
||||
@Override
|
||||
public short getInverterOutputPower() {
|
||||
return getData(2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getPV1Voltage() {
|
||||
return (double) getData(3) / 10;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getPV2Voltage() {
|
||||
return (double) getData(4) / 10;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getPV1Current() {
|
||||
return (double) getData(5) / 10;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getPV2Current() {
|
||||
return (double) getData(6) / 10;
|
||||
}
|
||||
|
||||
@Override
|
||||
public short getPV1Power() {
|
||||
return getData(7);
|
||||
}
|
||||
|
||||
@Override
|
||||
public short getPV2Power() {
|
||||
return getData(8);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getInverterFrequency() {
|
||||
return (double) getData(9) / 100;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getTotalEnergy() {
|
||||
return (double) getData(11) / 10;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getTodayEnergy() {
|
||||
return (double) getData(13) / 10;
|
||||
}
|
||||
|
||||
@Override
|
||||
public short getPowerUsage() {
|
||||
return (short) Math.round((double) getData(43) / 10);
|
||||
}
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2024 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.solax.internal.model.local.parsers;
|
||||
|
||||
import static org.openhab.binding.solax.internal.SolaxBindingConstants.*;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.solax.internal.connectivity.rawdata.local.LocalConnectRawDataBean;
|
||||
import org.openhab.binding.solax.internal.model.local.LocalInverterData;
|
||||
import org.openhab.binding.solax.internal.model.local.X1BoostAirMiniInverterData;
|
||||
|
||||
/**
|
||||
* The {@link X1BoostAirMiniDataParser} is the implementation that parses raw data into a LocalInverterData for the
|
||||
* X1 Mini / X1 Air Mini or X1 Boost Mini inverter.
|
||||
*
|
||||
* @author Konstantin Polihronov - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class X1BoostAirMiniDataParser implements RawDataParser {
|
||||
|
||||
private static final Set<String> X1_BOOST_AIR_MINI_SUPPORTED_CHANNELS = Set.of(CHANNEL_INVERTER_PV1_POWER,
|
||||
CHANNEL_INVERTER_PV1_VOLTAGE, CHANNEL_INVERTER_PV1_CURRENT, CHANNEL_INVERTER_PV2_POWER,
|
||||
CHANNEL_INVERTER_PV2_VOLTAGE, CHANNEL_INVERTER_PV2_CURRENT, CHANNEL_INVERTER_PV_TOTAL_POWER,
|
||||
CHANNEL_INVERTER_PV_TOTAL_CURRENT, CHANNEL_TIMESTAMP, CHANNEL_RAW_DATA, CHANNEL_INVERTER_OUTPUT_POWER,
|
||||
CHANNEL_INVERTER_OUTPUT_CURRENT, CHANNEL_INVERTER_OUTPUT_VOLTAGE, CHANNEL_INVERTER_OUTPUT_FREQUENCY,
|
||||
CHANNEL_TOTAL_ENERGY, CHANNEL_TODAY_ENERGY, CHANNEL_POWER_USAGE);
|
||||
|
||||
@Override
|
||||
public LocalInverterData getData(LocalConnectRawDataBean bean) {
|
||||
return new X1BoostAirMiniInverterData(bean);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getSupportedChannels() {
|
||||
return X1_BOOST_AIR_MINI_SUPPORTED_CHANNELS;
|
||||
}
|
||||
}
|
@ -22,7 +22,7 @@ import org.openhab.binding.solax.internal.model.local.LocalInverterData;
|
||||
import org.openhab.binding.solax.internal.model.local.X1HybridG4InverterData;
|
||||
|
||||
/**
|
||||
* The {@link SinglePhaseDataParser} is the implementation that parses raw data into a SinglePhaseInverterData for the
|
||||
* The {@link X1HybridG4DataParser} is the implementation that parses raw data into a LocalInverterData for the
|
||||
* X1 Hybrid G4 inverter.
|
||||
*
|
||||
* @author Konstantin Polihronov - Initial contribution
|
||||
|
@ -22,7 +22,7 @@ import org.openhab.binding.solax.internal.model.local.LocalInverterData;
|
||||
import org.openhab.binding.solax.internal.model.local.X3HybridG4InverterData;
|
||||
|
||||
/**
|
||||
* The {@link X3HybridG4DataParser} is the implementation that parses raw data into a SinglePhaseInverterData for the
|
||||
* The {@link X3HybridG4DataParser} is the implementation that parses raw data into a LocalInverterData for the
|
||||
* X3 Hybrid G4 inverter.
|
||||
*
|
||||
* @author Konstantin Polihronov - Initial contribution
|
||||
|
@ -0,0 +1,56 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2024 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.solax.internal.local;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.openhab.binding.solax.internal.connectivity.rawdata.local.LocalConnectRawDataBean;
|
||||
import org.openhab.binding.solax.internal.model.InverterType;
|
||||
import org.openhab.binding.solax.internal.model.local.LocalInverterData;
|
||||
import org.openhab.binding.solax.internal.model.local.parsers.RawDataParser;
|
||||
|
||||
/**
|
||||
* The {@link AbstractParserTest} Abstract class defining the common logic for testing local connections to the various
|
||||
* inverters and their parsers
|
||||
*
|
||||
* @author Konstantin Polihronov - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public abstract class AbstractParserTest {
|
||||
@Test
|
||||
public void testParser() {
|
||||
LocalConnectRawDataBean bean = LocalConnectRawDataBean.fromJson(getRawData());
|
||||
int type = bean.getType();
|
||||
InverterType inverterType = InverterType.fromIndex(type);
|
||||
assertEquals(getInverterType(), inverterType, "Inverter type not recognized properly");
|
||||
|
||||
RawDataParser parser = inverterType.getParser();
|
||||
assertNotNull(parser);
|
||||
|
||||
Set<String> supportedChannels = parser.getSupportedChannels();
|
||||
assertFalse(supportedChannels.isEmpty());
|
||||
|
||||
LocalInverterData data = parser.getData(bean);
|
||||
assertParserSpecific(data);
|
||||
}
|
||||
|
||||
protected abstract InverterType getInverterType();
|
||||
|
||||
protected abstract String getRawData();
|
||||
|
||||
protected abstract void assertParserSpecific(LocalInverterData data);
|
||||
}
|
@ -0,0 +1,79 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2024 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.solax.internal.local;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.solax.internal.model.InverterType;
|
||||
import org.openhab.binding.solax.internal.model.local.LocalInverterData;
|
||||
|
||||
/**
|
||||
* The {@link TestX1BoostAirMiniDataParser} Simple test that tests for proper parsing against a real data from the
|
||||
* inverter
|
||||
*
|
||||
* @author Konstantin Polihronov - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class TestX1BoostAirMiniDataParser extends AbstractParserTest {
|
||||
|
||||
private static final String RAW_DATA = """
|
||||
{
|
||||
sn:SR***,
|
||||
ver:3.006.04,
|
||||
type:4,
|
||||
Data:[
|
||||
2263,7,128,1519,0,9,0,138,0,5000,
|
||||
2,15569,0,7,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,13,
|
||||
0,4071,0,3456,0,0,0,0,0,0,
|
||||
0,0,0,0,0,23,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
],
|
||||
Information:[1.500,4,XM3A15IA669518,8,2.27,0.00,1.43,0.00,0.00,1]}
|
||||
""";
|
||||
|
||||
@Override
|
||||
protected String getRawData() {
|
||||
return RAW_DATA;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void assertParserSpecific(LocalInverterData data) {
|
||||
assertEquals("SR***", data.getWifiSerial());
|
||||
assertEquals("3.006.04", data.getWifiVersion());
|
||||
|
||||
assertEquals(226.3, data.getInverterVoltage()); // [0]
|
||||
assertEquals(0.7, data.getInverterCurrent()); // [1]
|
||||
assertEquals(128, data.getInverterOutputPower()); // [2]
|
||||
|
||||
assertEquals(151.9, data.getPV1Voltage()); // [3]
|
||||
assertEquals(0, data.getPV2Voltage()); // [4]
|
||||
assertEquals(0.9, data.getPV1Current()); // [5]
|
||||
assertEquals(0, data.getPV2Current()); // [6]
|
||||
assertEquals(138, data.getPV1Power()); // [7]
|
||||
assertEquals(0, data.getPV2Power()); // [8]
|
||||
|
||||
assertEquals(50, data.getInverterFrequency()); // [9]
|
||||
|
||||
assertEquals(1556.9, data.getTotalEnergy()); // [11]
|
||||
assertEquals(0.7, data.getTodayEnergy()); // [13]
|
||||
|
||||
assertEquals(346, data.getPowerUsage()); // [43]
|
||||
}
|
||||
|
||||
@Override
|
||||
protected InverterType getInverterType() {
|
||||
return InverterType.X1_BOOST_AIR_MINI;
|
||||
}
|
||||
}
|
@ -12,14 +12,11 @@
|
||||
*/
|
||||
package org.openhab.binding.solax.internal.local;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.openhab.binding.solax.internal.connectivity.rawdata.local.LocalConnectRawDataBean;
|
||||
import org.openhab.binding.solax.internal.model.InverterType;
|
||||
import org.openhab.binding.solax.internal.model.local.LocalInverterData;
|
||||
import org.openhab.binding.solax.internal.model.local.parsers.RawDataParser;
|
||||
|
||||
/**
|
||||
* The {@link TestX1HybridG4Parser} Simple test that tests for proper parsing against a real data from the inverter
|
||||
@ -27,7 +24,7 @@ import org.openhab.binding.solax.internal.model.local.parsers.RawDataParser;
|
||||
* @author Konstantin Polihronov - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class TestX1HybridG4Parser {
|
||||
public class TestX1HybridG4Parser extends AbstractParserTest {
|
||||
|
||||
private static final String RAW_DATA = """
|
||||
{
|
||||
@ -43,17 +40,13 @@ public class TestX1HybridG4Parser {
|
||||
Information:[7.500,15,H4752TI1063020,8,1.24,0.00,1.21,1.03,0.00,1]}
|
||||
""";
|
||||
|
||||
@Test
|
||||
public void testParser() {
|
||||
LocalConnectRawDataBean bean = LocalConnectRawDataBean.fromJson(RAW_DATA);
|
||||
int type = bean.getType();
|
||||
InverterType inverterType = InverterType.fromIndex(type);
|
||||
assertEquals(InverterType.X1_HYBRID_G4, inverterType, "Inverter type not recognized properly");
|
||||
@Override
|
||||
protected InverterType getInverterType() {
|
||||
return InverterType.X1_HYBRID_G4;
|
||||
}
|
||||
|
||||
RawDataParser parser = inverterType.getParser();
|
||||
assertNotNull(parser);
|
||||
|
||||
LocalInverterData data = parser.getData(bean);
|
||||
@Override
|
||||
protected void assertParserSpecific(LocalInverterData data) {
|
||||
assertEquals("SOME_SERIAL_NUMBER", data.getWifiSerial());
|
||||
assertEquals("3.008.10", data.getWifiVersion());
|
||||
|
||||
@ -81,6 +74,11 @@ public class TestX1HybridG4Parser {
|
||||
assertEquals(12, data.getFeedInPower()); // [32]
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getRawData() {
|
||||
return RAW_DATA;
|
||||
}
|
||||
|
||||
// Yield_Today: Data[13] / 10,
|
||||
// Yield_Total: read32BitUnsigned(Data[11], Data[12]) / 10,
|
||||
// PowerDc1: Data[8],
|
||||
|
@ -12,14 +12,11 @@
|
||||
*/
|
||||
package org.openhab.binding.solax.internal.local;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.openhab.binding.solax.internal.connectivity.rawdata.local.LocalConnectRawDataBean;
|
||||
import org.openhab.binding.solax.internal.model.InverterType;
|
||||
import org.openhab.binding.solax.internal.model.local.LocalInverterData;
|
||||
import org.openhab.binding.solax.internal.model.local.parsers.RawDataParser;
|
||||
|
||||
/**
|
||||
* The {@link TestX3HybridG4Parser} simple test that tests for proper parsing against a real data from the inverter
|
||||
@ -27,9 +24,9 @@ import org.openhab.binding.solax.internal.model.local.parsers.RawDataParser;
|
||||
* @author Konstantin Polihronov - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class TestX3HybridG4Parser {
|
||||
public class TestX3HybridG4Parser extends AbstractParserTest {
|
||||
|
||||
String rawData = """
|
||||
private static final String RAW_DATA = """
|
||||
{
|
||||
sn:XYZ,
|
||||
ver:3.005.01,
|
||||
@ -50,17 +47,13 @@ public class TestX3HybridG4Parser {
|
||||
}
|
||||
""";
|
||||
|
||||
@Test
|
||||
public void testParser() {
|
||||
LocalConnectRawDataBean bean = LocalConnectRawDataBean.fromJson(rawData);
|
||||
int type = bean.getType();
|
||||
InverterType inverterType = InverterType.fromIndex(type);
|
||||
assertEquals(InverterType.X3_HYBRID_G4, inverterType, "Inverter type not recognized properly");
|
||||
@Override
|
||||
protected InverterType getInverterType() {
|
||||
return InverterType.X3_HYBRID_G4;
|
||||
}
|
||||
|
||||
RawDataParser parser = inverterType.getParser();
|
||||
assertNotNull(parser);
|
||||
|
||||
LocalInverterData data = parser.getData(bean);
|
||||
@Override
|
||||
protected void assertParserSpecific(LocalInverterData data) {
|
||||
assertEquals("XYZ", data.getWifiSerial());
|
||||
assertEquals("3.005.01", data.getWifiVersion());
|
||||
|
||||
@ -114,4 +107,9 @@ public class TestX3HybridG4Parser {
|
||||
assertEquals(6.2, data.getTodayBatteryDischargeEnergy()); // [78] / 100
|
||||
assertEquals(11, data.getTodayBatteryChargeEnergy()); // [79] / 100
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getRawData() {
|
||||
return RAW_DATA;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user