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.upb.internal.message;
15 import static java.nio.charset.StandardCharsets.US_ASCII;
17 import java.util.Arrays;
19 import org.eclipse.jdt.annotation.NonNullByDefault;
20 import org.openhab.core.util.HexUtils;
23 * Model for a message sent or received from a UPB modem.
25 * @author cvanorman - Initial contribution
28 public class UPBMessage {
31 * An enum of possible modem response types.
42 private final byte[] prefix;
44 Type(final String prefix) {
45 this.prefix = prefix.getBytes(US_ASCII);
49 * Returns the message type for a message buffer.
51 * @param buf the byte array to check for a matching type prefix
52 * @return the matching message type, or {@code NONE}
54 public static Type forPrefix(final byte[] buf) {
55 if (buf.length >= 2) {
56 for (final Type t : values()) {
57 if (t.prefix.length >= 2 && buf[0] == t.prefix[0] && buf[1] == t.prefix[1]) {
66 private final Type type;
68 private ControlWord controlWord = new ControlWord();
70 private byte destination;
73 private Command command = Command.NULL;
74 private byte[] arguments = new byte[0];
76 private UPBMessage(final Type type) {
81 * Converts a hex string into a {@link UPBMessage}.
84 * the string as returned by the modem.
85 * @return a new UPBMessage.
87 public static UPBMessage parse(final byte[] buf) {
89 throw new MessageParseException("message too short");
91 final UPBMessage msg = new UPBMessage(Type.forPrefix(buf));
94 if (buf.length >= 15) {
95 byte[] data = unhex(buf, 2, buf.length - 1);
96 msg.getControlWord().setBytes(data[0], data[1]);
98 msg.setNetwork(data[index++]);
99 msg.setDestination(data[index++]);
100 msg.setSource(data[index++]);
102 byte commandCode = data[index++];
103 msg.setCommand(Command.valueOf(commandCode));
105 if (index <= data.length - 1) {
106 msg.setArguments(Arrays.copyOfRange(data, index, data.length - 1));
109 } catch (final RuntimeException e) {
110 throw new MessageParseException("failed to parse message", e);
116 private static byte[] unhex(final byte[] buf, final int start, final int end) {
117 final byte[] res = new byte[(end - start) / 2];
120 while (i < end - 1) {
121 res[j++] = HexUtils.hexToByte(buf[i++], buf[i++]);
129 public Type getType() {
134 * @return the controlWord
136 public ControlWord getControlWord() {
142 * the controlWord to set
144 public void setControlWord(ControlWord controlWord) {
145 this.controlWord = controlWord;
149 * @return the network
151 public byte getNetwork() {
159 public void setNetwork(byte network) {
160 this.network = network;
164 * @return the destination
166 public byte getDestination() {
172 * the destination to set
174 public void setDestination(byte destination) {
175 this.destination = destination;
181 public byte getSource() {
189 public void setSource(byte source) {
190 this.source = source;
194 * @return the command
196 public Command getCommand() {
204 public void setCommand(Command command) {
205 this.command = command;
209 * @return the arguments
211 public byte[] getArguments() {
217 * the arguments to set
219 public void setArguments(byte[] arguments) {
220 this.arguments = arguments;