2 * Copyright (c) 2010-2022 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.russound.internal.rio.controller;
15 import java.util.regex.Matcher;
16 import java.util.regex.Pattern;
18 import org.eclipse.jdt.annotation.Nullable;
19 import org.openhab.binding.russound.internal.net.SocketSession;
20 import org.openhab.binding.russound.internal.net.SocketSessionListener;
21 import org.openhab.binding.russound.internal.rio.AbstractRioProtocol;
22 import org.openhab.binding.russound.internal.rio.RioConstants;
23 import org.openhab.binding.russound.internal.rio.RioHandlerCallback;
24 import org.slf4j.Logger;
25 import org.slf4j.LoggerFactory;
28 * This is the protocol handler for the Russound controller. This handler will issue the protocol commands and will
29 * process the responses from the Russound system.
31 * @author Tim Roberts - Initial contribution
33 class RioControllerProtocol extends AbstractRioProtocol {
35 private final Logger logger = LoggerFactory.getLogger(RioControllerProtocol.class);
38 * The controller identifier
40 private final int controller;
43 private static final String CTL_TYPE = "type";
44 private static final String CTL_IPADDRESS = "ipaddress";
45 private static final String CTL_MACADDRESS = "macaddress";
48 private static final Pattern RSP_CONTROLLERNOTIFICATION = Pattern
49 .compile("(?i)^[SN] C\\[(\\d+)\\]\\.(\\w+)=\"(.*)\"$");
52 * Constructs the protocol handler from given parameters
54 * @param controller the controller identifier
55 * @param session a non-null {@link SocketSession} (may be connected or disconnected)
56 * @param callback a non-null {@link RioHandlerCallback} to callback
58 RioControllerProtocol(int controller, SocketSession session, RioHandlerCallback callback) {
59 super(session, callback);
60 this.controller = controller;
64 * Helper method to issue post online commands
67 refreshControllerType();
68 refreshControllerIpAddress();
69 refreshControllerMacAddress();
73 * Issues a get command for the controller given the keyname
75 * @param keyName a non-null, non-empty keyname to get
76 * @throws IllegalArgumentException if name is null or an empty string
78 private void refreshControllerKey(String keyName) {
79 if (keyName == null || keyName.trim().length() == 0) {
80 throw new IllegalArgumentException("keyName cannot be null or empty");
82 sendCommand("GET C[" + controller + "]." + keyName);
86 * Refreshes the controller IP address
88 void refreshControllerIpAddress() {
89 refreshControllerKey(CTL_IPADDRESS);
93 * Refreshes the controller MAC address
95 void refreshControllerMacAddress() {
96 refreshControllerKey(CTL_MACADDRESS);
100 * Refreshes the controller Model Type
102 void refreshControllerType() {
103 refreshControllerKey(CTL_TYPE);
107 * Handles any controller notifications returned by the russound system
109 * @param m a non-null matcher
110 * @param resp a possibly null, possibly empty response
112 private void handleControllerNotification(Matcher m, String resp) {
114 throw new IllegalArgumentException("m (matcher) cannot be null");
116 if (m.groupCount() == 3) {
118 final int notifyController = Integer.parseInt(m.group(1));
119 if (notifyController != controller) {
123 final String key = m.group(2).toLowerCase();
124 final String value = m.group(3);
128 setProperty(RioConstants.PROPERTY_CTLTYPE, value);
132 setProperty(RioConstants.PROPERTY_CTLIPADDRESS, value);
136 setProperty(RioConstants.PROPERTY_CTLMACADDRESS, value);
140 logger.debug("Unknown controller notification: '{}'", resp);
143 } catch (NumberFormatException e) {
144 logger.debug("Invalid Controller Notification (controller not a parsable integer): '{}')", resp);
147 logger.debug("Invalid Controller Notification response: '{}'", resp);
152 * Implements {@link SocketSessionListener#responseReceived(String)} to try to process the response from the
153 * russound system. This response may be for other protocol handler - so ignore if we don't recognize the response.
155 * @param a possibly null, possibly empty response
158 public void responseReceived(@Nullable String response) {
159 if (response == null || response.isEmpty()) {
163 final Matcher m = RSP_CONTROLLERNOTIFICATION.matcher(response);
165 handleControllerNotification(m, response);