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.gce.internal.model;
15 import java.util.regex.Pattern;
17 import org.eclipse.jdt.annotation.NonNullByDefault;
18 import org.openhab.binding.gce.internal.handler.Ipx800DeviceConnector;
19 import org.openhab.binding.gce.internal.handler.Ipx800EventListener;
20 import org.slf4j.Logger;
21 import org.slf4j.LoggerFactory;
24 * This class handles message translation to and from the IPX.
26 * @author Gaƫl L'hopital - Initial contribution
29 public class M2MMessageParser {
30 private static final String IO_DESCRIPTOR = "(\\d{32})";
31 private static final Pattern IO_PATTERN = Pattern.compile(IO_DESCRIPTOR);
32 private static final Pattern VALIDATION_PATTERN = Pattern
33 .compile("I=" + IO_DESCRIPTOR + "&O=" + IO_DESCRIPTOR + "&([AC]\\d{1,2}=\\d+&)*[^I]*");
35 private final Logger logger = LoggerFactory.getLogger(M2MMessageParser.class);
36 private final Ipx800DeviceConnector connector;
37 private final Ipx800EventListener listener;
39 private String expectedResponse = "";
41 public M2MMessageParser(Ipx800DeviceConnector connector, Ipx800EventListener listener) {
42 this.connector = connector;
43 this.listener = listener;
44 connector.setParser(this);
51 public void unsolicitedUpdate(String data) {
52 if (IO_PATTERN.matcher(data).matches()) {
53 PortDefinition portDefinition = PortDefinition.fromM2MCommand(expectedResponse);
54 decodeDataLine(portDefinition, data);
55 } else if (VALIDATION_PATTERN.matcher(data).matches()) {
56 for (String status : data.split("&")) {
57 String[] statusPart = status.split("=");
59 PortDefinition portDefinition = PortDefinition.fromPortName(statusPart[0].substring(0, 1));
60 switch (portDefinition) {
63 decodeDataLine(portDefinition, statusPart[1]);
67 portNumShift = 0; // Align counters on 1 based array
69 int portNumber = Integer.parseInt(statusPart[0].substring(1)) + portNumShift;
70 setStatus(portDefinition.getPortName() + portNumber, Double.parseDouble(statusPart[1]));
74 } else if (!expectedResponse.isEmpty()) {
75 setStatus(expectedResponse, Double.parseDouble(data));
78 expectedResponse = "";
81 private void decodeDataLine(PortDefinition portDefinition, String data) {
82 for (int count = 0; count < data.length(); count++) {
83 setStatus(portDefinition.getPortName() + (count + 1), (double) data.charAt(count) - '0');
87 private void setStatus(String port, double value) {
88 logger.debug("Received {} : {}", port, value);
89 listener.dataReceived(port, value);
92 public void setExpectedResponse(String expectedResponse) {
93 if (expectedResponse.endsWith("s")) { // GetInputs or GetOutputs
94 this.expectedResponse = expectedResponse;
95 } else { // GetAnx or GetCountx
96 PortDefinition portType = PortDefinition.fromM2MCommand(expectedResponse);
97 this.expectedResponse = expectedResponse.replaceAll(portType.getM2mCommand(), portType.getPortName());
102 * Set output of the device sending the corresponding command
107 public void setOutput(String targetPort, int targetValue, boolean pulse) {
108 logger.debug("Sending {} to {}", targetValue, targetPort);
109 String command = String.format("Set%02d%s%s", Integer.parseInt(targetPort), targetValue, pulse ? "p" : "");
110 connector.send(command);
114 * Resets the counter value to 0
116 * @param targetCounter
118 public void resetCounter(int targetCounter) {
119 logger.debug("Resetting counter {} to 0", targetCounter);
120 connector.send(String.format("ResetCount%d", targetCounter));
123 public void errorOccurred(Exception e) {
124 logger.warn("Error received from connector : {}", e.getMessage());
125 listener.errorOccurred(e);
128 public void resetPLC() {
129 connector.send("Reset");