]> git.basschouten.com Git - openhab-addons.git/blob
654a2e83090e0344305eff66a60dc2753c085327
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2024 Contributors to the openHAB project
3  *
4  * See the NOTICE file(s) distributed with this work for additional
5  * information.
6  *
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
10  *
11  * SPDX-License-Identifier: EPL-2.0
12  */
13 package org.openhab.binding.smartmeter.internal.iec62056;
14
15 import java.io.IOException;
16 import java.time.Duration;
17 import java.util.function.Supplier;
18
19 import org.eclipse.jdt.annotation.NonNullByDefault;
20 import org.eclipse.jdt.annotation.Nullable;
21 import org.openhab.binding.smartmeter.connectors.ConnectorBase;
22 import org.openhab.binding.smartmeter.internal.helper.Baudrate;
23 import org.openhab.binding.smartmeter.internal.helper.ProtocolMode;
24 import org.openhab.core.io.transport.serial.SerialPortManager;
25 import org.openmuc.j62056.DataMessage;
26 import org.openmuc.j62056.Iec21Port;
27 import org.openmuc.j62056.Iec21Port.Builder;
28 import org.openmuc.j62056.ModeDListener;
29 import org.reactivestreams.Publisher;
30 import org.slf4j.Logger;
31 import org.slf4j.LoggerFactory;
32
33 import io.reactivex.Flowable;
34 import io.reactivex.FlowableEmitter;
35
36 /**
37  * This connector reads meter values with IEC62056-21 protocol.
38  *
39  * @author Matthias Steigenberger - Initial contribution
40  *
41  */
42 @NonNullByDefault
43 public class Iec62056_21SerialConnector extends ConnectorBase<DataMessage> {
44
45     private final Logger logger = LoggerFactory.getLogger(Iec62056_21SerialConnector.class);
46     private int baudrate;
47     private int baudrateChangeDelay;
48     private ProtocolMode protocolMode;
49     @Nullable
50     private Iec21Port iec21Port;
51
52     public Iec62056_21SerialConnector(Supplier<SerialPortManager> serialPortManagerSupplier, String portName,
53             int baudrate, int baudrateChangeDelay, ProtocolMode protocolMode) {
54         super(portName);
55         this.baudrate = baudrate;
56         this.baudrateChangeDelay = baudrateChangeDelay;
57         this.protocolMode = protocolMode;
58     }
59
60     @Override
61     protected boolean applyPeriod() {
62         return protocolMode != ProtocolMode.D;
63     }
64
65     @Override
66     protected boolean applyRetryHandling() {
67         return protocolMode != ProtocolMode.D;
68     }
69
70     @Override
71     protected Publisher<?> getRetryPublisher(Duration period, Publisher<Throwable> attempts) {
72         if (protocolMode == ProtocolMode.D) {
73             return Flowable.empty();
74         } else {
75             return super.getRetryPublisher(period, attempts);
76         }
77     }
78
79     @Override
80     protected DataMessage readNext(byte @Nullable [] initMessage) throws IOException {
81         if (iec21Port != null) {
82             DataMessage dataMessage = iec21Port.read();
83             logger.debug("Datamessage read: {}", dataMessage);
84             return dataMessage;
85         }
86         throw new IOException("SerialPort was not yet created!");
87     }
88
89     @Override
90     protected void emitValues(byte @Nullable [] initMessage, FlowableEmitter<@Nullable DataMessage> emitter)
91             throws IOException {
92         switch (protocolMode) {
93             case ABC:
94                 super.emitValues(initMessage, emitter);
95                 break;
96             case D:
97                 if (iec21Port != null) {
98                     iec21Port.listen(new ModeDListener() {
99
100                         @Override
101                         public void newDataMessage(@Nullable DataMessage dataMessage) {
102                             logger.debug("Datamessage read: {}", dataMessage);
103                             emitter.onNext(dataMessage);
104                         }
105
106                         @Override
107                         public void exceptionWhileListening(@Nullable Exception e) {
108                             logger.warn("Exception while listening for mode D data message", e);
109                         }
110                     });
111                 }
112                 break;
113             case SML:
114                 throw new IOException("SML mode not supported");
115         }
116     }
117
118     @Override
119     public void openConnection() throws IOException {
120         Builder iec21Builder = new Iec21Port.Builder(getPortName());
121         if (Baudrate.fromBaudrate(this.baudrate) != Baudrate.AUTO) {
122             iec21Builder.setInitialBaudrate(this.baudrate);
123         }
124         iec21Builder.setBaudRateChangeDelay(baudrateChangeDelay);
125         iec21Builder.enableVerboseMode(true);
126         iec21Port = iec21Builder.buildAndOpen();
127     }
128
129     @Override
130     public void closeConnection() {
131         if (iec21Port != null) {
132             iec21Port.close();
133         }
134     }
135 }