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;
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),
--- /dev/null
+/**
+ * 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);
+ }
+}
--- /dev/null
+/**
+ * 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;
+ }
+}
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
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
--- /dev/null
+/**
+ * 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);
+}
--- /dev/null
+/**
+ * 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;
+ }
+}
*/
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
* @author Konstantin Polihronov - Initial contribution
*/
@NonNullByDefault
-public class TestX1HybridG4Parser {
+public class TestX1HybridG4Parser extends AbstractParserTest {
private static final String RAW_DATA = """
{
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");
-
- RawDataParser parser = inverterType.getParser();
- assertNotNull(parser);
+ @Override
+ protected InverterType getInverterType() {
+ return InverterType.X1_HYBRID_G4;
+ }
- LocalInverterData data = parser.getData(bean);
+ @Override
+ protected void assertParserSpecific(LocalInverterData data) {
assertEquals("SOME_SERIAL_NUMBER", data.getWifiSerial());
assertEquals("3.008.10", data.getWifiVersion());
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],
*/
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
* @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,
}
""";
- @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");
-
- RawDataParser parser = inverterType.getParser();
- assertNotNull(parser);
+ @Override
+ protected InverterType getInverterType() {
+ return InverterType.X3_HYBRID_G4;
+ }
- LocalInverterData data = parser.getData(bean);
+ @Override
+ protected void assertParserSpecific(LocalInverterData data) {
assertEquals("XYZ", data.getWifiSerial());
assertEquals("3.005.01", data.getWifiVersion());
assertEquals(6.2, data.getTodayBatteryDischargeEnergy()); // [78] / 100
assertEquals(11, data.getTodayBatteryChargeEnergy()); // [79] / 100
}
+
+ @Override
+ protected String getRawData() {
+ return RAW_DATA;
+ }
}