]> git.basschouten.com Git - openhab-addons.git/commitdiff
[solax] Support for x1 mini inverter local connection (#16412)
authorKonstantin Polihronov <polychronov@gmail.com>
Sat, 24 Feb 2024 10:49:52 +0000 (12:49 +0200)
committerGitHub <noreply@github.com>
Sat, 24 Feb 2024 10:49:52 +0000 (11:49 +0100)
Skeleton of the required classes for supporting X1 mini
Add the parser data

Signed-off-by: Konstantin Polihronov <polychronov@gmail.com>
bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/model/InverterType.java
bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/model/local/X1BoostAirMiniInverterData.java [new file with mode: 0644]
bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/model/local/parsers/X1BoostAirMiniDataParser.java [new file with mode: 0644]
bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/model/local/parsers/X1HybridG4DataParser.java
bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/model/local/parsers/X3HybridG4DataParser.java
bundles/org.openhab.binding.solax/src/test/java/org/openhab/binding/solax/internal/local/AbstractParserTest.java [new file with mode: 0644]
bundles/org.openhab.binding.solax/src/test/java/org/openhab/binding/solax/internal/local/TestX1BoostAirMiniDataParser.java [new file with mode: 0644]
bundles/org.openhab.binding.solax/src/test/java/org/openhab/binding/solax/internal/local/TestX1HybridG4Parser.java
bundles/org.openhab.binding.solax/src/test/java/org/openhab/binding/solax/internal/local/TestX3HybridG4Parser.java

index e24f1346445f4b7cf199c634c844350e7311fe19..d2d3fb96653e7e07cd1bacefe0edff0e887a6f77 100644 (file)
@@ -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),
diff --git a/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/model/local/X1BoostAirMiniInverterData.java b/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/model/local/X1BoostAirMiniInverterData.java
new file mode 100644 (file)
index 0000000..9c4e951
--- /dev/null
@@ -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);
+    }
+}
diff --git a/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/model/local/parsers/X1BoostAirMiniDataParser.java b/bundles/org.openhab.binding.solax/src/main/java/org/openhab/binding/solax/internal/model/local/parsers/X1BoostAirMiniDataParser.java
new file mode 100644 (file)
index 0000000..4b680b6
--- /dev/null
@@ -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;
+    }
+}
index dc6ac43f264475f2381095940f993d8aafe33275..2804f1dbbfff5a0f3d21a0e3aff986f870933cba 100644 (file)
@@ -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
index 781a5de752f2f99cd4911ae4138740bf996575a3..3cc4f11f5e196b18ddabe913b30f374650de7ac3 100644 (file)
@@ -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
diff --git a/bundles/org.openhab.binding.solax/src/test/java/org/openhab/binding/solax/internal/local/AbstractParserTest.java b/bundles/org.openhab.binding.solax/src/test/java/org/openhab/binding/solax/internal/local/AbstractParserTest.java
new file mode 100644 (file)
index 0000000..791e304
--- /dev/null
@@ -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);
+}
diff --git a/bundles/org.openhab.binding.solax/src/test/java/org/openhab/binding/solax/internal/local/TestX1BoostAirMiniDataParser.java b/bundles/org.openhab.binding.solax/src/test/java/org/openhab/binding/solax/internal/local/TestX1BoostAirMiniDataParser.java
new file mode 100644 (file)
index 0000000..66f6f4b
--- /dev/null
@@ -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;
+    }
+}
index a2dcc3400a47c9620b0e60cd4722d429f12a545e..f2d203246932defd95f265d5bda9db09020aea22 100644 (file)
  */
 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");
-
-        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());
 
@@ -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],
index 951d725d1a826ead164bc15c78bf41b823e05b46..a30172c98186e095d7bb5dfb13a370a2333b72ed 100644 (file)
  */
 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");
-
-        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());
 
@@ -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;
+    }
 }