2 * Copyright (c) 2010-2021 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.eclipse.jdt.annotation.Nullable;
19 import org.openhab.binding.gce.internal.handler.Ipx800DeviceConnector;
20 import org.openhab.binding.gce.internal.handler.Ipx800EventListener;
21 import org.slf4j.Logger;
22 import org.slf4j.LoggerFactory;
25 * This class handles message translation to and from the IPX.
27 * @author Gaƫl L'hopital - Initial contribution
30 public class M2MMessageParser {
31 private static final String IO_DESCRIPTOR = "(\\d{32})";
32 private static final Pattern IO_PATTERN = Pattern.compile(IO_DESCRIPTOR);
33 private static final Pattern VALIDATION_PATTERN = Pattern
34 .compile("I=" + IO_DESCRIPTOR + "&O=" + IO_DESCRIPTOR + "&([AC]\\d{1,2}=\\d+&)*[^I]*");
36 private final Logger logger = LoggerFactory.getLogger(M2MMessageParser.class);
37 private final Ipx800DeviceConnector connector;
38 private final @Nullable Ipx800EventListener listener;
40 private String expectedResponse = "";
42 public M2MMessageParser(Ipx800DeviceConnector connector, @Nullable Ipx800EventListener listener) {
43 this.connector = connector;
44 this.listener = listener;
45 connector.setParser(this);
52 public void unsolicitedUpdate(String data) {
53 if (IO_PATTERN.matcher(data).matches()) {
54 PortDefinition portDefinition = PortDefinition.fromM2MCommand(expectedResponse);
55 decodeDataLine(portDefinition, data);
56 } else if (VALIDATION_PATTERN.matcher(data).matches()) {
57 for (String status : data.split("&")) {
58 String statusPart[] = status.split("=");
60 PortDefinition portDefinition = PortDefinition.fromPortName(statusPart[0].substring(0, 1));
61 switch (portDefinition) {
64 decodeDataLine(portDefinition, statusPart[1]);
68 portNumShift = 0; // Align counters on 1 based array
70 int portNumber = Integer.parseInt(statusPart[0].substring(1)) + portNumShift;
71 setStatus(portDefinition.getPortName() + portNumber, Double.parseDouble(statusPart[1]));
75 } else if (!expectedResponse.isEmpty()) {
76 setStatus(expectedResponse, Double.parseDouble(data));
79 expectedResponse = "";
82 private void decodeDataLine(PortDefinition portDefinition, String data) {
83 for (int count = 0; count < data.length(); count++) {
84 setStatus(portDefinition.getPortName() + (count + 1), (double) data.charAt(count) - '0');
88 private void setStatus(String port, double value) {
89 logger.debug("Received {} : {}", port, value);
90 if (listener != null) {
91 listener.dataReceived(port, value);
95 public void setExpectedResponse(String expectedResponse) {
96 if (expectedResponse.endsWith("s")) { // GetInputs or GetOutputs
97 this.expectedResponse = expectedResponse;
98 } else { // GetAnx or GetCountx
99 PortDefinition portType = PortDefinition.fromM2MCommand(expectedResponse);
100 this.expectedResponse = expectedResponse.replaceAll(portType.getM2mCommand(), portType.getPortName());
105 * Set output of the device sending the corresponding command
110 public void setOutput(String targetPort, int targetValue, boolean pulse) {
111 logger.debug("Sending {} to {}", targetValue, targetPort);
112 String command = String.format("Set%02d%s%s", Integer.parseInt(targetPort), targetValue, pulse ? "p" : "");
113 connector.send(command);
117 * Resets the counter value to 0
119 * @param targetCounter
121 public void resetCounter(int targetCounter) {
122 logger.debug("Resetting counter {} to 0", targetCounter);
123 connector.send(String.format("ResetCount%d", targetCounter));
126 public void errorOccurred(Exception e) {
127 logger.warn("Error received from connector : {}", e.getMessage());
128 if (listener != null) {
129 listener.errorOccurred(e);
133 public void resetPLC() {
134 connector.send("Reset");