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.monopriceaudio.internal.communication;
15 import java.util.HashMap;
16 import java.util.List;
18 import java.util.regex.Matcher;
19 import java.util.regex.Pattern;
21 import org.eclipse.jdt.annotation.NonNullByDefault;
22 import org.openhab.binding.monopriceaudio.internal.configuration.MonopriceAudioThingConfiguration;
23 import org.openhab.binding.monopriceaudio.internal.dto.MonopriceAudioZoneDTO;
24 import org.openhab.core.types.StateOption;
27 * The {@link AmplifierModel} is responsible for mapping low level communications for each supported amplifier model.
29 * @author Michael Lobstein - Initial contribution
32 public enum AmplifierModel {
34 // Monoprice 10761/Dayton Audio DAX66
35 MONOPRICE("<", "\r", "?", "", "#>", "PR", "CH", "VO", "MU", "TR", "BS", "BL", "DT", 38, -7, 7, 7, -10, 10, 10, 18,
36 6, true, List.of("11", "12", "13", "14", "15", "16", "21", "22", "23", "24", "25", "26", "31", "32", "33",
39 public MonopriceAudioZoneDTO getZoneData(String newZoneData) {
40 return getMonopriceZoneData(newZoneData);
44 public List<StateOption> getSourceLabels(MonopriceAudioThingConfiguration config) {
45 return List.of(new StateOption("1", config.inputLabel1), new StateOption("2", config.inputLabel2),
46 new StateOption("3", config.inputLabel3), new StateOption("4", config.inputLabel4),
47 new StateOption("5", config.inputLabel5), new StateOption("6", config.inputLabel6));
51 DAX88("<", "\r", "?", "", ">", "PR", "CH", "VO", "MU", "TR", "BS", "BL", "DT", 38, -12, 12, 12, -10, 10, 10, 8, 8,
52 true, List.of("01", "02", "03", "04", "05", "06", "07", "08")) {
54 public MonopriceAudioZoneDTO getZoneData(String newZoneData) {
55 return getMonopriceZoneData(newZoneData);
59 public List<StateOption> getSourceLabels(MonopriceAudioThingConfiguration config) {
60 return List.of(new StateOption("1", config.inputLabel1), new StateOption("2", config.inputLabel2),
61 new StateOption("3", config.inputLabel3), new StateOption("4", config.inputLabel4),
62 new StateOption("5", config.inputLabel5), new StateOption("6", config.inputLabel6),
63 new StateOption("7", config.inputLabel7), new StateOption("8", config.inputLabel8));
66 MONOPRICE70("!", "+\r", "?", "ZS", "?", "PR", "IS", "VO", "MU", "TR", "BS", "BA", "", 38, -7, 7, 7, -32, 31, 32, 6,
67 2, false, List.of("1", "2", "3", "4", "5", "6")) {
69 public MonopriceAudioZoneDTO getZoneData(String newZoneData) {
70 MonopriceAudioZoneDTO zoneData = new MonopriceAudioZoneDTO();
72 Matcher matcher = MONOPRICE70_PATTERN.matcher(newZoneData);
74 zoneData.setZone(matcher.group(1));
75 zoneData.setVolume(Integer.parseInt(matcher.group(2)));
76 zoneData.setPower(matcher.group(3));
77 zoneData.setMute(matcher.group(4));
78 zoneData.setSource(matcher.group(5));
82 matcher = MONOPRICE70_TREB_PATTERN.matcher(newZoneData);
84 zoneData.setZone(matcher.group(1));
85 zoneData.setTreble(Integer.parseInt(matcher.group(2)));
89 matcher = MONOPRICE70_BASS_PATTERN.matcher(newZoneData);
91 zoneData.setZone(matcher.group(1));
92 zoneData.setBass(Integer.parseInt(matcher.group(2)));
96 matcher = MONOPRICE70_BALN_PATTERN.matcher(newZoneData);
98 zoneData.setZone(matcher.group(1));
99 zoneData.setBalance(Integer.parseInt(matcher.group(2)));
107 public List<StateOption> getSourceLabels(MonopriceAudioThingConfiguration config) {
108 return List.of(new StateOption("0", config.inputLabel1), new StateOption("1", config.inputLabel2));
111 XANTECH("!", "+\r", "?", "ZD", "#", "PR", "SS", "VO", "MU", "TR", "BS", "BL", "", 38, -7, 7, 7, -32, 31, 32, 16, 8,
112 false, List.of("1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16")) {
114 public MonopriceAudioZoneDTO getZoneData(String newZoneData) {
115 MonopriceAudioZoneDTO zoneData = new MonopriceAudioZoneDTO();
116 Matcher matcher = XANTECH_PATTERN.matcher(newZoneData);
118 if (matcher.find()) {
119 zoneData.setZone(matcher.group(1));
120 zoneData.setPower(matcher.group(2));
121 zoneData.setSource(matcher.group(3));
122 zoneData.setVolume(Integer.parseInt(matcher.group(4)));
123 zoneData.setMute(matcher.group(5));
124 zoneData.setTreble(Integer.parseInt(matcher.group(6)));
125 zoneData.setBass(Integer.parseInt(matcher.group(7)));
126 zoneData.setBalance(Integer.parseInt(matcher.group(8)));
127 zoneData.setKeypad(matcher.group(9));
128 zoneData.setPage(matcher.group(10));
134 public List<StateOption> getSourceLabels(MonopriceAudioThingConfiguration config) {
135 return List.of(new StateOption("1", config.inputLabel1), new StateOption("2", config.inputLabel2),
136 new StateOption("3", config.inputLabel3), new StateOption("4", config.inputLabel4),
137 new StateOption("5", config.inputLabel5), new StateOption("6", config.inputLabel6),
138 new StateOption("7", config.inputLabel7), new StateOption("8", config.inputLabel8));
142 // Used by 10761/DAX66 and DAX88
143 private static MonopriceAudioZoneDTO getMonopriceZoneData(String newZoneData) {
144 MonopriceAudioZoneDTO zoneData = new MonopriceAudioZoneDTO();
145 Matcher matcher = MONOPRICE_PATTERN.matcher(newZoneData);
147 if (matcher.find()) {
148 zoneData.setZone(matcher.group(1));
149 zoneData.setPage(matcher.group(2));
150 zoneData.setPower(matcher.group(3));
151 zoneData.setMute(matcher.group(4));
152 zoneData.setDnd(matcher.group(5));
153 zoneData.setVolume(Integer.parseInt(matcher.group(6)));
154 zoneData.setTreble(Integer.parseInt(matcher.group(7)));
155 zoneData.setBass(Integer.parseInt(matcher.group(8)));
156 zoneData.setBalance(Integer.parseInt(matcher.group(9)));
157 zoneData.setSource(matcher.group(10));
158 zoneData.setKeypad(matcher.group(11));
163 // Monoprice 10761/DAX66 status string: #>1200010000130809100601
164 // DAX88 status string is the same but does not have leading '#': >xxaabbccddeeffgghhiijj
165 private static final Pattern MONOPRICE_PATTERN = Pattern
166 .compile("^#?>(\\d{2})(\\d{2})(\\d{2})(\\d{2})(\\d{2})(\\d{2})(\\d{2})(\\d{2})(\\d{2})(\\d{2})(\\d{2})");
168 // Monoprice 31028 / PAM1270 status string: ?6ZS VO8 PO1 MU0 IS0+ (does not include treble, bass & balance)
169 private static final Pattern MONOPRICE70_PATTERN = Pattern
170 .compile("^\\?(\\d{1})ZS VO(\\d{1,2}) PO(\\d{1}) MU(\\d{1}) IS(\\d{1})+");
171 private static final Pattern MONOPRICE70_TREB_PATTERN = Pattern.compile("^\\?(\\d{1})TR(\\d{1,2})+");
172 private static final Pattern MONOPRICE70_BASS_PATTERN = Pattern.compile("^\\?(\\d{1})BS(\\d{1,2})+");
173 private static final Pattern MONOPRICE70_BALN_PATTERN = Pattern.compile("^\\?(\\d{1})BA(\\d{1,2})+");
175 // Xantech status string: #1ZS PR0 SS1 VO0 MU1 TR7 BS7 BA32 LS0 PS0+
176 private static final Pattern XANTECH_PATTERN = Pattern.compile(
177 "^#(\\d{1,2})ZS PR(\\d{1}) SS(\\d{1}) VO(\\d{1,2}) MU(\\d{1}) TR(\\d{1,2}) BS(\\d{1,2}) BA(\\d{1,2}) LS(\\d{1}) PS(\\d{1})+");
179 private String cmdPrefix;
180 private String cmdSuffix;
181 private String queryPrefix;
182 private String querySuffix;
183 private String respPrefix;
184 private String powerCmd;
185 private String sourceCmd;
186 private String volumeCmd;
187 private String muteCmd;
188 private String trebleCmd;
189 private String bassCmd;
190 private String balanceCmd;
191 private String dndCmd;
195 private int toneOffset;
198 private int balOffset;
199 private int maxZones;
200 private int numSources;
201 private boolean padNumbers;
202 private List<String> zoneIds;
203 private Map<String, String> zoneIdMap = new HashMap<>();
205 private static final String ON_STR = "1";
206 private static final String OFF_STR = "0";
208 private static final String ON_STR_PAD = "01";
209 private static final String OFF_STR_PAD = "00";
212 * Constructor for all the enum parameters
215 AmplifierModel(String cmdPrefix, String cmdSuffix, String queryPrefix, String querySuffix, String respPrefix,
216 String powerCmd, String sourceCmd, String volumeCmd, String muteCmd, String trebleCmd, String bassCmd,
217 String balanceCmd, String dndCmd, int maxVol, int minTone, int maxTone, int toneOffset, int minBal,
218 int maxBal, int balOffset, int maxZones, int numSources, boolean padNumbers, List<String> zoneIds) {
219 this.cmdPrefix = cmdPrefix;
220 this.cmdSuffix = cmdSuffix;
221 this.queryPrefix = queryPrefix;
222 this.querySuffix = querySuffix;
223 this.respPrefix = respPrefix;
224 this.powerCmd = powerCmd;
225 this.sourceCmd = sourceCmd;
226 this.volumeCmd = volumeCmd;
227 this.muteCmd = muteCmd;
228 this.trebleCmd = trebleCmd;
229 this.bassCmd = bassCmd;
230 this.balanceCmd = balanceCmd;
231 this.dndCmd = dndCmd;
232 this.maxVol = maxVol;
233 this.minTone = minTone;
234 this.maxTone = maxTone;
235 this.toneOffset = toneOffset;
236 this.minBal = minBal;
237 this.maxBal = maxBal;
238 this.balOffset = balOffset;
239 this.maxZones = maxZones;
240 this.numSources = numSources;
241 this.padNumbers = padNumbers;
242 this.zoneIds = zoneIds;
245 for (String zoneId : zoneIds) {
246 zoneIdMap.put(zoneId, "zone" + i);
251 public abstract MonopriceAudioZoneDTO getZoneData(String newZoneData);
253 public abstract List<StateOption> getSourceLabels(MonopriceAudioThingConfiguration config);
255 public String getZoneIdFromZoneName(String zoneName) {
256 for (String zoneId : zoneIdMap.keySet()) {
257 if (zoneIdMap.get(zoneId).equals(zoneName)) {
264 public String getZoneName(String zoneId) {
265 String zoneName = zoneIdMap.get(zoneId);
266 if (zoneName != null) {
273 public String getCmdPrefix() {
277 public String getQueryPrefix() {
281 public String getQuerySuffix() {
285 public String getRespPrefix() {
289 public String getPowerCmd() {
293 public String getSourceCmd() {
297 public String getVolumeCmd() {
301 public String getMuteCmd() {
305 public String getTrebleCmd() {
309 public String getBassCmd() {
313 public String getBalanceCmd() {
317 public String getDndCmd() {
321 public int getMaxVol() {
325 public int getMinTone() {
329 public int getMaxTone() {
333 public int getMinBal() {
337 public int getMaxBal() {
341 public int getBalOffset() {
345 public int getToneOffset() {
349 public int getMaxZones() {
353 public int getNumSources() {
357 public String getCmdSuffix() {
361 public List<String> getZoneIds() {
365 public String getFormattedValue(Integer value) {
367 return String.format("%02d", value);
369 return value.toString();
373 public String getOnStr() {
381 public String getOffStr() {