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.plclogo.internal;
15 import org.slf4j.Logger;
16 import org.slf4j.LoggerFactory;
19 import Moka7.S7Client;
22 * The {@link PLCLogoClient} is thread safe LOGO! client.
24 * @author Alexander Falkenstern - Initial contribution
26 public class PLCLogoClient extends S7Client {
28 private static final int MAX_RETRY_NUMBER = 10;
29 private final Logger logger = LoggerFactory.getLogger(PLCLogoClient.class);
31 private String plcIPAddress = "INVALID_IP";
34 * Connects a client to a PLC
37 public synchronized int Connect() {
38 return super.Connect();
42 * Connects a client to a PLC with specified parameters
44 * @param Address IP address of PLC
45 * @param LocalTSAP Local TSAP for the connection
46 * @param RemoteTSAP Remote TSAP for the connection
47 * @return Zero on success, error code otherwise
49 public synchronized int Connect(String Address, int LocalTSAP, int RemoteTSAP) {
50 SetConnectionParams(Address, LocalTSAP, RemoteTSAP);
51 return super.Connect();
55 * Set connection parameters
57 * @param Address IP address of PLC
58 * @param LocalTSAP Local TSAP for the connection
59 * @param RemoteTSAP Remote TSAP for the connection
62 public void SetConnectionParams(String Address, int LocalTSAP, int RemoteTSAP) {
63 plcIPAddress = Address; // Store ip address for logging
64 super.SetConnectionParams(Address, LocalTSAP, RemoteTSAP);
68 * Disconnects a client from a PLC
71 public synchronized void Disconnect() {
76 * Reads a data area from a PLC
78 * @param Area S7 Area ID. Can be S7AreaPE, S7AreaPA, S7AreaMK, S7AreaDB, S7AreaCT or S7AreaTM
79 * @param DBNumber S7 data block number
80 * @param Start First position within data block read from
81 * @param Amount Number of words to read
82 * @param WordLength Length of single word. Can be S7WLBit, S7WLByte, S7WLCounter or S7WLTimer
83 * @param Data Buffer to read into
84 * @return Zero on success, error code otherwise
87 public synchronized int ReadArea(int Area, int DBNumber, int Start, int Amount, int WordLength, byte[] Data) {
89 logger.debug("Reconnect during read from {}: {}", plcIPAddress, ErrorText(LastError));
96 final int packet = Math.min(Amount, 1024);
102 // read first portion directly to data
103 result = super.ReadArea(Area, DBNumber, Start, packet, WordLength, Data);
104 while ((result == 0) && (offset < Amount)) {
105 byte buffer[] = new byte[Math.min(Amount - offset, packet)];
106 result = super.ReadArea(Area, DBNumber, offset, buffer.length, WordLength, buffer);
107 System.arraycopy(buffer, 0, Data, offset, buffer.length);
108 offset = offset + buffer.length;
111 if (retry == MAX_RETRY_NUMBER) {
112 logger.info("Giving up reading from {} after {} retries.", plcIPAddress, MAX_RETRY_NUMBER);
117 logger.info("Reconnect during read from {}: {}", plcIPAddress, ErrorText(result));
122 } while (result != 0);
128 * Reads a data block area from a PLC
130 * @param DBNumber S7 data block number
131 * @param Start First position within data block read from
132 * @param Amount Number of words to read
133 * @param WordLength Length of single word. Can be S7WLBit, S7WLByte, S7WLCounter or S7WLTimer
134 * @param Data Buffer to read into
135 * @return Zero on success, error code otherwise
137 public int readDBArea(int DBNumber, int Start, int Amount, int WordLength, byte[] Data) {
138 return ReadArea(S7.S7AreaDB, DBNumber, Start, Amount, WordLength, Data);
142 * Writes a data area into a PLC
144 * @param Area S7 Area ID. Can be S7AreaPE, S7AreaPA, S7AreaMK, S7AreaDB, S7AreaCT or S7AreaTM
145 * @param DBNumber S7 data block number
146 * @param Start First position within data block write into
147 * @param Amount Number of words to write
148 * @param WordLength Length of single word. Can be S7WLBit, S7WLByte, S7WLCounter or S7WLTimer
149 * @param Data Buffer to write from
150 * @return Zero on success, error code otherwise
153 public synchronized int WriteArea(int Area, int DBNumber, int Start, int Amount, int WordLength, byte[] Data) {
154 if (LastError != 0) {
155 logger.debug("Reconnect during write to {}: {}", plcIPAddress, ErrorText(LastError));
165 result = super.WriteArea(Area, DBNumber, Start, Amount, WordLength, Data);
167 if (retry == MAX_RETRY_NUMBER) {
168 logger.info("Giving up writing to {} after {} retries.", plcIPAddress, MAX_RETRY_NUMBER);
173 logger.info("Reconnect during write to {}: {}", plcIPAddress, ErrorText(result));
178 } while (result != 0);
184 * Writes a data block area into a PLC
186 * @param DBNumber S7 data block number
187 * @param Start First position within data block write into
188 * @param Amount Number of words to write
189 * @param WordLength Length of single word. Can be S7WLBit, S7WLByte, S7WLCounter or S7WLTimer
190 * @param Data Buffer to write from
191 * @return Zero on success, error code otherwise
193 public int writeDBArea(int DBNumber, int Start, int Amount, int WordLength, byte[] Data) {
194 return WriteArea(S7.S7AreaDB, DBNumber, Start, Amount, WordLength, Data);
198 * Returns, if client is already connected or not
200 * @return True, if client is connected and false otherwise
202 public synchronized boolean isConnected() {