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.velux.internal.bridge.slip.utils;
15 import java.text.ParseException;
17 import org.eclipse.jdt.annotation.NonNullByDefault;
18 import org.slf4j.Logger;
19 import org.slf4j.LoggerFactory;
22 * Transport layer supported by the Velux bridge:
23 * SLIP wrapping supported by the Velux bridge.
27 * <LI>{@link #encode(byte[] payload) } converts a given payload into transfer byte encoding.</LI>
28 * <LI>{@link #decode(byte[] packet) } converts a given transfer byte encoding into a payload.</LI>
31 * @author Guenther Schreiner - Initial contribution.
34 public class SlipRFC1055 {
36 private final Logger logger = LoggerFactory.getLogger(SlipRFC1055.class);
38 private static final byte SLIP_BYTE_END = (byte) 0xC0;
39 private static final byte SLIP_BYTE_ESC = (byte) 0xDB;
40 private static final byte SLIP_BYTE_ESC_END = (byte) 0xDC;
41 private static final byte SLIP_BYTE_ESC_ESC = (byte) 0xDD;
44 * Converts a given payload into transfer byte encoding.
46 * @param payload Array of bytes to be transmitted.
47 * @return <b>packet</b>
48 * of type Array-of-byte as encoded payload.
50 public byte[] encode(byte[] payload) {
51 logger.trace("encode() for data size {} called.", payload.length);
54 for (byte b : payload) {
55 if ((b == SLIP_BYTE_ESC) || (b == SLIP_BYTE_END)) {
59 byte[] packet = new byte[payload.length + additional];
61 packet[packetIndex++] = SLIP_BYTE_END;
63 for (byte b : payload) {
64 if (b == SLIP_BYTE_ESC) {
65 packet[packetIndex++] = SLIP_BYTE_ESC;
66 packet[packetIndex++] = SLIP_BYTE_ESC_ESC;
67 } else if (b == SLIP_BYTE_END) {
68 packet[packetIndex++] = SLIP_BYTE_ESC;
69 packet[packetIndex++] = SLIP_BYTE_ESC_END;
71 packet[packetIndex++] = b;
74 packet[packetIndex++] = SLIP_BYTE_END;
75 assert (packetIndex == packet.length);
76 logger.trace("encode() provides transfer encoding: {}.", new Packet(packet));
81 * Converts a given transfer byte encoding into a payload.
83 * @param packet Array of bytes as being received.
84 * @return <b>payload</b>
85 * of type Array-of-byte as decoded payload.
86 * @throws ParseException in case of decoding errors.
88 public byte[] decode(byte[] packet) throws ParseException {
89 logger.trace("decode() for packet size {} called.", packet.length);
90 if (packet.length < 3) {
91 throw new ParseException("Packet too short", 0);
93 if (packet[0] != SLIP_BYTE_END) {
94 throw new ParseException("Unexpected byte at 1st position", 0);
96 if (packet[packet.length - 1] != SLIP_BYTE_END) {
97 throw new ParseException("Unexpected byte at last position", 0);
100 for (int i = 0; i < packet.length; i++) {
101 if (packet[i] == SLIP_BYTE_ESC) {
105 byte[] payload = new byte[packet.length + additional];
108 for (int i = 0; i < packet.length; i++) {
109 if ((i == 0) || (i == packet.length - 1)) {
112 if ((packet[i] == SLIP_BYTE_ESC) && (packet[i + 1] == SLIP_BYTE_ESC_ESC)) {
113 payload[packetIndex++] = SLIP_BYTE_ESC;
115 } else if ((packet[i] == SLIP_BYTE_ESC) && (packet[i + 1] == SLIP_BYTE_ESC_END)) {
116 payload[packetIndex++] = SLIP_BYTE_END;
119 payload[packetIndex++] = packet[i];
122 logger.trace("decode() provides payload: {}.", new Packet(payload));