]> git.basschouten.com Git - openhab-addons.git/blob
ab406c8cda11eb27349637885dc4725fad77542c
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2022 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.rotel.internal.protocol.ascii;
14
15 import static org.openhab.binding.rotel.internal.RotelBindingConstants.*;
16
17 import java.nio.charset.StandardCharsets;
18
19 import org.eclipse.jdt.annotation.NonNullByDefault;
20 import org.eclipse.jdt.annotation.Nullable;
21 import org.openhab.binding.rotel.internal.RotelException;
22 import org.openhab.binding.rotel.internal.RotelModel;
23 import org.openhab.binding.rotel.internal.communication.RotelCommand;
24 import org.openhab.binding.rotel.internal.protocol.RotelProtocol;
25 import org.slf4j.Logger;
26 import org.slf4j.LoggerFactory;
27
28 /**
29  * Class for handling the Rotel ASCII V2 protocol (build of command messages, decoding of incoming data)
30  *
31  * @author Laurent Garnier - Initial contribution
32  */
33 @NonNullByDefault
34 public class RotelAsciiV2ProtocolHandler extends RotelAbstractAsciiProtocolHandler {
35
36     private static final char CHAR_END_RESPONSE = '$';
37
38     private final Logger logger = LoggerFactory.getLogger(RotelAsciiV2ProtocolHandler.class);
39
40     /**
41      * Constructor
42      *
43      * @param model the Rotel model in use
44      */
45     public RotelAsciiV2ProtocolHandler(RotelModel model) {
46         super(model, CHAR_END_RESPONSE);
47     }
48
49     @Override
50     public RotelProtocol getProtocol() {
51         return RotelProtocol.ASCII_V2;
52     }
53
54     @Override
55     public byte[] buildCommandMessage(RotelCommand cmd, @Nullable Integer value) throws RotelException {
56         String messageStr = cmd.getAsciiCommandV2();
57         if (messageStr == null) {
58             throw new RotelException("Command \"" + cmd.getName() + "\" ignored: not available for ASCII V2 protocol");
59         }
60         if (value != null) {
61             switch (cmd) {
62                 case VOLUME_SET:
63                 case ZONE1_VOLUME_SET:
64                 case ZONE2_VOLUME_SET:
65                 case ZONE3_VOLUME_SET:
66                 case ZONE4_VOLUME_SET:
67                     messageStr += String.format("%02d", value);
68                     break;
69                 case BASS_SET:
70                 case ZONE1_BASS_SET:
71                 case ZONE2_BASS_SET:
72                 case ZONE3_BASS_SET:
73                 case ZONE4_BASS_SET:
74                 case TREBLE_SET:
75                 case ZONE1_TREBLE_SET:
76                 case ZONE2_TREBLE_SET:
77                 case ZONE3_TREBLE_SET:
78                 case ZONE4_TREBLE_SET:
79                     if (value == 0) {
80                         messageStr += "000";
81                     } else if (value > 0) {
82                         messageStr += String.format("+%02d", value);
83                     } else {
84                         messageStr += String.format("-%02d", -value);
85                     }
86                     break;
87                 case BALANCE_SET:
88                 case ZONE1_BALANCE_SET:
89                 case ZONE2_BALANCE_SET:
90                 case ZONE3_BALANCE_SET:
91                 case ZONE4_BALANCE_SET:
92                     if (value == 0) {
93                         messageStr += "000";
94                     } else if (value > 0) {
95                         messageStr += String.format("r%02d", value);
96                     } else {
97                         messageStr += String.format("l%02d", -value);
98                     }
99                     break;
100                 case DIMMER_LEVEL_SET:
101                     if (value > 0 && model.getDimmerLevelMin() < 0) {
102                         messageStr += String.format("+%d", value);
103                     } else {
104                         messageStr += String.format("%d", value);
105                     }
106                     break;
107                 default:
108                     break;
109             }
110         }
111         if (!messageStr.endsWith("?")) {
112             messageStr += "!";
113         }
114         byte[] message = messageStr.getBytes(StandardCharsets.US_ASCII);
115         logger.debug("Command \"{}\" => {}", cmd.getName(), messageStr);
116         return message;
117     }
118
119     @Override
120     protected void dispatchKeyValue(String key, String value) {
121         // For distribution amplifiers, we need to split certain values to get the value for each zone
122         if (model == RotelModel.C8 && value.contains(",")) {
123             switch (key) {
124                 case KEY_INPUT:
125                 case KEY_VOLUME:
126                 case KEY_MUTE:
127                 case KEY_BASS:
128                 case KEY_TREBLE:
129                 case KEY_BALANCE:
130                 case KEY_FREQ:
131                     String[] splitValues = value.split(",");
132                     int nb = splitValues.length;
133                     if (nb > MAX_NUMBER_OF_ZONES) {
134                         nb = MAX_NUMBER_OF_ZONES;
135                     }
136                     for (int i = 1; i <= nb; i++) {
137                         String val = KEY_INPUT.equals(key) ? String.format("z%d:input_%s", i, splitValues[i - 1])
138                                 : splitValues[i - 1];
139                         dispatchKeyValue(String.format("%s_zone%d", key, i), val);
140                     }
141                     break;
142                 default:
143                     super.dispatchKeyValue(key, value);
144                     break;
145             }
146         } else {
147             super.dispatchKeyValue(key, value);
148         }
149     }
150 }