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.smartmeter.internal.sml;
15 import java.util.List;
16 import java.util.function.Supplier;
18 import org.eclipse.jdt.annotation.NonNullByDefault;
19 import org.eclipse.jdt.annotation.Nullable;
20 import org.openhab.binding.smartmeter.connectors.IMeterReaderConnector;
21 import org.openhab.binding.smartmeter.internal.MeterDevice;
22 import org.openhab.binding.smartmeter.internal.MeterValue;
23 import org.openhab.binding.smartmeter.internal.helper.ProtocolMode;
24 import org.openhab.core.io.transport.serial.SerialPortManager;
25 import org.openmuc.jsml.structures.ASNObject;
26 import org.openmuc.jsml.structures.EMessageBody;
27 import org.openmuc.jsml.structures.SmlFile;
28 import org.openmuc.jsml.structures.SmlList;
29 import org.openmuc.jsml.structures.SmlListEntry;
30 import org.openmuc.jsml.structures.SmlMessage;
31 import org.openmuc.jsml.structures.SmlStatus;
32 import org.openmuc.jsml.structures.responses.SmlGetListRes;
33 import org.slf4j.Logger;
34 import org.slf4j.LoggerFactory;
37 * Represents a SML capable device.
39 * @author Matthias Steigenberger - Initial contribution
40 * @author Mathias Gilhuber - Also-By
43 public final class SmlMeterReader extends MeterDevice<SmlFile> {
45 protected final Logger logger = LoggerFactory.getLogger(SmlMeterReader.class);
48 * Static factory method to create a SmlDevice object with a serial connector member.
50 * @param serialPortManagerSupplier
51 * @param deviceId the id of the device as defined in openHAB configuration.
52 * @param serialPort the port where the device is connected as defined in openHAB configuration.
55 * @param baudrateChangeDelay
57 public static SmlMeterReader createInstance(Supplier<SerialPortManager> serialPortManagerSupplier, String deviceId,
58 String serialPort, byte @Nullable [] initMessage, int baudrate, int baudrateChangeDelay) {
59 SmlMeterReader device = new SmlMeterReader(serialPortManagerSupplier, deviceId, serialPort, initMessage,
60 baudrate, baudrateChangeDelay, ProtocolMode.SML);
66 * Constructor to create a SmlDevice object with a serial connector member.
68 * @param deviceId the id of the device as defined in openHAB configuration.
69 * @param serialPort the port where the device is connected as defined in openHAB configuration.
70 * @param serialParameter
74 private SmlMeterReader(Supplier<SerialPortManager> serialPortManagerSupplier, String deviceId, String serialPort,
75 byte @Nullable [] initMessage, int baudrate, int baudrateChangeDelay, ProtocolMode protocolMode) {
76 super(serialPortManagerSupplier, deviceId, serialPort, initMessage, baudrate, baudrateChangeDelay,
79 logger.debug("Created SmlDevice instance {} with serial connector on port {}", deviceId, serialPort);
83 * Decodes native SML informations from the device and stores them locally until the next read request.
85 * @param smlFile the native SML informations from the device
88 protected void populateValueCache(SmlFile smlFile) {
89 if (logger.isTraceEnabled()) {
90 logger.trace("Read out following SML file: {}", System.lineSeparator());
91 SmlFileDebugOutput.printFile(smlFile, (msg) -> logger.trace(msg));
93 List<SmlMessage> smlMessages = smlFile.getMessages();
95 if (smlMessages != null) {
96 int messageCount = smlMessages.size();
98 if (messageCount <= 0) {
99 logger.warn("{}: no valid SML messages list retrieved.", this.toString());
102 for (int i = 0; i < messageCount; i++) {
103 SmlMessage smlMessage = smlMessages.get(i);
105 int tag = smlMessage.getMessageBody().getTag().id();
107 if (tag != EMessageBody.GET_LIST_RESPONSE.id()) {
111 SmlGetListRes listResponse = (SmlGetListRes) smlMessage.getMessageBody().getChoice();
112 SmlList smlValueList = listResponse.getValList();
113 SmlListEntry[] smlListEntries = smlValueList.getValListEntry();
115 for (SmlListEntry entry : smlListEntries) {
116 SmlValueExtractor valueExtractor = new SmlValueExtractor(entry);
117 String obis = valueExtractor.getObisCode();
119 MeterValue<?> smlValue = getMeterValue(obis);
121 if (smlValue == null) {
122 smlValue = valueExtractor.getSmlValue();
125 SmlStatus status = entry.getStatus();
126 if (status != null) {
127 String statusValue = readStatus(status, obis);
128 if (statusValue != null) {
129 smlValue.setStatus(statusValue);
133 addObisCache(smlValue);
137 logger.warn("{}: no valid SML messages list retrieved.", this.toString());
141 private @Nullable String readStatus(SmlStatus status, String obis) {
142 ASNObject choice = status.getChoice();
143 if (choice != null) {
144 String statusValue = choice.toString();
151 protected IMeterReaderConnector<SmlFile> createConnector(Supplier<SerialPortManager> serialPortManagerSupplier,
152 String serialPort, int baudrate, int baudrateChangeDelay, ProtocolMode protocolMode) {
153 return new SmlSerialConnector(serialPortManagerSupplier, serialPort, baudrate, baudrateChangeDelay);
157 protected void printInfo() {