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.plugwise.internal.protocol;
15 import static org.openhab.binding.plugwise.internal.protocol.field.MessageType.*;
17 import java.util.HashMap;
19 import java.util.regex.Matcher;
20 import java.util.regex.Pattern;
22 import org.openhab.binding.plugwise.internal.protocol.field.MACAddress;
23 import org.openhab.binding.plugwise.internal.protocol.field.MessageType;
26 * Acknowledgement message class - ACKs are used in the Plugwise protocol to serve different means, from acknowledging a
27 * message sent to the Stick by the host, as well as confirmation messages from nodes in the network for various
28 * purposes. Not all purposes are yet reverse-engineered.
30 * @author Wouter Born, Karel Goderis - Initial contribution
32 public class AcknowledgementMessage extends Message {
34 public enum ExtensionCode {
36 SENSE_INTERVAL_SET_ACK(179),
37 SENSE_INTERVAL_SET_NACK(180),
38 SENSE_BOUNDARIES_SET_ACK(181),
39 SENSE_BOUNDARIES_SET_NACK(182),
40 LIGHT_CALIBRATION_ACK(189),
41 SCAN_PARAMETERS_SET_ACK(190),
42 SCAN_PARAMETERS_SET_NACK(191),
48 POWER_CALIBRATION_ACK(218),
50 REAL_TIME_CLOCK_SET_ACK(223),
53 REAL_TIME_CLOCK_SET_NACK(231),
55 POWER_LOG_INTERVAL_SET_ACK(248),
58 private static final Map<Integer, ExtensionCode> TYPES_BY_VALUE = new HashMap<>();
61 for (ExtensionCode type : ExtensionCode.values()) {
62 TYPES_BY_VALUE.put(type.identifier, type);
66 public static ExtensionCode forValue(int value) {
67 return TYPES_BY_VALUE.get(value);
70 private int identifier;
72 private ExtensionCode(int value) {
81 private static final Pattern V1_SHORT_PAYLOAD_PATTERN = Pattern.compile("(\\w{4})");
82 private static final Pattern V1_EXTENDED_PAYLOAD_PATTERN = Pattern.compile("(\\w{4})(\\w{16})");
83 private static final Pattern V2_EXTENDED_PAYLOAD_PATTERN = Pattern.compile("(\\w{16})(\\w{4})");
85 private ExtensionCode code;
87 public AcknowledgementMessage(MessageType messageType, int sequenceNumber, String payload) {
88 super(messageType, sequenceNumber, payload);
91 public ExtensionCode getExtensionCode() {
95 return ExtensionCode.NOT_EXTENDED;
100 public String getPayload() {
101 return payloadToHexString();
104 public boolean isError() {
105 return code == ExtensionCode.ERROR;
108 public boolean isExtended() {
109 return code != ExtensionCode.NOT_EXTENDED && code != ExtensionCode.SUCCESS && code != ExtensionCode.ERROR;
112 public boolean isSuccess() {
113 return code == ExtensionCode.SUCCESS;
116 public boolean isTimeOut() {
117 return code == ExtensionCode.TIMEOUT;
121 protected void parsePayload() {
122 if (getType() == ACKNOWLEDGEMENT_V1) {
124 } else if (getType() == ACKNOWLEDGEMENT_V2) {
129 private void parseV1Payload() {
130 Matcher shortMatcher = V1_SHORT_PAYLOAD_PATTERN.matcher(payload);
131 Matcher extendedMatcher = V1_EXTENDED_PAYLOAD_PATTERN.matcher(payload);
133 if (extendedMatcher.matches()) {
134 code = ExtensionCode.forValue(Integer.parseInt(extendedMatcher.group(1), 16));
136 code = ExtensionCode.UNKNOWN;
138 macAddress = new MACAddress(extendedMatcher.group(2));
139 } else if (shortMatcher.matches()) {
140 code = ExtensionCode.forValue(Integer.parseInt(shortMatcher.group(1), 16));
142 code = ExtensionCode.UNKNOWN;
145 code = ExtensionCode.UNKNOWN;
146 throw new PlugwisePayloadMismatchException(ACKNOWLEDGEMENT_V1, V1_SHORT_PAYLOAD_PATTERN,
147 V1_EXTENDED_PAYLOAD_PATTERN, payload);
151 private void parseV2Payload() {
152 Matcher matcher = V2_EXTENDED_PAYLOAD_PATTERN.matcher(payload);
154 if (matcher.matches()) {
155 macAddress = new MACAddress(matcher.group(1));
156 code = ExtensionCode.forValue(Integer.parseInt(matcher.group(2), 16));
158 code = ExtensionCode.UNKNOWN;
161 code = ExtensionCode.UNKNOWN;
162 throw new PlugwisePayloadMismatchException(ACKNOWLEDGEMENT_V2, V2_EXTENDED_PAYLOAD_PATTERN, payload);