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.milight.internal.protocol;
15 import java.net.DatagramPacket;
16 import java.net.DatagramSocket;
17 import java.net.InetAddress;
19 import org.eclipse.jdt.annotation.NonNullByDefault;
20 import org.eclipse.jdt.annotation.Nullable;
23 * A queue item meant to be used for {@link QueuedSend}.
25 * @author David Graeff - Initial contribution
28 public class QueueItem {
29 protected final int uniqueCommandId;
30 protected final boolean repeatable;
31 protected final int delayTime;
32 protected final int repeatCommands;
33 protected final DatagramPacket packet;
34 private boolean invalid = false;
36 final DatagramSocket socket;
37 private final QueueItem root;
38 private @Nullable QueueItem last;
39 public @Nullable QueueItem next;
42 * Add data to the send queue.
43 * Commands which need to be queued up and not replacing same type commands must be non-categorised.
44 * Items can be repeatable, in the sense that they do not cause side effects if they are send multiple times
45 * (e.g. absolute values).
47 * @param socket A socket
48 * @param uniqueCommandId A unique command id. A later command with the same id as previous ones will
49 * overwrite those. 0 means a non categorised entry.
50 * @param data Data to be send
51 * @param repeatable A repeatable command should not cause side effects by sending it multiple times.
52 * @param delayTime A delay time that is used instead of the default delay time between commands for all
53 * added byte sequences.
55 public QueueItem(DatagramSocket socket, int uniqueCommandId, byte[] data, boolean repeatable, int delayTime,
56 int repeatCommands, InetAddress address, int port) {
58 this.uniqueCommandId = uniqueCommandId;
59 this.repeatable = repeatable;
60 this.delayTime = delayTime;
61 this.repeatCommands = repeatCommands;
63 this.packet = new DatagramPacket(data, data.length, address, port);
67 * @see #QueueItem(int, byte[], boolean, int)
68 * @param uniqueCommandId A unique command id. A later command with the same id as previous ones will
69 * overwrite those. 0 means a non categorised entry.
70 * @param data Data to be send
71 * @param repeatable A repeatable command should not cause side effects by sending it multiple times.
72 * @param customDelayTime A delay time that is used instead of the default delay time between commands for all
73 * added byte sequences.
74 * @param root Another item is the root entry for this one.
76 private QueueItem(DatagramSocket socket, int uniqueCommandId, byte[] data, boolean repeatable, int customDelayTime,
77 int repeatCommands, InetAddress address, int port, QueueItem root) {
79 this.uniqueCommandId = uniqueCommandId;
80 this.repeatable = repeatable;
81 this.delayTime = customDelayTime;
82 this.repeatCommands = repeatCommands;
84 this.packet = new DatagramPacket(data, data.length, address, port);
88 * Add non-categorised, repeatable data to the send queue.
91 * Commands which need to be queued up and not replacing same type commands must use this method.
92 * Items added to the queue are considered not repeatable (suited for relative commands where a repetition would
93 * cause a change of value).
97 * If you want to, you can add multiple byte sequences to the queue, even if they have the same id.
98 * This is used for animations and multi-message commands. Be aware that a later added command with the
99 * same id will replace all those commands at once.
102 * @param data Data to be send
104 public static QueueItem createRepeatable(DatagramSocket socket, int customDelayTime, int repeatCommands,
105 InetAddress address, int port, byte[]... data) {
106 QueueItem item = new QueueItem(socket, QueuedSend.NO_CATEGORY, data[0], true, customDelayTime, repeatCommands,
109 QueueItem next = item;
110 for (int i = 1; i < data.length; ++i) {
111 next = next.addRepeatable(data[i]);
117 * Add non-categorised, non-repeatable data to the send queue.
120 * Commands which need to be queued up and not replacing same type commands must use this method.
121 * Items added to the queue are considered not repeatable (suited for relative commands where a repetition would
122 * cause a change of value).
126 * If you want to, you can add multiple byte sequences to the queue, even if they have the same id.
127 * This is used for animations and multi-message commands. Be aware that a later added command with the
128 * same id will replace all those commands at once.
131 * @param data Data to be send
133 public static QueueItem createNonRepeatable(DatagramSocket socket, int customDelayTime, InetAddress address,
134 int port, byte[]... data) {
135 QueueItem item = new QueueItem(socket, QueuedSend.NO_CATEGORY, data[0], false, customDelayTime, 1, address,
138 QueueItem next = item;
139 for (int i = 1; i < data.length; ++i) {
140 next = next.addRepeatable(data[i]);
145 private QueueItem createNewItem(byte[] data, boolean repeatable) {
146 QueueItem newItem = new QueueItem(socket, uniqueCommandId, data, repeatable, delayTime, repeatCommands,
147 packet.getAddress(), packet.getPort(), root);
149 // The the next pointer of the last element in the chain to the new item
150 QueueItem lastInChain = root.last != null ? root.last : root;
151 lastInChain.next = newItem;
157 * Add a command to the command chain. Can be called on any of the
158 * commands in the chain, but will overwrite the next command in chain.
160 * This method can be used in a cascading way like:
161 * QueueItem item ...;
162 * send(item.addNonRepeatable(...).addNonRepeatable(...))
165 * @param data Add data to the chain of commands
166 * @return Always return the root command
168 public QueueItem addNonRepeatable(byte[] data) {
169 root.last = createNewItem(data, false);
174 * Add a command to the command chain. Can be called on any of the
175 * commands in the chain, but will overwrite the next command in chain.
177 * This method can be used in a cascading way like:
178 * QueueItem item ...;
179 * send(item.addRepeatable(...).addRepeatable(...))
182 * @param data Add data to the chain of commands
183 * @return Always return the root command
185 public QueueItem addRepeatable(byte[] data) {
186 root.last = createNewItem(data, true);
190 public boolean isInvalid() {
194 public void makeInvalid() {