2 * Copyright (c) 2010-2023 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
7 * This program and the accompanying materials are made available under the
8 * terms of the Eclipse Public License 2.0 which is available at
9 * http://www.eclipse.org/legal/epl-2.0
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.modbus.sunspec.internal.parser;
15 import org.eclipse.jdt.annotation.NonNullByDefault;
16 import org.openhab.binding.modbus.sunspec.internal.SunSpecConstants;
17 import org.openhab.binding.modbus.sunspec.internal.dto.MeterModelBlock;
18 import org.openhab.core.io.transport.modbus.ModbusRegisterArray;
21 * Parser for sunspec compatible meters
23 * @author Nagy Attila Gabor - Initial contribution
27 public class MeterModelParser extends AbstractBaseParser implements SunspecParser<MeterModelBlock> {
30 public MeterModelBlock parse(ModbusRegisterArray raw) {
31 MeterModelBlock block = new MeterModelBlock();
33 block.sunspecDID = extractUInt16(raw, 0, SunSpecConstants.METER_SINGLE_PHASE);
34 block.length = extractUInt16(raw, 1, raw.size());
35 block.acCurrentTotal = extractInt16(raw, 2, (short) 0);
36 block.phaseA.acPhaseCurrent = extractOptionalInt16(raw, 3);
37 block.phaseB.acPhaseCurrent = extractOptionalInt16(raw, 4);
38 block.phaseC.acPhaseCurrent = extractOptionalInt16(raw, 5);
39 block.acCurrentSF = extractSunSSF(raw, 6);
41 block.acVoltageLineToNAverage = extractOptionalInt16(raw, 7);
42 block.phaseA.acVoltageToN = extractOptionalInt16(raw, 8);
43 block.phaseB.acVoltageToN = extractOptionalInt16(raw, 9);
44 block.phaseC.acVoltageToN = extractOptionalInt16(raw, 10);
45 block.acVoltageLineToLineAverage = extractOptionalInt16(raw, 11);
46 block.phaseA.acVoltageToNext = extractOptionalInt16(raw, 12);
47 block.phaseB.acVoltageToNext = extractOptionalInt16(raw, 13);
48 block.phaseC.acVoltageToNext = extractOptionalInt16(raw, 14);
49 block.acVoltageSF = extractSunSSF(raw, 15);
51 block.acFrequency = extractInt16(raw, 16, (short) 0);
52 block.acFrequencySF = extractOptionalSunSSF(raw, 17);
54 block.acRealPowerTotal = extractInt16(raw, 18, (short) 0);
55 block.phaseA.acRealPower = extractOptionalInt16(raw, 19);
56 block.phaseB.acRealPower = extractOptionalInt16(raw, 20);
57 block.phaseC.acRealPower = extractOptionalInt16(raw, 21);
58 block.acRealPowerSF = extractSunSSF(raw, 22);
60 block.acApparentPowerTotal = extractOptionalInt16(raw, 23);
61 block.phaseA.acApparentPower = extractOptionalInt16(raw, 24);
62 block.phaseB.acApparentPower = extractOptionalInt16(raw, 25);
63 block.phaseC.acApparentPower = extractOptionalInt16(raw, 26);
64 block.acApparentPowerSF = extractOptionalSunSSF(raw, 27);
66 block.acReactivePowerTotal = extractOptionalInt16(raw, 28);
67 block.phaseA.acReactivePower = extractOptionalInt16(raw, 29);
68 block.phaseB.acReactivePower = extractOptionalInt16(raw, 30);
69 block.phaseC.acReactivePower = extractOptionalInt16(raw, 31);
70 block.acReactivePowerSF = extractOptionalSunSSF(raw, 32);
72 block.acPowerFactor = extractOptionalInt16(raw, 33);
73 block.phaseA.acPowerFactor = extractOptionalInt16(raw, 34);
74 block.phaseB.acPowerFactor = extractOptionalInt16(raw, 35);
75 block.phaseC.acPowerFactor = extractOptionalInt16(raw, 36);
76 block.acPowerFactorSF = extractOptionalSunSSF(raw, 37);
78 block.acExportedRealEnergyTotal = extractOptionalAcc32(raw, 38);
79 block.phaseA.acExportedRealEnergy = extractOptionalAcc32(raw, 40);
80 block.phaseB.acExportedRealEnergy = extractOptionalAcc32(raw, 42);
81 block.phaseC.acExportedRealEnergy = extractOptionalAcc32(raw, 44);
82 block.acImportedRealEnergyTotal = extractAcc32(raw, 46, 0);
83 block.phaseA.acImportedRealEnergy = extractOptionalAcc32(raw, 48);
84 block.phaseB.acImportedRealEnergy = extractOptionalAcc32(raw, 50);
85 block.phaseC.acImportedRealEnergy = extractOptionalAcc32(raw, 52);
86 block.acRealEnergySF = extractSunSSF(raw, 54);
88 block.acExportedApparentEnergyTotal = extractOptionalAcc32(raw, 55);
89 block.phaseA.acExportedApparentEnergy = extractOptionalAcc32(raw, 57);
90 block.phaseB.acExportedApparentEnergy = extractOptionalAcc32(raw, 59);
91 block.phaseC.acExportedApparentEnergy = extractOptionalAcc32(raw, 61);
92 block.acImportedApparentEnergyTotal = extractOptionalAcc32(raw, 63);
93 block.phaseA.acImportedApparentEnergy = extractOptionalAcc32(raw, 65);
94 block.phaseB.acImportedApparentEnergy = extractOptionalAcc32(raw, 67);
95 block.phaseC.acImportedApparentEnergy = extractOptionalAcc32(raw, 69);
96 block.acApparentEnergySF = extractOptionalSunSSF(raw, 71);
98 block.acImportedReactiveEnergyQ1Total = extractOptionalAcc32(raw, 72);
99 block.phaseA.acImportedReactiveEnergyQ1 = extractOptionalAcc32(raw, 74);
100 block.phaseB.acImportedReactiveEnergyQ1 = extractOptionalAcc32(raw, 76);
101 block.phaseC.acImportedReactiveEnergyQ1 = extractOptionalAcc32(raw, 78);
102 block.acImportedReactiveEnergyQ2Total = extractOptionalAcc32(raw, 80);
103 block.phaseA.acImportedReactiveEnergyQ2 = extractOptionalAcc32(raw, 82);
104 block.phaseB.acImportedReactiveEnergyQ2 = extractOptionalAcc32(raw, 84);
105 block.phaseC.acImportedReactiveEnergyQ2 = extractOptionalAcc32(raw, 86);
106 block.acExportedReactiveEnergyQ3Total = extractOptionalAcc32(raw, 88);
107 block.phaseA.acExportedReactiveEnergyQ3 = extractOptionalAcc32(raw, 90);
108 block.phaseB.acExportedReactiveEnergyQ3 = extractOptionalAcc32(raw, 92);
109 block.phaseC.acExportedReactiveEnergyQ3 = extractOptionalAcc32(raw, 94);
110 block.acExportedReactiveEnergyQ4Total = extractOptionalAcc32(raw, 96);
111 block.phaseA.acExportedReactiveEnergyQ4 = extractOptionalAcc32(raw, 98);
112 block.phaseB.acExportedReactiveEnergyQ4 = extractOptionalAcc32(raw, 100);
113 block.phaseC.acExportedReactiveEnergyQ4 = extractOptionalAcc32(raw, 102);
114 block.acReactiveEnergySF = extractOptionalSunSSF(raw, 104);