[monopriceaudio] Add support for additional amplifiers (#13936)
* Add support for additional models * Clarify supported models and documentation * Add notes for amps with built-in serial over IP * Improve configuration validation and add i18n to status messages * Remove default values for port configuration Signed-off-by: Michael Lobstein <michael.lobstein@gmail.com>
This commit is contained in:
parent
e6d84ab488
commit
2f7bdbe966
|
@ -1,48 +1,55 @@
|
|||
# Monoprice Whole House Audio Binding
|
||||
|
||||
This binding can be used to control a Monoprice MPR-SG6Z (10761), Monoprice Passive Matrix (39261) & Dayton Audio DAX66 whole house multi-zone amplifier system.
|
||||
All amplifier functions available through the serial port interface can be controlled by the binding.
|
||||
Up to 18 zones can be controlled when 3 amps are connected together (if not all zones on the amp are used they can be excluded via configuration).
|
||||
Activating the 'Page All Zones' feature can only be done through the +12v trigger input on the back of the amplifier.
|
||||
This binding can be used to control the following types of whole house multi-zone amplifier systems:
|
||||
|
||||
- Monoprice MPR-SG6Z (10761), Monoprice Passive Matrix (39261), Dayton Audio DAX66 or compatible clones
|
||||
- Monoprice 31028 or OSD Audio PAM1270 **(untested)**
|
||||
- Dayton Audio DAX88 **(untested)**
|
||||
- Xantech MRC88, MX88, MRAUDIO8X8 or CM8X8 **(untested)**
|
||||
|
||||
The binding supports two different kinds of connections:
|
||||
|
||||
- serial connection,
|
||||
- serial port connection
|
||||
- serial over IP connection
|
||||
|
||||
For users without a serial port on the server side, you can use a USB to serial adapter.
|
||||
|
||||
You don't need to have your whole house amplifier device directly connected to your openHAB server.
|
||||
Some newer versions of the amplifier have a built-in ethernet port that supports serial over IP.
|
||||
Some newer versions of the amplifier have a built-in Ethernet port that supports serial over IP.
|
||||
Or you can connect it for example to a Raspberry Pi and use [ser2net Linux tool](https://sourceforge.net/projects/ser2net/) to make the serial connection available on the LAN (serial over IP).
|
||||
|
||||
## Supported Things
|
||||
|
||||
Monoprice 10761 & 39261 and Dayton Audio DAX66 Amplifiers use the `amplifier` thing id. Up to 18 zones with 3 linked amps, 6 source inputs.
|
||||
Monoprice 10761 & 39261 or Dayton Audio DAX66 amplifiers use the `amplifier` thing id. Up to 18 zones with 3 linked amps and 6 source inputs are supported.
|
||||
Note: Compatible clones (including 4 zone versions) from McLELLAND, Factor, Soundavo, etc. should work as well.
|
||||
|
||||
***The following three thing types were implemented via available documentation only and have not been tested. Please open an issue for any bugs found when using these thing types.***
|
||||
|
||||
Monoprice 31028 or OSD Audio PAM1270 70 volt amplifiers use the `monoprice70` thing id. 6 zones per amp (not linkable) and 2 source inputs are supported.
|
||||
|
||||
Dayton Audio DAX88 amplifiers use the `dax88` thing id. 8 zones (2 un-amplified) per amp (not linkable) and 8 source inputs are supported.
|
||||
|
||||
Xantech MRC88, MX88, MRAUDIO8X8 or CM8X8 amplifiers use the `xantech` thing id. Up to 16 zones with 2 linked amps and 8 source inputs are supported.
|
||||
Some Xantech amps provide unsolicited zone updates for keypad actions and may work with the `disableKeypadPolling` option set to true which will prevent un-necessary polling of the amplifier.
|
||||
Note: MRC44 amps do not support serial control.
|
||||
|
||||
## Discovery
|
||||
|
||||
Discovery is not supported.
|
||||
You have to add all things manually.
|
||||
|
||||
## Binding Configuration
|
||||
|
||||
There are no overall binding configuration settings that need to be set.
|
||||
All settings are through thing configuration parameters.
|
||||
|
||||
## Thing Configuration
|
||||
|
||||
The thing has the following configuration parameters:
|
||||
The thing has the following configuration parameters (number of sources and zones is amplifier dependent):
|
||||
|
||||
| Parameter Label | Parameter ID | Description | Accepted values |
|
||||
|----------------------|------------------|--------------------------------------------------------------------------------------------------------------------------------|------------------|
|
||||
| Serial Port | serialPort | Serial port to use for connecting to the Monoprice whole house amplifier device | Serial port name |
|
||||
|------------------------|----------------------|--------------------------------------------------------------------------------------------------------------------------------|------------------|
|
||||
| Serial Port | serialPort | Serial port to use for connecting to the whole house amplifier device | Serial port name |
|
||||
| Address | host | Host name or IP address of the amplifier or serial over IP device | Host name or IP |
|
||||
| Port | port | Communication port (default 8080 for newer amps with built-in serial over IP) | TCP port number |
|
||||
| Number of Zones | numZones | (Optional) Number of amplifier zones to utilize in the binding (up to 18 zones with 3 amplifiers connected together) | 1-18; default 6 |
|
||||
| Port | port | Communication port (8080 for newer amps with built-in serial over IP) | TCP port number |
|
||||
| Number of Zones | numZones | (Optional) Number of amplifier zones to utilize in the binding (See Supported Things for max number of zones per Thing type) | 1-18; default 6 |
|
||||
| Polling Interval | pollingInterval | (Optional) Configures how often (in seconds) to poll the amplifier to check for zone updates | 5-60; default 15 |
|
||||
| Ignore Zones | ignoreZones | (Optional) A comma seperated list of Zone numbers that will ignore the 'All Zone' (except All Off) commands | ie: "1,6,10" |
|
||||
| Ignore Zones | ignoreZones | (Optional) A comma separated list of Zone numbers that will ignore the 'All Zone' (except All Off) commands | ie: "1,6,10" |
|
||||
| Initial All Volume | initialAllVolume | (Optional) When 'All' zones are activated, the volume will reset to this value to prevent excessive blaring of sound ;) | 1-30; default 10 |
|
||||
| Source 1 Input Label | inputLabel1 | (Optional) Friendly name for the input source to be displayed in the UI (ie: Chromecast, Radio, CD, etc.) (default "Source 1") | A free text name |
|
||||
| Source 2 Input Label | inputLabel2 | (Optional) Friendly name for the input source to be displayed in the UI (ie: Chromecast, Radio, CD, etc.) (default "Source 2") | A free text name |
|
||||
|
@ -50,36 +57,55 @@ The thing has the following configuration parameters:
|
|||
| Source 4 Input Label | inputLabel4 | (Optional) Friendly name for the input source to be displayed in the UI (ie: Chromecast, Radio, CD, etc.) (default "Source 4") | A free text name |
|
||||
| Source 5 Input Label | inputLabel5 | (Optional) Friendly name for the input source to be displayed in the UI (ie: Chromecast, Radio, CD, etc.) (default "Source 5") | A free text name |
|
||||
| Source 6 Input Label | inputLabel6 | (Optional) Friendly name for the input source to be displayed in the UI (ie: Chromecast, Radio, CD, etc.) (default "Source 6") | A free text name |
|
||||
| Source 7 Input Label | inputLabel7 | (Optional) Friendly name for the input source to be displayed in the UI (ie: Chromecast, Radio, CD, etc.) (default "Source 7") | A free text name |
|
||||
| Source 8 Input Label | inputLabel8 | (Optional) Friendly name for the input source to be displayed in the UI (ie: Chromecast, Radio, CD, etc.) (default "Source 8") | A free text name |
|
||||
| Disable Keypad Polling | disableKeypadPolling | Set to **true** if physical keypads are not used so the binding will not needlessly poll the amplifier zones for changes | true or false |
|
||||
|
||||
Some notes:
|
||||
|
||||
- On the 10761/DAX66 amp, activating the 'Page All Zones' feature can only be done through the +12v trigger input on the back of the amplifier.
|
||||
|
||||
- On Linux, you may get an error stating the serial port cannot be opened when the MonopriceAudio binding tries to load.
|
||||
- You can get around this by adding the `openhab` user to the `dialout` group like this: `usermod -a -G dialout openhab`.
|
||||
- Also on Linux you may have issues with the USB if using two serial USB devices e.g. MonopriceAudio and RFXcom.
|
||||
- See the [general documentation about serial port configuration](/docs/administration/serial.html) for more on symlinking the USB ports.
|
||||
- Here is an example of ser2net.conf you can use to share your serial port /dev/ttyUSB0 on IP port 8080 using [ser2net Linux tool](https://sourceforge.net/projects/ser2net/):
|
||||
- Here is an example of ser2net.conf (for ser2net version < 4) you can use to share your serial port /dev/ttyUSB0 on IP port 8080 using [ser2net Linux tool](https://sourceforge.net/projects/ser2net/):
|
||||
|
||||
```text
|
||||
8080:raw:0:/dev/ttyUSB0:9600 8DATABITS NONE 1STOPBIT LOCAL
|
||||
```
|
||||
|
||||
- Here is an example of ser2net.yaml (for ser2net version >= 4) you can use to share your serial port /dev/ttyUSB0 on IP port 8080 using [ser2net Linux tool](https://sourceforge.net/projects/ser2net/):
|
||||
|
||||
```yaml
|
||||
connection: &conMono
|
||||
accepter: tcp,8080
|
||||
enable: on
|
||||
options:
|
||||
kickolduser: true
|
||||
connector: serialdev,
|
||||
/dev/ttyUSB0,
|
||||
9600n81,local
|
||||
```
|
||||
|
||||
## Channels
|
||||
|
||||
The following channels are available:
|
||||
Note that `dnd`, `page` and `keypad` are not available on all thing types.
|
||||
|
||||
| Channel ID | Item Type | Description |
|
||||
|-------------------------------|-----------|---------------------------------------------------------------------------------------------------------------|
|
||||
|-------------------------------|-----------|---------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| all#allpower | Switch | Turn all zones on or off simultaneously (those specified by the ignoreZones config option will not turn on) |
|
||||
| all#allsource | Number | Select the input source for all zones simultaneously (1-6) (except ignoreZones) |
|
||||
| all#allvolume | Dimmer | Control the volume for all zones simultaneously (0-100%) [translates to 0-38] (except ignoreZones) |
|
||||
| all#allsource | Number | Select the input source for all zones simultaneously (1-8) [number of sources is amplifier dependent] (except ignoreZones) |
|
||||
| all#allvolume | Dimmer | Control the volume for all zones simultaneously (0-100%) [translates to the particular amplifier's volume range] (except ignoreZones) |
|
||||
| all#allmute | Switch | Mute or unmute all zones simultaneously (except ignoreZones) |
|
||||
| zoneN#power (where N= 1-18) | Switch | Turn the power for a zone on or off |
|
||||
| zoneN#source (where N= 1-18) | Number | Select the input source for a zone (1-6) |
|
||||
| zoneN#volume (where N= 1-18) | Dimmer | Control the volume for a zone (0-100%) [translates to 0-38] |
|
||||
| zoneN#source (where N= 1-18) | Number | Select the input source for a zone (1-8) [number of sources is amplifier dependent] |
|
||||
| zoneN#volume (where N= 1-18) | Dimmer | Control the volume for a zone (0-100%) [translates to the particular amplifier's volume range] |
|
||||
| zoneN#mute (where N= 1-18) | Switch | Mute or unmute a zone |
|
||||
| zoneN#treble (where N= 1-18) | Number | Adjust the treble control for a zone (-7 to 7) -7=none, 0=flat, 7=full |
|
||||
| zoneN#bass (where N= 1-18) | Number | Adjust the bass control for a zone (-7 to 7) -7=none, 0=flat, 7=full |
|
||||
| zoneN#balance (where N= 1-18) | Number | Adjust the balance control for a zone (-10 to 10) -10=left, 0=center, 10=right |
|
||||
| zoneN#treble (where N= 1-18) | Number | Adjust the treble control for a zone [range is amplifier dependent] |
|
||||
| zoneN#bass (where N= 1-18) | Number | Adjust the bass control for a zone [range is amplifier dependent] |
|
||||
| zoneN#balance (where N= 1-18) | Number | Adjust the balance control for a zone [0=center, range is amplifier dependent] |
|
||||
| zoneN#dnd (where N= 1-18) | Switch | Turn on or off the Do Not Disturb for the zone (for when the amplifier's external page trigger is activated) |
|
||||
| zoneN#page (where N= 1-18) | Contact | Indicates if the page input is activated for the zone |
|
||||
| zoneN#keypad (where N= 1-18) | Contact | Indicates if the physical keypad is attached to a zone |
|
||||
|
@ -89,17 +115,29 @@ The following channels are available:
|
|||
monoprice.things:
|
||||
|
||||
```java
|
||||
// serial port connection
|
||||
// Monoprice 10761, 39261 / DAX66 (serial port connection)
|
||||
monopriceaudio:amplifier:myamp "Monoprice WHA" [ serialPort="COM5", pollingInterval=15, numZones=6, inputLabel1="Chromecast", inputLabel2="Radio", inputLabel3="CD Player", inputLabel4="Bluetooth Audio", inputLabel5="HTPC", inputLabel6="Phono" ]
|
||||
|
||||
// serial over IP connection
|
||||
// Monoprice 10761, 39261 / DAX66 (serial over IP connection)
|
||||
monopriceaudio:amplifier:myamp "Monoprice WHA" [ host="192.168.0.10", port=8080, pollingInterval=15, numZones=6, inputLabel1="Chromecast", inputLabel2="Radio", inputLabel3="CD Player", inputLabel4="Bluetooth Audio", inputLabel5="HTPC", inputLabel6="Phono" ]
|
||||
|
||||
// Monoprice 31028 or OSD Audio PAM1270
|
||||
monopriceaudio:monoprice70:myamp "Monoprice WHA" [ serialPort="COM5", pollingInterval=30, numZones=6, inputLabel1="Source 0 - Bus", inputLabel2="Source 1 - Line" ]
|
||||
|
||||
// Dayton DAX88
|
||||
monopriceaudio:dax88:myamp "Dayton WHA" [ serialPort="COM5", pollingInterval=15, numZones=8, inputLabel1="Chromecast", inputLabel2="Radio", inputLabel3="CD Player", inputLabel4="Bluetooth Audio", inputLabel5="HTPC", inputLabel6="Phono", inputLabel7="Ipod", inputLabel8="Streaming" ]
|
||||
|
||||
// Xantech 8x8
|
||||
monopriceaudio:xantech:myamp "Xantech WHA" [ serialPort="COM5", pollingInterval=30, numZones=8, inputLabel1="Chromecast", inputLabel2="Radio", inputLabel3="CD Player", inputLabel4="Bluetooth Audio", inputLabel5="HTPC", inputLabel6="Phono", inputLabel7="Ipod", inputLabel8="Sirius" ]
|
||||
|
||||
// Note that host and port can be used with any of the thing types to connect as serial over IP
|
||||
```
|
||||
|
||||
monoprice.items:
|
||||
|
||||
```java
|
||||
// substitute 'amplifier' for the appropriate thing id if using 31028, DAX88 or Xantech amplifier
|
||||
|
||||
Switch all_allpower "All Zones Power" { channel="monopriceaudio:amplifier:myamp:all#allpower" }
|
||||
Number all_source "Source Input [%s]" { channel="monopriceaudio:amplifier:myamp:all#allsource" }
|
||||
Dimmer all_volume "Volume [%d %%]" { channel="monopriceaudio:amplifier:myamp:all#allvolume" }
|
||||
|
@ -116,7 +154,7 @@ Switch z1_dnd "Do Not Disturb" { channel="monopriceaudio:amplifier:myamp:zone1#d
|
|||
Switch z1_page "Page Active: [%s]" { channel="monopriceaudio:amplifier:myamp:zone1#page" }
|
||||
Switch z1_keypad "Keypad Connected: [%s]" { channel="monopriceaudio:amplifier:myamp:zone1#keypad" }
|
||||
|
||||
// repeat for zones 2-18 (substitute z1 and zone1)
|
||||
// repeat for total number of zones used (substitute z1 and zone1)
|
||||
```
|
||||
|
||||
monoprice.sitemap:
|
||||
|
@ -137,6 +175,7 @@ sitemap monoprice label="Audio Control" {
|
|||
// Volume can be a Slider also
|
||||
Setpoint item=z1_volume minValue=0 maxValue=100 step=1 visibility=[z1_power==ON]
|
||||
Switch item=z1_mute visibility=[z1_power==ON]
|
||||
// Min and Max values are for the 10761 amp, adjust if using a different model
|
||||
Setpoint item=z1_treble label="Treble Adjustment [%d]" minValue=-7 maxValue=7 step=1 visibility=[z1_power==ON]
|
||||
Setpoint item=z1_bass label="Bass Adjustment [%d]" minValue=-7 maxValue=7 step=1 visibility=[z1_power==ON]
|
||||
Setpoint item=z1_balance label="Balance Adjustment [%d]" minValue=-10 maxValue=10 step=1 visibility=[z1_power==ON]
|
||||
|
@ -145,6 +184,6 @@ sitemap monoprice label="Audio Control" {
|
|||
Text item=z1_keypad label="Keypad Connected: [%s]" visibility=[z1_power==ON]
|
||||
}
|
||||
|
||||
// repeat for zones 2-18 (substitute z1)
|
||||
// repeat for total number of zones used (substitute z1)
|
||||
}
|
||||
```
|
||||
|
|
|
@ -20,6 +20,7 @@ import org.openhab.core.thing.ThingTypeUID;
|
|||
* used across the whole binding.
|
||||
*
|
||||
* @author Michael Lobstein - Initial contribution
|
||||
* @author Michael Lobstein - Add support for additional amplifier types
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class MonopriceAudioBindingConstants {
|
||||
|
@ -27,7 +28,11 @@ public class MonopriceAudioBindingConstants {
|
|||
public static final String BINDING_ID = "monopriceaudio";
|
||||
|
||||
// List of all Thing Type UIDs
|
||||
public static final ThingTypeUID THING_TYPE_AMP = new ThingTypeUID(BINDING_ID, "amplifier");
|
||||
// to avoid breaking existing installations, the 10761/DAX66 will still be known as 'amplifier'
|
||||
public static final ThingTypeUID THING_TYPE_MP = new ThingTypeUID(BINDING_ID, "amplifier");
|
||||
public static final ThingTypeUID THING_TYPE_MP70 = new ThingTypeUID(BINDING_ID, "monoprice70");
|
||||
public static final ThingTypeUID THING_TYPE_DAX88 = new ThingTypeUID(BINDING_ID, "dax88");
|
||||
public static final ThingTypeUID THING_TYPE_XT = new ThingTypeUID(BINDING_ID, "xantech");
|
||||
|
||||
// List of all Channel types
|
||||
public static final String CHANNEL_TYPE_POWER = "power";
|
||||
|
@ -44,4 +49,10 @@ public class MonopriceAudioBindingConstants {
|
|||
public static final String CHANNEL_TYPE_ALLSOURCE = "allsource";
|
||||
public static final String CHANNEL_TYPE_ALLVOLUME = "allvolume";
|
||||
public static final String CHANNEL_TYPE_ALLMUTE = "allmute";
|
||||
|
||||
// misc
|
||||
public static final String ONE = "1";
|
||||
public static final String ZERO = "0";
|
||||
public static final String EMPTY = "";
|
||||
public static final int NIL = -1;
|
||||
}
|
||||
|
|
|
@ -14,11 +14,11 @@ package org.openhab.binding.monopriceaudio.internal;
|
|||
|
||||
import static org.openhab.binding.monopriceaudio.internal.MonopriceAudioBindingConstants.*;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.monopriceaudio.internal.communication.AmplifierModel;
|
||||
import org.openhab.binding.monopriceaudio.internal.handler.MonopriceAudioHandler;
|
||||
import org.openhab.core.io.transport.serial.SerialPortManager;
|
||||
import org.openhab.core.thing.Thing;
|
||||
|
@ -29,23 +29,29 @@ import org.openhab.core.thing.binding.ThingHandlerFactory;
|
|||
import org.osgi.service.component.annotations.Activate;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
import org.osgi.service.component.annotations.Reference;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link MonopriceAudioHandlerFactory} is responsible for creating things and thing
|
||||
* handlers.
|
||||
*
|
||||
* @author Michael Lobstein - Initial contribution
|
||||
* @author Michael Lobstein - Add support for additional amplifier types
|
||||
*/
|
||||
@NonNullByDefault
|
||||
@Component(configurationPid = "binding.monopriceaudio", service = ThingHandlerFactory.class)
|
||||
public class MonopriceAudioHandlerFactory extends BaseThingHandlerFactory {
|
||||
|
||||
private static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Collections.singleton(THING_TYPE_AMP);
|
||||
private static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Set.of(THING_TYPE_MP, THING_TYPE_MP70,
|
||||
THING_TYPE_DAX88, THING_TYPE_XT);
|
||||
|
||||
private final SerialPortManager serialPortManager;
|
||||
|
||||
private final MonopriceAudioStateDescriptionOptionProvider stateDescriptionProvider;
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(MonopriceAudioHandlerFactory.class);
|
||||
|
||||
@Activate
|
||||
public MonopriceAudioHandlerFactory(final @Reference MonopriceAudioStateDescriptionOptionProvider provider,
|
||||
final @Reference SerialPortManager serialPortManager) {
|
||||
|
@ -62,10 +68,26 @@ public class MonopriceAudioHandlerFactory extends BaseThingHandlerFactory {
|
|||
protected @Nullable ThingHandler createHandler(Thing thing) {
|
||||
ThingTypeUID thingTypeUID = thing.getThingTypeUID();
|
||||
|
||||
if (SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID)) {
|
||||
return new MonopriceAudioHandler(thing, stateDescriptionProvider, serialPortManager);
|
||||
if (THING_TYPE_MP.equals(thingTypeUID)) {
|
||||
return new MonopriceAudioHandler(thing, AmplifierModel.MONOPRICE, stateDescriptionProvider,
|
||||
serialPortManager);
|
||||
}
|
||||
|
||||
if (THING_TYPE_MP70.equals(thingTypeUID)) {
|
||||
return new MonopriceAudioHandler(thing, AmplifierModel.MONOPRICE70, stateDescriptionProvider,
|
||||
serialPortManager);
|
||||
}
|
||||
|
||||
if (THING_TYPE_DAX88.equals(thingTypeUID)) {
|
||||
return new MonopriceAudioHandler(thing, AmplifierModel.DAX88, stateDescriptionProvider, serialPortManager);
|
||||
}
|
||||
|
||||
if (THING_TYPE_XT.equals(thingTypeUID)) {
|
||||
return new MonopriceAudioHandler(thing, AmplifierModel.XANTECH, stateDescriptionProvider,
|
||||
serialPortManager);
|
||||
}
|
||||
|
||||
logger.warn("Unknown thing type: {}: {}", thingTypeUID.getId(), thingTypeUID.getBindingId());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,388 @@
|
|||
/**
|
||||
* Copyright (c) 2010-2023 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.monopriceaudio.internal.communication;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.monopriceaudio.internal.configuration.MonopriceAudioThingConfiguration;
|
||||
import org.openhab.binding.monopriceaudio.internal.dto.MonopriceAudioZoneDTO;
|
||||
import org.openhab.core.types.StateOption;
|
||||
|
||||
/**
|
||||
* The {@link AmplifierModel} is responsible for mapping low level communications for each supported amplifier model.
|
||||
*
|
||||
* @author Michael Lobstein - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public enum AmplifierModel {
|
||||
|
||||
// Monoprice 10761/Dayton Audio DAX66
|
||||
MONOPRICE("<", "\r", "?", "", "#>", "PR", "CH", "VO", "MU", "TR", "BS", "BL", "DT", 38, -7, 7, 7, -10, 10, 10, 18,
|
||||
6, true, List.of("11", "12", "13", "14", "15", "16", "21", "22", "23", "24", "25", "26", "31", "32", "33",
|
||||
"34", "35", "36")) {
|
||||
@Override
|
||||
public MonopriceAudioZoneDTO getZoneData(String newZoneData) {
|
||||
return getMonopriceZoneData(newZoneData);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<StateOption> getSourceLabels(MonopriceAudioThingConfiguration config) {
|
||||
return List.of(new StateOption("1", config.inputLabel1), new StateOption("2", config.inputLabel2),
|
||||
new StateOption("3", config.inputLabel3), new StateOption("4", config.inputLabel4),
|
||||
new StateOption("5", config.inputLabel5), new StateOption("6", config.inputLabel6));
|
||||
}
|
||||
},
|
||||
// Dayton Audio DAX88
|
||||
DAX88("<", "\r", "?", "", ">", "PR", "CH", "VO", "MU", "TR", "BS", "BL", "DT", 38, -12, 12, 12, -10, 10, 10, 8, 8,
|
||||
true, List.of("01", "02", "03", "04", "05", "06", "07", "08")) {
|
||||
@Override
|
||||
public MonopriceAudioZoneDTO getZoneData(String newZoneData) {
|
||||
return getMonopriceZoneData(newZoneData);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<StateOption> getSourceLabels(MonopriceAudioThingConfiguration config) {
|
||||
return List.of(new StateOption("1", config.inputLabel1), new StateOption("2", config.inputLabel2),
|
||||
new StateOption("3", config.inputLabel3), new StateOption("4", config.inputLabel4),
|
||||
new StateOption("5", config.inputLabel5), new StateOption("6", config.inputLabel6),
|
||||
new StateOption("7", config.inputLabel7), new StateOption("8", config.inputLabel8));
|
||||
}
|
||||
},
|
||||
MONOPRICE70("!", "+\r", "?", "ZS", "?", "PR", "IS", "VO", "MU", "TR", "BS", "BA", "", 38, -7, 7, 7, -32, 31, 32, 6,
|
||||
2, false, List.of("1", "2", "3", "4", "5", "6")) {
|
||||
@Override
|
||||
public MonopriceAudioZoneDTO getZoneData(String newZoneData) {
|
||||
MonopriceAudioZoneDTO zoneData = new MonopriceAudioZoneDTO();
|
||||
|
||||
Matcher matcher = MONOPRICE70_PATTERN.matcher(newZoneData);
|
||||
if (matcher.find()) {
|
||||
zoneData.setZone(matcher.group(1));
|
||||
zoneData.setVolume(Integer.parseInt(matcher.group(2)));
|
||||
zoneData.setPower(matcher.group(3));
|
||||
zoneData.setMute(matcher.group(4));
|
||||
zoneData.setSource(matcher.group(5));
|
||||
return zoneData;
|
||||
}
|
||||
|
||||
matcher = MONOPRICE70_TREB_PATTERN.matcher(newZoneData);
|
||||
if (matcher.find()) {
|
||||
zoneData.setZone(matcher.group(1));
|
||||
zoneData.setTreble(Integer.parseInt(matcher.group(2)));
|
||||
return zoneData;
|
||||
}
|
||||
|
||||
matcher = MONOPRICE70_BASS_PATTERN.matcher(newZoneData);
|
||||
if (matcher.find()) {
|
||||
zoneData.setZone(matcher.group(1));
|
||||
zoneData.setBass(Integer.parseInt(matcher.group(2)));
|
||||
return zoneData;
|
||||
}
|
||||
|
||||
matcher = MONOPRICE70_BALN_PATTERN.matcher(newZoneData);
|
||||
if (matcher.find()) {
|
||||
zoneData.setZone(matcher.group(1));
|
||||
zoneData.setBalance(Integer.parseInt(matcher.group(2)));
|
||||
return zoneData;
|
||||
}
|
||||
|
||||
return zoneData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<StateOption> getSourceLabels(MonopriceAudioThingConfiguration config) {
|
||||
return List.of(new StateOption("0", config.inputLabel1), new StateOption("1", config.inputLabel2));
|
||||
}
|
||||
},
|
||||
XANTECH("!", "+\r", "?", "ZD", "#", "PR", "SS", "VO", "MU", "TR", "BS", "BL", "", 38, -7, 7, 7, -32, 31, 32, 16, 8,
|
||||
false, List.of("1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16")) {
|
||||
@Override
|
||||
public MonopriceAudioZoneDTO getZoneData(String newZoneData) {
|
||||
MonopriceAudioZoneDTO zoneData = new MonopriceAudioZoneDTO();
|
||||
Matcher matcher = XANTECH_PATTERN.matcher(newZoneData);
|
||||
|
||||
if (matcher.find()) {
|
||||
zoneData.setZone(matcher.group(1));
|
||||
zoneData.setPower(matcher.group(2));
|
||||
zoneData.setSource(matcher.group(3));
|
||||
zoneData.setVolume(Integer.parseInt(matcher.group(4)));
|
||||
zoneData.setMute(matcher.group(5));
|
||||
zoneData.setTreble(Integer.parseInt(matcher.group(6)));
|
||||
zoneData.setBass(Integer.parseInt(matcher.group(7)));
|
||||
zoneData.setBalance(Integer.parseInt(matcher.group(8)));
|
||||
zoneData.setKeypad(matcher.group(9));
|
||||
zoneData.setPage(matcher.group(10));
|
||||
}
|
||||
return zoneData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<StateOption> getSourceLabels(MonopriceAudioThingConfiguration config) {
|
||||
return List.of(new StateOption("1", config.inputLabel1), new StateOption("2", config.inputLabel2),
|
||||
new StateOption("3", config.inputLabel3), new StateOption("4", config.inputLabel4),
|
||||
new StateOption("5", config.inputLabel5), new StateOption("6", config.inputLabel6),
|
||||
new StateOption("7", config.inputLabel7), new StateOption("8", config.inputLabel8));
|
||||
}
|
||||
};
|
||||
|
||||
// Used by 10761/DAX66 and DAX88
|
||||
private static MonopriceAudioZoneDTO getMonopriceZoneData(String newZoneData) {
|
||||
MonopriceAudioZoneDTO zoneData = new MonopriceAudioZoneDTO();
|
||||
Matcher matcher = MONOPRICE_PATTERN.matcher(newZoneData);
|
||||
|
||||
if (matcher.find()) {
|
||||
zoneData.setZone(matcher.group(1));
|
||||
zoneData.setPage(matcher.group(2));
|
||||
zoneData.setPower(matcher.group(3));
|
||||
zoneData.setMute(matcher.group(4));
|
||||
zoneData.setDnd(matcher.group(5));
|
||||
zoneData.setVolume(Integer.parseInt(matcher.group(6)));
|
||||
zoneData.setTreble(Integer.parseInt(matcher.group(7)));
|
||||
zoneData.setBass(Integer.parseInt(matcher.group(8)));
|
||||
zoneData.setBalance(Integer.parseInt(matcher.group(9)));
|
||||
zoneData.setSource(matcher.group(10));
|
||||
zoneData.setKeypad(matcher.group(11));
|
||||
}
|
||||
return zoneData;
|
||||
}
|
||||
|
||||
// Monoprice 10761/DAX66 status string: #>1200010000130809100601
|
||||
// DAX88 status string is the same but does not have leading '#': >xxaabbccddeeffgghhiijj
|
||||
private static final Pattern MONOPRICE_PATTERN = Pattern
|
||||
.compile("^#?>(\\d{2})(\\d{2})(\\d{2})(\\d{2})(\\d{2})(\\d{2})(\\d{2})(\\d{2})(\\d{2})(\\d{2})(\\d{2})");
|
||||
|
||||
// Monoprice 31028 / PAM1270 status string: ?6ZS VO8 PO1 MU0 IS0+ (does not include treble, bass & balance)
|
||||
private static final Pattern MONOPRICE70_PATTERN = Pattern
|
||||
.compile("^\\?(\\d{1})ZS VO(\\d{1,2}) PO(\\d{1}) MU(\\d{1}) IS(\\d{1})+");
|
||||
private static final Pattern MONOPRICE70_TREB_PATTERN = Pattern.compile("^\\?(\\d{1})TR(\\d{1,2})+");
|
||||
private static final Pattern MONOPRICE70_BASS_PATTERN = Pattern.compile("^\\?(\\d{1})BS(\\d{1,2})+");
|
||||
private static final Pattern MONOPRICE70_BALN_PATTERN = Pattern.compile("^\\?(\\d{1})BA(\\d{1,2})+");
|
||||
|
||||
// Xantech status string: #1ZS PR0 SS1 VO0 MU1 TR7 BS7 BA32 LS0 PS0+
|
||||
private static final Pattern XANTECH_PATTERN = Pattern.compile(
|
||||
"^#(\\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})+");
|
||||
|
||||
private String cmdPrefix;
|
||||
private String cmdSuffix;
|
||||
private String queryPrefix;
|
||||
private String querySuffix;
|
||||
private String respPrefix;
|
||||
private String powerCmd;
|
||||
private String sourceCmd;
|
||||
private String volumeCmd;
|
||||
private String muteCmd;
|
||||
private String trebleCmd;
|
||||
private String bassCmd;
|
||||
private String balanceCmd;
|
||||
private String dndCmd;
|
||||
private int maxVol;
|
||||
private int minTone;
|
||||
private int maxTone;
|
||||
private int toneOffset;
|
||||
private int minBal;
|
||||
private int maxBal;
|
||||
private int balOffset;
|
||||
private int maxZones;
|
||||
private int numSources;
|
||||
private boolean padNumbers;
|
||||
private List<String> zoneIds;
|
||||
private Map<String, String> zoneIdMap = new HashMap<>();
|
||||
|
||||
private static final String ON_STR = "1";
|
||||
private static final String OFF_STR = "0";
|
||||
|
||||
private static final String ON_STR_PAD = "01";
|
||||
private static final String OFF_STR_PAD = "00";
|
||||
|
||||
/**
|
||||
* Constructor for all the enum parameters
|
||||
*
|
||||
**/
|
||||
AmplifierModel(String cmdPrefix, String cmdSuffix, String queryPrefix, String querySuffix, String respPrefix,
|
||||
String powerCmd, String sourceCmd, String volumeCmd, String muteCmd, String trebleCmd, String bassCmd,
|
||||
String balanceCmd, String dndCmd, int maxVol, int minTone, int maxTone, int toneOffset, int minBal,
|
||||
int maxBal, int balOffset, int maxZones, int numSources, boolean padNumbers, List<String> zoneIds) {
|
||||
this.cmdPrefix = cmdPrefix;
|
||||
this.cmdSuffix = cmdSuffix;
|
||||
this.queryPrefix = queryPrefix;
|
||||
this.querySuffix = querySuffix;
|
||||
this.respPrefix = respPrefix;
|
||||
this.powerCmd = powerCmd;
|
||||
this.sourceCmd = sourceCmd;
|
||||
this.volumeCmd = volumeCmd;
|
||||
this.muteCmd = muteCmd;
|
||||
this.trebleCmd = trebleCmd;
|
||||
this.bassCmd = bassCmd;
|
||||
this.balanceCmd = balanceCmd;
|
||||
this.dndCmd = dndCmd;
|
||||
this.maxVol = maxVol;
|
||||
this.minTone = minTone;
|
||||
this.maxTone = maxTone;
|
||||
this.toneOffset = toneOffset;
|
||||
this.minBal = minBal;
|
||||
this.maxBal = maxBal;
|
||||
this.balOffset = balOffset;
|
||||
this.maxZones = maxZones;
|
||||
this.numSources = numSources;
|
||||
this.padNumbers = padNumbers;
|
||||
this.zoneIds = zoneIds;
|
||||
|
||||
int i = 1;
|
||||
for (String zoneId : zoneIds) {
|
||||
zoneIdMap.put(zoneId, "zone" + i);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
public abstract MonopriceAudioZoneDTO getZoneData(String newZoneData);
|
||||
|
||||
public abstract List<StateOption> getSourceLabels(MonopriceAudioThingConfiguration config);
|
||||
|
||||
public String getZoneIdFromZoneName(String zoneName) {
|
||||
for (String zoneId : zoneIdMap.keySet()) {
|
||||
if (zoneIdMap.get(zoneId).equals(zoneName)) {
|
||||
return zoneId;
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
public String getZoneName(String zoneId) {
|
||||
String zoneName = zoneIdMap.get(zoneId);
|
||||
if (zoneName != null) {
|
||||
return zoneName;
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
public String getCmdPrefix() {
|
||||
return cmdPrefix;
|
||||
}
|
||||
|
||||
public String getQueryPrefix() {
|
||||
return queryPrefix;
|
||||
}
|
||||
|
||||
public String getQuerySuffix() {
|
||||
return querySuffix;
|
||||
}
|
||||
|
||||
public String getRespPrefix() {
|
||||
return respPrefix;
|
||||
}
|
||||
|
||||
public String getPowerCmd() {
|
||||
return powerCmd;
|
||||
}
|
||||
|
||||
public String getSourceCmd() {
|
||||
return sourceCmd;
|
||||
}
|
||||
|
||||
public String getVolumeCmd() {
|
||||
return volumeCmd;
|
||||
}
|
||||
|
||||
public String getMuteCmd() {
|
||||
return muteCmd;
|
||||
}
|
||||
|
||||
public String getTrebleCmd() {
|
||||
return trebleCmd;
|
||||
}
|
||||
|
||||
public String getBassCmd() {
|
||||
return bassCmd;
|
||||
}
|
||||
|
||||
public String getBalanceCmd() {
|
||||
return balanceCmd;
|
||||
}
|
||||
|
||||
public String getDndCmd() {
|
||||
return dndCmd;
|
||||
}
|
||||
|
||||
public int getMaxVol() {
|
||||
return maxVol;
|
||||
}
|
||||
|
||||
public int getMinTone() {
|
||||
return minTone;
|
||||
}
|
||||
|
||||
public int getMaxTone() {
|
||||
return maxTone;
|
||||
}
|
||||
|
||||
public int getMinBal() {
|
||||
return minBal;
|
||||
}
|
||||
|
||||
public int getMaxBal() {
|
||||
return maxBal;
|
||||
}
|
||||
|
||||
public int getBalOffset() {
|
||||
return balOffset;
|
||||
}
|
||||
|
||||
public int getToneOffset() {
|
||||
return toneOffset;
|
||||
}
|
||||
|
||||
public int getMaxZones() {
|
||||
return maxZones;
|
||||
}
|
||||
|
||||
public int getNumSources() {
|
||||
return numSources;
|
||||
}
|
||||
|
||||
public String getCmdSuffix() {
|
||||
return cmdSuffix;
|
||||
}
|
||||
|
||||
public List<String> getZoneIds() {
|
||||
return zoneIds;
|
||||
}
|
||||
|
||||
public String getFormattedValue(Integer value) {
|
||||
if (padNumbers) {
|
||||
return String.format("%02d", value);
|
||||
} else {
|
||||
return value.toString();
|
||||
}
|
||||
}
|
||||
|
||||
public String getOnStr() {
|
||||
if (padNumbers) {
|
||||
return ON_STR_PAD;
|
||||
} else {
|
||||
return ON_STR;
|
||||
}
|
||||
}
|
||||
|
||||
public String getOffStr() {
|
||||
if (padNumbers) {
|
||||
return OFF_STR_PAD;
|
||||
} else {
|
||||
return OFF_STR;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,48 +0,0 @@
|
|||
/**
|
||||
* Copyright (c) 2010-2023 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.monopriceaudio.internal.communication;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* Represents the different kinds of commands
|
||||
*
|
||||
* @author Michael Lobstein - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public enum MonopriceAudioCommand {
|
||||
QUERY("?"),
|
||||
POWER("PR"),
|
||||
SOURCE("CH"),
|
||||
VOLUME("VO"),
|
||||
MUTE("MU"),
|
||||
TREBLE("TR"),
|
||||
BASS("BS"),
|
||||
BALANCE("BL"),
|
||||
DND("DT");
|
||||
|
||||
private final String value;
|
||||
|
||||
MonopriceAudioCommand(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the command name
|
||||
*
|
||||
* @return the command name
|
||||
*/
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
}
|
|
@ -12,14 +12,14 @@
|
|||
*/
|
||||
package org.openhab.binding.monopriceaudio.internal.communication;
|
||||
|
||||
import static org.openhab.binding.monopriceaudio.internal.MonopriceAudioBindingConstants.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
@ -32,20 +32,13 @@ import org.slf4j.LoggerFactory;
|
|||
*
|
||||
* @author Laurent Garnier - Initial contribution
|
||||
* @author Michael Lobstein - Adapted for the MonopriceAudio binding
|
||||
* @author Michael Lobstein - Add support for additional amplifier types
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public abstract class MonopriceAudioConnector {
|
||||
public static final String READ_ERROR = "Command Error.";
|
||||
|
||||
// Message types
|
||||
public static final String KEY_ZONE_UPDATE = "zone_update";
|
||||
// Special keys used by the binding
|
||||
public static final String KEY_ERROR = "error";
|
||||
public static final String MSG_VALUE_ON = "on";
|
||||
|
||||
private static final Pattern PATTERN = Pattern.compile("^.*#>(\\d{22})$", Pattern.DOTALL);
|
||||
private static final String BEGIN_CMD = "<";
|
||||
private static final String END_CMD = "\r";
|
||||
public static final String KEY_PING = "ping";
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(MonopriceAudioConnector.class);
|
||||
|
||||
|
@ -57,6 +50,9 @@ public abstract class MonopriceAudioConnector {
|
|||
|
||||
/** true if the connection is established, false if not */
|
||||
private boolean connected;
|
||||
private boolean pingResponseOnly;
|
||||
|
||||
private @Nullable AmplifierModel amp;
|
||||
|
||||
private @Nullable Thread readerThread;
|
||||
|
||||
|
@ -78,6 +74,16 @@ public abstract class MonopriceAudioConnector {
|
|||
*/
|
||||
protected void setConnected(boolean connected) {
|
||||
this.connected = connected;
|
||||
this.pingResponseOnly = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the AmplifierModel
|
||||
*
|
||||
* @param amp the AmplifierModel being used
|
||||
*/
|
||||
protected void setAmplifierModel(AmplifierModel amp) {
|
||||
this.amp = amp;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -105,6 +111,7 @@ public abstract class MonopriceAudioConnector {
|
|||
* Stop the thread that handles the feedback messages and close the opened input and output streams
|
||||
*/
|
||||
protected void cleanup() {
|
||||
this.pingResponseOnly = false;
|
||||
Thread readerThread = this.readerThread;
|
||||
OutputStream dataOut = this.dataOut;
|
||||
if (dataOut != null) {
|
||||
|
@ -129,7 +136,7 @@ public abstract class MonopriceAudioConnector {
|
|||
try {
|
||||
readerThread.join(3000);
|
||||
} catch (InterruptedException e) {
|
||||
logger.warn("Error joining readerThread: {}", e.getMessage());
|
||||
logger.debug("Error joining readerThread: {}", e.getMessage());
|
||||
}
|
||||
this.readerThread = null;
|
||||
}
|
||||
|
@ -160,6 +167,19 @@ public abstract class MonopriceAudioConnector {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get only ping success events from the connector. If amplifier does not have keypads or supports
|
||||
* unsolicited updates, the use of this method will cause the connector to only send ping success events until the
|
||||
* next time the connection is reset.
|
||||
*
|
||||
* @throws MonopriceAudioException - In case of any problem
|
||||
*/
|
||||
public void sendPing() throws MonopriceAudioException {
|
||||
pingResponseOnly = true;
|
||||
// poll zone 1 status only to see if the amp responds
|
||||
queryZone(amp.getZoneIds().get(0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the status of a zone
|
||||
*
|
||||
|
@ -167,33 +187,55 @@ public abstract class MonopriceAudioConnector {
|
|||
*
|
||||
* @throws MonopriceAudioException - In case of any problem
|
||||
*/
|
||||
public void queryZone(MonopriceAudioZone zone) throws MonopriceAudioException {
|
||||
sendCommand(zone, MonopriceAudioCommand.QUERY, null);
|
||||
public void queryZone(String zoneId) throws MonopriceAudioException {
|
||||
sendCommand(amp.getQueryPrefix() + zoneId + amp.getQuerySuffix());
|
||||
}
|
||||
|
||||
/**
|
||||
* Request the MonopriceAudio controller to execute a command
|
||||
* Monoprice 31028 and OSD Audio PAM1270 amps do not report treble, bass and balance with the main status inquiry,
|
||||
* so we must send three extra commands to retrieve those values
|
||||
*
|
||||
* @param zone the zone for which the command is to be run
|
||||
* @param cmd the command to execute
|
||||
* @param value the integer value to consider for volume, bass, treble, etc. adjustment
|
||||
* @param zone the zone to query for current treble, bass and balance status
|
||||
*
|
||||
* @throws MonopriceAudioException - In case of any problem
|
||||
*/
|
||||
public void sendCommand(MonopriceAudioZone zone, MonopriceAudioCommand cmd, @Nullable Integer value)
|
||||
throws MonopriceAudioException {
|
||||
String messageStr = "";
|
||||
|
||||
if (cmd == MonopriceAudioCommand.QUERY) {
|
||||
// query special case (ie: ? + zoneId)
|
||||
messageStr = cmd.getValue() + zone.getZoneId();
|
||||
} else if (value != null) {
|
||||
// if the command passed a value, append it to the messageStr
|
||||
messageStr = BEGIN_CMD + zone.getZoneId() + cmd.getValue() + String.format("%02d", value);
|
||||
} else {
|
||||
throw new MonopriceAudioException("Send command \"" + messageStr + "\" failed: passed in value is null");
|
||||
public void queryTrebBassBalance(String zoneId) throws MonopriceAudioException {
|
||||
sendCommand(amp.getQueryPrefix() + zoneId + amp.getTrebleCmd());
|
||||
sendCommand(amp.getQueryPrefix() + zoneId + amp.getBassCmd());
|
||||
sendCommand(amp.getQueryPrefix() + zoneId + amp.getBalanceCmd());
|
||||
}
|
||||
|
||||
/**
|
||||
* Request the MonopriceAudio amplifier to execute a raw command
|
||||
*
|
||||
* @param cmd the command to execute
|
||||
*
|
||||
* @throws MonopriceAudioException - In case of any problem
|
||||
*/
|
||||
public void sendCommand(String cmd) throws MonopriceAudioException {
|
||||
sendCommand(null, cmd, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Request the MonopriceAudio amplifier to execute a command
|
||||
*
|
||||
* @param zoneId the zone for which the command is to be run
|
||||
* @param cmd the command to execute
|
||||
* @param value the integer value to consider for power, volume, bass, treble, etc. adjustment
|
||||
*
|
||||
* @throws MonopriceAudioException - In case of any problem
|
||||
*/
|
||||
public void sendCommand(@Nullable String zoneId, String cmd, @Nullable Integer value)
|
||||
throws MonopriceAudioException {
|
||||
String messageStr;
|
||||
|
||||
if (zoneId != null && value != null) {
|
||||
// if the command passed a value, build messageStr with prefix, zoneId, command, value and suffix
|
||||
messageStr = amp.getCmdPrefix() + zoneId + cmd + amp.getFormattedValue(value) + amp.getCmdSuffix();
|
||||
} else {
|
||||
// otherwise send the raw cmd from the query() methods
|
||||
messageStr = cmd + amp.getCmdSuffix();
|
||||
}
|
||||
messageStr += END_CMD;
|
||||
logger.debug("Send command {}", messageStr);
|
||||
|
||||
OutputStream dataOut = this.dataOut;
|
||||
|
@ -204,7 +246,7 @@ public abstract class MonopriceAudioConnector {
|
|||
dataOut.write(messageStr.getBytes(StandardCharsets.US_ASCII));
|
||||
dataOut.flush();
|
||||
} catch (IOException e) {
|
||||
throw new MonopriceAudioException("Send command \"" + cmd.getValue() + "\" failed: " + e.getMessage(), e);
|
||||
throw new MonopriceAudioException("Send command \"" + messageStr + "\" failed: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -232,20 +274,20 @@ public abstract class MonopriceAudioConnector {
|
|||
* @param incomingMessage the received message
|
||||
*/
|
||||
public void handleIncomingMessage(byte[] incomingMessage) {
|
||||
String message = new String(incomingMessage, StandardCharsets.US_ASCII).trim();
|
||||
|
||||
logger.debug("handleIncomingMessage: {}", message);
|
||||
|
||||
if (READ_ERROR.equals(message)) {
|
||||
dispatchKeyValue(KEY_ERROR, MSG_VALUE_ON);
|
||||
if (pingResponseOnly) {
|
||||
dispatchKeyValue(KEY_PING, EMPTY);
|
||||
return;
|
||||
}
|
||||
|
||||
// Amp controller sends status string: #>1200010000130809100601
|
||||
Matcher matcher = PATTERN.matcher(message);
|
||||
if (matcher.find()) {
|
||||
// pull out just the digits and send them as an event
|
||||
dispatchKeyValue(KEY_ZONE_UPDATE, matcher.group(1));
|
||||
String message = new String(incomingMessage, StandardCharsets.US_ASCII).trim();
|
||||
|
||||
if (EMPTY.equals(message)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (message.startsWith(amp.getRespPrefix())) {
|
||||
logger.debug("handleIncomingMessage: {}", message);
|
||||
dispatchKeyValue(KEY_ZONE_UPDATE, message);
|
||||
} else {
|
||||
logger.debug("no match on message: {}", message);
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@ public class MonopriceAudioDefaultConnector extends MonopriceAudioConnector {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void sendCommand(MonopriceAudioZone zone, MonopriceAudioCommand cmd, @Nullable Integer value) {
|
||||
public void sendCommand(@Nullable String zone, String cmd, @Nullable Integer value) {
|
||||
logger.warn(
|
||||
"MonopriceAudio binding incorrectly configured. Please configure for Serial or IP over serial connection");
|
||||
setConnected(false);
|
||||
|
|
|
@ -48,11 +48,13 @@ public class MonopriceAudioIpConnector extends MonopriceAudioConnector {
|
|||
* @param address the IP address of the serial over IP device
|
||||
* @param port the TCP port to be used
|
||||
* @param uid the thing uid string
|
||||
* @param amp the AmplifierModel being used
|
||||
*/
|
||||
public MonopriceAudioIpConnector(@Nullable String address, int port, String uid) {
|
||||
public MonopriceAudioIpConnector(@Nullable String address, int port, String uid, AmplifierModel amp) {
|
||||
this.address = address;
|
||||
this.port = port;
|
||||
this.uid = uid;
|
||||
setAmplifierModel(amp);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -78,7 +78,6 @@ public class MonopriceAudioReaderThread extends Thread {
|
|||
}
|
||||
} catch (MonopriceAudioException e) {
|
||||
logger.debug("Reading failed: {}", e.getMessage(), e);
|
||||
connector.handleIncomingMessage(MonopriceAudioConnector.READ_ERROR.getBytes());
|
||||
}
|
||||
|
||||
logger.debug("Data listener stopped");
|
||||
|
|
|
@ -51,11 +51,14 @@ public class MonopriceAudioSerialConnector extends MonopriceAudioConnector {
|
|||
* @param serialPortManager the serial port manager
|
||||
* @param serialPortName the serial port name to be used
|
||||
* @param uid the thing uid string
|
||||
* @param amp the AmplifierModel being used
|
||||
*/
|
||||
public MonopriceAudioSerialConnector(SerialPortManager serialPortManager, String serialPortName, String uid) {
|
||||
public MonopriceAudioSerialConnector(SerialPortManager serialPortManager, String serialPortName, String uid,
|
||||
AmplifierModel amp) {
|
||||
this.serialPortManager = serialPortManager;
|
||||
this.serialPortName = serialPortName;
|
||||
this.uid = uid;
|
||||
setAmplifierModel(amp);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,77 +0,0 @@
|
|||
/**
|
||||
* Copyright (c) 2010-2023 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.monopriceaudio.internal.communication;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.monopriceaudio.internal.MonopriceAudioException;
|
||||
|
||||
/**
|
||||
* Represents the different internal zone IDs of the Monoprice Whole House Amplifier
|
||||
*
|
||||
* @author Michael Lobstein - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public enum MonopriceAudioZone {
|
||||
|
||||
ALL("all"),
|
||||
ZONE1("11"),
|
||||
ZONE2("12"),
|
||||
ZONE3("13"),
|
||||
ZONE4("14"),
|
||||
ZONE5("15"),
|
||||
ZONE6("16"),
|
||||
ZONE7("21"),
|
||||
ZONE8("22"),
|
||||
ZONE9("23"),
|
||||
ZONE10("24"),
|
||||
ZONE11("25"),
|
||||
ZONE12("26"),
|
||||
ZONE13("31"),
|
||||
ZONE14("32"),
|
||||
ZONE15("33"),
|
||||
ZONE16("34"),
|
||||
ZONE17("35"),
|
||||
ZONE18("36");
|
||||
|
||||
private final String zoneId;
|
||||
|
||||
// make a list of all valid zone names
|
||||
public static final List<String> VALID_ZONES = Arrays.stream(values()).filter(z -> z != ALL)
|
||||
.map(MonopriceAudioZone::name).collect(Collectors.toList());
|
||||
|
||||
// make a list of all valid zone ids
|
||||
public static final List<String> VALID_ZONE_IDS = Arrays.stream(values()).filter(z -> z != ALL)
|
||||
.map(MonopriceAudioZone::getZoneId).collect(Collectors.toList());
|
||||
|
||||
public static MonopriceAudioZone fromZoneId(String zoneId) throws MonopriceAudioException {
|
||||
return Arrays.stream(values()).filter(z -> z.zoneId.equalsIgnoreCase(zoneId)).findFirst()
|
||||
.orElseThrow(() -> new MonopriceAudioException("Invalid zoneId specified: " + zoneId));
|
||||
}
|
||||
|
||||
MonopriceAudioZone(String zoneId) {
|
||||
this.zoneId = zoneId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the zone id
|
||||
*
|
||||
* @return the zone id
|
||||
*/
|
||||
public String getZoneId() {
|
||||
return zoneId;
|
||||
}
|
||||
}
|
|
@ -35,4 +35,7 @@ public class MonopriceAudioThingConfiguration {
|
|||
public @Nullable String inputLabel4;
|
||||
public @Nullable String inputLabel5;
|
||||
public @Nullable String inputLabel6;
|
||||
public @Nullable String inputLabel7;
|
||||
public @Nullable String inputLabel8;
|
||||
public boolean disableKeypadPolling = false;
|
||||
}
|
||||
|
|
|
@ -12,29 +12,42 @@
|
|||
*/
|
||||
package org.openhab.binding.monopriceaudio.internal.dto;
|
||||
|
||||
import static org.openhab.binding.monopriceaudio.internal.MonopriceAudioBindingConstants.*;
|
||||
|
||||
/**
|
||||
* Represents the data elements of a single zone of the Monoprice Whole House Amplifier
|
||||
* Represents the data elements of a single zone of a supported amplifier
|
||||
*
|
||||
* @author Michael Lobstein - Initial contribution
|
||||
*/
|
||||
public class MonopriceAudioZoneDTO {
|
||||
|
||||
private String zone;
|
||||
private String page;
|
||||
private String power;
|
||||
private String mute;
|
||||
private String dnd;
|
||||
private int volume;
|
||||
private int treble;
|
||||
private int bass;
|
||||
private int balance;
|
||||
private String source;
|
||||
private String keypad;
|
||||
private String zone = EMPTY;
|
||||
private String page = EMPTY;
|
||||
private String power = EMPTY;
|
||||
private String mute = EMPTY;
|
||||
private String dnd = EMPTY;
|
||||
private int volume = NIL;
|
||||
private int treble = NIL;
|
||||
private int bass = NIL;
|
||||
private int balance = NIL;
|
||||
private String source = EMPTY;
|
||||
private String keypad = EMPTY;
|
||||
|
||||
public MonopriceAudioZoneDTO() {
|
||||
}
|
||||
|
||||
public MonopriceAudioZoneDTO(String zone) {
|
||||
this.zone = zone;
|
||||
}
|
||||
|
||||
public void setZone(String zone) {
|
||||
this.zone = zone;
|
||||
}
|
||||
|
||||
public String getZone() {
|
||||
return this.zone;
|
||||
}
|
||||
|
||||
public void setPage(String page) {
|
||||
this.page = page;
|
||||
}
|
||||
|
@ -44,7 +57,7 @@ public class MonopriceAudioZoneDTO {
|
|||
}
|
||||
|
||||
public boolean isPageActive() {
|
||||
return ("01").equals(this.page);
|
||||
return this.page.contains(ONE);
|
||||
}
|
||||
|
||||
public void setPower(String power) {
|
||||
|
@ -56,7 +69,7 @@ public class MonopriceAudioZoneDTO {
|
|||
}
|
||||
|
||||
public boolean isPowerOn() {
|
||||
return ("01").equals(this.power);
|
||||
return this.power.contains(ONE);
|
||||
}
|
||||
|
||||
public void setMute(String mute) {
|
||||
|
@ -68,7 +81,7 @@ public class MonopriceAudioZoneDTO {
|
|||
}
|
||||
|
||||
public boolean isMuted() {
|
||||
return ("01").equals(this.mute);
|
||||
return this.mute.contains(ONE);
|
||||
}
|
||||
|
||||
public void setDnd(String dnd) {
|
||||
|
@ -80,7 +93,7 @@ public class MonopriceAudioZoneDTO {
|
|||
}
|
||||
|
||||
public boolean isDndOn() {
|
||||
return ("01").equals(this.dnd);
|
||||
return this.dnd.contains(ONE);
|
||||
}
|
||||
|
||||
public int getVolume() {
|
||||
|
@ -132,14 +145,12 @@ public class MonopriceAudioZoneDTO {
|
|||
}
|
||||
|
||||
public boolean isKeypadActive() {
|
||||
return ("01").equals(this.keypad);
|
||||
return this.keypad.contains(ONE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
// Re-construct the original status message from the controller
|
||||
// This is used to determine if something changed from the last polling update
|
||||
return zone + page + power + mute + dnd + (String.format("%02d", volume)) + (String.format("%02d", treble))
|
||||
+ (String.format("%02d", bass)) + (String.format("%02d", balance)) + source + keypad;
|
||||
return zone + page + power + mute + dnd + volume + treble + bass + balance + source + keypad;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,8 +22,6 @@ import java.util.Map;
|
|||
import java.util.Set;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
import java.util.stream.Stream;
|
||||
|
@ -32,14 +30,13 @@ import org.eclipse.jdt.annotation.NonNullByDefault;
|
|||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.monopriceaudio.internal.MonopriceAudioException;
|
||||
import org.openhab.binding.monopriceaudio.internal.MonopriceAudioStateDescriptionOptionProvider;
|
||||
import org.openhab.binding.monopriceaudio.internal.communication.MonopriceAudioCommand;
|
||||
import org.openhab.binding.monopriceaudio.internal.communication.AmplifierModel;
|
||||
import org.openhab.binding.monopriceaudio.internal.communication.MonopriceAudioConnector;
|
||||
import org.openhab.binding.monopriceaudio.internal.communication.MonopriceAudioDefaultConnector;
|
||||
import org.openhab.binding.monopriceaudio.internal.communication.MonopriceAudioIpConnector;
|
||||
import org.openhab.binding.monopriceaudio.internal.communication.MonopriceAudioMessageEvent;
|
||||
import org.openhab.binding.monopriceaudio.internal.communication.MonopriceAudioMessageEventListener;
|
||||
import org.openhab.binding.monopriceaudio.internal.communication.MonopriceAudioSerialConnector;
|
||||
import org.openhab.binding.monopriceaudio.internal.communication.MonopriceAudioZone;
|
||||
import org.openhab.binding.monopriceaudio.internal.configuration.MonopriceAudioThingConfiguration;
|
||||
import org.openhab.binding.monopriceaudio.internal.dto.MonopriceAudioZoneDTO;
|
||||
import org.openhab.core.io.transport.serial.SerialPortManager;
|
||||
|
@ -67,37 +64,23 @@ import org.slf4j.LoggerFactory;
|
|||
* Based on the Rotel binding by Laurent Garnier
|
||||
*
|
||||
* @author Michael Lobstein - Initial contribution
|
||||
* @author Michael Lobstein - Add support for additional amplifier types
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class MonopriceAudioHandler extends BaseThingHandler implements MonopriceAudioMessageEventListener {
|
||||
private static final long RECON_POLLING_INTERVAL_SEC = 60;
|
||||
private static final long INITIAL_POLLING_DELAY_SEC = 5;
|
||||
private static final Pattern PATTERN = Pattern
|
||||
.compile("^(\\d{2})(\\d{2})(\\d{2})(\\d{2})(\\d{2})(\\d{2})(\\d{2})(\\d{2})(\\d{2})(\\d{2})(\\d{2})");
|
||||
private static final long INITIAL_POLLING_DELAY_SEC = 10;
|
||||
|
||||
private static final String ZONE = "ZONE";
|
||||
private static final String ZONE = "zone";
|
||||
private static final String ALL = "all";
|
||||
private static final String CHANNEL_DELIMIT = "#";
|
||||
private static final String ON_STR = "01";
|
||||
private static final String OFF_STR = "00";
|
||||
|
||||
private static final int ZERO = 0;
|
||||
private static final int ONE = 1;
|
||||
private static final int MAX_ZONES = 18;
|
||||
private static final int MAX_SRC = 6;
|
||||
private static final int MIN_VOLUME = 0;
|
||||
private static final int MAX_VOLUME = 38;
|
||||
private static final int MIN_TONE = -7;
|
||||
private static final int MAX_TONE = 7;
|
||||
private static final int MIN_BALANCE = -10;
|
||||
private static final int MAX_BALANCE = 10;
|
||||
private static final int BALANCE_OFFSET = 10;
|
||||
private static final int TONE_OFFSET = 7;
|
||||
|
||||
// build a Map with a MonopriceAudioZoneDTO for each zoneId
|
||||
private final Map<String, MonopriceAudioZoneDTO> zoneDataMap = MonopriceAudioZone.VALID_ZONE_IDS.stream()
|
||||
.collect(Collectors.toMap(s -> s, s -> new MonopriceAudioZoneDTO()));
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(MonopriceAudioHandler.class);
|
||||
private final AmplifierModel amp;
|
||||
private final MonopriceAudioStateDescriptionOptionProvider stateDescriptionProvider;
|
||||
private final SerialPortManager serialPortManager;
|
||||
|
||||
|
@ -106,17 +89,21 @@ public class MonopriceAudioHandler extends BaseThingHandler implements Monoprice
|
|||
|
||||
private MonopriceAudioConnector connector = new MonopriceAudioDefaultConnector();
|
||||
|
||||
private Map<String, MonopriceAudioZoneDTO> zoneDataMap = Map.of(ZONE, new MonopriceAudioZoneDTO());
|
||||
private Set<String> ignoreZones = new HashSet<>();
|
||||
private long lastPollingUpdate = System.currentTimeMillis();
|
||||
private long pollingInterval = 0;
|
||||
private int numZones = 0;
|
||||
private int allVolume = 1;
|
||||
private int initialAllVolume = 0;
|
||||
private long pollingInterval = ZERO;
|
||||
private int numZones = ZERO;
|
||||
private int allVolume = ONE;
|
||||
private int initialAllVolume = ZERO;
|
||||
private boolean disableKeypadPolling = false;
|
||||
private Object sequenceLock = new Object();
|
||||
|
||||
public MonopriceAudioHandler(Thing thing, MonopriceAudioStateDescriptionOptionProvider stateDescriptionProvider,
|
||||
public MonopriceAudioHandler(Thing thing, AmplifierModel amp,
|
||||
MonopriceAudioStateDescriptionOptionProvider stateDescriptionProvider,
|
||||
SerialPortManager serialPortManager) {
|
||||
super(thing);
|
||||
this.amp = amp;
|
||||
this.stateDescriptionProvider = stateDescriptionProvider;
|
||||
this.serialPortManager = serialPortManager;
|
||||
}
|
||||
|
@ -128,89 +115,79 @@ public class MonopriceAudioHandler extends BaseThingHandler implements Monoprice
|
|||
final String serialPort = config.serialPort;
|
||||
final String host = config.host;
|
||||
final Integer port = config.port;
|
||||
numZones = config.numZones;
|
||||
final String ignoreZonesConfig = config.ignoreZones;
|
||||
disableKeypadPolling = config.disableKeypadPolling || amp == AmplifierModel.MONOPRICE70;
|
||||
|
||||
// build a Map with a MonopriceAudioZoneDTO for each zoneId
|
||||
zoneDataMap = amp.getZoneIds().stream().limit(numZones)
|
||||
.collect(Collectors.toMap(s -> s, s -> new MonopriceAudioZoneDTO(s)));
|
||||
|
||||
// Check configuration settings
|
||||
String configError = null;
|
||||
if ((serialPort == null || serialPort.isEmpty()) && (host == null || host.isEmpty())) {
|
||||
configError = "undefined serialPort and host configuration settings; please set one of them";
|
||||
} else if (serialPort != null && (host == null || host.isEmpty())) {
|
||||
if (serialPort != null && host == null && port == null) {
|
||||
if (serialPort.toLowerCase().startsWith("rfc2217")) {
|
||||
configError = "use host and port configuration settings for a serial over IP connection";
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
|
||||
"@text/offline.configuration-error-rfc2217");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (port == null) {
|
||||
configError = "undefined port configuration setting";
|
||||
} else if (port <= 0) {
|
||||
configError = "invalid port configuration setting";
|
||||
}
|
||||
}
|
||||
|
||||
if (configError != null) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, configError);
|
||||
} else if (serialPort != null && (host != null || port != null)) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
|
||||
"@text/offline.configuration-error-conflict");
|
||||
return;
|
||||
}
|
||||
|
||||
if (serialPort != null) {
|
||||
connector = new MonopriceAudioSerialConnector(serialPortManager, serialPort, uid);
|
||||
} else if (port != null) {
|
||||
connector = new MonopriceAudioIpConnector(host, port, uid);
|
||||
connector = new MonopriceAudioSerialConnector(serialPortManager, serialPort, uid, amp);
|
||||
} else if (host != null && (port != null && port > ZERO)) {
|
||||
connector = new MonopriceAudioIpConnector(host, port, uid, amp);
|
||||
} else {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
|
||||
"Either Serial port or Host & Port must be specifed");
|
||||
"@text/offline.configuration-error-missing");
|
||||
return;
|
||||
}
|
||||
|
||||
pollingInterval = config.pollingInterval;
|
||||
numZones = config.numZones;
|
||||
initialAllVolume = config.initialAllVolume;
|
||||
|
||||
// If zones were specified to be ignored by the 'all*' commands, use the specified binding
|
||||
// zone ids to get the controller's internal zone ids and save those to a list
|
||||
// zone ids to get the amplifier's internal zone ids and save those to a list
|
||||
if (ignoreZonesConfig != null) {
|
||||
for (String zone : ignoreZonesConfig.split(",")) {
|
||||
try {
|
||||
int zoneInt = Integer.parseInt(zone);
|
||||
if (zoneInt >= ONE && zoneInt <= MAX_ZONES) {
|
||||
if (zoneInt >= ONE && zoneInt <= amp.getMaxZones()) {
|
||||
ignoreZones.add(ZONE + zoneInt);
|
||||
} else {
|
||||
logger.warn("Invalid ignore zone value: {}, value must be between {} and {}", zone, ONE,
|
||||
MAX_ZONES);
|
||||
logger.debug("Invalid ignore zone value: {}, value must be between {} and {}", zone, ONE,
|
||||
amp.getMaxZones());
|
||||
}
|
||||
} catch (NumberFormatException nfe) {
|
||||
logger.warn("Invalid ignore zone value: {}", zone);
|
||||
logger.debug("Invalid ignore zone value: {}", zone);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Build a state option list for the source labels
|
||||
List<StateOption> sourcesLabels = new ArrayList<>();
|
||||
sourcesLabels.add(new StateOption("1", config.inputLabel1));
|
||||
sourcesLabels.add(new StateOption("2", config.inputLabel2));
|
||||
sourcesLabels.add(new StateOption("3", config.inputLabel3));
|
||||
sourcesLabels.add(new StateOption("4", config.inputLabel4));
|
||||
sourcesLabels.add(new StateOption("5", config.inputLabel5));
|
||||
sourcesLabels.add(new StateOption("6", config.inputLabel6));
|
||||
|
||||
// Put the source labels on all active zones
|
||||
List<Integer> activeZones = IntStream.range(1, numZones + 1).boxed().collect(Collectors.toList());
|
||||
|
||||
List<StateOption> sourceLabels = amp.getSourceLabels(config);
|
||||
stateDescriptionProvider.setStateOptions(
|
||||
new ChannelUID(getThing().getUID(), ALL + CHANNEL_DELIMIT + CHANNEL_TYPE_ALLSOURCE), sourcesLabels);
|
||||
new ChannelUID(getThing().getUID(), ALL + CHANNEL_DELIMIT + CHANNEL_TYPE_ALLSOURCE), sourceLabels);
|
||||
activeZones.forEach(zoneNum -> {
|
||||
stateDescriptionProvider.setStateOptions(new ChannelUID(getThing().getUID(),
|
||||
ZONE.toLowerCase() + zoneNum + CHANNEL_DELIMIT + CHANNEL_TYPE_SOURCE), sourcesLabels);
|
||||
stateDescriptionProvider.setStateOptions(
|
||||
new ChannelUID(getThing().getUID(), ZONE + zoneNum + CHANNEL_DELIMIT + CHANNEL_TYPE_SOURCE),
|
||||
sourceLabels);
|
||||
});
|
||||
|
||||
// remove the channels for the zones we are not using
|
||||
if (numZones < MAX_ZONES) {
|
||||
if (numZones < amp.getMaxZones()) {
|
||||
List<Channel> channels = new ArrayList<>(this.getThing().getChannels());
|
||||
|
||||
List<Integer> zonesToRemove = IntStream.range(numZones + 1, MAX_ZONES + 1).boxed()
|
||||
List<Integer> zonesToRemove = IntStream.range(numZones + 1, amp.getMaxZones() + 1).boxed()
|
||||
.collect(Collectors.toList());
|
||||
|
||||
zonesToRemove.forEach(zone -> {
|
||||
channels.removeIf(c -> (c.getUID().getId().contains(ZONE.toLowerCase() + zone)));
|
||||
channels.removeIf(c -> (c.getUID().getId().contains(ZONE + zone)));
|
||||
});
|
||||
updateThing(editThing().withChannels(channels).build());
|
||||
}
|
||||
|
@ -218,7 +195,7 @@ public class MonopriceAudioHandler extends BaseThingHandler implements Monoprice
|
|||
// initialize the all volume state
|
||||
allVolume = initialAllVolume;
|
||||
long allVolumePct = Math
|
||||
.round((double) (initialAllVolume - MIN_VOLUME) / (double) (MAX_VOLUME - MIN_VOLUME) * 100.0);
|
||||
.round((initialAllVolume - MIN_VOLUME) / (double) (amp.getMaxVol() - MIN_VOLUME) * 100.0);
|
||||
updateState(ALL + CHANNEL_DELIMIT + CHANNEL_TYPE_ALLVOLUME, new PercentType(BigDecimal.valueOf(allVolumePct)));
|
||||
|
||||
scheduleReconnectJob();
|
||||
|
@ -239,8 +216,9 @@ public class MonopriceAudioHandler extends BaseThingHandler implements Monoprice
|
|||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
String channel = channelUID.getId();
|
||||
String[] channelSplit = channel.split(CHANNEL_DELIMIT);
|
||||
MonopriceAudioZone zone = MonopriceAudioZone.valueOf(channelSplit[0].toUpperCase());
|
||||
String channelType = channelSplit[1];
|
||||
String zoneName = channelSplit[0];
|
||||
String zoneId = amp.getZoneIdFromZoneName(zoneName);
|
||||
|
||||
if (getThing().getStatus() != ThingStatus.ONLINE) {
|
||||
logger.debug("Thing is not ONLINE; command {} from channel {} is ignored", command, channel);
|
||||
|
@ -255,100 +233,100 @@ public class MonopriceAudioHandler extends BaseThingHandler implements Monoprice
|
|||
}
|
||||
|
||||
if (command instanceof RefreshType) {
|
||||
MonopriceAudioZoneDTO zoneDTO = zoneDataMap.get(zone.getZoneId());
|
||||
if (zoneDTO != null) {
|
||||
updateChannelState(zone, channelType, zoneDTO);
|
||||
} else {
|
||||
logger.info("Could not execute REFRESH command for zone {}: null", zone.getZoneId());
|
||||
}
|
||||
updateChannelState(zoneId, channelType);
|
||||
return;
|
||||
}
|
||||
|
||||
Stream<String> zoneStream = MonopriceAudioZone.VALID_ZONES.stream().limit(numZones);
|
||||
Stream<String> zoneStream = amp.getZoneIds().stream().limit(numZones);
|
||||
try {
|
||||
switch (channelType) {
|
||||
case CHANNEL_TYPE_POWER:
|
||||
if (command instanceof OnOffType) {
|
||||
connector.sendCommand(zone, MonopriceAudioCommand.POWER, command == OnOffType.ON ? 1 : 0);
|
||||
zoneDataMap.get(zone.getZoneId()).setPower(command == OnOffType.ON ? ON_STR : OFF_STR);
|
||||
connector.sendCommand(zoneId, amp.getPowerCmd(), command == OnOffType.ON ? ONE : ZERO);
|
||||
zoneDataMap.get(zoneId)
|
||||
.setPower(command == OnOffType.ON ? amp.getOnStr() : amp.getOffStr());
|
||||
}
|
||||
break;
|
||||
case CHANNEL_TYPE_SOURCE:
|
||||
if (command instanceof DecimalType) {
|
||||
int value = ((DecimalType) command).intValue();
|
||||
if (value >= ONE && value <= MAX_SRC) {
|
||||
logger.debug("Got source command {} zone {}", value, zone);
|
||||
connector.sendCommand(zone, MonopriceAudioCommand.SOURCE, value);
|
||||
zoneDataMap.get(zone.getZoneId()).setSource(String.format("%02d", value));
|
||||
final int value = ((DecimalType) command).intValue();
|
||||
if (value >= ONE && value <= amp.getNumSources()) {
|
||||
logger.debug("Got source command {} zone {}", value, zoneId);
|
||||
connector.sendCommand(zoneId, amp.getSourceCmd(), value);
|
||||
zoneDataMap.get(zoneId).setSource(amp.getFormattedValue(value));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CHANNEL_TYPE_VOLUME:
|
||||
if (command instanceof PercentType) {
|
||||
int value = (int) Math
|
||||
.round(((PercentType) command).doubleValue() / 100.0 * (MAX_VOLUME - MIN_VOLUME))
|
||||
final int value = (int) Math.round(
|
||||
((PercentType) command).doubleValue() / 100.0 * (amp.getMaxVol() - MIN_VOLUME))
|
||||
+ MIN_VOLUME;
|
||||
logger.debug("Got volume command {} zone {}", value, zone);
|
||||
connector.sendCommand(zone, MonopriceAudioCommand.VOLUME, value);
|
||||
zoneDataMap.get(zone.getZoneId()).setVolume(value);
|
||||
logger.debug("Got volume command {} zone {}", value, zoneId);
|
||||
connector.sendCommand(zoneId, amp.getVolumeCmd(), value);
|
||||
zoneDataMap.get(zoneId).setVolume(value);
|
||||
}
|
||||
break;
|
||||
case CHANNEL_TYPE_MUTE:
|
||||
if (command instanceof OnOffType) {
|
||||
connector.sendCommand(zone, MonopriceAudioCommand.MUTE, command == OnOffType.ON ? 1 : 0);
|
||||
zoneDataMap.get(zone.getZoneId()).setMute(command == OnOffType.ON ? ON_STR : OFF_STR);
|
||||
connector.sendCommand(zoneId, amp.getMuteCmd(), command == OnOffType.ON ? ONE : ZERO);
|
||||
zoneDataMap.get(zoneId).setMute(command == OnOffType.ON ? amp.getOnStr() : amp.getOffStr());
|
||||
}
|
||||
break;
|
||||
case CHANNEL_TYPE_TREBLE:
|
||||
if (command instanceof DecimalType) {
|
||||
int value = ((DecimalType) command).intValue();
|
||||
if (value >= MIN_TONE && value <= MAX_TONE) {
|
||||
logger.debug("Got treble command {} zone {}", value, zone);
|
||||
connector.sendCommand(zone, MonopriceAudioCommand.TREBLE, value + TONE_OFFSET);
|
||||
zoneDataMap.get(zone.getZoneId()).setTreble(value + TONE_OFFSET);
|
||||
final int value = ((DecimalType) command).intValue();
|
||||
if (value >= amp.getMinTone() && value <= amp.getMaxTone()) {
|
||||
logger.debug("Got treble command {} zone {}", value, zoneId);
|
||||
connector.sendCommand(zoneId, amp.getTrebleCmd(), value + amp.getToneOffset());
|
||||
zoneDataMap.get(zoneId).setTreble(value + amp.getToneOffset());
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CHANNEL_TYPE_BASS:
|
||||
if (command instanceof DecimalType) {
|
||||
int value = ((DecimalType) command).intValue();
|
||||
if (value >= MIN_TONE && value <= MAX_TONE) {
|
||||
logger.debug("Got bass command {} zone {}", value, zone);
|
||||
connector.sendCommand(zone, MonopriceAudioCommand.BASS, value + TONE_OFFSET);
|
||||
zoneDataMap.get(zone.getZoneId()).setBass(value + TONE_OFFSET);
|
||||
final int value = ((DecimalType) command).intValue();
|
||||
if (value >= amp.getMinTone() && value <= amp.getMaxTone()) {
|
||||
logger.debug("Got bass command {} zone {}", value, zoneId);
|
||||
connector.sendCommand(zoneId, amp.getBassCmd(), value + amp.getToneOffset());
|
||||
zoneDataMap.get(zoneId).setBass(value + amp.getToneOffset());
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CHANNEL_TYPE_BALANCE:
|
||||
if (command instanceof DecimalType) {
|
||||
int value = ((DecimalType) command).intValue();
|
||||
if (value >= MIN_BALANCE && value <= MAX_BALANCE) {
|
||||
logger.debug("Got balance command {} zone {}", value, zone);
|
||||
connector.sendCommand(zone, MonopriceAudioCommand.BALANCE, value + BALANCE_OFFSET);
|
||||
zoneDataMap.get(zone.getZoneId()).setBalance(value + BALANCE_OFFSET);
|
||||
final int value = ((DecimalType) command).intValue();
|
||||
if (value >= amp.getMinBal() && value <= amp.getMaxBal()) {
|
||||
logger.debug("Got balance command {} zone {}", value, zoneId);
|
||||
connector.sendCommand(zoneId, amp.getBalanceCmd(), value + amp.getBalOffset());
|
||||
zoneDataMap.get(zoneId).setBalance(value + amp.getBalOffset());
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CHANNEL_TYPE_DND:
|
||||
if (command instanceof OnOffType) {
|
||||
connector.sendCommand(zone, MonopriceAudioCommand.DND, command == OnOffType.ON ? 1 : 0);
|
||||
zoneDataMap.get(zone.getZoneId()).setDnd(command == OnOffType.ON ? ON_STR : OFF_STR);
|
||||
connector.sendCommand(zoneId, amp.getDndCmd(), command == OnOffType.ON ? ONE : ZERO);
|
||||
zoneDataMap.get(zoneId).setDnd(command == OnOffType.ON ? amp.getOnStr() : amp.getOffStr());
|
||||
}
|
||||
break;
|
||||
case CHANNEL_TYPE_ALLPOWER:
|
||||
if (command instanceof OnOffType) {
|
||||
zoneStream.forEach((zoneName) -> {
|
||||
if (command == OnOffType.OFF || !ignoreZones.contains(zoneName)) {
|
||||
final int cmd = command == OnOffType.ON ? ONE : ZERO;
|
||||
zoneStream.forEach((streamZoneId) -> {
|
||||
if (command == OnOffType.OFF || !ignoreZones.contains(amp.getZoneName(streamZoneId))) {
|
||||
try {
|
||||
connector.sendCommand(MonopriceAudioZone.valueOf(zoneName),
|
||||
MonopriceAudioCommand.POWER, command == OnOffType.ON ? 1 : 0);
|
||||
connector.sendCommand(streamZoneId, amp.getPowerCmd(), cmd);
|
||||
zoneDataMap.get(streamZoneId).setPower(amp.getFormattedValue(cmd));
|
||||
updateChannelState(streamZoneId, CHANNEL_TYPE_POWER);
|
||||
|
||||
if (command == OnOffType.ON) {
|
||||
// reset the volume of each zone to allVolume
|
||||
connector.sendCommand(MonopriceAudioZone.valueOf(zoneName),
|
||||
MonopriceAudioCommand.VOLUME, allVolume);
|
||||
connector.sendCommand(streamZoneId, amp.getVolumeCmd(), allVolume);
|
||||
zoneDataMap.get(streamZoneId).setVolume(allVolume);
|
||||
updateChannelState(streamZoneId, CHANNEL_TYPE_VOLUME);
|
||||
}
|
||||
} catch (MonopriceAudioException e) {
|
||||
logger.warn("Error Turning All Zones On: {}", e.getMessage());
|
||||
logger.debug("Error Turning All Zones On: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -357,15 +335,19 @@ public class MonopriceAudioHandler extends BaseThingHandler implements Monoprice
|
|||
break;
|
||||
case CHANNEL_TYPE_ALLSOURCE:
|
||||
if (command instanceof DecimalType) {
|
||||
int value = ((DecimalType) command).intValue();
|
||||
if (value >= ONE && value <= MAX_SRC) {
|
||||
zoneStream.forEach((zoneName) -> {
|
||||
if (!ignoreZones.contains(zoneName)) {
|
||||
final int value = ((DecimalType) command).intValue();
|
||||
if (value >= ONE && value <= amp.getNumSources()) {
|
||||
zoneStream.forEach((streamZoneId) -> {
|
||||
if (!ignoreZones.contains(amp.getZoneName(streamZoneId))) {
|
||||
try {
|
||||
connector.sendCommand(MonopriceAudioZone.valueOf(zoneName),
|
||||
MonopriceAudioCommand.SOURCE, value);
|
||||
connector.sendCommand(streamZoneId, amp.getSourceCmd(), value);
|
||||
if (zoneDataMap.get(streamZoneId).isPowerOn()
|
||||
&& !zoneDataMap.get(streamZoneId).isMuted()) {
|
||||
zoneDataMap.get(streamZoneId).setSource(amp.getFormattedValue(value));
|
||||
updateChannelState(streamZoneId, CHANNEL_TYPE_SOURCE);
|
||||
}
|
||||
} catch (MonopriceAudioException e) {
|
||||
logger.warn("Error Setting Source for All Zones: {}", e.getMessage());
|
||||
logger.debug("Error Setting Source for All Zones: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -374,17 +356,20 @@ public class MonopriceAudioHandler extends BaseThingHandler implements Monoprice
|
|||
break;
|
||||
case CHANNEL_TYPE_ALLVOLUME:
|
||||
if (command instanceof PercentType) {
|
||||
int value = (int) Math
|
||||
.round(((PercentType) command).doubleValue() / 100.0 * (MAX_VOLUME - MIN_VOLUME))
|
||||
allVolume = (int) Math.round(
|
||||
((PercentType) command).doubleValue() / 100.0 * (amp.getMaxVol() - MIN_VOLUME))
|
||||
+ MIN_VOLUME;
|
||||
allVolume = value;
|
||||
zoneStream.forEach((zoneName) -> {
|
||||
if (!ignoreZones.contains(zoneName)) {
|
||||
zoneStream.forEach((streamZoneId) -> {
|
||||
if (!ignoreZones.contains(amp.getZoneName(streamZoneId))) {
|
||||
try {
|
||||
connector.sendCommand(MonopriceAudioZone.valueOf(zoneName),
|
||||
MonopriceAudioCommand.VOLUME, value);
|
||||
connector.sendCommand(streamZoneId, amp.getVolumeCmd(), allVolume);
|
||||
if (zoneDataMap.get(streamZoneId).isPowerOn()
|
||||
&& !zoneDataMap.get(streamZoneId).isMuted()) {
|
||||
zoneDataMap.get(streamZoneId).setVolume(allVolume);
|
||||
updateChannelState(streamZoneId, CHANNEL_TYPE_VOLUME);
|
||||
}
|
||||
} catch (MonopriceAudioException e) {
|
||||
logger.warn("Error Setting Volume for All Zones: {}", e.getMessage());
|
||||
logger.debug("Error Setting Volume for All Zones: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -392,14 +377,17 @@ public class MonopriceAudioHandler extends BaseThingHandler implements Monoprice
|
|||
break;
|
||||
case CHANNEL_TYPE_ALLMUTE:
|
||||
if (command instanceof OnOffType) {
|
||||
int cmd = command == OnOffType.ON ? 1 : 0;
|
||||
zoneStream.forEach((zoneName) -> {
|
||||
if (!ignoreZones.contains(zoneName)) {
|
||||
final int cmd = command == OnOffType.ON ? ONE : ZERO;
|
||||
zoneStream.forEach((streamZoneId) -> {
|
||||
if (!ignoreZones.contains(amp.getZoneName(streamZoneId))) {
|
||||
try {
|
||||
connector.sendCommand(MonopriceAudioZone.valueOf(zoneName),
|
||||
MonopriceAudioCommand.MUTE, cmd);
|
||||
connector.sendCommand(streamZoneId, amp.getMuteCmd(), cmd);
|
||||
if (zoneDataMap.get(streamZoneId).isPowerOn()) {
|
||||
zoneDataMap.get(streamZoneId).setMute(amp.getFormattedValue(cmd));
|
||||
updateChannelState(streamZoneId, CHANNEL_TYPE_MUTE);
|
||||
}
|
||||
} catch (MonopriceAudioException e) {
|
||||
logger.warn("Error Setting Mute for All Zones: {}", e.getMessage());
|
||||
logger.debug("Error Setting Mute for All Zones: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -415,8 +403,9 @@ public class MonopriceAudioHandler extends BaseThingHandler implements Monoprice
|
|||
logger.trace("Command {} from channel {} succeeded", command, channel);
|
||||
}
|
||||
} catch (MonopriceAudioException e) {
|
||||
logger.warn("Command {} from channel {} failed: {}", command, channel, e.getMessage());
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "Sending command failed");
|
||||
logger.debug("Command {} from channel {} failed: {}", command, channel, e.getMessage());
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
"@text/offline.communication-error-failed");
|
||||
closeConnection();
|
||||
scheduleReconnectJob();
|
||||
}
|
||||
|
@ -424,7 +413,7 @@ public class MonopriceAudioHandler extends BaseThingHandler implements Monoprice
|
|||
}
|
||||
|
||||
/**
|
||||
* Open the connection with the MonopriceAudio device
|
||||
* Open the connection to the amplifier
|
||||
*
|
||||
* @return true if the connection is opened successfully or false if not
|
||||
*/
|
||||
|
@ -440,7 +429,7 @@ public class MonopriceAudioHandler extends BaseThingHandler implements Monoprice
|
|||
}
|
||||
|
||||
/**
|
||||
* Close the connection with the MonopriceAudio device
|
||||
* Close the connection to the amplifier
|
||||
*/
|
||||
private synchronized void closeConnection() {
|
||||
if (connector.isConnected()) {
|
||||
|
@ -453,37 +442,30 @@ public class MonopriceAudioHandler extends BaseThingHandler implements Monoprice
|
|||
@Override
|
||||
public void onNewMessageEvent(MonopriceAudioMessageEvent evt) {
|
||||
String key = evt.getKey();
|
||||
String updateData = evt.getValue().trim();
|
||||
if (!MonopriceAudioConnector.KEY_ERROR.equals(key)) {
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
}
|
||||
try {
|
||||
|
||||
switch (key) {
|
||||
case MonopriceAudioConnector.KEY_ERROR:
|
||||
logger.debug("Reading feedback message failed");
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "Reading thread ended");
|
||||
closeConnection();
|
||||
case MonopriceAudioConnector.KEY_ZONE_UPDATE:
|
||||
MonopriceAudioZoneDTO newZoneData = amp.getZoneData(evt.getValue());
|
||||
MonopriceAudioZoneDTO zoneData = zoneDataMap.get(newZoneData.getZone());
|
||||
if (amp.getZoneIds().contains(newZoneData.getZone()) && zoneData != null) {
|
||||
if (amp == AmplifierModel.MONOPRICE70) {
|
||||
processMonoprice70Update(zoneData, newZoneData);
|
||||
} else {
|
||||
processZoneUpdate(zoneData, newZoneData);
|
||||
}
|
||||
} else {
|
||||
logger.debug("invalid event: {} for key: {} or zone data null", evt.getValue(), key);
|
||||
}
|
||||
break;
|
||||
|
||||
case MonopriceAudioConnector.KEY_ZONE_UPDATE:
|
||||
String zoneId = updateData.substring(0, 2);
|
||||
MonopriceAudioZoneDTO zoneDTO = zoneDataMap.get(zoneId);
|
||||
if (MonopriceAudioZone.VALID_ZONE_IDS.contains(zoneId) && zoneDTO != null) {
|
||||
MonopriceAudioZone targetZone = MonopriceAudioZone.fromZoneId(zoneId);
|
||||
processZoneUpdate(targetZone, zoneDTO, updateData);
|
||||
} else {
|
||||
logger.warn("invalid event: {} for key: {} or zone data null", evt.getValue(), key);
|
||||
}
|
||||
case MonopriceAudioConnector.KEY_PING:
|
||||
lastPollingUpdate = System.currentTimeMillis();
|
||||
break;
|
||||
|
||||
default:
|
||||
logger.debug("onNewMessageEvent: unhandled key {}", key);
|
||||
break;
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
logger.warn("Invalid value {} for key {}", updateData, key);
|
||||
} catch (MonopriceAudioException e) {
|
||||
logger.warn("Error processing zone update: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -500,24 +482,39 @@ public class MonopriceAudioHandler extends BaseThingHandler implements Monoprice
|
|||
String error = null;
|
||||
|
||||
if (openConnection()) {
|
||||
try {
|
||||
long prevUpdateTime = lastPollingUpdate;
|
||||
connector.queryZone(MonopriceAudioZone.ZONE1);
|
||||
// poll all zones on the amplifier to get current state
|
||||
amp.getZoneIds().stream().limit(numZones).forEach((streamZoneId) -> {
|
||||
try {
|
||||
connector.queryZone(streamZoneId);
|
||||
|
||||
if (amp == AmplifierModel.MONOPRICE70) {
|
||||
connector.queryTrebBassBalance(streamZoneId);
|
||||
}
|
||||
} catch (MonopriceAudioException e) {
|
||||
logger.debug("Polling error: {}", e.getMessage());
|
||||
}
|
||||
});
|
||||
|
||||
if (amp == AmplifierModel.XANTECH) {
|
||||
try {
|
||||
// for xantech send the commands to enable unsolicited updates
|
||||
connector.sendCommand("!ZA1");
|
||||
connector.sendCommand("!ZP10"); // Zone Periodic Auto Update set to 10 secs
|
||||
} catch (MonopriceAudioException e) {
|
||||
logger.debug("Error sending Xantech periodic update commands: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// prevUpdateTime should have changed if a zone update was received
|
||||
if (lastPollingUpdate == prevUpdateTime) {
|
||||
error = "Controller not responding to status requests";
|
||||
}
|
||||
|
||||
} catch (MonopriceAudioException e) {
|
||||
error = "First command after connection failed";
|
||||
logger.warn("{}: {}", error, e.getMessage());
|
||||
closeConnection();
|
||||
error = "@text/offline.communication-error-polling";
|
||||
}
|
||||
} else {
|
||||
error = "Reconnection failed";
|
||||
error = "@text/offline.communication-error-reconnection";
|
||||
}
|
||||
if (error != null) {
|
||||
closeConnection();
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, error);
|
||||
} else {
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
|
@ -549,23 +546,32 @@ public class MonopriceAudioHandler extends BaseThingHandler implements Monoprice
|
|||
pollingJob = scheduler.scheduleWithFixedDelay(() -> {
|
||||
synchronized (sequenceLock) {
|
||||
if (connector.isConnected()) {
|
||||
logger.debug("Polling the controller for updated status...");
|
||||
logger.debug("Polling the amplifier for updated status...");
|
||||
|
||||
if (!disableKeypadPolling) {
|
||||
// poll each zone up to the number of zones specified in the configuration
|
||||
MonopriceAudioZone.VALID_ZONES.stream().limit(numZones).forEach((zoneName) -> {
|
||||
amp.getZoneIds().stream().limit(numZones).forEach((streamZoneId) -> {
|
||||
try {
|
||||
connector.queryZone(MonopriceAudioZone.valueOf(zoneName));
|
||||
connector.queryZone(streamZoneId);
|
||||
} catch (MonopriceAudioException e) {
|
||||
logger.warn("Polling error: {}", e.getMessage());
|
||||
logger.debug("Polling error for zone id {}: {}", streamZoneId, e.getMessage());
|
||||
}
|
||||
});
|
||||
} else {
|
||||
try {
|
||||
// ping only (no zone updates) to verify the connection is still alive
|
||||
connector.sendPing();
|
||||
} catch (MonopriceAudioException e) {
|
||||
logger.debug("Ping error: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// if the last successful polling update was more than 2.25 intervals ago, the controller
|
||||
// if the last successful polling update was more than 2.25 intervals ago, the amplifier
|
||||
// is either switched off or not responding even though the connection is still good
|
||||
if ((System.currentTimeMillis() - lastPollingUpdate) > (pollingInterval * 2.25 * 1000)) {
|
||||
logger.warn("Controller not responding to status requests");
|
||||
logger.debug("Amplifier not responding to status requests");
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
"Controller not responding to status requests");
|
||||
"@text/offline.communication-error-polling");
|
||||
closeConnection();
|
||||
scheduleReconnectJob();
|
||||
}
|
||||
|
@ -585,45 +591,132 @@ public class MonopriceAudioHandler extends BaseThingHandler implements Monoprice
|
|||
}
|
||||
}
|
||||
|
||||
private void processZoneUpdate(MonopriceAudioZoneDTO zoneData, MonopriceAudioZoneDTO newZoneData) {
|
||||
// only process the update if something actually changed in this zone since the last polling update
|
||||
if (!newZoneData.toString().equals(zoneData.toString())) {
|
||||
if (!newZoneData.getPage().equals(zoneData.getPage())) {
|
||||
zoneData.setPage(newZoneData.getPage());
|
||||
updateChannelState(zoneData.getZone(), CHANNEL_TYPE_PAGE);
|
||||
}
|
||||
|
||||
if (!newZoneData.getPower().equals(zoneData.getPower())) {
|
||||
zoneData.setPower(newZoneData.getPower());
|
||||
updateChannelState(zoneData.getZone(), CHANNEL_TYPE_POWER);
|
||||
}
|
||||
|
||||
if (!newZoneData.getMute().equals(zoneData.getMute())) {
|
||||
zoneData.setMute(newZoneData.getMute());
|
||||
updateChannelState(zoneData.getZone(), CHANNEL_TYPE_MUTE);
|
||||
}
|
||||
|
||||
if (!newZoneData.getDnd().equals(zoneData.getDnd())) {
|
||||
zoneData.setDnd(newZoneData.getDnd());
|
||||
updateChannelState(zoneData.getZone(), CHANNEL_TYPE_DND);
|
||||
}
|
||||
|
||||
if (newZoneData.getVolume() != zoneData.getVolume()) {
|
||||
zoneData.setVolume(newZoneData.getVolume());
|
||||
updateChannelState(zoneData.getZone(), CHANNEL_TYPE_VOLUME);
|
||||
}
|
||||
|
||||
if (newZoneData.getTreble() != zoneData.getTreble()) {
|
||||
zoneData.setTreble(newZoneData.getTreble());
|
||||
updateChannelState(zoneData.getZone(), CHANNEL_TYPE_TREBLE);
|
||||
}
|
||||
|
||||
if (newZoneData.getBass() != zoneData.getBass()) {
|
||||
zoneData.setBass(newZoneData.getBass());
|
||||
updateChannelState(zoneData.getZone(), CHANNEL_TYPE_BASS);
|
||||
}
|
||||
|
||||
if (newZoneData.getBalance() != zoneData.getBalance()) {
|
||||
zoneData.setBalance(newZoneData.getBalance());
|
||||
updateChannelState(zoneData.getZone(), CHANNEL_TYPE_BALANCE);
|
||||
}
|
||||
|
||||
if (!newZoneData.getSource().equals(zoneData.getSource())) {
|
||||
zoneData.setSource(newZoneData.getSource());
|
||||
updateChannelState(zoneData.getZone(), CHANNEL_TYPE_SOURCE);
|
||||
}
|
||||
|
||||
if (!newZoneData.getKeypad().equals(zoneData.getKeypad())) {
|
||||
zoneData.setKeypad(newZoneData.getKeypad());
|
||||
updateChannelState(zoneData.getZone(), CHANNEL_TYPE_KEYPAD);
|
||||
}
|
||||
|
||||
}
|
||||
lastPollingUpdate = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
private void processMonoprice70Update(MonopriceAudioZoneDTO zoneData, MonopriceAudioZoneDTO newZoneData) {
|
||||
if (newZoneData.getTreble() != NIL) {
|
||||
zoneData.setTreble(newZoneData.getTreble());
|
||||
updateChannelState(zoneData.getZone(), CHANNEL_TYPE_TREBLE);
|
||||
} else if (newZoneData.getBass() != NIL) {
|
||||
zoneData.setBass(newZoneData.getBass());
|
||||
updateChannelState(zoneData.getZone(), CHANNEL_TYPE_BASS);
|
||||
} else if (newZoneData.getBalance() != NIL) {
|
||||
zoneData.setBalance(newZoneData.getBalance());
|
||||
updateChannelState(zoneData.getZone(), CHANNEL_TYPE_BALANCE);
|
||||
} else {
|
||||
zoneData.setPower(newZoneData.getPower());
|
||||
zoneData.setMute(newZoneData.getMute());
|
||||
zoneData.setVolume(newZoneData.getVolume());
|
||||
zoneData.setSource(newZoneData.getSource());
|
||||
updateChannelState(zoneData.getZone(), CHANNEL_TYPE_POWER);
|
||||
updateChannelState(zoneData.getZone(), CHANNEL_TYPE_MUTE);
|
||||
updateChannelState(zoneData.getZone(), CHANNEL_TYPE_VOLUME);
|
||||
updateChannelState(zoneData.getZone(), CHANNEL_TYPE_SOURCE);
|
||||
|
||||
}
|
||||
lastPollingUpdate = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the state of a channel
|
||||
*
|
||||
* @param channel the channel
|
||||
* @param zoneId the zone id used to lookup the channel to be updated
|
||||
* @param channelType the channel type to be updated
|
||||
*/
|
||||
private void updateChannelState(MonopriceAudioZone zone, String channelType, MonopriceAudioZoneDTO zoneData) {
|
||||
String channel = zone.name().toLowerCase() + CHANNEL_DELIMIT + channelType;
|
||||
private void updateChannelState(String zoneId, String channelType) {
|
||||
MonopriceAudioZoneDTO zoneData = zoneDataMap.get(zoneId);
|
||||
|
||||
if (zoneData != null) {
|
||||
String channel = amp.getZoneName(zoneId) + CHANNEL_DELIMIT + channelType;
|
||||
|
||||
if (!isLinked(channel)) {
|
||||
return;
|
||||
}
|
||||
|
||||
logger.debug("updating channel state for zone: {}, channel type: {}", zoneId, channelType);
|
||||
|
||||
State state = UnDefType.UNDEF;
|
||||
switch (channelType) {
|
||||
case CHANNEL_TYPE_POWER:
|
||||
state = zoneData.isPowerOn() ? OnOffType.ON : OnOffType.OFF;
|
||||
state = OnOffType.from(zoneData.isPowerOn());
|
||||
break;
|
||||
case CHANNEL_TYPE_SOURCE:
|
||||
state = new DecimalType(zoneData.getSource());
|
||||
break;
|
||||
case CHANNEL_TYPE_VOLUME:
|
||||
long volumePct = Math.round(
|
||||
(double) (zoneData.getVolume() - MIN_VOLUME) / (double) (MAX_VOLUME - MIN_VOLUME) * 100.0);
|
||||
(zoneData.getVolume() - MIN_VOLUME) / (double) (amp.getMaxVol() - MIN_VOLUME) * 100.0);
|
||||
state = new PercentType(BigDecimal.valueOf(volumePct));
|
||||
break;
|
||||
case CHANNEL_TYPE_MUTE:
|
||||
state = zoneData.isMuted() ? OnOffType.ON : OnOffType.OFF;
|
||||
state = OnOffType.from(zoneData.isMuted());
|
||||
break;
|
||||
case CHANNEL_TYPE_TREBLE:
|
||||
state = new DecimalType(BigDecimal.valueOf(zoneData.getTreble() - TONE_OFFSET));
|
||||
state = new DecimalType(BigDecimal.valueOf(zoneData.getTreble() - amp.getToneOffset()));
|
||||
break;
|
||||
case CHANNEL_TYPE_BASS:
|
||||
state = new DecimalType(BigDecimal.valueOf(zoneData.getBass() - TONE_OFFSET));
|
||||
state = new DecimalType(BigDecimal.valueOf(zoneData.getBass() - amp.getToneOffset()));
|
||||
break;
|
||||
case CHANNEL_TYPE_BALANCE:
|
||||
state = new DecimalType(BigDecimal.valueOf(zoneData.getBalance() - BALANCE_OFFSET));
|
||||
state = new DecimalType(BigDecimal.valueOf(zoneData.getBalance() - amp.getBalOffset()));
|
||||
break;
|
||||
case CHANNEL_TYPE_DND:
|
||||
state = zoneData.isDndOn() ? OnOffType.ON : OnOffType.OFF;
|
||||
state = OnOffType.from(zoneData.isDndOn());
|
||||
break;
|
||||
case CHANNEL_TYPE_PAGE:
|
||||
state = zoneData.isPageActive() ? OpenClosedType.OPEN : OpenClosedType.CLOSED;
|
||||
|
@ -636,74 +729,5 @@ public class MonopriceAudioHandler extends BaseThingHandler implements Monoprice
|
|||
}
|
||||
updateState(channel, state);
|
||||
}
|
||||
|
||||
private void processZoneUpdate(MonopriceAudioZone zone, MonopriceAudioZoneDTO zoneData, String newZoneData) {
|
||||
// only process the update if something actually changed in this zone since the last time through
|
||||
if (!newZoneData.equals(zoneData.toString())) {
|
||||
// example status string: 1200010000130809100601, matcher pattern from above:
|
||||
// "^(\\d{2})(\\d{2})(\\d{2})(\\d{2})(\\d{2})(\\d{2})(\\d{2})(\\d{2})(\\d{2})(\\d{2})(\\d{2})"
|
||||
Matcher matcher = PATTERN.matcher(newZoneData);
|
||||
if (matcher.find()) {
|
||||
zoneData.setZone(matcher.group(1));
|
||||
|
||||
if (!matcher.group(2).equals(zoneData.getPage())) {
|
||||
zoneData.setPage(matcher.group(2));
|
||||
updateChannelState(zone, CHANNEL_TYPE_PAGE, zoneData);
|
||||
}
|
||||
|
||||
if (!matcher.group(3).equals(zoneData.getPower())) {
|
||||
zoneData.setPower(matcher.group(3));
|
||||
updateChannelState(zone, CHANNEL_TYPE_POWER, zoneData);
|
||||
}
|
||||
|
||||
if (!matcher.group(4).equals(zoneData.getMute())) {
|
||||
zoneData.setMute(matcher.group(4));
|
||||
updateChannelState(zone, CHANNEL_TYPE_MUTE, zoneData);
|
||||
}
|
||||
|
||||
if (!matcher.group(5).equals(zoneData.getDnd())) {
|
||||
zoneData.setDnd(matcher.group(5));
|
||||
updateChannelState(zone, CHANNEL_TYPE_DND, zoneData);
|
||||
}
|
||||
|
||||
int volume = Integer.parseInt(matcher.group(6));
|
||||
if (volume != zoneData.getVolume()) {
|
||||
zoneData.setVolume(volume);
|
||||
updateChannelState(zone, CHANNEL_TYPE_VOLUME, zoneData);
|
||||
}
|
||||
|
||||
int treble = Integer.parseInt(matcher.group(7));
|
||||
if (treble != zoneData.getTreble()) {
|
||||
zoneData.setTreble(treble);
|
||||
updateChannelState(zone, CHANNEL_TYPE_TREBLE, zoneData);
|
||||
}
|
||||
|
||||
int bass = Integer.parseInt(matcher.group(8));
|
||||
if (bass != zoneData.getBass()) {
|
||||
zoneData.setBass(bass);
|
||||
updateChannelState(zone, CHANNEL_TYPE_BASS, zoneData);
|
||||
}
|
||||
|
||||
int balance = Integer.parseInt(matcher.group(9));
|
||||
if (balance != zoneData.getBalance()) {
|
||||
zoneData.setBalance(balance);
|
||||
updateChannelState(zone, CHANNEL_TYPE_BALANCE, zoneData);
|
||||
}
|
||||
|
||||
if (!matcher.group(10).equals(zoneData.getSource())) {
|
||||
zoneData.setSource(matcher.group(10));
|
||||
updateChannelState(zone, CHANNEL_TYPE_SOURCE, zoneData);
|
||||
}
|
||||
|
||||
if (!matcher.group(11).equals(zoneData.getKeypad())) {
|
||||
zoneData.setKeypad(matcher.group(11));
|
||||
updateChannelState(zone, CHANNEL_TYPE_KEYPAD, zoneData);
|
||||
}
|
||||
} else {
|
||||
logger.debug("Invalid zone update message: {}", newZoneData);
|
||||
}
|
||||
|
||||
}
|
||||
lastPollingUpdate = System.currentTimeMillis();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,8 @@
|
|||
|
||||
<type>binding</type>
|
||||
<name>Monoprice Whole House Audio Binding</name>
|
||||
<description>Controls Monoprice and Dayton Audio Whole House Amplifiers.</description>
|
||||
<description>Controls Monoprice, Dayton Audio and Xantech Whole House Amplifiers.</description>
|
||||
|
||||
<connection>local</connection>
|
||||
|
||||
</addon:addon>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# add-on
|
||||
|
||||
addon.monopriceaudio.name = Monoprice Whole House Audio Binding
|
||||
addon.monopriceaudio.description = Controls Monoprice and Dayton Audio Whole House Amplifiers.
|
||||
addon.monopriceaudio.description = Controls Monoprice, Dayton Audio and Xantech Whole House Amplifiers.
|
||||
|
||||
# thing types
|
||||
|
||||
|
@ -45,11 +45,85 @@ thing-type.monopriceaudio.amplifier.group.zone17.label = Zone 17
|
|||
thing-type.monopriceaudio.amplifier.group.zone17.description = The Controls for Zone 17
|
||||
thing-type.monopriceaudio.amplifier.group.zone18.label = Zone 18
|
||||
thing-type.monopriceaudio.amplifier.group.zone18.description = The Controls for Zone 18
|
||||
thing-type.monopriceaudio.dax88.label = Dayton DAX88 Amplifier
|
||||
thing-type.monopriceaudio.dax88.description = A Multi-zone Whole House Amplifier System
|
||||
thing-type.monopriceaudio.dax88.group.all.label = All Zones
|
||||
thing-type.monopriceaudio.dax88.group.all.description = Control All Zones Simultaneously
|
||||
thing-type.monopriceaudio.dax88.group.zone1.label = Zone 1
|
||||
thing-type.monopriceaudio.dax88.group.zone1.description = The Controls for Zone 1
|
||||
thing-type.monopriceaudio.dax88.group.zone2.label = Zone 2
|
||||
thing-type.monopriceaudio.dax88.group.zone2.description = The Controls for Zone 2
|
||||
thing-type.monopriceaudio.dax88.group.zone3.label = Zone 3
|
||||
thing-type.monopriceaudio.dax88.group.zone3.description = The Controls for Zone 3
|
||||
thing-type.monopriceaudio.dax88.group.zone4.label = Zone 4
|
||||
thing-type.monopriceaudio.dax88.group.zone4.description = The Controls for Zone 4
|
||||
thing-type.monopriceaudio.dax88.group.zone5.label = Zone 5
|
||||
thing-type.monopriceaudio.dax88.group.zone5.description = The Controls for Zone 5
|
||||
thing-type.monopriceaudio.dax88.group.zone6.label = Zone 6
|
||||
thing-type.monopriceaudio.dax88.group.zone6.description = The Controls for Zone 6
|
||||
thing-type.monopriceaudio.dax88.group.zone7.label = Zone 7
|
||||
thing-type.monopriceaudio.dax88.group.zone7.description = The Controls for Zone 7
|
||||
thing-type.monopriceaudio.dax88.group.zone8.label = Zone 8
|
||||
thing-type.monopriceaudio.dax88.group.zone8.description = The Controls for Zone 8
|
||||
thing-type.monopriceaudio.monoprice70.label = Monoprice 31028 70V Amplifier
|
||||
thing-type.monopriceaudio.monoprice70.description = A Multi-zone Whole House Amplifier System
|
||||
thing-type.monopriceaudio.monoprice70.group.all.label = All Zones
|
||||
thing-type.monopriceaudio.monoprice70.group.all.description = Control All Zones Simultaneously
|
||||
thing-type.monopriceaudio.monoprice70.group.zone1.label = Zone 1
|
||||
thing-type.monopriceaudio.monoprice70.group.zone1.description = The Controls for Zone 1
|
||||
thing-type.monopriceaudio.monoprice70.group.zone2.label = Zone 2
|
||||
thing-type.monopriceaudio.monoprice70.group.zone2.description = The Controls for Zone 2
|
||||
thing-type.monopriceaudio.monoprice70.group.zone3.label = Zone 3
|
||||
thing-type.monopriceaudio.monoprice70.group.zone3.description = The Controls for Zone 3
|
||||
thing-type.monopriceaudio.monoprice70.group.zone4.label = Zone 4
|
||||
thing-type.monopriceaudio.monoprice70.group.zone4.description = The Controls for Zone 4
|
||||
thing-type.monopriceaudio.monoprice70.group.zone5.label = Zone 5
|
||||
thing-type.monopriceaudio.monoprice70.group.zone5.description = The Controls for Zone 5
|
||||
thing-type.monopriceaudio.monoprice70.group.zone6.label = Zone 6
|
||||
thing-type.monopriceaudio.monoprice70.group.zone6.description = The Controls for Zone 6
|
||||
thing-type.monopriceaudio.xantech.label = Xantech 8x8 Amplifier
|
||||
thing-type.monopriceaudio.xantech.description = A Multi-zone Whole House Amplifier System
|
||||
thing-type.monopriceaudio.xantech.group.all.label = All Zones
|
||||
thing-type.monopriceaudio.xantech.group.all.description = Control All Zones Simultaneously
|
||||
thing-type.monopriceaudio.xantech.group.zone1.label = Zone 1
|
||||
thing-type.monopriceaudio.xantech.group.zone1.description = The Controls for Zone 1
|
||||
thing-type.monopriceaudio.xantech.group.zone2.label = Zone 2
|
||||
thing-type.monopriceaudio.xantech.group.zone2.description = The Controls for Zone 2
|
||||
thing-type.monopriceaudio.xantech.group.zone3.label = Zone 3
|
||||
thing-type.monopriceaudio.xantech.group.zone3.description = The Controls for Zone 3
|
||||
thing-type.monopriceaudio.xantech.group.zone4.label = Zone 4
|
||||
thing-type.monopriceaudio.xantech.group.zone4.description = The Controls for Zone 4
|
||||
thing-type.monopriceaudio.xantech.group.zone5.label = Zone 5
|
||||
thing-type.monopriceaudio.xantech.group.zone5.description = The Controls for Zone 5
|
||||
thing-type.monopriceaudio.xantech.group.zone6.label = Zone 6
|
||||
thing-type.monopriceaudio.xantech.group.zone6.description = The Controls for Zone 6
|
||||
thing-type.monopriceaudio.xantech.group.zone7.label = Zone 7
|
||||
thing-type.monopriceaudio.xantech.group.zone7.description = The Controls for Zone 7
|
||||
thing-type.monopriceaudio.xantech.group.zone8.label = Zone 8
|
||||
thing-type.monopriceaudio.xantech.group.zone8.description = The Controls for Zone 8
|
||||
thing-type.monopriceaudio.xantech.group.zone9.label = Zone 9
|
||||
thing-type.monopriceaudio.xantech.group.zone9.description = The Controls for Zone 9
|
||||
thing-type.monopriceaudio.xantech.group.zone10.label = Zone 10
|
||||
thing-type.monopriceaudio.xantech.group.zone10.description = The Controls for Zone 10
|
||||
thing-type.monopriceaudio.xantech.group.zone11.label = Zone 11
|
||||
thing-type.monopriceaudio.xantech.group.zone11.description = The Controls for Zone 11
|
||||
thing-type.monopriceaudio.xantech.group.zone12.label = Zone 12
|
||||
thing-type.monopriceaudio.xantech.group.zone12.description = The Controls for Zone 12
|
||||
thing-type.monopriceaudio.xantech.group.zone13.label = Zone 13
|
||||
thing-type.monopriceaudio.xantech.group.zone13.description = The Controls for Zone 13
|
||||
thing-type.monopriceaudio.xantech.group.zone14.label = Zone 14
|
||||
thing-type.monopriceaudio.xantech.group.zone14.description = The Controls for Zone 14
|
||||
thing-type.monopriceaudio.xantech.group.zone15.label = Zone 15
|
||||
thing-type.monopriceaudio.xantech.group.zone15.description = The Controls for Zone 15
|
||||
thing-type.monopriceaudio.xantech.group.zone16.label = Zone 16
|
||||
thing-type.monopriceaudio.xantech.group.zone16.description = The Controls for Zone 16
|
||||
|
||||
# thing types config
|
||||
|
||||
thing-type.config.monopriceaudio.amplifier.disableKeypadPolling.label = Disable Keypad Polling
|
||||
thing-type.config.monopriceaudio.amplifier.disableKeypadPolling.description = If physical keypads are not used, this option will disable polling the amplifier for zone updates
|
||||
thing-type.config.monopriceaudio.amplifier.host.label = Address
|
||||
thing-type.config.monopriceaudio.amplifier.host.description = Host Name or IP Address of the Amplifier or Serial over IP device
|
||||
thing-type.config.monopriceaudio.amplifier.host.description = Host Name or IP Address of the Monoprice Amplifier or Serial over IP device
|
||||
thing-type.config.monopriceaudio.amplifier.ignoreZones.label = Ignore Zones
|
||||
thing-type.config.monopriceaudio.amplifier.ignoreZones.description = (Optional) A Comma Seperated List of Zone Numbers That Will Ignore the 'All Zone' (Except All Off) Commands (ie: 1,6,10)
|
||||
thing-type.config.monopriceaudio.amplifier.initialAllVolume.label = Initial All Volume
|
||||
|
@ -69,16 +143,110 @@ thing-type.config.monopriceaudio.amplifier.inputLabel6.description = Friendly Na
|
|||
thing-type.config.monopriceaudio.amplifier.numZones.label = Number of Zones
|
||||
thing-type.config.monopriceaudio.amplifier.numZones.description = Number of Zones on the Amplifier to Utilize in the Binding (Up to 18 Zones With 3 Amplifiers Connected Together)
|
||||
thing-type.config.monopriceaudio.amplifier.pollingInterval.label = Polling Interval
|
||||
thing-type.config.monopriceaudio.amplifier.pollingInterval.description = Configures How Often to Poll the Controller to Check for Zone Updates (5-60; Default 15)
|
||||
thing-type.config.monopriceaudio.amplifier.pollingInterval.description = Configures How Often to Poll the Amplifier to Check for Zone Updates (5-60; Default 15)
|
||||
thing-type.config.monopriceaudio.amplifier.port.label = Port
|
||||
thing-type.config.monopriceaudio.amplifier.port.description = Communication Port for Serial over IP connection to the Amplifier (Default 8080 for amps with built-in Serial over IP)
|
||||
thing-type.config.monopriceaudio.amplifier.port.description = Communication Port for Serial over IP connection to the Monoprice Amplifier (8080 for amps with built-in Serial over IP)
|
||||
thing-type.config.monopriceaudio.amplifier.serialPort.label = Serial Port
|
||||
thing-type.config.monopriceaudio.amplifier.serialPort.description = Serial Port to Use for Connecting to the Monoprice Amplifier
|
||||
thing-type.config.monopriceaudio.dax88.disableKeypadPolling.label = Disable Keypad Polling
|
||||
thing-type.config.monopriceaudio.dax88.disableKeypadPolling.description = If physical keypads are not used, this option will disable polling the amplifier for zone updates
|
||||
thing-type.config.monopriceaudio.dax88.host.label = Address
|
||||
thing-type.config.monopriceaudio.dax88.host.description = Host Name or IP Address of the Machine Connected to the Dayton Amplifier (Serial over IP)
|
||||
thing-type.config.monopriceaudio.dax88.ignoreZones.label = Ignore Zones
|
||||
thing-type.config.monopriceaudio.dax88.ignoreZones.description = (Optional) A Comma Seperated List of Zone Numbers That Will Ignore the 'All Zone' (Except All Off) Commands (ie: 1,6,10)
|
||||
thing-type.config.monopriceaudio.dax88.initialAllVolume.label = Initial All Volume
|
||||
thing-type.config.monopriceaudio.dax88.initialAllVolume.description = When 'All' Zones Are Activated, the Volume Will Reset to This Value (1-30; default 10) to Prevent Excessive Blaring of Sound ;)
|
||||
thing-type.config.monopriceaudio.dax88.inputLabel1.label = Source 1 Input Label
|
||||
thing-type.config.monopriceaudio.dax88.inputLabel1.description = Friendly Name for the Input Source to Be Displayed in the UI (ie: Chromecast, Radio, CD, etc.)
|
||||
thing-type.config.monopriceaudio.dax88.inputLabel2.label = Source 2 Input Label
|
||||
thing-type.config.monopriceaudio.dax88.inputLabel2.description = Friendly Name for the Input Source to Be Displayed in the UI (ie: Chromecast, Radio, CD, etc.)
|
||||
thing-type.config.monopriceaudio.dax88.inputLabel3.label = Source 3 Input Label
|
||||
thing-type.config.monopriceaudio.dax88.inputLabel3.description = Friendly Name for the Input Source to Be Displayed in the UI (ie: Chromecast, Radio, CD, etc.)
|
||||
thing-type.config.monopriceaudio.dax88.inputLabel4.label = Source 4 Input Label
|
||||
thing-type.config.monopriceaudio.dax88.inputLabel4.description = Friendly Name for the Input Source to Be Displayed in the UI (ie: Chromecast, Radio, CD, etc.)
|
||||
thing-type.config.monopriceaudio.dax88.inputLabel5.label = Source 5 Input Label
|
||||
thing-type.config.monopriceaudio.dax88.inputLabel5.description = Friendly Name for the Input Source to Be Displayed in the UI (ie: Chromecast, Radio, CD, etc.)
|
||||
thing-type.config.monopriceaudio.dax88.inputLabel6.label = Source 6 Input Label
|
||||
thing-type.config.monopriceaudio.dax88.inputLabel6.description = Friendly Name for the Input Source to Be Displayed in the UI (ie: Chromecast, Radio, CD, etc.)
|
||||
thing-type.config.monopriceaudio.dax88.inputLabel7.label = Source 7 Input Label
|
||||
thing-type.config.monopriceaudio.dax88.inputLabel7.description = Friendly Name for the Input Source to Be Displayed in the UI (ie: Chromecast, Radio, CD, etc.)
|
||||
thing-type.config.monopriceaudio.dax88.inputLabel8.label = Source 8 Input Label
|
||||
thing-type.config.monopriceaudio.dax88.inputLabel8.description = Friendly Name for the Input Source to Be Displayed in the UI (ie: Chromecast, Radio, CD, etc.)
|
||||
thing-type.config.monopriceaudio.dax88.numZones.label = Number of Zones
|
||||
thing-type.config.monopriceaudio.dax88.numZones.description = Number of Zones on the Amplifier to Utilize in the Binding
|
||||
thing-type.config.monopriceaudio.dax88.pollingInterval.label = Polling Interval
|
||||
thing-type.config.monopriceaudio.dax88.pollingInterval.description = Configures How Often to Poll the Amplifier to Check for Zone Updates (5-60; Default 15)
|
||||
thing-type.config.monopriceaudio.dax88.port.label = Port
|
||||
thing-type.config.monopriceaudio.dax88.port.description = Communication Port for Serial over IP connection to the Dayton Amplifier
|
||||
thing-type.config.monopriceaudio.dax88.serialPort.label = Serial Port
|
||||
thing-type.config.monopriceaudio.dax88.serialPort.description = Serial Port to Use for Connecting to the Dayton Amplifier
|
||||
thing-type.config.monopriceaudio.monoprice70.host.label = Address
|
||||
thing-type.config.monopriceaudio.monoprice70.host.description = Host Name or IP Address of the Machine Connected to the Monoprice Amplifier (Serial over IP)
|
||||
thing-type.config.monopriceaudio.monoprice70.ignoreZones.label = Ignore Zones
|
||||
thing-type.config.monopriceaudio.monoprice70.ignoreZones.description = (Optional) A Comma Seperated List of Zone Numbers That Will Ignore the 'All Zone' (Except All Off) Commands (ie: 1,5,6)
|
||||
thing-type.config.monopriceaudio.monoprice70.initialAllVolume.label = Initial All Volume
|
||||
thing-type.config.monopriceaudio.monoprice70.initialAllVolume.description = When 'All' Zones Are Activated, the Volume Will Reset to This Value (1-30; default 10) to Prevent Excessive Blaring of Sound ;)
|
||||
thing-type.config.monopriceaudio.monoprice70.inputLabel1.label = Source 0 Input Label
|
||||
thing-type.config.monopriceaudio.monoprice70.inputLabel1.description = Friendly Name for the Input Source to Be Displayed in the UI (ie: Chromecast, Radio, CD, etc.)
|
||||
thing-type.config.monopriceaudio.monoprice70.inputLabel2.label = Source 1 Input Label
|
||||
thing-type.config.monopriceaudio.monoprice70.inputLabel2.description = Friendly Name for the Input Source to Be Displayed in the UI (ie: Chromecast, Radio, CD, etc.)
|
||||
thing-type.config.monopriceaudio.monoprice70.numZones.label = Number of Zones
|
||||
thing-type.config.monopriceaudio.monoprice70.numZones.description = Number of Zones on the Amplifier to Utilize in the Binding
|
||||
thing-type.config.monopriceaudio.monoprice70.pollingInterval.label = Polling Interval
|
||||
thing-type.config.monopriceaudio.monoprice70.pollingInterval.description = Configures How Often to Poll the Amplifier to Check for Zone Updates (5-60; Default 30)
|
||||
thing-type.config.monopriceaudio.monoprice70.port.label = Port
|
||||
thing-type.config.monopriceaudio.monoprice70.port.description = Communication Port for Serial over IP connection to the Monoprice Amplifier
|
||||
thing-type.config.monopriceaudio.monoprice70.serialPort.label = Serial Port
|
||||
thing-type.config.monopriceaudio.monoprice70.serialPort.description = Serial Port to Use for Connecting to the Monoprice Amplifier
|
||||
thing-type.config.monopriceaudio.xantech.disableKeypadPolling.label = Disable Keypad Polling
|
||||
thing-type.config.monopriceaudio.xantech.disableKeypadPolling.description = If physical keypads are not used, this option will disable polling the amplifier for zone updates
|
||||
thing-type.config.monopriceaudio.xantech.host.label = Address
|
||||
thing-type.config.monopriceaudio.xantech.host.description = Host Name or IP Address of the Machine Connected to the Xantech Amplifier (Serial over IP)
|
||||
thing-type.config.monopriceaudio.xantech.ignoreZones.label = Ignore Zones
|
||||
thing-type.config.monopriceaudio.xantech.ignoreZones.description = (Optional) A Comma Seperated List of Zone Numbers That Will Ignore the 'All Zone' (Except All Off) Commands (ie: 1,6,10)
|
||||
thing-type.config.monopriceaudio.xantech.initialAllVolume.label = Initial All Volume
|
||||
thing-type.config.monopriceaudio.xantech.initialAllVolume.description = When 'All' Zones Are Activated, the Volume Will Reset to This Value (1-30; default 10) to Prevent Excessive Blaring of Sound ;)
|
||||
thing-type.config.monopriceaudio.xantech.inputLabel1.label = Source 1 Input Label
|
||||
thing-type.config.monopriceaudio.xantech.inputLabel1.description = Friendly Name for the Input Source to Be Displayed in the UI (ie: Chromecast, Radio, CD, etc.)
|
||||
thing-type.config.monopriceaudio.xantech.inputLabel2.label = Source 2 Input Label
|
||||
thing-type.config.monopriceaudio.xantech.inputLabel2.description = Friendly Name for the Input Source to Be Displayed in the UI (ie: Chromecast, Radio, CD, etc.)
|
||||
thing-type.config.monopriceaudio.xantech.inputLabel3.label = Source 3 Input Label
|
||||
thing-type.config.monopriceaudio.xantech.inputLabel3.description = Friendly Name for the Input Source to Be Displayed in the UI (ie: Chromecast, Radio, CD, etc.)
|
||||
thing-type.config.monopriceaudio.xantech.inputLabel4.label = Source 4 Input Label
|
||||
thing-type.config.monopriceaudio.xantech.inputLabel4.description = Friendly Name for the Input Source to Be Displayed in the UI (ie: Chromecast, Radio, CD, etc.)
|
||||
thing-type.config.monopriceaudio.xantech.inputLabel5.label = Source 5 Input Label
|
||||
thing-type.config.monopriceaudio.xantech.inputLabel5.description = Friendly Name for the Input Source to Be Displayed in the UI (ie: Chromecast, Radio, CD, etc.)
|
||||
thing-type.config.monopriceaudio.xantech.inputLabel6.label = Source 6 Input Label
|
||||
thing-type.config.monopriceaudio.xantech.inputLabel6.description = Friendly Name for the Input Source to Be Displayed in the UI (ie: Chromecast, Radio, CD, etc.)
|
||||
thing-type.config.monopriceaudio.xantech.inputLabel7.label = Source 7 Input Label
|
||||
thing-type.config.monopriceaudio.xantech.inputLabel7.description = Friendly Name for the Input Source to Be Displayed in the UI (ie: Chromecast, Radio, CD, etc.)
|
||||
thing-type.config.monopriceaudio.xantech.inputLabel8.label = Source 8 Input Label
|
||||
thing-type.config.monopriceaudio.xantech.inputLabel8.description = Friendly Name for the Input Source to Be Displayed in the UI (ie: Chromecast, Radio, CD, etc.)
|
||||
thing-type.config.monopriceaudio.xantech.numZones.label = Number of Zones
|
||||
thing-type.config.monopriceaudio.xantech.numZones.description = Number of Zones on the Amplifier to Utilize in the Binding (Up to 16 Zones With 2 Amplifiers Connected Together)
|
||||
thing-type.config.monopriceaudio.xantech.pollingInterval.label = Polling Interval
|
||||
thing-type.config.monopriceaudio.xantech.pollingInterval.description = Configures How Often to Poll the Amplifier to Check for Zone Updates (5-60; Default 30)
|
||||
thing-type.config.monopriceaudio.xantech.port.label = Port
|
||||
thing-type.config.monopriceaudio.xantech.port.description = Communication Port for Serial over IP connection to the Xantech Amplifier
|
||||
thing-type.config.monopriceaudio.xantech.serialPort.label = Serial Port
|
||||
thing-type.config.monopriceaudio.xantech.serialPort.description = Serial Port to Use for Connecting to the Xantech Amplifier
|
||||
|
||||
# channel group types
|
||||
|
||||
channel-group-type.monopriceaudio.all.label = All Zones
|
||||
channel-group-type.monopriceaudio.all.description = Control All Zones Simultaneously
|
||||
channel-group-type.monopriceaudio.dax88-all.label = All Zones
|
||||
channel-group-type.monopriceaudio.dax88-all.description = Control All Zones Simultaneously
|
||||
channel-group-type.monopriceaudio.dax88-zone.label = Zone Controls
|
||||
channel-group-type.monopriceaudio.dax88-zone.description = The Controls for the Zone
|
||||
channel-group-type.monopriceaudio.monoprice70-all.label = All Zones
|
||||
channel-group-type.monopriceaudio.monoprice70-all.description = Control All Zones Simultaneously
|
||||
channel-group-type.monopriceaudio.monoprice70-zone.label = Zone Controls
|
||||
channel-group-type.monopriceaudio.monoprice70-zone.description = The Controls for the Zone
|
||||
channel-group-type.monopriceaudio.xantech-all.label = All Zones
|
||||
channel-group-type.monopriceaudio.xantech-all.description = Control All Zones Simultaneously
|
||||
channel-group-type.monopriceaudio.xantech-zone.label = Zone Controls
|
||||
channel-group-type.monopriceaudio.xantech-zone.description = The Controls for the Zone
|
||||
channel-group-type.monopriceaudio.zone.label = Zone Controls
|
||||
channel-group-type.monopriceaudio.zone.description = The Controls for the Zone
|
||||
|
||||
|
@ -90,12 +258,42 @@ channel-type.monopriceaudio.balance.label = Balance Adjustment
|
|||
channel-type.monopriceaudio.balance.description = Adjust the Balance
|
||||
channel-type.monopriceaudio.bass.label = Bass Adjustment
|
||||
channel-type.monopriceaudio.bass.description = Adjust the Bass
|
||||
channel-type.monopriceaudio.dax88-allpower.label = All On
|
||||
channel-type.monopriceaudio.dax88-allpower.description = Turn All Zones On or Off
|
||||
channel-type.monopriceaudio.dax88-balance.label = Balance Adjustment
|
||||
channel-type.monopriceaudio.dax88-balance.description = Adjust the Balance
|
||||
channel-type.monopriceaudio.dax88-bass.label = Bass Adjustment
|
||||
channel-type.monopriceaudio.dax88-bass.description = Adjust the Bass
|
||||
channel-type.monopriceaudio.dax88-dnd.label = Do Not Disturb
|
||||
channel-type.monopriceaudio.dax88-dnd.description = Controls if the Zone Should Ignore an Incoming Audio Page
|
||||
channel-type.monopriceaudio.dax88-keypad.label = Keypad Connected
|
||||
channel-type.monopriceaudio.dax88-keypad.description = Indicates if a Physical Keypad is Attached to This Zone
|
||||
channel-type.monopriceaudio.dax88-keypad.state.option.CLOSED = Disconnected
|
||||
channel-type.monopriceaudio.dax88-keypad.state.option.OPEN = Connected
|
||||
channel-type.monopriceaudio.dax88-page.label = Page Active
|
||||
channel-type.monopriceaudio.dax88-page.description = Indicates if the Page Mode is Active for This Zone
|
||||
channel-type.monopriceaudio.dax88-page.state.option.CLOSED = Inactive
|
||||
channel-type.monopriceaudio.dax88-page.state.option.OPEN = Active
|
||||
channel-type.monopriceaudio.dax88-source.label = Source Input
|
||||
channel-type.monopriceaudio.dax88-source.description = Select the Source Input
|
||||
channel-type.monopriceaudio.dax88-treble.label = Treble Adjustment
|
||||
channel-type.monopriceaudio.dax88-treble.description = Adjust the Treble
|
||||
channel-type.monopriceaudio.dnd.label = Do Not Disturb
|
||||
channel-type.monopriceaudio.dnd.description = Controls if the Zone Should Ignore an Incoming Audio Page
|
||||
channel-type.monopriceaudio.keypad.label = Keypad Connected
|
||||
channel-type.monopriceaudio.keypad.description = Indicates if a Physical Keypad is Attached to This Zone
|
||||
channel-type.monopriceaudio.keypad.state.option.CLOSED = Disconnected
|
||||
channel-type.monopriceaudio.keypad.state.option.OPEN = Connected
|
||||
channel-type.monopriceaudio.monoprice70-allpower.label = All On
|
||||
channel-type.monopriceaudio.monoprice70-allpower.description = Turn All Zones On or Off
|
||||
channel-type.monopriceaudio.monoprice70-balance.label = Balance Adjustment
|
||||
channel-type.monopriceaudio.monoprice70-balance.description = Adjust the Balance
|
||||
channel-type.monopriceaudio.monoprice70-bass.label = Bass Adjustment
|
||||
channel-type.monopriceaudio.monoprice70-bass.description = Adjust the Bass
|
||||
channel-type.monopriceaudio.monoprice70-source.label = Source Input
|
||||
channel-type.monopriceaudio.monoprice70-source.description = Select the Source Input
|
||||
channel-type.monopriceaudio.monoprice70-treble.label = Treble Adjustment
|
||||
channel-type.monopriceaudio.monoprice70-treble.description = Adjust the Treble
|
||||
channel-type.monopriceaudio.page.label = Page Active
|
||||
channel-type.monopriceaudio.page.description = Indicates if the Page Mode is Active for This Zone
|
||||
channel-type.monopriceaudio.page.state.option.CLOSED = Inactive
|
||||
|
@ -104,3 +302,30 @@ channel-type.monopriceaudio.source.label = Source Input
|
|||
channel-type.monopriceaudio.source.description = Select the Source Input
|
||||
channel-type.monopriceaudio.treble.label = Treble Adjustment
|
||||
channel-type.monopriceaudio.treble.description = Adjust the Treble
|
||||
channel-type.monopriceaudio.xantech-allpower.label = All On
|
||||
channel-type.monopriceaudio.xantech-allpower.description = Turn All Zones On or Off
|
||||
channel-type.monopriceaudio.xantech-balance.label = Balance Adjustment
|
||||
channel-type.monopriceaudio.xantech-balance.description = Adjust the Balance
|
||||
channel-type.monopriceaudio.xantech-bass.label = Bass Adjustment
|
||||
channel-type.monopriceaudio.xantech-bass.description = Adjust the Bass
|
||||
channel-type.monopriceaudio.xantech-keypad.label = Keypad Connected
|
||||
channel-type.monopriceaudio.xantech-keypad.description = Indicates if a Physical Keypad is Attached to This Zone
|
||||
channel-type.monopriceaudio.xantech-keypad.state.option.CLOSED = Disconnected
|
||||
channel-type.monopriceaudio.xantech-keypad.state.option.OPEN = Connected
|
||||
channel-type.monopriceaudio.xantech-page.label = Page Active
|
||||
channel-type.monopriceaudio.xantech-page.description = Indicates if the Page Mode is Active for This Zone
|
||||
channel-type.monopriceaudio.xantech-page.state.option.CLOSED = Inactive
|
||||
channel-type.monopriceaudio.xantech-page.state.option.OPEN = Active
|
||||
channel-type.monopriceaudio.xantech-source.label = Source Input
|
||||
channel-type.monopriceaudio.xantech-source.description = Select the Source Input
|
||||
channel-type.monopriceaudio.xantech-treble.label = Treble Adjustment
|
||||
channel-type.monopriceaudio.xantech-treble.description = Adjust the Treble
|
||||
|
||||
# message strings
|
||||
|
||||
offline.configuration-error-rfc2217 = Use Host and Port configuration settings for a serial over IP connection
|
||||
offline.configuration-error-conflict = Serial port cannot be used at the same time that Host & Port is used
|
||||
offline.configuration-error-missing = Either Serial port or Host & Port must be specifed
|
||||
offline.communication-error-failed = Sending command failed
|
||||
offline.communication-error-polling = Amplifier not responding to status requests
|
||||
offline.communication-error-reconnection = Reconnection failed
|
||||
|
|
|
@ -0,0 +1,230 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<thing:thing-descriptions bindingId="monopriceaudio"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
|
||||
|
||||
<!-- Dayton DAX88 Amplifier Thing -->
|
||||
<thing-type id="dax88">
|
||||
<label>Dayton DAX88 Amplifier</label>
|
||||
<description>
|
||||
A Multi-zone Whole House Amplifier System
|
||||
</description>
|
||||
|
||||
<channel-groups>
|
||||
<channel-group id="all" typeId="dax88-all">
|
||||
<label>All Zones</label>
|
||||
<description>Control All Zones Simultaneously</description>
|
||||
</channel-group>
|
||||
<channel-group id="zone1" typeId="dax88-zone">
|
||||
<label>Zone 1</label>
|
||||
<description>The Controls for Zone 1</description>
|
||||
</channel-group>
|
||||
<channel-group id="zone2" typeId="dax88-zone">
|
||||
<label>Zone 2</label>
|
||||
<description>The Controls for Zone 2</description>
|
||||
</channel-group>
|
||||
<channel-group id="zone3" typeId="dax88-zone">
|
||||
<label>Zone 3</label>
|
||||
<description>The Controls for Zone 3</description>
|
||||
</channel-group>
|
||||
<channel-group id="zone4" typeId="dax88-zone">
|
||||
<label>Zone 4</label>
|
||||
<description>The Controls for Zone 4</description>
|
||||
</channel-group>
|
||||
<channel-group id="zone5" typeId="dax88-zone">
|
||||
<label>Zone 5</label>
|
||||
<description>The Controls for Zone 5</description>
|
||||
</channel-group>
|
||||
<channel-group id="zone6" typeId="dax88-zone">
|
||||
<label>Zone 6</label>
|
||||
<description>The Controls for Zone 6</description>
|
||||
</channel-group>
|
||||
<channel-group id="zone7" typeId="dax88-zone">
|
||||
<label>Zone 7</label>
|
||||
<description>The Controls for Zone 7</description>
|
||||
</channel-group>
|
||||
<channel-group id="zone8" typeId="dax88-zone">
|
||||
<label>Zone 8</label>
|
||||
<description>The Controls for Zone 8</description>
|
||||
</channel-group>
|
||||
</channel-groups>
|
||||
|
||||
<config-description>
|
||||
<parameter name="serialPort" type="text" required="false">
|
||||
<context>serial-port</context>
|
||||
<limitToOptions>false</limitToOptions>
|
||||
<label>Serial Port</label>
|
||||
<description>Serial Port to Use for Connecting to the Dayton Amplifier</description>
|
||||
</parameter>
|
||||
<parameter name="host" type="text" required="false">
|
||||
<context>network-address</context>
|
||||
<label>Address</label>
|
||||
<description>Host Name or IP Address of the Machine Connected to the Dayton Amplifier (Serial over IP)</description>
|
||||
</parameter>
|
||||
<parameter name="port" type="integer" min="1" max="65535" required="false">
|
||||
<label>Port</label>
|
||||
<description>Communication Port for Serial over IP connection to the Dayton Amplifier</description>
|
||||
</parameter>
|
||||
<parameter name="numZones" type="integer" min="1" max="8" required="true">
|
||||
<label>Number of Zones</label>
|
||||
<description>Number of Zones on the Amplifier to Utilize in the Binding</description>
|
||||
<default>8</default>
|
||||
</parameter>
|
||||
<parameter name="pollingInterval" type="integer" min="5" max="60" unit="s" required="false">
|
||||
<label>Polling Interval</label>
|
||||
<description>Configures How Often to Poll the Amplifier to Check for Zone Updates (5-60; Default 15)</description>
|
||||
<default>15</default>
|
||||
</parameter>
|
||||
<parameter name="ignoreZones" type="text" required="false">
|
||||
<label>Ignore Zones</label>
|
||||
<description>(Optional) A Comma Seperated List of Zone Numbers That Will Ignore the 'All Zone' (Except All Off)
|
||||
Commands (ie: 1,6,10)</description>
|
||||
</parameter>
|
||||
<parameter name="initialAllVolume" type="integer" min="1" max="30" required="false">
|
||||
<label>Initial All Volume</label>
|
||||
<description>When 'All' Zones Are Activated, the Volume Will Reset to This Value (1-30; default 10) to Prevent
|
||||
Excessive Blaring of Sound ;)</description>
|
||||
<default>10</default>
|
||||
</parameter>
|
||||
<parameter name="inputLabel1" type="text" required="false">
|
||||
<label>Source 1 Input Label</label>
|
||||
<description>Friendly Name for the Input Source to Be Displayed in the UI (ie: Chromecast, Radio, CD, etc.)</description>
|
||||
<default>Source 1</default>
|
||||
</parameter>
|
||||
<parameter name="inputLabel2" type="text" required="false">
|
||||
<label>Source 2 Input Label</label>
|
||||
<description>Friendly Name for the Input Source to Be Displayed in the UI (ie: Chromecast, Radio, CD, etc.)</description>
|
||||
<default>Source 2</default>
|
||||
</parameter>
|
||||
<parameter name="inputLabel3" type="text" required="false">
|
||||
<label>Source 3 Input Label</label>
|
||||
<description>Friendly Name for the Input Source to Be Displayed in the UI (ie: Chromecast, Radio, CD, etc.)</description>
|
||||
<default>Source 3</default>
|
||||
</parameter>
|
||||
<parameter name="inputLabel4" type="text" required="false">
|
||||
<label>Source 4 Input Label</label>
|
||||
<description>Friendly Name for the Input Source to Be Displayed in the UI (ie: Chromecast, Radio, CD, etc.)</description>
|
||||
<default>Source 4</default>
|
||||
</parameter>
|
||||
<parameter name="inputLabel5" type="text" required="false">
|
||||
<label>Source 5 Input Label</label>
|
||||
<description>Friendly Name for the Input Source to Be Displayed in the UI (ie: Chromecast, Radio, CD, etc.)</description>
|
||||
<default>Source 5</default>
|
||||
</parameter>
|
||||
<parameter name="inputLabel6" type="text" required="false">
|
||||
<label>Source 6 Input Label</label>
|
||||
<description>Friendly Name for the Input Source to Be Displayed in the UI (ie: Chromecast, Radio, CD, etc.)</description>
|
||||
<default>Source 6</default>
|
||||
</parameter>
|
||||
<parameter name="inputLabel7" type="text" required="false">
|
||||
<label>Source 7 Input Label</label>
|
||||
<description>Friendly Name for the Input Source to Be Displayed in the UI (ie: Chromecast, Radio, CD, etc.)</description>
|
||||
<default>Source 7</default>
|
||||
</parameter>
|
||||
<parameter name="inputLabel8" type="text" required="false">
|
||||
<label>Source 8 Input Label</label>
|
||||
<description>Friendly Name for the Input Source to Be Displayed in the UI (ie: Chromecast, Radio, CD, etc.)</description>
|
||||
<default>Wi-Fi streaming</default>
|
||||
</parameter>
|
||||
<parameter name="disableKeypadPolling" type="boolean" required="false">
|
||||
<label>Disable Keypad Polling</label>
|
||||
<description>If physical keypads are not used, this option will disable polling the amplifier for zone updates</description>
|
||||
<default>false</default>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</thing-type>
|
||||
|
||||
<channel-group-type id="dax88-all">
|
||||
<label>All Zones</label>
|
||||
<description>Control All Zones Simultaneously</description>
|
||||
<channels>
|
||||
<channel id="allpower" typeId="dax88-allpower"/>
|
||||
<channel id="allsource" typeId="dax88-source"/>
|
||||
<channel id="allvolume" typeId="system.volume"/>
|
||||
<channel id="allmute" typeId="system.mute"/>
|
||||
</channels>
|
||||
</channel-group-type>
|
||||
|
||||
<channel-group-type id="dax88-zone">
|
||||
<label>Zone Controls</label>
|
||||
<description>The Controls for the Zone</description>
|
||||
<channels>
|
||||
<channel id="power" typeId="system.power"/>
|
||||
<channel id="source" typeId="dax88-source"/>
|
||||
<channel id="volume" typeId="system.volume"/>
|
||||
<channel id="mute" typeId="system.mute"/>
|
||||
<channel id="treble" typeId="dax88-treble"/>
|
||||
<channel id="bass" typeId="dax88-bass"/>
|
||||
<channel id="balance" typeId="dax88-balance"/>
|
||||
<channel id="dnd" typeId="dax88-dnd"/>
|
||||
<channel id="page" typeId="dax88-page"/>
|
||||
<channel id="keypad" typeId="dax88-keypad"/>
|
||||
</channels>
|
||||
</channel-group-type>
|
||||
|
||||
<channel-type id="dax88-allpower">
|
||||
<item-type>Switch</item-type>
|
||||
<label>All On</label>
|
||||
<description>Turn All Zones On or Off</description>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="dax88-source">
|
||||
<item-type>Number</item-type>
|
||||
<label>Source Input</label>
|
||||
<description>Select the Source Input</description>
|
||||
<state min="1" max="8"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="dax88-treble">
|
||||
<item-type>Number</item-type>
|
||||
<label>Treble Adjustment</label>
|
||||
<description>Adjust the Treble</description>
|
||||
<state min="-12" max="12" step="1" pattern="%d"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="dax88-bass">
|
||||
<item-type>Number</item-type>
|
||||
<label>Bass Adjustment</label>
|
||||
<description>Adjust the Bass</description>
|
||||
<state min="-12" max="12" step="1" pattern="%d"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="dax88-balance">
|
||||
<item-type>Number</item-type>
|
||||
<label>Balance Adjustment</label>
|
||||
<description>Adjust the Balance</description>
|
||||
<state min="-10" max="10" step="1" pattern="%d"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="dax88-dnd">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Do Not Disturb</label>
|
||||
<description>Controls if the Zone Should Ignore an Incoming Audio Page</description>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="dax88-page">
|
||||
<item-type>Contact</item-type>
|
||||
<label>Page Active</label>
|
||||
<description>Indicates if the Page Mode is Active for This Zone</description>
|
||||
<state readOnly="true">
|
||||
<options>
|
||||
<option value="CLOSED">Inactive</option>
|
||||
<option value="OPEN">Active</option>
|
||||
</options>
|
||||
</state>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="dax88-keypad">
|
||||
<item-type>Contact</item-type>
|
||||
<label>Keypad Connected</label>
|
||||
<description>Indicates if a Physical Keypad is Attached to This Zone</description>
|
||||
<state readOnly="true">
|
||||
<options>
|
||||
<option value="CLOSED">Disconnected</option>
|
||||
<option value="OPEN">Connected</option>
|
||||
</options>
|
||||
</state>
|
||||
</channel-type>
|
||||
|
||||
</thing:thing-descriptions>
|
|
@ -100,13 +100,12 @@
|
|||
<parameter name="host" type="text" required="false">
|
||||
<context>network-address</context>
|
||||
<label>Address</label>
|
||||
<description>Host Name or IP Address of the Amplifier or Serial over IP device</description>
|
||||
<description>Host Name or IP Address of the Monoprice Amplifier or Serial over IP device</description>
|
||||
</parameter>
|
||||
<parameter name="port" type="integer" min="1" max="65535" required="false">
|
||||
<label>Port</label>
|
||||
<description>Communication Port for Serial over IP connection to the Amplifier (Default 8080 for amps with built-in
|
||||
Serial over IP)</description>
|
||||
<default>8080</default>
|
||||
<description>Communication Port for Serial over IP connection to the Monoprice Amplifier (8080 for amps with
|
||||
built-in Serial over IP)</description>
|
||||
</parameter>
|
||||
<parameter name="numZones" type="integer" min="1" max="18" required="true">
|
||||
<label>Number of Zones</label>
|
||||
|
@ -116,7 +115,7 @@
|
|||
</parameter>
|
||||
<parameter name="pollingInterval" type="integer" min="5" max="60" unit="s" required="false">
|
||||
<label>Polling Interval</label>
|
||||
<description>Configures How Often to Poll the Controller to Check for Zone Updates (5-60; Default 15)</description>
|
||||
<description>Configures How Often to Poll the Amplifier to Check for Zone Updates (5-60; Default 15)</description>
|
||||
<default>15</default>
|
||||
</parameter>
|
||||
<parameter name="ignoreZones" type="text" required="false">
|
||||
|
@ -160,6 +159,11 @@
|
|||
<description>Friendly Name for the Input Source to Be Displayed in the UI (ie: Chromecast, Radio, CD, etc.)</description>
|
||||
<default>Source 6</default>
|
||||
</parameter>
|
||||
<parameter name="disableKeypadPolling" type="boolean" required="false">
|
||||
<label>Disable Keypad Polling</label>
|
||||
<description>If physical keypads are not used, this option will disable polling the amplifier for zone updates</description>
|
||||
<default>false</default>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</thing-type>
|
||||
|
|
@ -0,0 +1,154 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<thing:thing-descriptions bindingId="monopriceaudio"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
|
||||
|
||||
<!-- Monoprice 31028/PAM1270 Amplifier Thing -->
|
||||
<thing-type id="monoprice70">
|
||||
<label>Monoprice 31028 70V Amplifier</label>
|
||||
<description>
|
||||
A Multi-zone Whole House Amplifier System
|
||||
</description>
|
||||
|
||||
<channel-groups>
|
||||
<channel-group id="all" typeId="monoprice70-all">
|
||||
<label>All Zones</label>
|
||||
<description>Control All Zones Simultaneously</description>
|
||||
</channel-group>
|
||||
<channel-group id="zone1" typeId="monoprice70-zone">
|
||||
<label>Zone 1</label>
|
||||
<description>The Controls for Zone 1</description>
|
||||
</channel-group>
|
||||
<channel-group id="zone2" typeId="monoprice70-zone">
|
||||
<label>Zone 2</label>
|
||||
<description>The Controls for Zone 2</description>
|
||||
</channel-group>
|
||||
<channel-group id="zone3" typeId="monoprice70-zone">
|
||||
<label>Zone 3</label>
|
||||
<description>The Controls for Zone 3</description>
|
||||
</channel-group>
|
||||
<channel-group id="zone4" typeId="monoprice70-zone">
|
||||
<label>Zone 4</label>
|
||||
<description>The Controls for Zone 4</description>
|
||||
</channel-group>
|
||||
<channel-group id="zone5" typeId="monoprice70-zone">
|
||||
<label>Zone 5</label>
|
||||
<description>The Controls for Zone 5</description>
|
||||
</channel-group>
|
||||
<channel-group id="zone6" typeId="monoprice70-zone">
|
||||
<label>Zone 6</label>
|
||||
<description>The Controls for Zone 6</description>
|
||||
</channel-group>
|
||||
</channel-groups>
|
||||
|
||||
<config-description>
|
||||
<parameter name="serialPort" type="text" required="false">
|
||||
<context>serial-port</context>
|
||||
<limitToOptions>false</limitToOptions>
|
||||
<label>Serial Port</label>
|
||||
<description>Serial Port to Use for Connecting to the Monoprice Amplifier</description>
|
||||
</parameter>
|
||||
<parameter name="host" type="text" required="false">
|
||||
<context>network-address</context>
|
||||
<label>Address</label>
|
||||
<description>Host Name or IP Address of the Machine Connected to the Monoprice Amplifier (Serial over IP)</description>
|
||||
</parameter>
|
||||
<parameter name="port" type="integer" min="1" max="65535" required="false">
|
||||
<label>Port</label>
|
||||
<description>Communication Port for Serial over IP connection to the Monoprice Amplifier</description>
|
||||
</parameter>
|
||||
<parameter name="numZones" type="integer" min="1" max="6" required="true">
|
||||
<label>Number of Zones</label>
|
||||
<description>Number of Zones on the Amplifier to Utilize in the Binding</description>
|
||||
<default>6</default>
|
||||
</parameter>
|
||||
<parameter name="pollingInterval" type="integer" min="5" max="60" unit="s" required="false">
|
||||
<label>Polling Interval</label>
|
||||
<description>Configures How Often to Poll the Amplifier to Check for Zone Updates (5-60; Default 30)</description>
|
||||
<default>30</default>
|
||||
</parameter>
|
||||
<parameter name="ignoreZones" type="text" required="false">
|
||||
<label>Ignore Zones</label>
|
||||
<description>(Optional) A Comma Seperated List of Zone Numbers That Will Ignore the 'All Zone' (Except All Off)
|
||||
Commands (ie: 1,5,6)</description>
|
||||
</parameter>
|
||||
<parameter name="initialAllVolume" type="integer" min="1" max="30" required="false">
|
||||
<label>Initial All Volume</label>
|
||||
<description>When 'All' Zones Are Activated, the Volume Will Reset to This Value (1-30; default 10) to Prevent
|
||||
Excessive Blaring of Sound ;)</description>
|
||||
<default>10</default>
|
||||
</parameter>
|
||||
<parameter name="inputLabel1" type="text" required="false">
|
||||
<label>Source 0 Input Label</label>
|
||||
<description>Friendly Name for the Input Source to Be Displayed in the UI (ie: Chromecast, Radio, CD, etc.)</description>
|
||||
<default>Source 0 - Bus</default>
|
||||
</parameter>
|
||||
<parameter name="inputLabel2" type="text" required="false">
|
||||
<label>Source 1 Input Label</label>
|
||||
<description>Friendly Name for the Input Source to Be Displayed in the UI (ie: Chromecast, Radio, CD, etc.)</description>
|
||||
<default>Source 1 - Line</default>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</thing-type>
|
||||
|
||||
<channel-group-type id="monoprice70-all">
|
||||
<label>All Zones</label>
|
||||
<description>Control All Zones Simultaneously</description>
|
||||
<channels>
|
||||
<channel id="allpower" typeId="monoprice70-allpower"/>
|
||||
<channel id="allsource" typeId="monoprice70-source"/>
|
||||
<channel id="allvolume" typeId="system.volume"/>
|
||||
<channel id="allmute" typeId="system.mute"/>
|
||||
</channels>
|
||||
</channel-group-type>
|
||||
|
||||
<channel-group-type id="monoprice70-zone">
|
||||
<label>Zone Controls</label>
|
||||
<description>The Controls for the Zone</description>
|
||||
<channels>
|
||||
<channel id="power" typeId="system.power"/>
|
||||
<channel id="source" typeId="monoprice70-source"/>
|
||||
<channel id="volume" typeId="system.volume"/>
|
||||
<channel id="mute" typeId="system.mute"/>
|
||||
<channel id="treble" typeId="monoprice70-treble"/>
|
||||
<channel id="bass" typeId="monoprice70-bass"/>
|
||||
<channel id="balance" typeId="monoprice70-balance"/>
|
||||
</channels>
|
||||
</channel-group-type>
|
||||
|
||||
<channel-type id="monoprice70-allpower">
|
||||
<item-type>Switch</item-type>
|
||||
<label>All On</label>
|
||||
<description>Turn All Zones On or Off</description>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="monoprice70-source">
|
||||
<item-type>Number</item-type>
|
||||
<label>Source Input</label>
|
||||
<description>Select the Source Input</description>
|
||||
<state min="0" max="1"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="monoprice70-treble">
|
||||
<item-type>Number</item-type>
|
||||
<label>Treble Adjustment</label>
|
||||
<description>Adjust the Treble</description>
|
||||
<state min="-7" max="7" step="1" pattern="%d"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="monoprice70-bass">
|
||||
<item-type>Number</item-type>
|
||||
<label>Bass Adjustment</label>
|
||||
<description>Adjust the Bass</description>
|
||||
<state min="-7" max="7" step="1" pattern="%d"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="monoprice70-balance">
|
||||
<item-type>Number</item-type>
|
||||
<label>Balance Adjustment</label>
|
||||
<description>Adjust the Balance</description>
|
||||
<state min="-32" max="31" step="1" pattern="%d"/>
|
||||
</channel-type>
|
||||
|
||||
</thing:thing-descriptions>
|
|
@ -0,0 +1,256 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<thing:thing-descriptions bindingId="monopriceaudio"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
|
||||
|
||||
<!-- Xantech 8x8 Amplifier Thing -->
|
||||
<thing-type id="xantech">
|
||||
<label>Xantech 8x8 Amplifier</label>
|
||||
<description>
|
||||
A Multi-zone Whole House Amplifier System
|
||||
</description>
|
||||
|
||||
<channel-groups>
|
||||
<channel-group id="all" typeId="xantech-all">
|
||||
<label>All Zones</label>
|
||||
<description>Control All Zones Simultaneously</description>
|
||||
</channel-group>
|
||||
<channel-group id="zone1" typeId="xantech-zone">
|
||||
<label>Zone 1</label>
|
||||
<description>The Controls for Zone 1</description>
|
||||
</channel-group>
|
||||
<channel-group id="zone2" typeId="xantech-zone">
|
||||
<label>Zone 2</label>
|
||||
<description>The Controls for Zone 2</description>
|
||||
</channel-group>
|
||||
<channel-group id="zone3" typeId="xantech-zone">
|
||||
<label>Zone 3</label>
|
||||
<description>The Controls for Zone 3</description>
|
||||
</channel-group>
|
||||
<channel-group id="zone4" typeId="xantech-zone">
|
||||
<label>Zone 4</label>
|
||||
<description>The Controls for Zone 4</description>
|
||||
</channel-group>
|
||||
<channel-group id="zone5" typeId="xantech-zone">
|
||||
<label>Zone 5</label>
|
||||
<description>The Controls for Zone 5</description>
|
||||
</channel-group>
|
||||
<channel-group id="zone6" typeId="xantech-zone">
|
||||
<label>Zone 6</label>
|
||||
<description>The Controls for Zone 6</description>
|
||||
</channel-group>
|
||||
<channel-group id="zone7" typeId="xantech-zone">
|
||||
<label>Zone 7</label>
|
||||
<description>The Controls for Zone 7</description>
|
||||
</channel-group>
|
||||
<channel-group id="zone8" typeId="xantech-zone">
|
||||
<label>Zone 8</label>
|
||||
<description>The Controls for Zone 8</description>
|
||||
</channel-group>
|
||||
<channel-group id="zone9" typeId="xantech-zone">
|
||||
<label>Zone 9</label>
|
||||
<description>The Controls for Zone 9</description>
|
||||
</channel-group>
|
||||
<channel-group id="zone10" typeId="xantech-zone">
|
||||
<label>Zone 10</label>
|
||||
<description>The Controls for Zone 10</description>
|
||||
</channel-group>
|
||||
<channel-group id="zone11" typeId="xantech-zone">
|
||||
<label>Zone 11</label>
|
||||
<description>The Controls for Zone 11</description>
|
||||
</channel-group>
|
||||
<channel-group id="zone12" typeId="xantech-zone">
|
||||
<label>Zone 12</label>
|
||||
<description>The Controls for Zone 12</description>
|
||||
</channel-group>
|
||||
<channel-group id="zone13" typeId="xantech-zone">
|
||||
<label>Zone 13</label>
|
||||
<description>The Controls for Zone 13</description>
|
||||
</channel-group>
|
||||
<channel-group id="zone14" typeId="xantech-zone">
|
||||
<label>Zone 14</label>
|
||||
<description>The Controls for Zone 14</description>
|
||||
</channel-group>
|
||||
<channel-group id="zone15" typeId="xantech-zone">
|
||||
<label>Zone 15</label>
|
||||
<description>The Controls for Zone 15</description>
|
||||
</channel-group>
|
||||
<channel-group id="zone16" typeId="xantech-zone">
|
||||
<label>Zone 16</label>
|
||||
<description>The Controls for Zone 16</description>
|
||||
</channel-group>
|
||||
</channel-groups>
|
||||
|
||||
<config-description>
|
||||
<parameter name="serialPort" type="text" required="false">
|
||||
<context>serial-port</context>
|
||||
<limitToOptions>false</limitToOptions>
|
||||
<label>Serial Port</label>
|
||||
<description>Serial Port to Use for Connecting to the Xantech Amplifier</description>
|
||||
</parameter>
|
||||
<parameter name="host" type="text" required="false">
|
||||
<context>network-address</context>
|
||||
<label>Address</label>
|
||||
<description>Host Name or IP Address of the Machine Connected to the Xantech Amplifier (Serial over IP)</description>
|
||||
</parameter>
|
||||
<parameter name="port" type="integer" min="1" max="65535" required="false">
|
||||
<label>Port</label>
|
||||
<description>Communication Port for Serial over IP connection to the Xantech Amplifier</description>
|
||||
</parameter>
|
||||
<parameter name="numZones" type="integer" min="1" max="16" required="true">
|
||||
<label>Number of Zones</label>
|
||||
<description>Number of Zones on the Amplifier to Utilize in the Binding (Up to 16 Zones With 2 Amplifiers Connected
|
||||
Together)</description>
|
||||
<default>8</default>
|
||||
</parameter>
|
||||
<parameter name="pollingInterval" type="integer" min="5" max="60" unit="s" required="false">
|
||||
<label>Polling Interval</label>
|
||||
<description>Configures How Often to Poll the Amplifier to Check for Zone Updates (5-60; Default 30)</description>
|
||||
<default>30</default>
|
||||
</parameter>
|
||||
<parameter name="ignoreZones" type="text" required="false">
|
||||
<label>Ignore Zones</label>
|
||||
<description>(Optional) A Comma Seperated List of Zone Numbers That Will Ignore the 'All Zone' (Except All Off)
|
||||
Commands (ie: 1,6,10)</description>
|
||||
</parameter>
|
||||
<parameter name="initialAllVolume" type="integer" min="1" max="30" required="false">
|
||||
<label>Initial All Volume</label>
|
||||
<description>When 'All' Zones Are Activated, the Volume Will Reset to This Value (1-30; default 10) to Prevent
|
||||
Excessive Blaring of Sound ;)</description>
|
||||
<default>10</default>
|
||||
</parameter>
|
||||
<parameter name="inputLabel1" type="text" required="false">
|
||||
<label>Source 1 Input Label</label>
|
||||
<description>Friendly Name for the Input Source to Be Displayed in the UI (ie: Chromecast, Radio, CD, etc.)</description>
|
||||
<default>Source 1</default>
|
||||
</parameter>
|
||||
<parameter name="inputLabel2" type="text" required="false">
|
||||
<label>Source 2 Input Label</label>
|
||||
<description>Friendly Name for the Input Source to Be Displayed in the UI (ie: Chromecast, Radio, CD, etc.)</description>
|
||||
<default>Source 2</default>
|
||||
</parameter>
|
||||
<parameter name="inputLabel3" type="text" required="false">
|
||||
<label>Source 3 Input Label</label>
|
||||
<description>Friendly Name for the Input Source to Be Displayed in the UI (ie: Chromecast, Radio, CD, etc.)</description>
|
||||
<default>Source 3</default>
|
||||
</parameter>
|
||||
<parameter name="inputLabel4" type="text" required="false">
|
||||
<label>Source 4 Input Label</label>
|
||||
<description>Friendly Name for the Input Source to Be Displayed in the UI (ie: Chromecast, Radio, CD, etc.)</description>
|
||||
<default>Source 4</default>
|
||||
</parameter>
|
||||
<parameter name="inputLabel5" type="text" required="false">
|
||||
<label>Source 5 Input Label</label>
|
||||
<description>Friendly Name for the Input Source to Be Displayed in the UI (ie: Chromecast, Radio, CD, etc.)</description>
|
||||
<default>Source 5</default>
|
||||
</parameter>
|
||||
<parameter name="inputLabel6" type="text" required="false">
|
||||
<label>Source 6 Input Label</label>
|
||||
<description>Friendly Name for the Input Source to Be Displayed in the UI (ie: Chromecast, Radio, CD, etc.)</description>
|
||||
<default>Source 6</default>
|
||||
</parameter>
|
||||
<parameter name="inputLabel7" type="text" required="false">
|
||||
<label>Source 7 Input Label</label>
|
||||
<description>Friendly Name for the Input Source to Be Displayed in the UI (ie: Chromecast, Radio, CD, etc.)</description>
|
||||
<default>Source 7</default>
|
||||
</parameter>
|
||||
<parameter name="inputLabel8" type="text" required="false">
|
||||
<label>Source 8 Input Label</label>
|
||||
<description>Friendly Name for the Input Source to Be Displayed in the UI (ie: Chromecast, Radio, CD, etc.)</description>
|
||||
<default>Source 8</default>
|
||||
</parameter>
|
||||
<parameter name="disableKeypadPolling" type="boolean" required="false">
|
||||
<label>Disable Keypad Polling</label>
|
||||
<description>If physical keypads are not used, this option will disable polling the amplifier for zone updates</description>
|
||||
<default>false</default>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</thing-type>
|
||||
|
||||
<channel-group-type id="xantech-all">
|
||||
<label>All Zones</label>
|
||||
<description>Control All Zones Simultaneously</description>
|
||||
<channels>
|
||||
<channel id="allpower" typeId="xantech-allpower"/>
|
||||
<channel id="allsource" typeId="xantech-source"/>
|
||||
<channel id="allvolume" typeId="system.volume"/>
|
||||
<channel id="allmute" typeId="system.mute"/>
|
||||
</channels>
|
||||
</channel-group-type>
|
||||
|
||||
<channel-group-type id="xantech-zone">
|
||||
<label>Zone Controls</label>
|
||||
<description>The Controls for the Zone</description>
|
||||
<channels>
|
||||
<channel id="power" typeId="system.power"/>
|
||||
<channel id="source" typeId="xantech-source"/>
|
||||
<channel id="volume" typeId="system.volume"/>
|
||||
<channel id="mute" typeId="system.mute"/>
|
||||
<channel id="treble" typeId="xantech-treble"/>
|
||||
<channel id="bass" typeId="xantech-bass"/>
|
||||
<channel id="balance" typeId="xantech-balance"/>
|
||||
<channel id="page" typeId="xantech-page"/>
|
||||
<channel id="keypad" typeId="xantech-keypad"/>
|
||||
</channels>
|
||||
</channel-group-type>
|
||||
|
||||
<channel-type id="xantech-allpower">
|
||||
<item-type>Switch</item-type>
|
||||
<label>All On</label>
|
||||
<description>Turn All Zones On or Off</description>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="xantech-source">
|
||||
<item-type>Number</item-type>
|
||||
<label>Source Input</label>
|
||||
<description>Select the Source Input</description>
|
||||
<state min="1" max="8"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="xantech-treble">
|
||||
<item-type>Number</item-type>
|
||||
<label>Treble Adjustment</label>
|
||||
<description>Adjust the Treble</description>
|
||||
<state min="-7" max="7" step="1" pattern="%d"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="xantech-bass">
|
||||
<item-type>Number</item-type>
|
||||
<label>Bass Adjustment</label>
|
||||
<description>Adjust the Bass</description>
|
||||
<state min="-7" max="7" step="1" pattern="%d"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="xantech-balance">
|
||||
<item-type>Number</item-type>
|
||||
<label>Balance Adjustment</label>
|
||||
<description>Adjust the Balance</description>
|
||||
<state min="-32" max="31" step="1" pattern="%d"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="xantech-page">
|
||||
<item-type>Contact</item-type>
|
||||
<label>Page Active</label>
|
||||
<description>Indicates if the Page Mode is Active for This Zone</description>
|
||||
<state readOnly="true">
|
||||
<options>
|
||||
<option value="CLOSED">Inactive</option>
|
||||
<option value="OPEN">Active</option>
|
||||
</options>
|
||||
</state>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="xantech-keypad">
|
||||
<item-type>Contact</item-type>
|
||||
<label>Keypad Connected</label>
|
||||
<description>Indicates if a Physical Keypad is Attached to This Zone</description>
|
||||
<state readOnly="true">
|
||||
<options>
|
||||
<option value="CLOSED">Disconnected</option>
|
||||
<option value="OPEN">Connected</option>
|
||||
</options>
|
||||
</state>
|
||||
</channel-type>
|
||||
|
||||
</thing:thing-descriptions>
|
Loading…
Reference in New Issue