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.rotel.internal.protocol;
15 import static org.openhab.binding.rotel.internal.RotelBindingConstants.*;
17 import java.util.ArrayList;
18 import java.util.List;
20 import org.eclipse.jdt.annotation.NonNullByDefault;
21 import org.eclipse.jdt.annotation.Nullable;
22 import org.openhab.binding.rotel.internal.RotelException;
23 import org.openhab.binding.rotel.internal.RotelModel;
24 import org.openhab.binding.rotel.internal.communication.RotelCommand;
25 import org.openhab.core.util.HexUtils;
26 import org.slf4j.Logger;
27 import org.slf4j.LoggerFactory;
30 * Abstract class for handling a Rotel protocol (build of command messages, decoding of incoming data)
32 * @author Laurent Garnier - Initial contribution
35 public abstract class RotelAbstractProtocolHandler {
37 private final Logger logger = LoggerFactory.getLogger(RotelAbstractProtocolHandler.class);
39 protected final RotelModel model;
41 private final List<RotelMessageEventListener> listeners = new ArrayList<>();
46 * @param model the Rotel model in use
48 public RotelAbstractProtocolHandler(RotelModel model) {
52 public abstract RotelProtocol getProtocol();
55 * Build the message associated to a Rotel command
57 * @param cmd the command to execute
58 * @param value the integer value to consider for volume, bass or treble adjustment
60 * @throws RotelException - In case the command is not supported by the protocol
62 public abstract byte[] buildCommandMessage(RotelCommand cmd, @Nullable Integer value) throws RotelException;
64 public abstract void handleIncomingData(byte[] inDataBuffer, int length);
66 public void handleInIncomingError() {
67 dispatchKeyValue(KEY_ERROR, MSG_VALUE_ON);
71 * Analyze an incoming message and dispatch corresponding (key, value) to the event listeners
73 * @param incomingMessage the received message
75 protected void handleIncomingMessage(byte[] incomingMessage) {
76 logger.debug("handleIncomingMessage: bytes {}", HexUtils.bytesToHex(incomingMessage));
79 validateResponse(incomingMessage);
80 } catch (RotelException e) {
84 handleValidMessage(incomingMessage);
88 * Validate the content of a feedback message
90 * @param responseMessage the buffer containing the feedback message
92 * @throws RotelException - If the message has unexpected content
94 protected abstract void validateResponse(byte[] responseMessage) throws RotelException;
97 * Analyze a valid HEX message and dispatch corresponding (key, value) to the event listeners
99 * @param incomingMessage the received message
101 protected abstract void handleValidMessage(byte[] incomingMessage);
104 * Add a listener to the list of listeners to be notified with events
106 * @param listener the listener
108 public void addEventListener(RotelMessageEventListener listener) {
109 listeners.add(listener);
113 * Remove a listener from the list of listeners to be notified with events
115 * @param listener the listener
117 public void removeEventListener(RotelMessageEventListener listener) {
118 listeners.remove(listener);
122 * Dispatch an event (key, value) to the event listeners
125 * @param value the value
127 protected void dispatchKeyValue(String key, String value) {
128 RotelMessageEvent event = new RotelMessageEvent(this, key, value);
129 for (int i = 0; i < listeners.size(); i++) {
130 listeners.get(i).onNewMessageEvent(event);