]> git.basschouten.com Git - openhab-addons.git/blob
e3422e18b3e9d9747df40bfae2466507ffaf9bab
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2023 Contributors to the openHAB project
3  *
4  * See the NOTICE file(s) distributed with this work for additional
5  * information.
6  *
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
10  *
11  * SPDX-License-Identifier: EPL-2.0
12  */
13 package org.openhab.binding.velux.internal.bridge.slip.utils;
14
15 import java.text.ParseException;
16
17 import org.eclipse.jdt.annotation.NonNullByDefault;
18 import org.slf4j.Logger;
19 import org.slf4j.LoggerFactory;
20
21 /**
22  * Transport layer supported by the Velux bridge:
23  * SLIP wrapping supported by the Velux bridge.
24  * <P>
25  * Methods available:
26  * <UL>
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>
29  * </UL>
30  *
31  * @author Guenther Schreiner - Initial contribution.
32  */
33 @NonNullByDefault
34 public class SlipRFC1055 {
35
36     private final Logger logger = LoggerFactory.getLogger(SlipRFC1055.class);
37
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;
42
43     /**
44      * Converts a given payload into transfer byte encoding.
45      *
46      * @param payload Array of bytes to be transmitted.
47      * @return <b>packet</b>
48      *         of type Array-of-byte as encoded payload.
49      */
50     public byte[] encode(byte[] payload) {
51         logger.trace("encode() for data size {} called.", payload.length);
52
53         int additional = 2;
54         for (byte b : payload) {
55             if ((b == SLIP_BYTE_ESC) || (b == SLIP_BYTE_END)) {
56                 additional++;
57             }
58         }
59         byte[] packet = new byte[payload.length + additional];
60         int packetIndex = 0;
61         packet[packetIndex++] = SLIP_BYTE_END;
62
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;
70             } else {
71                 packet[packetIndex++] = b;
72             }
73         }
74         packet[packetIndex++] = SLIP_BYTE_END;
75         assert (packetIndex == packet.length);
76         logger.trace("encode() provides transfer encoding: {}.", new Packet(packet));
77         return packet;
78     }
79
80     /**
81      * Converts a given transfer byte encoding into a payload.
82      *
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.
87      */
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);
92         }
93         if (packet[0] != SLIP_BYTE_END) {
94             throw new ParseException("Unexpected byte at 1st position", 0);
95         }
96         if (packet[packet.length - 1] != SLIP_BYTE_END) {
97             throw new ParseException("Unexpected byte at last position", 0);
98         }
99         int additional = -2;
100         for (int i = 0; i < packet.length; i++) {
101             if (packet[i] == SLIP_BYTE_ESC) {
102                 additional--;
103             }
104         }
105         byte[] payload = new byte[packet.length + additional];
106
107         int packetIndex = 0;
108         for (int i = 0; i < packet.length; i++) {
109             if ((i == 0) || (i == packet.length - 1)) {
110                 continue;
111             }
112             if ((packet[i] == SLIP_BYTE_ESC) && (packet[i + 1] == SLIP_BYTE_ESC_ESC)) {
113                 payload[packetIndex++] = SLIP_BYTE_ESC;
114                 i++;
115             } else if ((packet[i] == SLIP_BYTE_ESC) && (packet[i + 1] == SLIP_BYTE_ESC_END)) {
116                 payload[packetIndex++] = SLIP_BYTE_END;
117                 i++;
118             } else {
119                 payload[packetIndex++] = packet[i];
120             }
121         }
122         logger.trace("decode() provides payload: {}.", new Packet(payload));
123         return payload;
124     }
125 }