mirror of
https://github.com/openhab/openhab-addons.git
synced 2025-01-10 07:02:02 +01:00
[rotel] Support added for model RX-1052 (#16486)
* Two new channels to enable/disable speaker A and speaker B Signed-off-by: Laurent Garnier <lg.hc@free.fr>
This commit is contained in:
parent
d68adfab21
commit
0d308665c7
@ -22,7 +22,7 @@ You can connect it for example to a Raspberry Pi and use [ser2net Linux tool](ht
|
||||
Recent devices provide a network interface (RJ45 connector).
|
||||
So you can use the device IP to connect to the device, keeping 9590 as default port.
|
||||
|
||||
The binding has been tested with a RSP-1066 and a RSP-1570.
|
||||
The binding has been tested with an RSP-1066, an RSP-1570 and an RX-1052.
|
||||
|
||||
## Supported Things
|
||||
|
||||
@ -72,6 +72,7 @@ This binding supports the following thing types:
|
||||
| rt09 | Connection to the Rotel RT-09 tuner |
|
||||
| rt11 | Connection to the Rotel RT-11 tuner |
|
||||
| rt1570 | Connection to the Rotel RT-1570 tuner |
|
||||
| rx1052 | Connection to the Rotel RX-1052 stereo receiver |
|
||||
| s5 | Connection to the Rotel Michi S5 stereo amplifier |
|
||||
| t11 | Connection to the Rotel T11 tuner |
|
||||
| t14 | Connection to the Rotel T14 tuner |
|
||||
@ -95,6 +96,7 @@ The thing requires the following configuration parameters:
|
||||
| Parameter Label | Parameter ID | Description | Accepted values |
|
||||
|-------------------------|------------------|-------------------------------------------------------|-----------------|
|
||||
| Serial Port | serialPort | Serial port to use for connecting to the Rotel device | |
|
||||
| Baud Rate | baudRate | Baud rate to use for connecting to the Rotel device | 19200, 38400 |
|
||||
| Address | host | Host name or IP address of the Rotel device (IP connection) or the machine connected to the Rotel device (serial over IP) | |
|
||||
| Port | port | Communication port (IP or serial over IP). For IP connection to the Rotel device, keep the default port (9590) | |
|
||||
| Protocol Version | Protocol | Choose one of the two protocol versions (depends on your device firmware). Default is ASCII_V2 | ASCII_V1 or ASCII_V2 |
|
||||
@ -135,7 +137,7 @@ Some have additional parameters listed in the next table:
|
||||
| rsx1550 | inputLabelCd, inputLabelTuner, inputLabelTape, inputLabelVideo1, inputLabelVideo2, inputLabelVideo3, inputLabelVideo4, inputLabelVideo5, inputLabelMulti |
|
||||
| rsx1560 | inputLabelCd, inputLabelTuner, inputLabelTape, inputLabelVideo1, inputLabelVideo2, inputLabelVideo3, inputLabelVideo4, inputLabelVideo5, inputLabelMulti |
|
||||
| rsx1562 | inputLabelCd, inputLabelTuner, inputLabelUsb, inputLabelVideo1, inputLabelVideo2, inputLabelVideo3, inputLabelVideo4, inputLabelVideo5, inputLabelVideo6, inputLabelMulti |
|
||||
|
||||
| rx1052 | baudRate, inputLabelVideo1, inputLabelVideo2, inputLabelVideo3, inputLabelVideo4 |
|
||||
Some notes:
|
||||
|
||||
- On Linux, you may get an error stating the serial port cannot be opened when the Rotel 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`.
|
||||
@ -154,7 +156,7 @@ The following channels are available:
|
||||
|--------------|---------------------|-----------|---------------------------------------|------------------------------------|
|
||||
| power, mainZone#power, allZones#power, zone2#power, zone3#power, zone4#power | Power | Switch | Power ON/OFF the equipment or the zone | ON, OFF |
|
||||
| source, mainZone#source, zone1#source, zone2#source, zone3#source, zone4#source | Source Input | String | Select the source input | CD, TUNER, TAPE, VIDEO1, VIDEO2, VIDEO3, VIDEO4, VIDEO5, VIDEO6, VIDEO7, VIDEO8, USB, PCUSB, MULTI, PHONO, BLUETOOTH, AUX, AUX1, AUX2, AUX1_COAX, AUX1_OPTICAL, COAX1, COAX2, COAX3, OPTICAL1, OPTICAL2, OPTICAL3, XLR, RCD, FM, DAB, PLAYFI, IRADIO, NETWORK, INPUTA, INPUTB, INPUTC, INPUTD |
|
||||
| mainZone#recordSource | Record Source | String | Select the source to be recorded | CD, TUNER, TAPE, VIDEO1, VIDEO2, VIDEO3, VIDEO4, VIDEO5, VIDEO6, USB, MAIN |
|
||||
| mainZone#recordSource | Record Source | String | Select the source to be recorded | CD, TUNER, TAPE, VIDEO1, VIDEO2, VIDEO3, VIDEO4, VIDEO5, VIDEO6, USB, PHONO, MAIN |
|
||||
| dsp, mainZone#dsp | DSP Mode | String | Select the DSP mode | NONE, STEREO3, STEREO5, STEREO7, STEREO9, STEREO11, MUSIC1, MUSIC2, MUSIC3, MUSIC4, PROLOGIC, PLIICINEMA, PLIIMUSIC, PLIIGAME, PLIIXCINEMA, PLIIXMUSIC, PLIIXGAME, PLIIZ, NEO6MUSIC, NEO6CINEMA, ATMOS, NEURALX, BYPASS |
|
||||
| mainZone#volumeUpDown, zone2#volumeUpDown | Volume | Number | Increase or decrease the volume | INCREASE, DECREASE, value |
|
||||
| volume, mainZone#volume, zone1#volume, zone2#volume, zone3#volume, zone4#volume | Volume | Dimmer | Adjust the volume | value between 0 and 100 |
|
||||
@ -221,6 +223,7 @@ Here are the list of channels available for each thing type:
|
||||
| rt09 | power, source, playControl, brightness |
|
||||
| rt11 | power, source, radioPreset, brightness |
|
||||
| rt1570 | power, source, radioPreset, brightness |
|
||||
| rx1052 | mainZone#power, mainZone#source, mainZone#recordSource, mainZone#volume, mainZone#mute, mainZone#bass, mainZone#treble, mainZone#speakera, mainZone#speakerb, mainZone#line1, mainZone#otherCommand, zone2#power, zone2#source, zone2#volume, zone2#mute, zone3#power, zone3#source, zone3#volume, zone3#mute, zone4#power, zone4#source, zone4#volume, zone4#mute |
|
||||
| s5 | power, brightness |
|
||||
| t11 | power, source, radioPreset, brightness |
|
||||
| t14 | power, source, radioPreset, brightness |
|
||||
@ -270,6 +273,7 @@ Here are the available commands for the otherCommand channel depending on the th
|
||||
| rsx1550 | DSP_TOGGLE, PROLOGIC_TOGGLE, DOLBY_TOGGLE, PLII_PANORAMA_TOGGLE, PLII_DIMENSION_UP, PLII_DIMENSION_DOWN, PLII_CENTER_WIDTH_UP, PLII_CENTER_WIDTH_DOWN, DDEX_TOGGLE, NEO6_TOGGLE, NEXT_MODE, TUNE_UP, TUNE_DOWN, PRESET_UP, PRESET_DOWN, FREQUENCY_UP, FREQUENCY_DOWN, MEMORY, BAND_TOGGLE, AM, FM, TUNE_PRESET_TOGGLE, TUNING_MODE_SELECT, PRESET_MODE_SELECT, FREQUENCY_DIRECT, PRESET_SCAN, TUNER_DISPLAY, RDS_PTY, RDS_TP, RDS_TA, FM_MONO_TOGGLE, ZONE2_TUNE_UP, ZONE2_TUNE_DOWN, ZONE2_PRESET_UP, ZONE2_PRESET_DOWN, ZONE2_FREQUENCY_UP, ZONE2_FREQUENCY_DOWN, ZONE2_BAND_TOGGLE, ZONE2_AM, ZONE2_FM, ZONE2_TUNE_PRESET_TOGGLE, ZONE2_TUNING_MODE_SELECT, ZONE2_PRESET_MODE_SELECT, ZONE2_PRESET_SCAN, ZONE2_FM_MONO_TOGGLE, ZONE3_TUNE_UP, ZONE3_TUNE_DOWN, ZONE3_PRESET_UP, ZONE3_PRESET_DOWN, ZONE3_FREQUENCY_UP, ZONE3_FREQUENCY_DOWN, ZONE3_BAND_TOGGLE, ZONE3_AM, ZONE3_FM, ZONE3_TUNE_PRESET_TOGGLE, ZONE3_TUNING_MODE_SELECT, ZONE3_PRESET_MODE_SELECT, ZONE3_PRESET_SCAN, ZONE3_FM_MONO_TOGGLE, ZONE4_TUNE_UP, ZONE4_TUNE_DOWN, ZONE4_PRESET_UP, ZONE4_PRESET_DOWN, ZONE4_FREQUENCY_UP, ZONE4_FREQUENCY_DOWN, ZONE4_BAND_TOGGLE, ZONE4_AM, ZONE4_FM, ZONE4_TUNE_PRESET_TOGGLE, ZONE4_TUNING_MODE_SELECT, ZONE4_PRESET_MODE_SELECT, ZONE4_PRESET_SCAN, ZONE4_FM_MONO_TOGGLE, KEY1, KEY2, KEY3, KEY4, KEY5, KEY6, KEY7, KEY8, KEY9, KEY0, ZONE2_KEY1, ZONE2_KEY2, ZONE2_KEY3, ZONE2_KEY4, ZONE2_KEY5, ZONE2_KEY6, ZONE2_KEY7, ZONE2_KEY8, ZONE2_KEY9, ZONE2_KEY0, ZONE3_KEY1, ZONE3_KEY2, ZONE3_KEY3, ZONE3_KEY4, ZONE3_KEY5, ZONE3_KEY6, ZONE3_KEY7, ZONE3_KEY8, ZONE3_KEY9, ZONE3_KEY0, ZONE4_KEY1, ZONE4_KEY2, ZONE4_KEY3, ZONE4_KEY4, ZONE4_KEY5, ZONE4_KEY6, ZONE4_KEY7, ZONE4_KEY8, ZONE4_KEY9, ZONE4_KEY0, MENU, UP, DOWN, LEFT, RIGHT, ENTER, RECORD_FONCTION_SELECT, TONE_CONTROL_SELECT, DYNAMIC_RANGE, DIGITAL_INPUT_SELECT, ZONE_TOGGLE, CENTER_TRIM, SUB_TRIM, SURROUND_TRIM, CINEMA_EQ_TOGGLE, POWER_OFF_ALL_ZONES, PARTY_MODE_TOGGLE, ZONE2_PARTY_MODE_TOGGLE, ZONE3_PARTY_MODE_TOGGLE, ZONE4_PARTY_MODE_TOGGLE, OUTPUT_RESOLUTION, HDMI_AMP_MODE, HDMI_TV_MODE, RESET_FACTORY |
|
||||
| rsx1560 | DSP_TOGGLE, PROLOGIC_TOGGLE, DOLBY_TOGGLE, PLII_PANORAMA_TOGGLE, PLII_DIMENSION_UP, PLII_DIMENSION_DOWN, PLII_CENTER_WIDTH_UP, PLII_CENTER_WIDTH_DOWN, DDEX_TOGGLE, NEO6_TOGGLE, NEXT_MODE, TUNE_UP, TUNE_DOWN, PRESET_UP, PRESET_DOWN, FREQUENCY_UP, FREQUENCY_DOWN, MEMORY, BAND_TOGGLE, AM, FM, TUNE_PRESET_TOGGLE, TUNING_MODE_SELECT, PRESET_MODE_SELECT, FREQUENCY_DIRECT, PRESET_SCAN, TUNER_DISPLAY, RDS_PTY, RDS_TP, RDS_TA, FM_MONO_TOGGLE, ZONE2_TUNE_UP, ZONE2_TUNE_DOWN, ZONE2_PRESET_UP, ZONE2_PRESET_DOWN, ZONE2_FREQUENCY_UP, ZONE2_FREQUENCY_DOWN, ZONE2_BAND_TOGGLE, ZONE2_AM, ZONE2_FM, ZONE2_TUNE_PRESET_TOGGLE, ZONE2_TUNING_MODE_SELECT, ZONE2_PRESET_MODE_SELECT, ZONE2_PRESET_SCAN, ZONE2_FM_MONO_TOGGLE, ZONE3_TUNE_UP, ZONE3_TUNE_DOWN, ZONE3_PRESET_UP, ZONE3_PRESET_DOWN, ZONE3_FREQUENCY_UP, ZONE3_FREQUENCY_DOWN, ZONE3_BAND_TOGGLE, ZONE3_AM, ZONE3_FM, ZONE3_TUNE_PRESET_TOGGLE, ZONE3_TUNING_MODE_SELECT, ZONE3_PRESET_MODE_SELECT, ZONE3_PRESET_SCAN, ZONE3_FM_MONO_TOGGLE, ZONE4_TUNE_UP, ZONE4_TUNE_DOWN, ZONE4_PRESET_UP, ZONE4_PRESET_DOWN, ZONE4_FREQUENCY_UP, ZONE4_FREQUENCY_DOWN, ZONE4_BAND_TOGGLE, ZONE4_AM, ZONE4_FM, ZONE4_TUNE_PRESET_TOGGLE, ZONE4_TUNING_MODE_SELECT, ZONE4_PRESET_MODE_SELECT, ZONE4_PRESET_SCAN, ZONE4_FM_MONO_TOGGLE, KEY1, KEY2, KEY3, KEY4, KEY5, KEY6, KEY7, KEY8, KEY9, KEY0, ZONE2_KEY1, ZONE2_KEY2, ZONE2_KEY3, ZONE2_KEY4, ZONE2_KEY5, ZONE2_KEY6, ZONE2_KEY7, ZONE2_KEY8, ZONE2_KEY9, ZONE2_KEY0, ZONE3_KEY1, ZONE3_KEY2, ZONE3_KEY3, ZONE3_KEY4, ZONE3_KEY5, ZONE3_KEY6, ZONE3_KEY7, ZONE3_KEY8, ZONE3_KEY9, ZONE3_KEY0, ZONE4_KEY1, ZONE4_KEY2, ZONE4_KEY3, ZONE4_KEY4, ZONE4_KEY5, ZONE4_KEY6, ZONE4_KEY7, ZONE4_KEY8, ZONE4_KEY9, ZONE4_KEY0, MENU, UP, DOWN, LEFT, RIGHT, ENTER, RECORD_FONCTION_SELECT, TONE_CONTROL_SELECT, DYNAMIC_RANGE, DIGITAL_INPUT_SELECT, ZONE_TOGGLE, CENTER_TRIM, SUB_TRIM, SURROUND_TRIM, CINEMA_EQ_TOGGLE, POWER_OFF_ALL_ZONES, PARTY_MODE_TOGGLE, ZONE2_PARTY_MODE_TOGGLE, ZONE3_PARTY_MODE_TOGGLE, ZONE4_PARTY_MODE_TOGGLE, OUTPUT_RESOLUTION, HDMI_AMP_MODE, HDMI_TV_MODE, RESET_FACTORY |
|
||||
| rsx1562 | STEREO_BYPASS_TOGGLE, DSP_TOGGLE, PROLOGIC_TOGGLE, DOLBY_TOGGLE, PLII_PANORAMA_TOGGLE, PLII_DIMENSION_UP, PLII_DIMENSION_DOWN, PLII_CENTER_WIDTH_UP, PLII_CENTER_WIDTH_DOWN, DDEX_TOGGLE, NEO6_TOGGLE, NEXT_MODE, TUNE_UP, TUNE_DOWN, PRESET_UP, PRESET_DOWN, FREQUENCY_UP, FREQUENCY_DOWN, MEMORY, BAND_TOGGLE, AM, FM, TUNE_PRESET_TOGGLE, TUNING_MODE_SELECT, PRESET_MODE_SELECT, FREQUENCY_DIRECT, PRESET_SCAN, TUNER_DISPLAY, RDS_PTY, RDS_TP, RDS_TA, FM_MONO_TOGGLE, ZONE2_TUNE_UP, ZONE2_TUNE_DOWN, ZONE2_PRESET_UP, ZONE2_PRESET_DOWN, ZONE2_FREQUENCY_UP, ZONE2_FREQUENCY_DOWN, ZONE2_BAND_TOGGLE, ZONE2_AM, ZONE2_FM, ZONE2_TUNE_PRESET_TOGGLE, ZONE2_TUNING_MODE_SELECT, ZONE2_PRESET_MODE_SELECT, ZONE2_PRESET_SCAN, ZONE2_FM_MONO_TOGGLE, ZONE3_TUNE_UP, ZONE3_TUNE_DOWN, ZONE3_PRESET_UP, ZONE3_PRESET_DOWN, ZONE3_FREQUENCY_UP, ZONE3_FREQUENCY_DOWN, ZONE3_BAND_TOGGLE, ZONE3_AM, ZONE3_FM, ZONE3_TUNE_PRESET_TOGGLE, ZONE3_TUNING_MODE_SELECT, ZONE3_PRESET_MODE_SELECT, ZONE3_PRESET_SCAN, ZONE3_FM_MONO_TOGGLE, ZONE4_TUNE_UP, ZONE4_TUNE_DOWN, ZONE4_PRESET_UP, ZONE4_PRESET_DOWN, ZONE4_FREQUENCY_UP, ZONE4_FREQUENCY_DOWN, ZONE4_BAND_TOGGLE, ZONE4_AM, ZONE4_FM, ZONE4_TUNE_PRESET_TOGGLE, ZONE4_TUNING_MODE_SELECT, ZONE4_PRESET_MODE_SELECT, ZONE4_PRESET_SCAN, ZONE4_FM_MONO_TOGGLE, KEY1, KEY2, KEY3, KEY4, KEY5, KEY6, KEY7, KEY8, KEY9, KEY0, ZONE2_KEY1, ZONE2_KEY2, ZONE2_KEY3, ZONE2_KEY4, ZONE2_KEY5, ZONE2_KEY6, ZONE2_KEY7, ZONE2_KEY8, ZONE2_KEY9, ZONE2_KEY0, ZONE3_KEY1, ZONE3_KEY2, ZONE3_KEY3, ZONE3_KEY4, ZONE3_KEY5, ZONE3_KEY6, ZONE3_KEY7, ZONE3_KEY8, ZONE3_KEY9, ZONE3_KEY0, ZONE4_KEY1, ZONE4_KEY2, ZONE4_KEY3, ZONE4_KEY4, ZONE4_KEY5, ZONE4_KEY6, ZONE4_KEY7, ZONE4_KEY8, ZONE4_KEY9, ZONE4_KEY0, MENU, EXIT, UP_PRESSED, UP_RELEASED, DOWN_PRESSED, DOWN_RELEASED, LEFT_PRESSED, LEFT_RELEASED, RIGHT_PRESSED, RIGHT_RELEASED, ENTER, RECORD_FONCTION_SELECT, TONE_CONTROL_SELECT, DYNAMIC_RANGE, DIGITAL_INPUT_SELECT, ZONE_TOGGLE, CENTER_TRIM, SUB_TRIM, SURROUND_TRIM, CINEMA_EQ_TOGGLE, POWER_OFF_ALL_ZONES, PARTY_MODE_TOGGLE, ZONE2_PARTY_MODE_TOGGLE, ZONE3_PARTY_MODE_TOGGLE, ZONE4_PARTY_MODE_TOGGLE, OUTPUT_RESOLUTION, HDMI_AMP_MODE, HDMI_TV_MODE, ROOM_EQ_TOGGLE, SPEAKER_SETTING_TOGGLE, RESET_FACTORY |
|
||||
| rx1052 | TUNE_UP, TUNE_DOWN, PRESET_UP, PRESET_DOWN, FREQUENCY_UP, FREQUENCY_DOWN, MEMORY, BAND_TOGGLE, AM, FM, TUNE_PRESET_TOGGLE, TUNING_MODE_SELECT, PRESET_MODE_SELECT, FREQUENCY_DIRECT, PRESET_SCAN, FM_MONO_TOGGLE, ZONE2_TUNE_UP, ZONE2_TUNE_DOWN, ZONE2_PRESET_UP, ZONE2_PRESET_DOWN, ZONE2_FREQUENCY_UP, ZONE2_FREQUENCY_DOWN, ZONE2_BAND_TOGGLE, ZONE2_AM, ZONE2_FM, ZONE2_TUNE_PRESET_TOGGLE, ZONE2_TUNING_MODE_SELECT, ZONE2_PRESET_MODE_SELECT, ZONE2_PRESET_SCAN, ZONE2_FM_MONO_TOGGLE, ZONE3_TUNE_UP, ZONE3_TUNE_DOWN, ZONE3_PRESET_UP, ZONE3_PRESET_DOWN, ZONE3_FREQUENCY_UP, ZONE3_FREQUENCY_DOWN, ZONE3_BAND_TOGGLE, ZONE3_AM, ZONE3_FM, ZONE3_TUNE_PRESET_TOGGLE, ZONE3_TUNING_MODE_SELECT, ZONE3_PRESET_MODE_SELECT, ZONE3_PRESET_SCAN, ZONE3_FM_MONO_TOGGLE, ZONE4_TUNE_UP, ZONE4_TUNE_DOWN, ZONE4_PRESET_UP, ZONE4_PRESET_DOWN, ZONE4_FREQUENCY_UP, ZONE4_FREQUENCY_DOWN, ZONE4_BAND_TOGGLE, ZONE4_AM, ZONE4_FM, ZONE4_TUNE_PRESET_TOGGLE, ZONE4_TUNING_MODE_SELECT, ZONE4_PRESET_MODE_SELECT, ZONE4_PRESET_SCAN, ZONE4_FM_MONO_TOGGLE, KEY1, KEY2, KEY3, KEY4, KEY5, KEY6, KEY7, KEY8, KEY9, KEY0, ZONE2_KEY1, ZONE2_KEY2, ZONE2_KEY3, ZONE2_KEY4, ZONE2_KEY5, ZONE2_KEY6, ZONE2_KEY7, ZONE2_KEY8, ZONE2_KEY9, ZONE2_KEY0, ZONE3_KEY1, ZONE3_KEY2, ZONE3_KEY3, ZONE3_KEY4, ZONE3_KEY5, ZONE3_KEY6, ZONE3_KEY7, ZONE3_KEY8, ZONE3_KEY9, ZONE3_KEY0, ZONE4_KEY1, ZONE4_KEY2, ZONE4_KEY3, ZONE4_KEY4, ZONE4_KEY5, ZONE4_KEY6, ZONE4_KEY7, ZONE4_KEY8, ZONE4_KEY9, ZONE4_KEY0, POWER_OFF_ALL_ZONES, PARTY_MODE_TOGGLE, ZONE2_PARTY_MODE_TOGGLE, ZONE3_PARTY_MODE_TOGGLE, ZONE4_PARTY_MODE_TOGGLE, RECORD_FONCTION_SELECT, TONE_CONTROL_SELECT, ZONE_TOGGLE |
|
||||
| x3 | PLAY, PAUSE, STOP, TRACK_FWD, TRACK_BACK |
|
||||
| x5 | PLAY, PAUSE, STOP, TRACK_FWD, TRACK_BACK |
|
||||
|
||||
|
@ -42,6 +42,7 @@ public class RotelBindingConstants {
|
||||
public static final String THING_TYPE_ID_RSX1550 = "rsx1550";
|
||||
public static final String THING_TYPE_ID_RSX1560 = "rsx1560";
|
||||
public static final String THING_TYPE_ID_RSX1562 = "rsx1562";
|
||||
public static final String THING_TYPE_ID_RX1052 = "rx1052";
|
||||
public static final String THING_TYPE_ID_A11 = "a11";
|
||||
public static final String THING_TYPE_ID_A12 = "a12";
|
||||
public static final String THING_TYPE_ID_A14 = "a14";
|
||||
@ -91,6 +92,7 @@ public class RotelBindingConstants {
|
||||
public static final ThingTypeUID THING_TYPE_RSX1550 = new ThingTypeUID(BINDING_ID, THING_TYPE_ID_RSX1550);
|
||||
public static final ThingTypeUID THING_TYPE_RSX1560 = new ThingTypeUID(BINDING_ID, THING_TYPE_ID_RSX1560);
|
||||
public static final ThingTypeUID THING_TYPE_RSX1562 = new ThingTypeUID(BINDING_ID, THING_TYPE_ID_RSX1562);
|
||||
public static final ThingTypeUID THING_TYPE_RX1052 = new ThingTypeUID(BINDING_ID, THING_TYPE_ID_RX1052);
|
||||
public static final ThingTypeUID THING_TYPE_A11 = new ThingTypeUID(BINDING_ID, THING_TYPE_ID_A11);
|
||||
public static final ThingTypeUID THING_TYPE_A12 = new ThingTypeUID(BINDING_ID, THING_TYPE_ID_A12);
|
||||
public static final ThingTypeUID THING_TYPE_A14 = new ThingTypeUID(BINDING_ID, THING_TYPE_ID_A14);
|
||||
@ -163,6 +165,8 @@ public class RotelBindingConstants {
|
||||
public static final String CHANNEL_MAIN_MUTE = CHANNEL_GROUP_MAIN_ZONE + "#" + CHANNEL_MUTE;
|
||||
public static final String CHANNEL_MAIN_BASS = CHANNEL_GROUP_MAIN_ZONE + "#" + CHANNEL_BASS;
|
||||
public static final String CHANNEL_MAIN_TREBLE = CHANNEL_GROUP_MAIN_ZONE + "#" + CHANNEL_TREBLE;
|
||||
public static final String CHANNEL_MAIN_SPEAKER_A = CHANNEL_GROUP_MAIN_ZONE + "#" + CHANNEL_SPEAKER_A;
|
||||
public static final String CHANNEL_MAIN_SPEAKER_B = CHANNEL_GROUP_MAIN_ZONE + "#" + CHANNEL_SPEAKER_B;
|
||||
public static final String CHANNEL_MAIN_OTHER_COMMAND = CHANNEL_GROUP_MAIN_ZONE + "#" + CHANNEL_OTHER_COMMAND;
|
||||
|
||||
public static final String CHANNEL_GROUP_ZONE1 = "zone1";
|
||||
@ -332,6 +336,7 @@ public class RotelBindingConstants {
|
||||
public static final String KEY_POWER_ZONE2 = "power_zone2";
|
||||
public static final String KEY_POWER_ZONE3 = "power_zone3";
|
||||
public static final String KEY_POWER_ZONE4 = "power_zone4";
|
||||
public static final String KEY_POWER_ZONES = "power_zones";
|
||||
public static final String KEY_SOURCE_ZONE2 = "source_zone2";
|
||||
public static final String KEY_SOURCE_ZONE3 = "source_zone3";
|
||||
public static final String KEY_SOURCE_ZONE4 = "source_zone4";
|
||||
|
@ -14,10 +14,7 @@ package org.openhab.binding.rotel.internal;
|
||||
|
||||
import static org.openhab.binding.rotel.internal.RotelBindingConstants.*;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
@ -42,17 +39,16 @@ import org.osgi.service.component.annotations.Reference;
|
||||
@Component(configurationPid = "binding.rotel", service = ThingHandlerFactory.class)
|
||||
public class RotelHandlerFactory extends BaseThingHandlerFactory {
|
||||
|
||||
private static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Collections.unmodifiableSet(Stream
|
||||
.of(THING_TYPE_RSP1066, THING_TYPE_RSP1068, THING_TYPE_RSP1069, THING_TYPE_RSP1098, THING_TYPE_RSP1570,
|
||||
THING_TYPE_RSP1572, THING_TYPE_RSX1055, THING_TYPE_RSX1056, THING_TYPE_RSX1057, THING_TYPE_RSX1058,
|
||||
THING_TYPE_RSX1065, THING_TYPE_RSX1067, THING_TYPE_RSX1550, THING_TYPE_RSX1560, THING_TYPE_RSX1562,
|
||||
THING_TYPE_A11, THING_TYPE_A12, THING_TYPE_A14, THING_TYPE_CD11, THING_TYPE_CD14, THING_TYPE_RA11,
|
||||
THING_TYPE_RA12, THING_TYPE_RA1570, THING_TYPE_RA1572, THING_TYPE_RA1592, THING_TYPE_RAP1580,
|
||||
THING_TYPE_RC1570, THING_TYPE_RC1572, THING_TYPE_RC1590, THING_TYPE_RCD1570, THING_TYPE_RCD1572,
|
||||
THING_TYPE_RCX1500, THING_TYPE_RDD1580, THING_TYPE_RDG1520, THING_TYPE_RSP1576, THING_TYPE_RSP1582,
|
||||
THING_TYPE_RT09, THING_TYPE_RT11, THING_TYPE_RT1570, THING_TYPE_T11, THING_TYPE_T14, THING_TYPE_C8,
|
||||
THING_TYPE_M8, THING_TYPE_P5, THING_TYPE_S5, THING_TYPE_X3, THING_TYPE_X5)
|
||||
.collect(Collectors.toSet()));
|
||||
private static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Set.of(THING_TYPE_RSP1066, THING_TYPE_RSP1068,
|
||||
THING_TYPE_RSP1069, THING_TYPE_RSP1098, THING_TYPE_RSP1570, THING_TYPE_RSP1572, THING_TYPE_RSX1055,
|
||||
THING_TYPE_RSX1056, THING_TYPE_RSX1057, THING_TYPE_RSX1058, THING_TYPE_RSX1065, THING_TYPE_RSX1067,
|
||||
THING_TYPE_RSX1550, THING_TYPE_RSX1560, THING_TYPE_RSX1562, THING_TYPE_RX1052, THING_TYPE_A11,
|
||||
THING_TYPE_A12, THING_TYPE_A14, THING_TYPE_CD11, THING_TYPE_CD14, THING_TYPE_RA11, THING_TYPE_RA12,
|
||||
THING_TYPE_RA1570, THING_TYPE_RA1572, THING_TYPE_RA1592, THING_TYPE_RAP1580, THING_TYPE_RC1570,
|
||||
THING_TYPE_RC1572, THING_TYPE_RC1590, THING_TYPE_RCD1570, THING_TYPE_RCD1572, THING_TYPE_RCX1500,
|
||||
THING_TYPE_RDD1580, THING_TYPE_RDG1520, THING_TYPE_RSP1576, THING_TYPE_RSP1582, THING_TYPE_RT09,
|
||||
THING_TYPE_RT11, THING_TYPE_RT1570, THING_TYPE_T11, THING_TYPE_T14, THING_TYPE_C8, THING_TYPE_M8,
|
||||
THING_TYPE_P5, THING_TYPE_S5, THING_TYPE_X3, THING_TYPE_X5);
|
||||
|
||||
private final SerialPortManager serialPortManager;
|
||||
private final RotelStateDescriptionOptionProvider stateDescriptionProvider;
|
||||
|
@ -23,6 +23,8 @@ import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.rotel.internal.communication.RotelCommand;
|
||||
import org.openhab.binding.rotel.internal.communication.RotelDsp;
|
||||
import org.openhab.binding.rotel.internal.communication.RotelFlagInfo;
|
||||
import org.openhab.binding.rotel.internal.communication.RotelFlagInfoType;
|
||||
import org.openhab.binding.rotel.internal.communication.RotelFlagsMapping;
|
||||
import org.openhab.binding.rotel.internal.communication.RotelSource;
|
||||
import org.openhab.binding.rotel.internal.protocol.RotelProtocol;
|
||||
@ -44,19 +46,19 @@ public enum RotelModel {
|
||||
concatenate(DSP_CMDS_SET1, MENU2_CTRL_CMDS, OTHER_CMDS_SET1), (byte) 0xA1, 42, 5, true,
|
||||
RotelFlagsMapping.MAPPING2),
|
||||
RSP1069("RSP-1069", 38400, 1, 3, true, 96, true, 6, false, RECORD_FONCTION_SELECT, 2,
|
||||
concatenate(DSP_CMDS_SET1, MENU2_CTRL_CMDS, OTHER_CMDS_SET1, OTHER_CMDS_SET2), (byte) 0xA2, 42, 5, true,
|
||||
RotelFlagsMapping.MAPPING5),
|
||||
concatenate(DSP_CMDS_SET1, MENU2_CTRL_CMDS, OTHER_CMDS_SET1, OTHER_CMDS_SET2, OTHER_CMDS_SET4), (byte) 0xA2,
|
||||
42, 5, true, RotelFlagsMapping.MAPPING3),
|
||||
RSP1098("RSP-1098", 19200, 1, 1, true, 96, true, 6, false, ZONE_SELECT, 2,
|
||||
concatenate(DSP_CMDS_SET1, MENU2_CTRL_CMDS, OTHER_CMDS_SET1, List.of(REMOTE_VOLUME_UP, REMOTE_VOLUME_DOWN)),
|
||||
(byte) 0xA0, 13, 8, true, RotelFlagsMapping.MAPPING1),
|
||||
RSP1570("RSP-1570", 115200, 1, 3, true, 96, true, 6, false, RECORD_FONCTION_SELECT, 3,
|
||||
concatenate(DSP_CMDS_SET2, DSP_CMDS_SET1, MENU2_CTRL_CMDS, OTHER_CMDS_SET1, OTHER_CMDS_SET2,
|
||||
List.of(RESET_FACTORY)),
|
||||
(byte) 0xA3, 42, 5, true, RotelFlagsMapping.MAPPING5),
|
||||
OTHER_CMDS_SET4, List.of(RESET_FACTORY)),
|
||||
(byte) 0xA3, 42, 5, true, RotelFlagsMapping.MAPPING3),
|
||||
RSP1572("RSP-1572", 115200, 2, 3, true, 96, true, null, false, RECORD_FONCTION_SELECT, 4,
|
||||
concatenate(DSP_CMDS_SET2, DSP_CMDS_SET1, NUMERIC_KEY_CMDS, MENU3_CTRL_CMDS, OTHER_CMDS_SET1,
|
||||
OTHER_CMDS_SET4),
|
||||
(byte) 0xA5, 42, 5, true, RotelFlagsMapping.MAPPING5),
|
||||
OTHER_CMDS_SET2, OTHER_CMDS_SET4, OTHER_CMDS_SET8),
|
||||
(byte) 0xA5, 42, 5, true, RotelFlagsMapping.MAPPING3),
|
||||
RSX1055("RSX-1055", 19200, 3, 1, false, 90, false, 12, false, ZONE_SELECT, 1,
|
||||
concatenate(DSP_CMDS_SET1, TUNER_CMDS_SET1, NUMERIC_KEY_CMDS, MENU2_CTRL_CMDS, OTHER_CMDS_SET1),
|
||||
(byte) 0xC3, 13, 8, true, RotelFlagsMapping.MAPPING1),
|
||||
@ -65,13 +67,20 @@ public enum RotelModel {
|
||||
MENU2_CTRL_CMDS, OTHER_CMDS_SET1),
|
||||
(byte) 0xC5, 13, 8, true, RotelFlagsMapping.MAPPING1),
|
||||
RSX1057("RSX-1057", 19200, 1, 1, true, 96, true, 6, false, RECORD_FONCTION_SELECT, 2,
|
||||
concatenate(DSP_CMDS_SET1, TUNER_CMDS_SET2, ZONE2_TUNER_CMDS_SET2, NUMERIC_KEY_CMDS, ZONE2_NUMERIC_KEY_CMDS,
|
||||
MENU2_CTRL_CMDS, OTHER_CMDS_SET1),
|
||||
concatenate(DSP_CMDS_SET1, TUNER_CMDS_SET2, TUNER_CMDS_SET3, ZONE2_TUNER_CMDS_SET2, NUMERIC_KEY_CMDS,
|
||||
ZONE2_NUMERIC_KEY_CMDS, MENU2_CTRL_CMDS, OTHER_CMDS_SET1),
|
||||
(byte) 0xC7, 13, 8, true, RotelFlagsMapping.MAPPING1),
|
||||
RSX1058("RSX-1058", 38400, 1, 3, true, 96, true, 6, false, RECORD_FONCTION_SELECT, 2,
|
||||
concatenate(DSP_CMDS_SET1, TUNER_CMDS_SET2, ZONE234_TUNER_CMDS_SET1, NUMERIC_KEY_CMDS,
|
||||
ZONE234_NUMERIC_KEY_CMDS, MENU2_CTRL_CMDS, OTHER_CMDS_SET1, OTHER_CMDS_SET2),
|
||||
(byte) 0xC8, 13, 8, true, RotelFlagsMapping.MAPPING4),
|
||||
concatenate(DSP_CMDS_SET1, TUNER_CMDS_SET2, TUNER_CMDS_SET3, ZONE234_TUNER_CMDS_SET1, NUMERIC_KEY_CMDS,
|
||||
ZONE234_NUMERIC_KEY_CMDS, MENU2_CTRL_CMDS, OTHER_CMDS_SET1, OTHER_CMDS_SET2, OTHER_CMDS_SET4),
|
||||
(byte) 0xC8, 13, 8, true, new RotelFlagsMapping(List.of(//
|
||||
new RotelFlagInfo(RotelFlagInfoType.MULTI_INPUT, 3, 1), //
|
||||
new RotelFlagInfo(RotelFlagInfoType.ZONE2, 1, 7), //
|
||||
new RotelFlagInfo(RotelFlagInfoType.ZONE3, 2, 7), //
|
||||
new RotelFlagInfo(RotelFlagInfoType.ZONE4, 6, 2), //
|
||||
new RotelFlagInfo(RotelFlagInfoType.CENTER, 8, 6), //
|
||||
new RotelFlagInfo(RotelFlagInfoType.SURROUND_LEFT, 8, 4), //
|
||||
new RotelFlagInfo(RotelFlagInfoType.SURROUND_RIGHT, 8, 3)))),
|
||||
RSX1065("RSX-1065", 19200, 3, 1, false, 96, false, 12, false, ZONE_SELECT, 1,
|
||||
concatenate(DSP_CMDS_SET1, TUNER_CMDS_SET1, NUMERIC_KEY_CMDS, MENU2_CTRL_CMDS, OTHER_CMDS_SET3),
|
||||
(byte) 0xC1, 42, 5, true, RotelFlagsMapping.MAPPING2),
|
||||
@ -80,19 +89,34 @@ public enum RotelModel {
|
||||
MENU2_CTRL_CMDS, OTHER_CMDS_SET1),
|
||||
(byte) 0xC4, 42, 5, true, RotelFlagsMapping.MAPPING2),
|
||||
RSX1550("RSX-1550", 115200, 1, 3, true, 96, true, 6, false, RECORD_FONCTION_SELECT, 3,
|
||||
concatenate(DSP_CMDS_SET1, TUNER_CMDS_SET2, ZONE234_TUNER_CMDS_SET1, NUMERIC_KEY_CMDS,
|
||||
ZONE234_NUMERIC_KEY_CMDS, MENU2_CTRL_CMDS, OTHER_CMDS_SET1, OTHER_CMDS_SET2,
|
||||
concatenate(DSP_CMDS_SET1, TUNER_CMDS_SET2, TUNER_CMDS_SET3, ZONE234_TUNER_CMDS_SET1, NUMERIC_KEY_CMDS,
|
||||
ZONE234_NUMERIC_KEY_CMDS, MENU2_CTRL_CMDS, OTHER_CMDS_SET1, OTHER_CMDS_SET2, OTHER_CMDS_SET4,
|
||||
List.of(RESET_FACTORY)),
|
||||
(byte) 0xC9, 13, 8, true, RotelFlagsMapping.MAPPING3),
|
||||
(byte) 0xC9, 13, 8, true, new RotelFlagsMapping(List.of(//
|
||||
new RotelFlagInfo(RotelFlagInfoType.MULTI_INPUT, 4, 7), //
|
||||
new RotelFlagInfo(RotelFlagInfoType.ZONE2, 1, 7), //
|
||||
new RotelFlagInfo(RotelFlagInfoType.ZONE3, 2, 7), //
|
||||
new RotelFlagInfo(RotelFlagInfoType.ZONE4, 6, 2), //
|
||||
new RotelFlagInfo(RotelFlagInfoType.CENTER, 5, 6), //
|
||||
new RotelFlagInfo(RotelFlagInfoType.SURROUND_LEFT, 5, 4), //
|
||||
new RotelFlagInfo(RotelFlagInfoType.SURROUND_RIGHT, 5, 3)))),
|
||||
RSX1560("RSX-1560", 115200, 1, 3, true, 96, true, 6, false, RECORD_FONCTION_SELECT, 3,
|
||||
concatenate(DSP_CMDS_SET1, TUNER_CMDS_SET2, ZONE234_TUNER_CMDS_SET1, NUMERIC_KEY_CMDS,
|
||||
ZONE234_NUMERIC_KEY_CMDS, MENU2_CTRL_CMDS, OTHER_CMDS_SET1, OTHER_CMDS_SET2,
|
||||
concatenate(DSP_CMDS_SET1, TUNER_CMDS_SET2, TUNER_CMDS_SET3, ZONE234_TUNER_CMDS_SET1, NUMERIC_KEY_CMDS,
|
||||
ZONE234_NUMERIC_KEY_CMDS, MENU2_CTRL_CMDS, OTHER_CMDS_SET1, OTHER_CMDS_SET2, OTHER_CMDS_SET4,
|
||||
List.of(RESET_FACTORY)),
|
||||
(byte) 0xCA, 42, 5, true, RotelFlagsMapping.MAPPING5),
|
||||
(byte) 0xCA, 42, 5, true, RotelFlagsMapping.MAPPING3),
|
||||
RSX1562("RSX-1562", 115200, 2, 3, true, 96, true, null, false, RECORD_FONCTION_SELECT, 4,
|
||||
concatenate(DSP_CMDS_SET2, DSP_CMDS_SET1, TUNER_CMDS_SET2, ZONE234_TUNER_CMDS_SET1, NUMERIC_KEY_CMDS,
|
||||
ZONE234_NUMERIC_KEY_CMDS, MENU3_CTRL_CMDS, OTHER_CMDS_SET1, OTHER_CMDS_SET4),
|
||||
(byte) 0xCC, 42, 5, true, RotelFlagsMapping.MAPPING5),
|
||||
concatenate(DSP_CMDS_SET2, DSP_CMDS_SET1, TUNER_CMDS_SET2, TUNER_CMDS_SET3, ZONE234_TUNER_CMDS_SET1,
|
||||
NUMERIC_KEY_CMDS, ZONE234_NUMERIC_KEY_CMDS, MENU3_CTRL_CMDS, OTHER_CMDS_SET1, OTHER_CMDS_SET2,
|
||||
OTHER_CMDS_SET4, OTHER_CMDS_SET8),
|
||||
(byte) 0xCC, 42, 5, true, RotelFlagsMapping.MAPPING3),
|
||||
RX1052("RX-1052", 38400, 22, 3, true, 90, true, 10, false, RECORD_FONCTION_SELECT, -1,
|
||||
concatenate(TUNER_CMDS_SET2, ZONE234_TUNER_CMDS_SET1, NUMERIC_KEY_CMDS, ZONE234_NUMERIC_KEY_CMDS,
|
||||
OTHER_CMDS_SET2, OTHER_CMDS_SET9),
|
||||
(byte) 0x61, 11, 5, false, new RotelFlagsMapping(List.of(//
|
||||
new RotelFlagInfo(RotelFlagInfoType.ZONE, 1, 1), //
|
||||
new RotelFlagInfo(RotelFlagInfoType.SPEAKER_A, 1, 3), //
|
||||
new RotelFlagInfo(RotelFlagInfoType.SPEAKER_B, 1, 2)))),
|
||||
A11("A11", 115200, 4, 96, true, 10, 15, false, -1, false, true, true, 6, 0, SRC_CTRL_CMDS_SET1,
|
||||
NO_SPECIAL_CHARACTERS),
|
||||
A12("A12", 115200, 5, 96, true, 10, 15, false, -1, true, true, true, 6, 0,
|
||||
@ -154,7 +178,7 @@ public enum RotelModel {
|
||||
T11("T11", 115200, 12, null, false, null, false, -1, false, true, 6, 0, List.of(), NO_SPECIAL_CHARACTERS),
|
||||
T14("T14", 115200, 13, null, false, null, false, -1, false, true, 6, 0, List.of(), NO_SPECIAL_CHARACTERS),
|
||||
C8("C8", 115200, POWER, 21, 3, true, false, 96, true, 10, false, 10, false, null, -1, true, false, true, 4, 0,
|
||||
List.of(), (byte) 0, 0, 0, false, RotelFlagsMapping.NO_MAPPING, NO_SPECIAL_CHARACTERS),
|
||||
List.of(), (byte) 0, 0, 0, false, new RotelFlagsMapping(), NO_SPECIAL_CHARACTERS),
|
||||
M8("M8", 115200, 0, null, false, null, false, -1, false, true, 4, 0, List.of(), NO_SPECIAL_CHARACTERS),
|
||||
P5("P5", 115200, 20, 96, true, 10, 10, false, -1, true, false, true, 4, 0, SRC_CTRL_CMDS_SET1,
|
||||
NO_SPECIAL_CHARACTERS),
|
||||
@ -248,7 +272,7 @@ public enum RotelModel {
|
||||
this(name, baudRate, POWER, sourceCategory, 0, false, false, volumeMax, directVolume, toneLevelMax,
|
||||
toneLevelMax != null, null, playControl, null, dspCategory, getFrequencyAvailable, false,
|
||||
getDimmerLevelAvailable, diummerLevelMin, diummerLevelMax, otherCommands, (byte) 0, 0, 0, false,
|
||||
RotelFlagsMapping.NO_MAPPING, specialCharacters);
|
||||
new RotelFlagsMapping(), specialCharacters);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -279,7 +303,7 @@ public enum RotelModel {
|
||||
this(name, baudRate, POWER, sourceCategory, 0, false, false, volumeMax, directVolume, toneLevelMax,
|
||||
toneLevelMax != null, balanceLevelMax, playControl, null, dspCategory, getFrequencyAvailable,
|
||||
getSpeakerGroupsAvailable, getDimmerLevelAvailable, diummerLevelMin, diummerLevelMax, otherCommands,
|
||||
(byte) 0, 0, 0, false, RotelFlagsMapping.NO_MAPPING, specialCharacters);
|
||||
(byte) 0, 0, 0, false, new RotelFlagsMapping(), specialCharacters);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -736,103 +760,41 @@ public enum RotelModel {
|
||||
}
|
||||
|
||||
/**
|
||||
* Inform whether the multiple input source is set to ON in the flags
|
||||
* Inform whether the information is present in flags
|
||||
*
|
||||
* @param flags the flag from the standard response message
|
||||
* @param infoType the type of information
|
||||
*
|
||||
* @return true if the multiple input source is ON
|
||||
*
|
||||
* @throws RotelException - If this information is not present in the flags for this model
|
||||
* @return true if the information is available
|
||||
*/
|
||||
public boolean isMultiInputOn(byte[] flags) throws RotelException {
|
||||
return flagsMapping.isMultiInputOn(flags);
|
||||
public boolean isInfoPresentInFlags(RotelFlagInfoType infoType) {
|
||||
return flagsMapping.isInfoPresent(infoType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the multiple input source to ON or OFF in the flags
|
||||
* Inform whether the information is set to ON in the flags
|
||||
*
|
||||
* @param infoType the type of information
|
||||
* @param flags the flag from the standard response message
|
||||
*
|
||||
* @return true if the information is ON
|
||||
*
|
||||
* @throws RotelException - If this information is not present in the flags for this model
|
||||
*/
|
||||
public boolean isInfoOnInFlags(RotelFlagInfoType infoType, byte[] flags) throws RotelException {
|
||||
return flagsMapping.isInfoOn(infoType, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the information to ON or OFF in the flags
|
||||
*
|
||||
* @param infoType the type of information
|
||||
* @param flags the flag from the standard response message
|
||||
* @param on true for ON and false for OFF
|
||||
*
|
||||
* @throws RotelException - If this information is not present in the flags for this model
|
||||
* @return true if the information was updated in the flags, false if not
|
||||
*/
|
||||
public void setMultiInput(byte[] flags, boolean on) throws RotelException {
|
||||
flagsMapping.setMultiInput(flags, on);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inform whether the zone 2 is set to ON in the flags
|
||||
*
|
||||
* @param flags the flag from the standard response message
|
||||
*
|
||||
* @return true if the zone 2 is ON
|
||||
*
|
||||
* @throws RotelException - If this information is not present in the flags for this model
|
||||
*/
|
||||
public boolean isZone2On(byte[] flags) throws RotelException {
|
||||
return flagsMapping.isZone2On(flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the zone 2 to ON or OFF in the flags
|
||||
*
|
||||
* @param flags the flag from the standard response message
|
||||
* @param on true for ON and false for OFF
|
||||
*
|
||||
* @throws RotelException - If this information is not present in the flags for this model
|
||||
*/
|
||||
public void setZone2(byte[] flags, boolean on) throws RotelException {
|
||||
flagsMapping.setZone2(flags, on);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inform whether the zone 3 is set to ON in the flags
|
||||
*
|
||||
* @param flags the flag from the standard response message
|
||||
*
|
||||
* @return true if the zone 3 is ON
|
||||
*
|
||||
* @throws RotelException - If this information is not present in the flags for this model
|
||||
*/
|
||||
public boolean isZone3On(byte[] flags) throws RotelException {
|
||||
return flagsMapping.isZone3On(flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the zone 3 to ON or OFF in the flags
|
||||
*
|
||||
* @param flags the flag from the standard response message
|
||||
* @param on true for ON and false for OFF
|
||||
*
|
||||
* @throws RotelException - If this information is not present in the flags for this model
|
||||
*/
|
||||
public void setZone3(byte[] flags, boolean on) throws RotelException {
|
||||
flagsMapping.setZone3(flags, on);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inform whether the zone 4 is set to ON in the flags
|
||||
*
|
||||
* @param flags the flag from the standard response message
|
||||
*
|
||||
* @return true if the zone 4 is ON
|
||||
*
|
||||
* @throws RotelException - If this information is not present in the flags for this model
|
||||
*/
|
||||
public boolean isZone4On(byte[] flags) throws RotelException {
|
||||
return flagsMapping.isZone4On(flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the zone 4 to ON or OFF in the flags
|
||||
*
|
||||
* @param flags the flag from the standard response message
|
||||
* @param on true for ON and false for OFF
|
||||
*
|
||||
* @throws RotelException - If this information is not present in the flags for this model
|
||||
*/
|
||||
public void setZone4(byte[] flags, boolean on) throws RotelException {
|
||||
flagsMapping.setZone4(flags, on);
|
||||
public boolean setInfoInFlags(RotelFlagInfoType infoType, byte[] flags, boolean on) {
|
||||
return flagsMapping.setInfo(infoType, flags, on);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -150,6 +150,7 @@ public enum RotelCommand {
|
||||
"main_zone_video5"),
|
||||
MAIN_ZONE_SOURCE_VIDEO6("Main Zone Source Video 6", MAIN_ZONE_CMD, (byte) 0x94, "main_zone_video6",
|
||||
"main_zone_video6"),
|
||||
MAIN_ZONE_SOURCE_PHONO("Main Zone Source Phono", MAIN_ZONE_CMD, (byte) 0x35, "main_zone_phono", "main_zone_phono"),
|
||||
MAIN_ZONE_SOURCE_USB("Main Zone Source Front USB", MAIN_ZONE_CMD, (byte) 0x8E, "main_zone_usb", "main_zone_usb"),
|
||||
MAIN_ZONE_SOURCE_MULTI_INPUT("Main Zone Source Multi Input", MAIN_ZONE_CMD, (byte) 0x15, "main_zone_multi_input",
|
||||
"main_zone_multi_input"),
|
||||
@ -166,6 +167,7 @@ public enum RotelCommand {
|
||||
RECORD_SOURCE_VIDEO4("Record Source Video 4", RECORD_SRC_CMD, (byte) 0x08, "record_video4", "record_video4"),
|
||||
RECORD_SOURCE_VIDEO5("Record Source Video 5", RECORD_SRC_CMD, (byte) 0x09, "record_video5", "record_video5"),
|
||||
RECORD_SOURCE_VIDEO6("Record Source Video 6", RECORD_SRC_CMD, (byte) 0x94, "record_video6", "record_video6"),
|
||||
RECORD_SOURCE_PHONO("Record Source Phono", RECORD_SRC_CMD, (byte) 0x35, "record_phono", "record_phono"),
|
||||
RECORD_SOURCE_USB("Record Source Front USB", RECORD_SRC_CMD, (byte) 0x8E, "record_usb", "record_usb"),
|
||||
RECORD_SOURCE_MAIN("Record Follow Main Zone Source", RECORD_SRC_CMD, (byte) 0x6B, "record_follow_main",
|
||||
"record_follow_main"),
|
||||
@ -178,6 +180,7 @@ public enum RotelCommand {
|
||||
ZONE2_SOURCE_VIDEO4("Zone 2 Source Video 4", ZONE2_CMD, (byte) 0x08, "zone2_video4", "zone2_video4"),
|
||||
ZONE2_SOURCE_VIDEO5("Zone 2 Source Video 5", ZONE2_CMD, (byte) 0x09, "zone2_video5", "zone2_video5"),
|
||||
ZONE2_SOURCE_VIDEO6("Zone 2 Source Video 6", ZONE2_CMD, (byte) 0x94, "zone2_video6", "zone2_video6"),
|
||||
ZONE2_SOURCE_PHONO("Zone 2 Source Phono", ZONE2_CMD, (byte) 0x35, "zone2_phono", "zone2_phono"),
|
||||
ZONE2_SOURCE_USB("Zone 2 Source Front USB", ZONE2_CMD, (byte) 0x8E, "zone2_usb", "zone2_usb"),
|
||||
ZONE2_SOURCE_MAIN("Zone 2 Follow Main Zone Source", ZONE2_CMD, (byte) 0x6B, "zone2_follow_main",
|
||||
"zone2_follow_main"),
|
||||
@ -194,6 +197,7 @@ public enum RotelCommand {
|
||||
ZONE3_SOURCE_VIDEO4("Zone 3 Source Video 4", ZONE3_CMD, (byte) 0x08, "zone3_video4", "zone3_video4"),
|
||||
ZONE3_SOURCE_VIDEO5("Zone 3 Source Video 5", ZONE3_CMD, (byte) 0x09, "zone3_video5", "zone3_video5"),
|
||||
ZONE3_SOURCE_VIDEO6("Zone 3 Source Video 6", ZONE3_CMD, (byte) 0x94, "zone3_video6", "zone3_video6"),
|
||||
ZONE3_SOURCE_PHONO("Zone 3 Source Phono", ZONE3_CMD, (byte) 0x35, "zone3_phono", "zone3_phono"),
|
||||
ZONE3_SOURCE_USB("Zone 3 Source Front USB", ZONE3_CMD, (byte) 0x8E, "zone3_usb", "zone3_usb"),
|
||||
ZONE3_SOURCE_MAIN("Zone 3 Follow Main Zone Source", ZONE3_CMD, (byte) 0x6B, "zone3_follow_main",
|
||||
"zone3_follow_main"),
|
||||
@ -210,6 +214,7 @@ public enum RotelCommand {
|
||||
ZONE4_SOURCE_VIDEO4("Zone 4 Source Video 4", ZONE4_CMD, (byte) 0x08, "zone4_video4", "zone4_video4"),
|
||||
ZONE4_SOURCE_VIDEO5("Zone 4 Source Video 5", ZONE4_CMD, (byte) 0x09, "zone4_video5", "zone4_video5"),
|
||||
ZONE4_SOURCE_VIDEO6("Zone 4 Source Video 6", ZONE4_CMD, (byte) 0x94, "zone4_video6", "zone4_video6"),
|
||||
ZONE4_SOURCE_PHONO("Zone 4 Source Phono", ZONE4_CMD, (byte) 0x35, "zone4_phono", "zone4_phono"),
|
||||
ZONE4_SOURCE_USB("Zone 4 Source Front USB", ZONE4_CMD, (byte) 0x8E, "zone4_usb", "zone4_usb"),
|
||||
ZONE4_SOURCE_MAIN("Zone 4 Follow Main Zone Source", ZONE4_CMD, (byte) 0x6B, "zone4_follow_main",
|
||||
"zone4_follow_main"),
|
||||
@ -520,7 +525,8 @@ public enum RotelCommand {
|
||||
RDS_PTY, RDS_TP, RDS_TA, FM_MONO_TOGGLE);
|
||||
public static final List<RotelCommand> TUNER_CMDS_SET2 = List.of(TUNE_UP, TUNE_DOWN, PRESET_UP, PRESET_DOWN,
|
||||
FREQUENCY_UP, FREQUENCY_DOWN, MEMORY, BAND_TOGGLE, AM, FM, TUNE_PRESET_TOGGLE, TUNING_MODE_SELECT,
|
||||
PRESET_MODE_SELECT, FREQUENCY_DIRECT, PRESET_SCAN, TUNER_DISPLAY, RDS_PTY, RDS_TP, RDS_TA, FM_MONO_TOGGLE);
|
||||
PRESET_MODE_SELECT, FREQUENCY_DIRECT, PRESET_SCAN, FM_MONO_TOGGLE);
|
||||
public static final List<RotelCommand> TUNER_CMDS_SET3 = List.of(TUNER_DISPLAY, RDS_PTY, RDS_TP, RDS_TA);
|
||||
public static final List<RotelCommand> ZONE2_TUNER_CMDS_SET1 = List.of(ZONE2_TUNE_UP, ZONE2_TUNE_DOWN,
|
||||
ZONE2_BAND_TOGGLE, ZONE2_AM, ZONE2_FM, ZONE2_TUNE_PRESET_TOGGLE, ZONE2_TUNING_MODE_SELECT,
|
||||
ZONE2_PRESET_MODE_SELECT, ZONE2_PRESET_SCAN, ZONE2_FM_MONO_TOGGLE);
|
||||
@ -563,17 +569,18 @@ public enum RotelCommand {
|
||||
public static final List<RotelCommand> OTHER_CMDS_SET1 = List.of(RECORD_FONCTION_SELECT, TONE_CONTROL_SELECT,
|
||||
DYNAMIC_RANGE, DIGITAL_INPUT_SELECT, ZONE_TOGGLE, CENTER_TRIM, SUB_TRIM, SURROUND_TRIM, CINEMA_EQ_TOGGLE);
|
||||
public static final List<RotelCommand> OTHER_CMDS_SET2 = List.of(POWER_OFF_ALL_ZONES, PARTY_MODE_TOGGLE,
|
||||
ZONE2_PARTY_MODE_TOGGLE, ZONE3_PARTY_MODE_TOGGLE, ZONE4_PARTY_MODE_TOGGLE, OUTPUT_RESOLUTION, HDMI_AMP_MODE,
|
||||
HDMI_TV_MODE);
|
||||
ZONE2_PARTY_MODE_TOGGLE, ZONE3_PARTY_MODE_TOGGLE, ZONE4_PARTY_MODE_TOGGLE);
|
||||
public static final List<RotelCommand> OTHER_CMDS_SET3 = List.of(RECORD_FONCTION_SELECT, DYNAMIC_RANGE,
|
||||
DIGITAL_INPUT_SELECT, ZONE_TOGGLE, CENTER_TRIM, SUB_TRIM, SURROUND_TRIM, CINEMA_EQ_TOGGLE);
|
||||
public static final List<RotelCommand> OTHER_CMDS_SET4 = List.of(POWER_OFF_ALL_ZONES, PARTY_MODE_TOGGLE,
|
||||
ZONE2_PARTY_MODE_TOGGLE, ZONE3_PARTY_MODE_TOGGLE, ZONE4_PARTY_MODE_TOGGLE, OUTPUT_RESOLUTION, HDMI_AMP_MODE,
|
||||
HDMI_TV_MODE, ROOM_EQ_TOGGLE, SPEAKER_SETTING_TOGGLE, RESET_FACTORY);
|
||||
public static final List<RotelCommand> OTHER_CMDS_SET4 = List.of(OUTPUT_RESOLUTION, HDMI_AMP_MODE, HDMI_TV_MODE);
|
||||
public static final List<RotelCommand> OTHER_CMDS_SET5 = List.of(POWER_MODE, POWER_MODE_QUICK, POWER_MODE_NORMAL,
|
||||
RESET_FACTORY);
|
||||
public static final List<RotelCommand> OTHER_CMDS_SET6 = List.of(POWER_MODE, RESET_FACTORY);
|
||||
public static final List<RotelCommand> OTHER_CMDS_SET7 = List.of(NEXT_MODE, RESET_FACTORY);
|
||||
public static final List<RotelCommand> OTHER_CMDS_SET8 = List.of(ROOM_EQ_TOGGLE, SPEAKER_SETTING_TOGGLE,
|
||||
RESET_FACTORY);
|
||||
public static final List<RotelCommand> OTHER_CMDS_SET9 = List.of(RECORD_FONCTION_SELECT, TONE_CONTROL_SELECT,
|
||||
ZONE_TOGGLE);
|
||||
|
||||
public static final byte PRIMARY_COMMAND = (byte) 0x10;
|
||||
|
||||
@ -766,4 +773,27 @@ public enum RotelCommand {
|
||||
return Stream.of(list1, list2, list3, list4, list5, list6, list7, list8, list9).flatMap(Collection::stream)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public static List<RotelCommand> concatenate(List<RotelCommand> list1, List<RotelCommand> list2,
|
||||
List<RotelCommand> list3, List<RotelCommand> list4, List<RotelCommand> list5, List<RotelCommand> list6,
|
||||
List<RotelCommand> list7, List<RotelCommand> list8, List<RotelCommand> list9, List<RotelCommand> list10) {
|
||||
return Stream.of(list1, list2, list3, list4, list5, list6, list7, list8, list9, list10)
|
||||
.flatMap(Collection::stream).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public static List<RotelCommand> concatenate(List<RotelCommand> list1, List<RotelCommand> list2,
|
||||
List<RotelCommand> list3, List<RotelCommand> list4, List<RotelCommand> list5, List<RotelCommand> list6,
|
||||
List<RotelCommand> list7, List<RotelCommand> list8, List<RotelCommand> list9, List<RotelCommand> list10,
|
||||
List<RotelCommand> list11) {
|
||||
return Stream.of(list1, list2, list3, list4, list5, list6, list7, list8, list9, list10, list11)
|
||||
.flatMap(Collection::stream).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public static List<RotelCommand> concatenate(List<RotelCommand> list1, List<RotelCommand> list2,
|
||||
List<RotelCommand> list3, List<RotelCommand> list4, List<RotelCommand> list5, List<RotelCommand> list6,
|
||||
List<RotelCommand> list7, List<RotelCommand> list8, List<RotelCommand> list9, List<RotelCommand> list10,
|
||||
List<RotelCommand> list11, List<RotelCommand> list12) {
|
||||
return Stream.of(list1, list2, list3, list4, list5, list6, list7, list8, list9, list10, list11, list12)
|
||||
.flatMap(Collection::stream).collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,24 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2024 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.rotel.internal.communication;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* Record describing one information in response flags (HEX protocol)
|
||||
*
|
||||
* @author Laurent Garnier - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public record RotelFlagInfo(RotelFlagInfoType infoType, int flagNumber, int bitNumber) {
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2024 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.rotel.internal.communication;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* Represents the different types of information that can be included in response flags (HEX protocol)
|
||||
*
|
||||
* @author Laurent Garnier - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public enum RotelFlagInfoType {
|
||||
MULTI_INPUT,
|
||||
ZONE2,
|
||||
ZONE3,
|
||||
ZONE4,
|
||||
ZONE,
|
||||
CENTER,
|
||||
SURROUND_LEFT,
|
||||
SURROUND_RIGHT,
|
||||
SPEAKER_A,
|
||||
SPEAKER_B
|
||||
}
|
@ -12,6 +12,10 @@
|
||||
*/
|
||||
package org.openhab.binding.rotel.internal.communication;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.rotel.internal.RotelException;
|
||||
|
||||
@ -23,174 +27,77 @@ import org.openhab.binding.rotel.internal.RotelException;
|
||||
@NonNullByDefault
|
||||
public class RotelFlagsMapping {
|
||||
|
||||
public static final RotelFlagsMapping MAPPING1 = new RotelFlagsMapping(3, 1, 5, 0, -1, -1, -1, -1, 8, 6, 8, 4, 8,
|
||||
3);
|
||||
public static final RotelFlagsMapping MAPPING2 = new RotelFlagsMapping(-1, -1, 4, 7, -1, -1, -1, -1, 5, 6, 5, 4, 5,
|
||||
3);
|
||||
public static final RotelFlagsMapping MAPPING3 = new RotelFlagsMapping(4, 7, 1, 7, 2, 7, 6, 2, 5, 6, 5, 4, 5, 3);
|
||||
public static final RotelFlagsMapping MAPPING4 = new RotelFlagsMapping(3, 1, 1, 7, 2, 7, 6, 2, 8, 6, 8, 4, 8, 3);
|
||||
public static final RotelFlagsMapping MAPPING5 = new RotelFlagsMapping(-1, -1, 3, 2, 4, 2, 4, 1, 5, 6, 5, 4, 5, 3);
|
||||
public static final RotelFlagsMapping NO_MAPPING = new RotelFlagsMapping(-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1);
|
||||
public static final RotelFlagsMapping MAPPING1 = new RotelFlagsMapping(
|
||||
List.of(new RotelFlagInfo(RotelFlagInfoType.MULTI_INPUT, 3, 1), //
|
||||
new RotelFlagInfo(RotelFlagInfoType.ZONE2, 5, 0), //
|
||||
new RotelFlagInfo(RotelFlagInfoType.CENTER, 8, 6), //
|
||||
new RotelFlagInfo(RotelFlagInfoType.SURROUND_LEFT, 8, 4), //
|
||||
new RotelFlagInfo(RotelFlagInfoType.SURROUND_RIGHT, 8, 3)));
|
||||
public static final RotelFlagsMapping MAPPING2 = new RotelFlagsMapping(
|
||||
List.of(new RotelFlagInfo(RotelFlagInfoType.ZONE2, 4, 7), //
|
||||
new RotelFlagInfo(RotelFlagInfoType.CENTER, 5, 6), //
|
||||
new RotelFlagInfo(RotelFlagInfoType.SURROUND_LEFT, 5, 4), //
|
||||
new RotelFlagInfo(RotelFlagInfoType.SURROUND_RIGHT, 5, 3)));
|
||||
public static final RotelFlagsMapping MAPPING3 = new RotelFlagsMapping(
|
||||
List.of(new RotelFlagInfo(RotelFlagInfoType.ZONE2, 3, 2), //
|
||||
new RotelFlagInfo(RotelFlagInfoType.ZONE3, 4, 2), //
|
||||
new RotelFlagInfo(RotelFlagInfoType.ZONE4, 4, 1), //
|
||||
new RotelFlagInfo(RotelFlagInfoType.CENTER, 5, 6), //
|
||||
new RotelFlagInfo(RotelFlagInfoType.SURROUND_LEFT, 5, 4), //
|
||||
new RotelFlagInfo(RotelFlagInfoType.SURROUND_RIGHT, 5, 3)));
|
||||
|
||||
private int multiInputFlagNumber;
|
||||
private int multiInputBitNumber;
|
||||
private int zone2FlagNumber;
|
||||
private int zone2BitNumber;
|
||||
private int zone3FlagNumber;
|
||||
private int zone3BitNumber;
|
||||
private int zone4FlagNumber;
|
||||
private int zone4BitNumber;
|
||||
private int centerFlagNumber;
|
||||
private int centerBitNumber;
|
||||
private int surroundLeftFlagNumber;
|
||||
private int surroundLeftBitNumber;
|
||||
private int surroundRightFlagNumber;
|
||||
private int surroundRightBitNumber;
|
||||
private Map<RotelFlagInfoType, RotelFlagInfo> infoMap;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* For each flag number, value 1 means the first flag; a negative value is used for an undefined indicator.
|
||||
* For each bit number, value is from 0 to 7; a negative value is used for an undefined indicator.
|
||||
*
|
||||
* @param multiInputFlagNumber the flag number in the standard feedback message in which to find the multi input
|
||||
* indicator
|
||||
* @param multiInputBitNumber the bit number in the flag in which to find the multi input indicator
|
||||
* @param zone2FlagNumber the flag number in the standard feedback message in which to find the zone 2 indicator
|
||||
* @param zone2BitNumber the bit number in the flag in which to find the zone 2 indicator
|
||||
* @param zone3FlagNumber the flag number in the standard feedback message in which to find the zone 3 indicator
|
||||
* @param zone3BitNumber the bit number in the flag in which to find the zone 3 indicator
|
||||
* @param zone4FlagNumber the flag number in the standard feedback message in which to find the zone 4 indicator
|
||||
* @param zone4BitNumber the bit number in the flag in which to find the zone 4 indicator
|
||||
* @param centerFlagNumber the flag number in the standard feedback message in which to find the center channel
|
||||
* indicator
|
||||
* @param centerBitNumber the bit number in the flag in which to find the center channel indicator
|
||||
* @param surroundLeftFlagNumber the flag number in the standard feedback message in which to find the surround left
|
||||
* channel indicator
|
||||
* @param surroundLeftBitNumber the bit number in the flag in which to find the surround left channel indicator
|
||||
* @param surroundRightFlagNumber the flag number in the standard feedback message in which to find the surround
|
||||
* right channel indicator
|
||||
* @param surroundRightBitNumber the bit number in the flag in which to find the surround right channel indicator
|
||||
*/
|
||||
private RotelFlagsMapping(int multiInputFlagNumber, int multiInputBitNumber, int zone2FlagNumber,
|
||||
int zone2BitNumber, int zone3FlagNumber, int zone3BitNumber, int zone4FlagNumber, int zone4BitNumber,
|
||||
int centerFlagNumber, int centerBitNumber, int surroundLeftFlagNumber, int surroundLeftBitNumber,
|
||||
int surroundRightFlagNumber, int surroundRightBitNumber) {
|
||||
this.multiInputFlagNumber = multiInputFlagNumber;
|
||||
this.multiInputBitNumber = multiInputBitNumber;
|
||||
this.zone2FlagNumber = zone2FlagNumber;
|
||||
this.zone2BitNumber = zone2BitNumber;
|
||||
this.zone3FlagNumber = zone3FlagNumber;
|
||||
this.zone3BitNumber = zone3BitNumber;
|
||||
this.zone4FlagNumber = zone4FlagNumber;
|
||||
this.zone4BitNumber = zone4BitNumber;
|
||||
this.centerFlagNumber = centerFlagNumber;
|
||||
this.centerBitNumber = centerBitNumber;
|
||||
this.surroundLeftFlagNumber = surroundLeftFlagNumber;
|
||||
this.surroundLeftBitNumber = surroundLeftBitNumber;
|
||||
this.surroundRightFlagNumber = surroundRightFlagNumber;
|
||||
this.surroundRightBitNumber = surroundRightBitNumber;
|
||||
public RotelFlagsMapping() {
|
||||
this.infoMap = new HashMap<>();
|
||||
}
|
||||
|
||||
public RotelFlagsMapping(List<RotelFlagInfo> infos) {
|
||||
this.infoMap = new HashMap<>();
|
||||
for (RotelFlagInfo info : infos) {
|
||||
this.infoMap.put(info.infoType(), info);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the multi input indicator
|
||||
* Get the availability of the information
|
||||
*
|
||||
* @param flags the table of flags
|
||||
*
|
||||
* @return true if the indicator is ON in the flags or false if OFF
|
||||
*
|
||||
* @throws RotelException in case the multi input indicator is undefined
|
||||
* @return true if the information is available
|
||||
*/
|
||||
public boolean isMultiInputOn(byte[] flags) throws RotelException {
|
||||
return RotelFlagsMapping.isBitFlagOn(flags, multiInputFlagNumber, multiInputBitNumber);
|
||||
public boolean isInfoPresent(RotelFlagInfoType infoType) {
|
||||
return infoMap.get(infoType) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the multi input indicator
|
||||
* Get the information
|
||||
*
|
||||
* @param infoType the type of information
|
||||
* @param flags the table of flags
|
||||
* @param on true to set the indicator to ON or false to set it to OFF
|
||||
*
|
||||
* @throws RotelException in case the multi input indicator is undefined
|
||||
* @return true if the information is ON in the flags or false if OFF
|
||||
*
|
||||
* @throws RotelException in case the information is undefined
|
||||
*/
|
||||
public void setMultiInput(byte[] flags, boolean on) throws RotelException {
|
||||
RotelFlagsMapping.setBitFlag(flags, multiInputFlagNumber, multiInputBitNumber, on);
|
||||
public boolean isInfoOn(RotelFlagInfoType infoType, byte[] flags) throws RotelException {
|
||||
RotelFlagInfo info = infoMap.get(infoType);
|
||||
if (info == null || info.flagNumber() > flags.length) {
|
||||
throw new RotelException("Info " + infoType.name() + " not available in flags");
|
||||
}
|
||||
return RotelFlagsMapping.isBitFlagOn(flags, info.flagNumber(), info.bitNumber());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the zone 2 indicator
|
||||
* Set the information
|
||||
*
|
||||
* @param infoType the type of information
|
||||
* @param flags the table of flags
|
||||
* @param on true to set the information to ON or false to set it to OFF
|
||||
*
|
||||
* @return true if the indicator is ON in the flags or false if OFF
|
||||
*
|
||||
* @throws RotelException in case the zone 2 indicator is undefined
|
||||
* @return true if the information was updated, false if not
|
||||
*/
|
||||
public boolean isZone2On(byte[] flags) throws RotelException {
|
||||
return RotelFlagsMapping.isBitFlagOn(flags, zone2FlagNumber, zone2BitNumber);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the zone 2 indicator
|
||||
*
|
||||
* @param flags the table of flags
|
||||
* @param on true to set the indicator to ON or false to set it to OFF
|
||||
*
|
||||
* @throws RotelException in case the zone 2 indicator is undefined
|
||||
*/
|
||||
public void setZone2(byte[] flags, boolean on) throws RotelException {
|
||||
RotelFlagsMapping.setBitFlag(flags, zone2FlagNumber, zone2BitNumber, on);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the zone 3 indicator
|
||||
*
|
||||
* @param flags the table of flags
|
||||
*
|
||||
* @return true if the indicator is ON in the flags or false if OFF
|
||||
*
|
||||
* @throws RotelException in case the zone 3 indicator is undefined
|
||||
*/
|
||||
public boolean isZone3On(byte[] flags) throws RotelException {
|
||||
return RotelFlagsMapping.isBitFlagOn(flags, zone3FlagNumber, zone3BitNumber);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the zone 3 indicator
|
||||
*
|
||||
* @param flags the table of flags
|
||||
* @param on true to set the indicator to ON or false to set it to OFF
|
||||
*
|
||||
* @throws RotelException in case the zone 3 indicator is undefined
|
||||
*/
|
||||
public void setZone3(byte[] flags, boolean on) throws RotelException {
|
||||
RotelFlagsMapping.setBitFlag(flags, zone3FlagNumber, zone3BitNumber, on);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the zone 4 indicator
|
||||
*
|
||||
* @param flags the table of flags
|
||||
*
|
||||
* @return true if the indicator is ON in the flags or false if OFF
|
||||
*
|
||||
* @throws RotelException in case the zone 4 indicator is undefined
|
||||
*/
|
||||
public boolean isZone4On(byte[] flags) throws RotelException {
|
||||
return RotelFlagsMapping.isBitFlagOn(flags, zone4FlagNumber, zone4BitNumber);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the zone 4 indicator
|
||||
*
|
||||
* @param flags the table of flags
|
||||
* @param on true to set the indicator to ON or false to set it to OFF
|
||||
*
|
||||
* @throws RotelException in case the zone 4 indicator is undefined
|
||||
*/
|
||||
public void setZone4(byte[] flags, boolean on) throws RotelException {
|
||||
RotelFlagsMapping.setBitFlag(flags, zone4FlagNumber, zone4BitNumber, on);
|
||||
public boolean setInfo(RotelFlagInfoType infoType, byte[] flags, boolean on) {
|
||||
RotelFlagInfo info = infoMap.get(infoType);
|
||||
return info == null ? false : RotelFlagsMapping.setBitFlag(flags, info.flagNumber(), info.bitNumber(), on);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -203,12 +110,15 @@ public class RotelFlagsMapping {
|
||||
* @throws RotelException in case the center or surround channel indicators are undefined
|
||||
*/
|
||||
public boolean isMoreThan2Channels(byte[] flags) throws RotelException {
|
||||
return (centerFlagNumber >= 1 && centerFlagNumber <= flags.length
|
||||
&& RotelFlagsMapping.isBitFlagOn(flags, centerFlagNumber, centerBitNumber))
|
||||
|| (surroundLeftFlagNumber >= 1 && surroundLeftFlagNumber <= flags.length
|
||||
&& RotelFlagsMapping.isBitFlagOn(flags, surroundLeftFlagNumber, surroundLeftBitNumber))
|
||||
|| (surroundRightFlagNumber >= 1 && surroundRightFlagNumber <= flags.length
|
||||
&& RotelFlagsMapping.isBitFlagOn(flags, surroundRightFlagNumber, surroundRightBitNumber));
|
||||
RotelFlagInfo center = infoMap.get(RotelFlagInfoType.CENTER);
|
||||
RotelFlagInfo surroundLeft = infoMap.get(RotelFlagInfoType.SURROUND_LEFT);
|
||||
RotelFlagInfo surroundRight = infoMap.get(RotelFlagInfoType.SURROUND_RIGHT);
|
||||
return (center != null && center.flagNumber() <= flags.length
|
||||
&& RotelFlagsMapping.isBitFlagOn(flags, center.flagNumber(), center.bitNumber()))
|
||||
|| (surroundLeft != null && surroundLeft.flagNumber() <= flags.length
|
||||
&& RotelFlagsMapping.isBitFlagOn(flags, surroundLeft.flagNumber(), surroundLeft.bitNumber()))
|
||||
|| (surroundRight != null && surroundRight.flagNumber() <= flags.length
|
||||
&& RotelFlagsMapping.isBitFlagOn(flags, surroundRight.flagNumber(), surroundRight.bitNumber()));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -241,19 +151,17 @@ public class RotelFlagsMapping {
|
||||
* @param bitNumber the bit number in the flag to consider
|
||||
* @param on true to set the bit value to 1 or false to set it to 0
|
||||
*
|
||||
* @throws RotelException in case of out of bounds value for the flag number or the bit number
|
||||
* @return true if the flag was updated, false if not
|
||||
*/
|
||||
private static void setBitFlag(byte[] flags, int flagNumber, int bitNumber, boolean on) throws RotelException {
|
||||
if (flagNumber < 1 || flagNumber > flags.length) {
|
||||
throw new RotelException("Flag number out of bounds");
|
||||
}
|
||||
if (bitNumber < 0 || bitNumber > 7) {
|
||||
throw new RotelException("Bit number out of bounds");
|
||||
private static boolean setBitFlag(byte[] flags, int flagNumber, int bitNumber, boolean on) {
|
||||
if (flagNumber < 1 || flagNumber > flags.length || bitNumber < 0 || bitNumber > 7) {
|
||||
return false;
|
||||
}
|
||||
if (on) {
|
||||
flags[flagNumber - 1] |= (1 << bitNumber);
|
||||
} else {
|
||||
flags[flagNumber - 1] &= ~(1 << bitNumber);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -312,11 +312,11 @@ public class RotelSimuConnector extends RotelConnector {
|
||||
case RECORD_FONCTION_SELECT:
|
||||
if (model.getNumberOfZones() > 1 && model.getZoneSelectCmd() == cmd) {
|
||||
showZone++;
|
||||
if (showZone >= model.getNumberOfZones()) {
|
||||
if (showZone > model.getNumberOfZones()) {
|
||||
showZone = 1;
|
||||
if (!powers[0]) {
|
||||
showZone++;
|
||||
}
|
||||
}
|
||||
if (showZone == 1 && !powers[0]) {
|
||||
showZone++;
|
||||
}
|
||||
} else {
|
||||
showZone = 1;
|
||||
@ -325,6 +325,9 @@ public class RotelSimuConnector extends RotelConnector {
|
||||
selectingRecord = powers[0];
|
||||
showTreble = false;
|
||||
textLine2 = buildRecordResponse();
|
||||
if (model.getRespNbChars() == 11) {
|
||||
text = textLine2;
|
||||
}
|
||||
} else if (showZone >= 2 && showZone <= 4) {
|
||||
selectingRecord = false;
|
||||
text = textLine2 = buildZonePowerResponse(showZone);
|
||||
@ -1182,8 +1185,8 @@ public class RotelSimuConnector extends RotelConnector {
|
||||
// Check if command is a change of record source
|
||||
try {
|
||||
recordSource = model.getRecordSourceFromCommand(cmd);
|
||||
text = buildSourceLine1Response();
|
||||
textLine2 = buildRecordResponse();
|
||||
text = model.getRespNbChars() == 11 ? textLine2 : buildSourceLine1Response();
|
||||
accepted = true;
|
||||
} catch (RotelException e) {
|
||||
}
|
||||
@ -1217,21 +1220,26 @@ public class RotelSimuConnector extends RotelConnector {
|
||||
if (protocol == RotelProtocol.HEX) {
|
||||
byte[] chars = Arrays.copyOf(text.getBytes(StandardCharsets.US_ASCII), model.getRespNbChars());
|
||||
byte[] flags = new byte[model.getRespNbFlags()];
|
||||
try {
|
||||
model.setMultiInput(flags, multiinput);
|
||||
} catch (RotelException e) {
|
||||
if (model.isInfoPresentInFlags(RotelFlagInfoType.MULTI_INPUT)) {
|
||||
model.setInfoInFlags(RotelFlagInfoType.MULTI_INPUT, flags, multiinput);
|
||||
}
|
||||
try {
|
||||
model.setZone2(flags, powers[2]);
|
||||
} catch (RotelException e) {
|
||||
if (model.isInfoPresentInFlags(RotelFlagInfoType.ZONE2)) {
|
||||
model.setInfoInFlags(RotelFlagInfoType.ZONE2, flags, powers[2]);
|
||||
}
|
||||
try {
|
||||
model.setZone3(flags, powers[3]);
|
||||
} catch (RotelException e) {
|
||||
if (model.isInfoPresentInFlags(RotelFlagInfoType.ZONE3)) {
|
||||
model.setInfoInFlags(RotelFlagInfoType.ZONE3, flags, powers[3]);
|
||||
}
|
||||
try {
|
||||
model.setZone4(flags, powers[4]);
|
||||
} catch (RotelException e) {
|
||||
if (model.isInfoPresentInFlags(RotelFlagInfoType.ZONE4)) {
|
||||
model.setInfoInFlags(RotelFlagInfoType.ZONE4, flags, powers[4]);
|
||||
}
|
||||
if (model.isInfoPresentInFlags(RotelFlagInfoType.ZONE)) {
|
||||
model.setInfoInFlags(RotelFlagInfoType.ZONE, flags, powers[2] || powers[3] || powers[4]);
|
||||
}
|
||||
if (model.isInfoPresentInFlags(RotelFlagInfoType.SPEAKER_A)) {
|
||||
model.setInfoInFlags(RotelFlagInfoType.SPEAKER_A, flags, speakerA);
|
||||
}
|
||||
if (model.isInfoPresentInFlags(RotelFlagInfoType.SPEAKER_B)) {
|
||||
model.setInfoInFlags(RotelFlagInfoType.SPEAKER_B, flags, speakerB);
|
||||
}
|
||||
int size = 6 + model.getRespNbChars() + model.getRespNbFlags();
|
||||
byte[] dataBuffer = new byte[size];
|
||||
@ -1479,9 +1487,18 @@ public class RotelSimuConnector extends RotelConnector {
|
||||
if (!powers[0]) {
|
||||
text = "";
|
||||
} else if (mutes[0]) {
|
||||
text = "MUTE ON";
|
||||
text = model.getRespNbChars() == 11 ? " MUTE ON " : "MUTE ON";
|
||||
} else {
|
||||
text = getSourceLabel(sources[0], false) + " " + getSourceLabel(recordSource, true);
|
||||
text = getSourceLabel(sources[0], false);
|
||||
if (model.getRespNbChars() == 11) {
|
||||
if ("TUNER".equals(text)) {
|
||||
text = "104.30M 10 ";
|
||||
} else {
|
||||
text += " " + buildVolumeValue(0);
|
||||
}
|
||||
} else {
|
||||
text += " " + getSourceLabel(recordSource, true);
|
||||
}
|
||||
}
|
||||
return text;
|
||||
}
|
||||
@ -1507,26 +1524,16 @@ public class RotelSimuConnector extends RotelConnector {
|
||||
}
|
||||
|
||||
private String buildZonePowerResponse(int numZone) {
|
||||
String zone;
|
||||
if (numZone == 2) {
|
||||
zone = model.getNumberOfZones() > 2 ? "ZONE2" : "ZONE";
|
||||
} else {
|
||||
zone = String.format("ZONE%d", numZone);
|
||||
String zone = model.getRespNbChars() == 11 ? " Z" : "ZONE";
|
||||
if (numZone != 2 || model.getNumberOfZones() > 2) {
|
||||
zone += String.format("%d", numZone);
|
||||
}
|
||||
String state = powers[numZone] ? getSourceLabel(sources[numZone], true) : "OFF";
|
||||
return zone + " " + state;
|
||||
}
|
||||
|
||||
private String buildVolumeLine1Response() {
|
||||
String text;
|
||||
if (volumes[0] == minVolume) {
|
||||
text = " VOLUME MIN ";
|
||||
} else if (volumes[0] == maxVolume) {
|
||||
text = " VOLUME MAX ";
|
||||
} else {
|
||||
text = String.format(" VOLUME %02d ", volumes[0]);
|
||||
}
|
||||
return text;
|
||||
return String.format(model.getRespNbChars() == 11 ? "VOLUME %s" : " VOLUME %s ", buildVolumeValue(0));
|
||||
}
|
||||
|
||||
private String buildVolumeLine1RightResponse() {
|
||||
@ -1535,32 +1542,36 @@ public class RotelSimuConnector extends RotelConnector {
|
||||
text = "";
|
||||
} else if (mutes[0]) {
|
||||
text = "MUTE ON";
|
||||
} else if (volumes[0] == minVolume) {
|
||||
text = "VOL MIN";
|
||||
} else if (volumes[0] == maxVolume) {
|
||||
text = "VOL MAX";
|
||||
} else {
|
||||
text = String.format("VOL %02d", volumes[0]);
|
||||
text = String.format("VOL %s", buildVolumeValue(0));
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
private String buildZoneVolumeResponse(int numZone) {
|
||||
String zone;
|
||||
if (numZone == 2) {
|
||||
zone = model.getNumberOfZones() > 2 ? "ZONE2" : "ZONE";
|
||||
} else {
|
||||
zone = String.format("ZONE%d", numZone);
|
||||
String zone = model.getRespNbChars() == 11 ? " Z" : "ZONE";
|
||||
if (numZone != 2 || model.getNumberOfZones() > 2) {
|
||||
zone += String.format("%d", numZone);
|
||||
}
|
||||
String text;
|
||||
if (mutes[numZone]) {
|
||||
text = zone + " MUTE ON";
|
||||
} else if (volumes[numZone] == minVolume) {
|
||||
text = zone + " VOL MIN";
|
||||
} else if (volumes[numZone] == maxVolume) {
|
||||
text = zone + " VOL MAX";
|
||||
} else {
|
||||
text = String.format("%s VOL %02d", zone, volumes[numZone]);
|
||||
text = String.format("%s VOL %s", zone, buildVolumeValue(numZone));
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
private String buildVolumeValue(int numZone) {
|
||||
String text;
|
||||
if (volumes[numZone] == minVolume) {
|
||||
text = "MIN";
|
||||
} else if (volumes[numZone] == maxVolume) {
|
||||
text = "MAX";
|
||||
} else if (model.getRespNbChars() == 11) {
|
||||
text = String.format(volumes[numZone] < 10 ? " %d" : " %d", volumes[numZone]);
|
||||
} else {
|
||||
text = String.format(" %02d", volumes[numZone]);
|
||||
}
|
||||
return text;
|
||||
}
|
||||
@ -1568,15 +1579,15 @@ public class RotelSimuConnector extends RotelConnector {
|
||||
private String buildBassLine1Response() {
|
||||
String text;
|
||||
if (basses[0] == minToneLevel) {
|
||||
text = " BASS MIN ";
|
||||
text = model.getRespNbChars() == 11 ? " BASS MIN " : " BASS MIN ";
|
||||
} else if (basses[0] == maxToneLevel) {
|
||||
text = " BASS MAX ";
|
||||
text = model.getRespNbChars() == 11 ? " BASS MAX " : " BASS MAX ";
|
||||
} else if (basses[0] == 0) {
|
||||
text = " BASS 0 ";
|
||||
text = model.getRespNbChars() == 11 ? " BASS 0 " : " BASS 0 ";
|
||||
} else if (basses[0] > 0) {
|
||||
text = String.format(" BASS +%02d ", basses[0]);
|
||||
text = String.format(model.getRespNbChars() == 11 ? " BASS + %d " : " BASS +%02d ", basses[0]);
|
||||
} else {
|
||||
text = String.format(" BASS -%02d ", -basses[0]);
|
||||
text = String.format(model.getRespNbChars() == 11 ? " BASS - %d " : " BASS -%02d ", -basses[0]);
|
||||
}
|
||||
return text;
|
||||
}
|
||||
@ -1600,15 +1611,15 @@ public class RotelSimuConnector extends RotelConnector {
|
||||
private String buildTrebleLine1Response() {
|
||||
String text;
|
||||
if (trebles[0] == minToneLevel) {
|
||||
text = " TREBLE MIN ";
|
||||
text = model.getRespNbChars() == 11 ? "TREBLE MIN " : " TREBLE MIN ";
|
||||
} else if (trebles[0] == maxToneLevel) {
|
||||
text = " TREBLE MAX ";
|
||||
text = model.getRespNbChars() == 11 ? "TREBLE MAX " : " TREBLE MAX ";
|
||||
} else if (trebles[0] == 0) {
|
||||
text = " TREBLE 0 ";
|
||||
text = model.getRespNbChars() == 11 ? "TREBLE 0 " : " TREBLE 0 ";
|
||||
} else if (trebles[0] > 0) {
|
||||
text = String.format(" TREBLE +%02d ", trebles[0]);
|
||||
text = String.format(model.getRespNbChars() == 11 ? "TREBLE + %d " : " TREBLE +%02d ", trebles[0]);
|
||||
} else {
|
||||
text = String.format(" TREBLE -%02d ", -trebles[0]);
|
||||
text = String.format(model.getRespNbChars() == 11 ? "TREBLE - %d " : " TREBLE -%02d ", trebles[0]);
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
@ -310,7 +310,33 @@ public enum RotelSource {
|
||||
CAT21_INPUTC(21, "INPUTC", "Input C", RotelCommand.SOURCE_INPUT_C, null, RotelCommand.ZONE1_SOURCE_INPUT_C,
|
||||
RotelCommand.ZONE2_SOURCE_INPUT_C, RotelCommand.ZONE3_SOURCE_INPUT_C, RotelCommand.ZONE4_SOURCE_INPUT_C),
|
||||
CAT21_INPUTD(21, "INPUTD", "Input D", RotelCommand.SOURCE_INPUT_D, null, RotelCommand.ZONE1_SOURCE_INPUT_D,
|
||||
RotelCommand.ZONE2_SOURCE_INPUT_D, RotelCommand.ZONE3_SOURCE_INPUT_D, RotelCommand.ZONE4_SOURCE_INPUT_D);
|
||||
RotelCommand.ZONE2_SOURCE_INPUT_D, RotelCommand.ZONE3_SOURCE_INPUT_D, RotelCommand.ZONE4_SOURCE_INPUT_D),
|
||||
|
||||
CAT22_CD(22, "CD", "CD", RotelCommand.SOURCE_CD, RotelCommand.RECORD_SOURCE_CD, RotelCommand.MAIN_ZONE_SOURCE_CD,
|
||||
RotelCommand.ZONE2_SOURCE_CD, RotelCommand.ZONE3_SOURCE_CD, RotelCommand.ZONE4_SOURCE_CD),
|
||||
CAT22_TUNER(22, "TUNER", "TUNER", RotelCommand.SOURCE_TUNER, RotelCommand.RECORD_SOURCE_TUNER,
|
||||
RotelCommand.MAIN_ZONE_SOURCE_TUNER, RotelCommand.ZONE2_SOURCE_TUNER, RotelCommand.ZONE3_SOURCE_TUNER,
|
||||
RotelCommand.ZONE4_SOURCE_TUNER),
|
||||
CAT22_TAPE(22, "TAPE", "TAPE", RotelCommand.SOURCE_TAPE, RotelCommand.RECORD_SOURCE_TAPE,
|
||||
RotelCommand.MAIN_ZONE_SOURCE_TAPE, RotelCommand.ZONE2_SOURCE_TAPE, RotelCommand.ZONE3_SOURCE_TAPE,
|
||||
RotelCommand.ZONE4_SOURCE_TAPE),
|
||||
CAT22_PHONO(22, "PHONO", "PHONO", RotelCommand.SOURCE_PHONO, RotelCommand.RECORD_SOURCE_PHONO,
|
||||
RotelCommand.MAIN_ZONE_SOURCE_PHONO, RotelCommand.ZONE2_SOURCE_PHONO, RotelCommand.ZONE3_SOURCE_PHONO,
|
||||
RotelCommand.ZONE4_SOURCE_PHONO),
|
||||
CAT22_VIDEO1(22, "VIDEO1", "VIDEO 1", RotelCommand.SOURCE_VIDEO1, RotelCommand.RECORD_SOURCE_VIDEO1,
|
||||
RotelCommand.MAIN_ZONE_SOURCE_VIDEO1, RotelCommand.ZONE2_SOURCE_VIDEO1, RotelCommand.ZONE3_SOURCE_VIDEO1,
|
||||
RotelCommand.ZONE4_SOURCE_VIDEO1),
|
||||
CAT22_VIDEO2(22, "VIDEO2", "VIDEO 2", RotelCommand.SOURCE_VIDEO2, RotelCommand.RECORD_SOURCE_VIDEO2,
|
||||
RotelCommand.MAIN_ZONE_SOURCE_VIDEO2, RotelCommand.ZONE2_SOURCE_VIDEO2, RotelCommand.ZONE3_SOURCE_VIDEO2,
|
||||
RotelCommand.ZONE4_SOURCE_VIDEO2),
|
||||
CAT22_VIDEO3(22, "VIDEO3", "VIDEO 3", RotelCommand.SOURCE_VIDEO3, RotelCommand.RECORD_SOURCE_VIDEO3,
|
||||
RotelCommand.MAIN_ZONE_SOURCE_VIDEO3, RotelCommand.ZONE2_SOURCE_VIDEO3, RotelCommand.ZONE3_SOURCE_VIDEO3,
|
||||
RotelCommand.ZONE4_SOURCE_VIDEO3),
|
||||
CAT22_VIDEO4(22, "VIDEO4", "VIDEO 4", RotelCommand.SOURCE_VIDEO4, RotelCommand.RECORD_SOURCE_VIDEO4,
|
||||
RotelCommand.MAIN_ZONE_SOURCE_VIDEO4, RotelCommand.ZONE2_SOURCE_VIDEO4, RotelCommand.ZONE3_SOURCE_VIDEO4,
|
||||
RotelCommand.ZONE4_SOURCE_VIDEO4),
|
||||
CAT22_FOLLOW_MAIN(22, "MAIN", "Follow Main Zone Source", null, RotelCommand.RECORD_SOURCE_MAIN, null,
|
||||
RotelCommand.ZONE2_SOURCE_MAIN, RotelCommand.ZONE3_SOURCE_MAIN, RotelCommand.ZONE4_SOURCE_MAIN);
|
||||
|
||||
private int category;
|
||||
private String name;
|
||||
|
@ -13,6 +13,7 @@
|
||||
package org.openhab.binding.rotel.internal.configuration;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* The {@link RotelThingConfiguration} class contains fields mapping thing configuration parameters.
|
||||
@ -23,6 +24,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
public class RotelThingConfiguration {
|
||||
|
||||
public @NonNullByDefault({}) String serialPort;
|
||||
public @Nullable Integer baudRate;
|
||||
public @NonNullByDefault({}) String host;
|
||||
public @NonNullByDefault({}) Integer port;
|
||||
public @NonNullByDefault({}) String inputLabelCd;
|
||||
|
@ -90,6 +90,7 @@ public class RotelHandler extends BaseThingHandler implements RotelMessageEventL
|
||||
|
||||
private @Nullable ScheduledFuture<?> reconnectJob;
|
||||
private @Nullable ScheduledFuture<?> powerOffJob;
|
||||
private @Nullable ScheduledFuture<?> powerZonesJob;
|
||||
private @Nullable ScheduledFuture<?>[] powerOnZoneJobs = { null, null, null, null, null };
|
||||
|
||||
private RotelModel model;
|
||||
@ -104,6 +105,7 @@ public class RotelHandler extends BaseThingHandler implements RotelMessageEventL
|
||||
|
||||
private int currentZone = 1;
|
||||
private boolean selectingRecord;
|
||||
private @Nullable Boolean powerZones;
|
||||
private @Nullable Boolean[] powers = { null, false, false, false, false };
|
||||
private boolean powerControlPerZone;
|
||||
private @Nullable RotelSource recordSource;
|
||||
@ -219,6 +221,9 @@ public class RotelHandler extends BaseThingHandler implements RotelMessageEventL
|
||||
case THING_TYPE_ID_RSX1562:
|
||||
model = RotelModel.RSX1562;
|
||||
break;
|
||||
case THING_TYPE_ID_RX1052:
|
||||
model = RotelModel.RX1052;
|
||||
break;
|
||||
case THING_TYPE_ID_A11:
|
||||
model = RotelModel.A11;
|
||||
break;
|
||||
@ -435,8 +440,9 @@ public class RotelHandler extends BaseThingHandler implements RotelMessageEventL
|
||||
if (USE_SIMULATED_DEVICE) {
|
||||
connector = new RotelSimuConnector(model, protocolHandler, sourcesLabels, readerThreadName);
|
||||
} else if (config.serialPort != null) {
|
||||
connector = new RotelSerialConnector(serialPortManager, config.serialPort, model.getBaudRate(),
|
||||
protocolHandler, readerThreadName);
|
||||
connector = new RotelSerialConnector(serialPortManager, config.serialPort,
|
||||
config.baudRate != null ? config.baudRate : model.getBaudRate(), protocolHandler,
|
||||
readerThreadName);
|
||||
} else {
|
||||
connector = new RotelIpConnector(config.host, config.port, protocolHandler, readerThreadName);
|
||||
}
|
||||
@ -493,6 +499,7 @@ public class RotelHandler extends BaseThingHandler implements RotelMessageEventL
|
||||
public void dispose() {
|
||||
logger.debug("Disposing handler for thing {}", getThing().getUID());
|
||||
cancelPowerOffJob();
|
||||
cancelCheckPowerZonesJob();
|
||||
for (int zone = 0; zone <= model.getNumberOfZones(); zone++) {
|
||||
cancelPowerOnZoneJob(zone);
|
||||
}
|
||||
@ -946,6 +953,7 @@ public class RotelHandler extends BaseThingHandler implements RotelMessageEventL
|
||||
}
|
||||
break;
|
||||
case CHANNEL_SPEAKER_A:
|
||||
case CHANNEL_MAIN_SPEAKER_A:
|
||||
if (!isPowerOn()) {
|
||||
success = false;
|
||||
logger.debug("Command {} from channel {} ignored: device in standby", command, channel);
|
||||
@ -955,6 +963,7 @@ public class RotelHandler extends BaseThingHandler implements RotelMessageEventL
|
||||
}
|
||||
break;
|
||||
case CHANNEL_SPEAKER_B:
|
||||
case CHANNEL_MAIN_SPEAKER_B:
|
||||
if (!isPowerOn()) {
|
||||
success = false;
|
||||
logger.debug("Command {} from channel {} ignored: device in standby", command, channel);
|
||||
@ -1431,6 +1440,13 @@ public class RotelHandler extends BaseThingHandler implements RotelMessageEventL
|
||||
throw new RotelException("Invalid value");
|
||||
}
|
||||
break;
|
||||
case KEY_POWER_ZONES:
|
||||
if (POWER_ON.equalsIgnoreCase(value) || STANDBY.equalsIgnoreCase(value)) {
|
||||
handlePowerZones(POWER_ON.equalsIgnoreCase(value));
|
||||
} else {
|
||||
throw new RotelException("Invalid value");
|
||||
}
|
||||
break;
|
||||
case KEY_POWER_ZONE2:
|
||||
case KEY_POWER_ZONE3:
|
||||
case KEY_POWER_ZONE4:
|
||||
@ -1747,21 +1763,29 @@ public class RotelHandler extends BaseThingHandler implements RotelMessageEventL
|
||||
speakerb = false;
|
||||
updateChannelState(CHANNEL_SPEAKER_A);
|
||||
updateChannelState(CHANNEL_SPEAKER_B);
|
||||
updateChannelState(CHANNEL_MAIN_SPEAKER_A);
|
||||
updateChannelState(CHANNEL_MAIN_SPEAKER_B);
|
||||
} else if (MSG_VALUE_SPEAKER_B.equalsIgnoreCase(value)) {
|
||||
speakera = false;
|
||||
speakerb = true;
|
||||
updateChannelState(CHANNEL_SPEAKER_A);
|
||||
updateChannelState(CHANNEL_SPEAKER_B);
|
||||
updateChannelState(CHANNEL_MAIN_SPEAKER_A);
|
||||
updateChannelState(CHANNEL_MAIN_SPEAKER_B);
|
||||
} else if (MSG_VALUE_SPEAKER_AB.equalsIgnoreCase(value)) {
|
||||
speakera = true;
|
||||
speakerb = true;
|
||||
updateChannelState(CHANNEL_SPEAKER_A);
|
||||
updateChannelState(CHANNEL_SPEAKER_B);
|
||||
updateChannelState(CHANNEL_MAIN_SPEAKER_A);
|
||||
updateChannelState(CHANNEL_MAIN_SPEAKER_B);
|
||||
} else if (MSG_VALUE_OFF.equalsIgnoreCase(value)) {
|
||||
speakera = false;
|
||||
speakerb = false;
|
||||
updateChannelState(CHANNEL_SPEAKER_A);
|
||||
updateChannelState(CHANNEL_SPEAKER_B);
|
||||
updateChannelState(CHANNEL_MAIN_SPEAKER_A);
|
||||
updateChannelState(CHANNEL_MAIN_SPEAKER_B);
|
||||
} else {
|
||||
throw new RotelException("Invalid value");
|
||||
}
|
||||
@ -1864,11 +1888,30 @@ public class RotelHandler extends BaseThingHandler implements RotelMessageEventL
|
||||
updateChannelState(CHANNEL_MAIN_MUTE);
|
||||
updateChannelState(CHANNEL_MAIN_BASS);
|
||||
updateChannelState(CHANNEL_MAIN_TREBLE);
|
||||
updateChannelState(CHANNEL_MAIN_SPEAKER_A);
|
||||
updateChannelState(CHANNEL_MAIN_SPEAKER_B);
|
||||
|
||||
updateChannelState(CHANNEL_ALL_POWER);
|
||||
updateChannelState(CHANNEL_ALL_BRIGHTNESS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the received information that at least one zone power is ON or all zones power is OFF
|
||||
*/
|
||||
private void handlePowerZones(boolean power) {
|
||||
Boolean prev = powerZones;
|
||||
powerZones = power;
|
||||
if (prev == null && power) {
|
||||
// We know that at least one zone is ON but we don't know which ones
|
||||
scheduleCheckPowerZonesJob();
|
||||
} else if ((prev == null || prev.booleanValue() != power) && !power) {
|
||||
cancelCheckPowerZonesJob();
|
||||
for (int zone = 1; zone <= model.getNumberOfZones(); zone++) {
|
||||
handlePowerOffZone(zone);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the received information that a zone power is ON
|
||||
*/
|
||||
@ -2178,6 +2221,41 @@ public class RotelHandler extends BaseThingHandler implements RotelMessageEventL
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedule the job to run with a few seconds delay
|
||||
*/
|
||||
private void scheduleCheckPowerZonesJob() {
|
||||
logger.debug("Schedule check power zones job");
|
||||
cancelCheckPowerZonesJob();
|
||||
powerZonesJob = scheduler.schedule(() -> {
|
||||
synchronized (sequenceLock) {
|
||||
logger.debug("Check power zones job");
|
||||
try {
|
||||
selectZone(model.getNumberOfZones(), model.getZoneSelectCmd());
|
||||
} catch (RotelException e) {
|
||||
logger.debug("Check power zones sequence failed: {}", e.getMessage());
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
"@text/offline.comm-error-check-power-zones-sequence");
|
||||
closeConnection();
|
||||
} catch (InterruptedException e) {
|
||||
logger.debug("Check power zones sequence interrupted: {}", e.getMessage());
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
}, 2500, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancel the job scheduled when the device power (main zone) or a zone power switched ON
|
||||
*/
|
||||
private void cancelCheckPowerZonesJob() {
|
||||
ScheduledFuture<?> job = powerZonesJob;
|
||||
if (job != null && !job.isCancelled()) {
|
||||
job.cancel(true);
|
||||
powerZonesJob = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedule the reconnection job
|
||||
*/
|
||||
@ -2443,11 +2521,13 @@ public class RotelHandler extends BaseThingHandler implements RotelMessageEventL
|
||||
}
|
||||
break;
|
||||
case CHANNEL_SPEAKER_A:
|
||||
case CHANNEL_MAIN_SPEAKER_A:
|
||||
if (isPowerOn()) {
|
||||
state = OnOffType.from(speakera);
|
||||
}
|
||||
break;
|
||||
case CHANNEL_SPEAKER_B:
|
||||
case CHANNEL_MAIN_SPEAKER_B:
|
||||
if (isPowerOn()) {
|
||||
state = OnOffType.from(speakerb);
|
||||
}
|
||||
@ -2536,7 +2616,11 @@ public class RotelHandler extends BaseThingHandler implements RotelMessageEventL
|
||||
private RotelCommand getVolumeUpCommand(int numZone) {
|
||||
switch (numZone) {
|
||||
case 0:
|
||||
return model.hasOtherThanPrimaryCommands() ? RotelCommand.MAIN_ZONE_VOLUME_UP : RotelCommand.VOLUME_UP;
|
||||
// Spec for RX-1052 defines an unusual code for main zone volume up.
|
||||
// An error in the spec is suspected. The general volume up code is preferred.
|
||||
return (model.hasOtherThanPrimaryCommands() && model != RotelModel.RX1052)
|
||||
? RotelCommand.MAIN_ZONE_VOLUME_UP
|
||||
: RotelCommand.VOLUME_UP;
|
||||
case 1:
|
||||
return RotelCommand.ZONE1_VOLUME_UP;
|
||||
case 2:
|
||||
@ -2560,7 +2644,10 @@ public class RotelHandler extends BaseThingHandler implements RotelMessageEventL
|
||||
private RotelCommand getVolumeDownCommand(int numZone) {
|
||||
switch (numZone) {
|
||||
case 0:
|
||||
return model.hasOtherThanPrimaryCommands() ? RotelCommand.MAIN_ZONE_VOLUME_DOWN
|
||||
// Spec for RX-1052 defines an unusual code for main zone volume down.
|
||||
// An error in the spec is suspected. The general volume down code is preferred.
|
||||
return (model.hasOtherThanPrimaryCommands() && model != RotelModel.RX1052)
|
||||
? RotelCommand.MAIN_ZONE_VOLUME_DOWN
|
||||
: RotelCommand.VOLUME_DOWN;
|
||||
case 1:
|
||||
return RotelCommand.ZONE1_VOLUME_DOWN;
|
||||
|
@ -17,6 +17,7 @@ import static org.openhab.binding.rotel.internal.RotelBindingConstants.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
@ -24,6 +25,7 @@ import org.openhab.binding.rotel.internal.RotelException;
|
||||
import org.openhab.binding.rotel.internal.RotelModel;
|
||||
import org.openhab.binding.rotel.internal.communication.RotelCommand;
|
||||
import org.openhab.binding.rotel.internal.communication.RotelDsp;
|
||||
import org.openhab.binding.rotel.internal.communication.RotelFlagInfoType;
|
||||
import org.openhab.binding.rotel.internal.communication.RotelFlagsMapping;
|
||||
import org.openhab.binding.rotel.internal.communication.RotelSource;
|
||||
import org.openhab.binding.rotel.internal.protocol.RotelAbstractProtocolHandler;
|
||||
@ -93,11 +95,17 @@ public class RotelHexProtocolHandler extends RotelAbstractProtocolHandler {
|
||||
private static final String KEY_HEX_BYPASS = "bypass";
|
||||
private static final String KEY1_HEX_ZONE2 = "zone ";
|
||||
private static final String KEY2_HEX_ZONE2 = "zone2 ";
|
||||
private static final String KEY3_HEX_ZONE2 = "z2 ";
|
||||
private static final String KEY_HEX_ZONE3 = "zone3 ";
|
||||
private static final String KEY2_HEX_ZONE3 = "z3 ";
|
||||
private static final String KEY_HEX_ZONE4 = "zone4 ";
|
||||
private static final String KEY2_HEX_ZONE4 = "z4 ";
|
||||
private static final String KEY_HEX_RECORD = "rec ";
|
||||
private static final String SOURCE = "source";
|
||||
|
||||
private static final Pattern PATTERN_TUNER_FREQ_FM = Pattern.compile("\\d{2,3}[\\.,]\\d{1,2}M.*");
|
||||
private static final Pattern PATTERN_TUNER_FREQ_AM = Pattern.compile("\\d{3,4}K.*");
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(RotelHexProtocolHandler.class);
|
||||
|
||||
private final Map<RotelSource, String> sourcesLabels;
|
||||
@ -325,25 +333,59 @@ public class RotelHexProtocolHandler extends RotelAbstractProtocolHandler {
|
||||
}
|
||||
}
|
||||
}
|
||||
try {
|
||||
dispatchKeyValue(KEY_POWER_ZONE2, model.isZone2On(flags) ? POWER_ON : STANDBY);
|
||||
} catch (RotelException e1) {
|
||||
// Can't get zone power information from flags data, so we just do not notify of this information that way
|
||||
if (model.isInfoPresentInFlags(RotelFlagInfoType.ZONE2)) {
|
||||
try {
|
||||
dispatchKeyValue(KEY_POWER_ZONE2,
|
||||
model.isInfoOnInFlags(RotelFlagInfoType.ZONE2, flags) ? POWER_ON : STANDBY);
|
||||
} catch (RotelException e1) {
|
||||
// Ignore it
|
||||
}
|
||||
}
|
||||
try {
|
||||
dispatchKeyValue(KEY_POWER_ZONE3, model.isZone3On(flags) ? POWER_ON : STANDBY);
|
||||
} catch (RotelException e1) {
|
||||
// Can't get zone power information from flags data, so we just do not notify of this information that way
|
||||
if (model.isInfoPresentInFlags(RotelFlagInfoType.ZONE3)) {
|
||||
try {
|
||||
dispatchKeyValue(KEY_POWER_ZONE3,
|
||||
model.isInfoOnInFlags(RotelFlagInfoType.ZONE3, flags) ? POWER_ON : STANDBY);
|
||||
} catch (RotelException e1) {
|
||||
// Ignore it
|
||||
}
|
||||
}
|
||||
try {
|
||||
dispatchKeyValue(KEY_POWER_ZONE4, model.isZone4On(flags) ? POWER_ON : STANDBY);
|
||||
} catch (RotelException e1) {
|
||||
// Can't get zone power information from flags data, so we just do not notify of this information that way
|
||||
if (model.isInfoPresentInFlags(RotelFlagInfoType.ZONE4)) {
|
||||
try {
|
||||
dispatchKeyValue(KEY_POWER_ZONE4,
|
||||
model.isInfoOnInFlags(RotelFlagInfoType.ZONE4, flags) ? POWER_ON : STANDBY);
|
||||
} catch (RotelException e1) {
|
||||
// Ignore it
|
||||
}
|
||||
}
|
||||
if (model.isInfoPresentInFlags(RotelFlagInfoType.ZONE)) {
|
||||
try {
|
||||
dispatchKeyValue(KEY_POWER_ZONES,
|
||||
model.isInfoOnInFlags(RotelFlagInfoType.ZONE, flags) ? POWER_ON : STANDBY);
|
||||
} catch (RotelException e1) {
|
||||
// Ignore it
|
||||
}
|
||||
}
|
||||
if (model.isInfoPresentInFlags(RotelFlagInfoType.SPEAKER_A)
|
||||
&& model.isInfoPresentInFlags(RotelFlagInfoType.SPEAKER_B)) {
|
||||
try {
|
||||
String speakerValue = MSG_VALUE_OFF;
|
||||
if (model.isInfoOnInFlags(RotelFlagInfoType.SPEAKER_A, flags)
|
||||
&& model.isInfoOnInFlags(RotelFlagInfoType.SPEAKER_B, flags)) {
|
||||
speakerValue = MSG_VALUE_SPEAKER_AB;
|
||||
} else if (model.isInfoOnInFlags(RotelFlagInfoType.SPEAKER_A, flags)) {
|
||||
speakerValue = MSG_VALUE_SPEAKER_A;
|
||||
} else if (model.isInfoOnInFlags(RotelFlagInfoType.SPEAKER_B, flags)) {
|
||||
speakerValue = MSG_VALUE_SPEAKER_B;
|
||||
}
|
||||
dispatchKeyValue(KEY_SPEAKER, speakerValue);
|
||||
} catch (RotelException e1) {
|
||||
// Ignore it
|
||||
}
|
||||
}
|
||||
boolean checkMultiIn = false;
|
||||
boolean checkSource = true;
|
||||
try {
|
||||
if (model.isMultiInputOn(flags)) {
|
||||
if (model.isInfoOnInFlags(RotelFlagInfoType.MULTI_INPUT, flags)) {
|
||||
checkSource = false;
|
||||
try {
|
||||
RotelSource source = model.getSourceFromName(RotelSource.CAT1_MULTI.getName());
|
||||
@ -373,8 +415,9 @@ public class RotelHexProtocolHandler extends RotelAbstractProtocolHandler {
|
||||
|
||||
String valueLowerCase = value.trim().toLowerCase();
|
||||
if (!valueLowerCase.isEmpty() && !valueLowerCase.startsWith(KEY1_HEX_ZONE2)
|
||||
&& !valueLowerCase.startsWith(KEY2_HEX_ZONE2) && !valueLowerCase.startsWith(KEY_HEX_ZONE3)
|
||||
&& !valueLowerCase.startsWith(KEY_HEX_ZONE4)) {
|
||||
&& !valueLowerCase.startsWith(KEY2_HEX_ZONE2) && !valueLowerCase.startsWith(KEY3_HEX_ZONE2)
|
||||
&& !valueLowerCase.startsWith(KEY_HEX_ZONE3) && !valueLowerCase.startsWith(KEY2_HEX_ZONE3)
|
||||
&& !valueLowerCase.startsWith(KEY_HEX_ZONE4) && !valueLowerCase.startsWith(KEY2_HEX_ZONE4)) {
|
||||
dispatchKeyValue(KEY_POWER, POWER_ON);
|
||||
}
|
||||
|
||||
@ -384,12 +427,12 @@ public class RotelHexProtocolHandler extends RotelAbstractProtocolHandler {
|
||||
// Line 1 left
|
||||
value = new String(incomingMessage, idxChars, 14, StandardCharsets.US_ASCII);
|
||||
logger.debug("handleValidHexMessage: line 1 left *{}*", value);
|
||||
parseText(value, checkSource, checkMultiIn, false, false, false, false, false, true);
|
||||
parseText(value, checkSource, checkMultiIn, false, false, false, false, false, false, true, false);
|
||||
|
||||
// Line 1 right
|
||||
value = new String(incomingMessage, idxChars + 14, 7, StandardCharsets.US_ASCII);
|
||||
logger.debug("handleValidHexMessage: line 1 right *{}*", value);
|
||||
parseText(value, false, false, false, false, false, false, false, true);
|
||||
parseText(value, false, false, false, false, false, false, false, false, true, false);
|
||||
|
||||
// Full line 1
|
||||
value = new String(incomingMessage, idxChars, 21, StandardCharsets.US_ASCII);
|
||||
@ -398,16 +441,18 @@ public class RotelHexProtocolHandler extends RotelAbstractProtocolHandler {
|
||||
// Line 2 right
|
||||
value = new String(incomingMessage, idxChars + 35, 7, StandardCharsets.US_ASCII);
|
||||
logger.debug("handleValidHexMessage: line 2 right *{}*", value);
|
||||
parseText(value, false, false, false, false, false, false, false, true);
|
||||
parseText(value, false, false, false, false, false, false, false, false, true, false);
|
||||
|
||||
// Full line 2
|
||||
value = new String(incomingMessage, idxChars + 21, 21, StandardCharsets.US_ASCII);
|
||||
logger.debug("handleValidHexMessage: line 2 *{}*", value);
|
||||
parseText(value, false, false, true, true, false, true, true, true);
|
||||
parseText(value, false, false, true, true, false, false, true, true, true, false);
|
||||
dispatchKeyValue(KEY_LINE2, value);
|
||||
} else {
|
||||
value = new String(incomingMessage, idxChars, model.getRespNbChars(), StandardCharsets.US_ASCII);
|
||||
parseText(value, checkSource, checkMultiIn, true, false, true, true, checkStereo, false);
|
||||
parseText(value, checkSource, checkMultiIn, true, model.getRespNbChars() == 11,
|
||||
model.getRespNbChars() != 11, model.getRespNbChars() == 11, model.hasDspControl(), checkStereo,
|
||||
false, model.getRespNbChars() == 11);
|
||||
dispatchKeyValue(KEY_LINE1, value);
|
||||
}
|
||||
|
||||
@ -424,25 +469,28 @@ public class RotelHexProtocolHandler extends RotelAbstractProtocolHandler {
|
||||
* @param searchMultiIn true if MULTI IN indication has to be searched in the text
|
||||
* @param searchZone true if a zone information has to be searched in the text
|
||||
* @param searchRecord true if a record source has to be searched in the text
|
||||
* @param searchRecordAfterSource true if a record source has to be searched in the text after the a found source
|
||||
* @param searchRecordAfterSource true if a record source has to be searched in the text after the found source
|
||||
* @param searchVolumeAfterSource true if a volume value has to be searched in the text after the found source
|
||||
* @param searchDsp true if a DSP mode has to be searched in the text
|
||||
* @param searchStereo true if a STEREO has to be considered in the search
|
||||
* @param multipleInfo true if source and volume/mute are provided separately
|
||||
* @param searchTunerFreq true if a tuner frequency has to be searched in the text
|
||||
*/
|
||||
private void parseText(String text, boolean searchSource, boolean searchMultiIn, boolean searchZone,
|
||||
boolean searchRecord, boolean searchRecordAfterSource, boolean searchDsp, boolean searchStereo,
|
||||
boolean multipleInfo) {
|
||||
boolean searchRecord, boolean searchRecordAfterSource, boolean searchVolumeAfterSource, boolean searchDsp,
|
||||
boolean searchStereo, boolean multipleInfo, boolean searchTunerFreq) {
|
||||
String value = text.trim();
|
||||
String valueLowerCase = value.toLowerCase();
|
||||
if (searchRecord) {
|
||||
dispatchKeyValue(KEY_RECORD_SEL, valueLowerCase.startsWith(KEY_HEX_RECORD) ? MSG_VALUE_ON : MSG_VALUE_OFF);
|
||||
}
|
||||
if (searchZone) {
|
||||
if (valueLowerCase.startsWith(KEY1_HEX_ZONE2) || valueLowerCase.startsWith(KEY2_HEX_ZONE2)) {
|
||||
if (valueLowerCase.startsWith(KEY1_HEX_ZONE2) || valueLowerCase.startsWith(KEY2_HEX_ZONE2)
|
||||
|| valueLowerCase.startsWith(KEY3_HEX_ZONE2)) {
|
||||
dispatchKeyValue(KEY_ZONE, "2");
|
||||
} else if (valueLowerCase.startsWith(KEY_HEX_ZONE3)) {
|
||||
} else if (valueLowerCase.startsWith(KEY_HEX_ZONE3) || valueLowerCase.startsWith(KEY2_HEX_ZONE3)) {
|
||||
dispatchKeyValue(KEY_ZONE, "3");
|
||||
} else if (valueLowerCase.startsWith(KEY_HEX_ZONE4)) {
|
||||
} else if (valueLowerCase.startsWith(KEY_HEX_ZONE4) || valueLowerCase.startsWith(KEY2_HEX_ZONE4)) {
|
||||
dispatchKeyValue(KEY_ZONE, "4");
|
||||
} else {
|
||||
dispatchKeyValue(KEY_ZONE, "1");
|
||||
@ -555,19 +603,41 @@ public class RotelHexProtocolHandler extends RotelAbstractProtocolHandler {
|
||||
} else if (searchDsp && valueLowerCase.startsWith(KEY_HEX_MPEG)) {
|
||||
logger.debug("MPEG");
|
||||
dispatchKeyValue(KEY_DSP_MODE, RotelDsp.CAT4_NONE.getFeedback());
|
||||
} else if (searchZone
|
||||
&& (valueLowerCase.startsWith(KEY1_HEX_ZONE2) || valueLowerCase.startsWith(KEY2_HEX_ZONE2))) {
|
||||
value = value.substring(
|
||||
valueLowerCase.startsWith(KEY1_HEX_ZONE2) ? KEY1_HEX_ZONE2.length() : KEY2_HEX_ZONE2.length());
|
||||
parseZone2(value, multipleInfo);
|
||||
} else if (searchZone && valueLowerCase.startsWith(KEY1_HEX_ZONE2)) {
|
||||
parseZone2(value.substring(KEY1_HEX_ZONE2.length()), multipleInfo);
|
||||
} else if (searchZone && valueLowerCase.startsWith(KEY2_HEX_ZONE2)) {
|
||||
parseZone2(value.substring(KEY2_HEX_ZONE2.length()), multipleInfo);
|
||||
} else if (searchZone && valueLowerCase.startsWith(KEY3_HEX_ZONE2)) {
|
||||
parseZone2(value.substring(KEY3_HEX_ZONE2.length()), multipleInfo);
|
||||
} else if (searchZone && valueLowerCase.startsWith(KEY_HEX_ZONE3)) {
|
||||
parseZone3(value.substring(KEY_HEX_ZONE3.length()), multipleInfo);
|
||||
} else if (searchZone && valueLowerCase.startsWith(KEY2_HEX_ZONE3)) {
|
||||
parseZone3(value.substring(KEY2_HEX_ZONE3.length()), multipleInfo);
|
||||
} else if (searchZone && valueLowerCase.startsWith(KEY_HEX_ZONE4)) {
|
||||
parseZone4(value.substring(KEY_HEX_ZONE4.length()), multipleInfo);
|
||||
} else if (searchZone && valueLowerCase.startsWith(KEY2_HEX_ZONE4)) {
|
||||
parseZone4(value.substring(KEY2_HEX_ZONE4.length()), multipleInfo);
|
||||
} else if (searchRecord && valueLowerCase.startsWith(KEY_HEX_RECORD)) {
|
||||
parseRecord(value.substring(KEY_HEX_RECORD.length()));
|
||||
} else if (searchSource || searchRecordAfterSource) {
|
||||
parseSourceAndRecord(value, searchSource, searchRecordAfterSource, multipleInfo);
|
||||
} else if (searchSource && searchTunerFreq
|
||||
&& (PATTERN_TUNER_FREQ_FM.matcher(value).matches() || PATTERN_TUNER_FREQ_AM.matcher(value).matches())) {
|
||||
try {
|
||||
RotelSource source = model.getSourceFromName("TUNER");
|
||||
RotelCommand cmd = source.getCommand();
|
||||
if (cmd != null) {
|
||||
String value2 = cmd.getAsciiCommandV2();
|
||||
if (value2 != null) {
|
||||
dispatchKeyValue(KEY_SOURCE, value2);
|
||||
if (!multipleInfo) {
|
||||
dispatchKeyValue(KEY_MUTE, MSG_VALUE_OFF);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (RotelException e) {
|
||||
// Ignore it, no tuner source found for this model
|
||||
}
|
||||
} else if (searchSource || searchRecordAfterSource || searchVolumeAfterSource) {
|
||||
parseSourceAndOther(value, searchSource, searchRecordAfterSource, searchVolumeAfterSource, multipleInfo);
|
||||
}
|
||||
}
|
||||
|
||||
@ -603,8 +673,8 @@ public class RotelHexProtocolHandler extends RotelAbstractProtocolHandler {
|
||||
return source;
|
||||
}
|
||||
|
||||
private void parseSourceAndRecord(String text, boolean searchSource, boolean searchRecordAfterSource,
|
||||
boolean multipleInfo) {
|
||||
private void parseSourceAndOther(String text, boolean searchSource, boolean searchRecordAfterSource,
|
||||
boolean searchVolumeAfterSource, boolean multipleInfo) {
|
||||
RotelSource source = parseSource(text, false);
|
||||
if (source != null) {
|
||||
if (searchSource) {
|
||||
@ -620,6 +690,16 @@ public class RotelHexProtocolHandler extends RotelAbstractProtocolHandler {
|
||||
}
|
||||
}
|
||||
|
||||
if (searchVolumeAfterSource) {
|
||||
String value = extractNumber(text, getSourceLabel(source).length());
|
||||
if (!value.isEmpty()) {
|
||||
dispatchKeyValue(KEY_VOLUME, value);
|
||||
if (!searchSource && !multipleInfo) {
|
||||
dispatchKeyValue(KEY_MUTE, MSG_VALUE_OFF);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (searchRecordAfterSource) {
|
||||
String value = text.substring(getSourceLabel(source).length()).trim();
|
||||
source = parseSource(value, true);
|
||||
@ -659,6 +739,9 @@ public class RotelHexProtocolHandler extends RotelAbstractProtocolHandler {
|
||||
|
||||
private void parseZone2(String text, boolean multipleInfo) {
|
||||
String value = text.trim();
|
||||
if (!model.isInfoPresentInFlags(RotelFlagInfoType.ZONE2)) {
|
||||
dispatchKeyValue(KEY_POWER_ZONE2, MSG_VALUE_OFF.equalsIgnoreCase(value) ? STANDBY : MSG_VALUE_ON);
|
||||
}
|
||||
String valueLowerCase = value.toLowerCase();
|
||||
if (valueLowerCase.startsWith(KEY1_HEX_VOLUME) || valueLowerCase.startsWith(KEY2_HEX_VOLUME)) {
|
||||
value = extractNumber(value,
|
||||
@ -693,6 +776,9 @@ public class RotelHexProtocolHandler extends RotelAbstractProtocolHandler {
|
||||
|
||||
private void parseZone3(String text, boolean multipleInfo) {
|
||||
String value = text.trim();
|
||||
if (!model.isInfoPresentInFlags(RotelFlagInfoType.ZONE3)) {
|
||||
dispatchKeyValue(KEY_POWER_ZONE3, MSG_VALUE_OFF.equalsIgnoreCase(value) ? STANDBY : MSG_VALUE_ON);
|
||||
}
|
||||
String valueLowerCase = value.toLowerCase();
|
||||
if (valueLowerCase.startsWith(KEY1_HEX_VOLUME) || valueLowerCase.startsWith(KEY2_HEX_VOLUME)) {
|
||||
value = extractNumber(value,
|
||||
@ -727,6 +813,9 @@ public class RotelHexProtocolHandler extends RotelAbstractProtocolHandler {
|
||||
|
||||
private void parseZone4(String text, boolean multipleInfo) {
|
||||
String value = text.trim();
|
||||
if (!model.isInfoPresentInFlags(RotelFlagInfoType.ZONE4)) {
|
||||
dispatchKeyValue(KEY_POWER_ZONE4, MSG_VALUE_OFF.equalsIgnoreCase(value) ? STANDBY : MSG_VALUE_ON);
|
||||
}
|
||||
String valueLowerCase = value.toLowerCase();
|
||||
if (valueLowerCase.startsWith(KEY1_HEX_VOLUME) || valueLowerCase.startsWith(KEY2_HEX_VOLUME)) {
|
||||
value = extractNumber(value,
|
||||
|
@ -320,4 +320,48 @@
|
||||
</parameter>
|
||||
</config-description>
|
||||
|
||||
<config-description uri="thing-type:rotel:serial6">
|
||||
<parameter name="serialPort" type="text" required="false">
|
||||
<context>serial-port</context>
|
||||
<limitToOptions>false</limitToOptions>
|
||||
<label>@text/config.serialPort.label</label>
|
||||
<description>@text/config.serialPort.description</description>
|
||||
</parameter>
|
||||
<parameter name="baudRate" type="integer" required="false">
|
||||
<label>@text/config.baudRate.label</label>
|
||||
<description>@text/config.baudRate.description</description>
|
||||
<limitToOptions>true</limitToOptions>
|
||||
<options>
|
||||
<option value="19200">19200</option>
|
||||
<option value="38400">38400</option>
|
||||
</options>
|
||||
<default>38400</default>
|
||||
</parameter>
|
||||
<parameter name="host" type="text" required="false">
|
||||
<context>network-address</context>
|
||||
<label>@text/config.hostOverIp.label</label>
|
||||
<description>@text/config.hostOverIp.description</description>
|
||||
</parameter>
|
||||
<parameter name="port" type="integer" required="false">
|
||||
<label>@text/config.portOverIp.label</label>
|
||||
<description>@text/config.portOverIp.description</description>
|
||||
</parameter>
|
||||
<parameter name="inputLabelVideo1" type="text" required="false">
|
||||
<label>@text/config.inputLabelVideo1.label</label>
|
||||
<description>@text/config.inputLabelVideo1.description</description>
|
||||
</parameter>
|
||||
<parameter name="inputLabelVideo2" type="text" required="false">
|
||||
<label>@text/config.inputLabelVideo2.label</label>
|
||||
<description>@text/config.inputLabelVideo2.description</description>
|
||||
</parameter>
|
||||
<parameter name="inputLabelVideo3" type="text" required="false">
|
||||
<label>@text/config.inputLabelVideo3.label</label>
|
||||
<description>@text/config.inputLabelVideo3.description</description>
|
||||
</parameter>
|
||||
<parameter name="inputLabelVideo4" type="text" required="false">
|
||||
<label>@text/config.inputLabelVideo4.label</label>
|
||||
<description>@text/config.inputLabelVideo4.description</description>
|
||||
</parameter>
|
||||
</config-description>
|
||||
|
||||
</config-description:config-descriptions>
|
||||
|
@ -89,6 +89,8 @@ thing-type.rotel.rt11.label = RT-11 Tuner
|
||||
thing-type.rotel.rt11.description = Connection to the Rotel RT-11 tuner
|
||||
thing-type.rotel.rt1570.label = RT-1570 Tuner
|
||||
thing-type.rotel.rt1570.description = Connection to the Rotel RT-1570 tuner
|
||||
thing-type.rotel.rx1052.label = RX-1052 Stereo Receiver
|
||||
thing-type.rotel.rx1052.description = Connection to the Rotel RX-1052 stereo receiver
|
||||
thing-type.rotel.s5.label = S5 Stereo Amplifier
|
||||
thing-type.rotel.s5.description = Connection to the Rotel Michi S5 stereo amplifier
|
||||
thing-type.rotel.t11.label = T11 Tuner
|
||||
@ -144,6 +146,8 @@ channel-type.rotel.volumeUpDown.description = Increase or decrease the volume
|
||||
|
||||
# thing type configuration
|
||||
|
||||
config.baudRate.label = Baud Rate
|
||||
config.baudRate.description = Baud rate to use for connecting to the Rotel device. Select the highest baud rate if your black unit has at least serial number 090-6441001 or your silver unit has at least serial number 990-6441001.
|
||||
config.host.label = Address
|
||||
config.host.description = Host name or IP address of the Rotel device (IP connection) or the machine connected to the Rotel device (serial over IP)
|
||||
config.hostOverIp.label = Address
|
||||
@ -428,6 +432,7 @@ offline.config-error-invalid-port = Invalid port configuration setting
|
||||
offline.config-error-invalid-serial-over-ip = Use host and port configuration settings for a serial over IP connection
|
||||
offline.comm-error-init-sequence = Init sequence failed
|
||||
offline.comm-error-init-sequence-zone = Init sequence zone {0} failed
|
||||
offline.comm-error-check-power-zones-sequence = Check power zones sequence failed
|
||||
offline.comm-error-reading-thread = Reading thread ended
|
||||
offline.comm-error-sending-command = Sending command failed
|
||||
offline.comm-error-reconnection = Reconnection failed
|
||||
|
@ -90,6 +90,24 @@
|
||||
</channels>
|
||||
</channel-group-type>
|
||||
|
||||
<channel-group-type id="mainZoneType6">
|
||||
<label>@text/channel-group.mainZone.label</label>
|
||||
<description>@text/channel-group.mainZone.description</description>
|
||||
<channels>
|
||||
<channel id="power" typeId="system.power"/>
|
||||
<channel id="source" typeId="source"/>
|
||||
<channel id="recordSource" typeId="recordSource"/>
|
||||
<channel id="volume" typeId="system.volume"/>
|
||||
<channel id="mute" typeId="system.mute"/>
|
||||
<channel id="bass" typeId="bass"/>
|
||||
<channel id="treble" typeId="treble"/>
|
||||
<channel id="speakera" typeId="speakera"/>
|
||||
<channel id="speakerb" typeId="speakerb"/>
|
||||
<channel id="line1" typeId="frontPanelLine"/>
|
||||
<channel id="otherCommand" typeId="otherCommand"/>
|
||||
</channels>
|
||||
</channel-group-type>
|
||||
|
||||
<channel-group-type id="zone2type1">
|
||||
<label>@text/channel-group.zone2.label</label>
|
||||
<description>@text/channel-group.zone2.description</description>
|
||||
|
@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<thing:thing-descriptions bindingId="rotel"
|
||||
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">
|
||||
|
||||
<!-- Rotel RX-1052 Connection Thing Type -->
|
||||
<thing-type id="rx1052">
|
||||
<label>RX-1052 Stereo Receiver</label>
|
||||
<description>Connection to the Rotel RX-1052 stereo receiver</description>
|
||||
|
||||
<channel-groups>
|
||||
<channel-group id="mainZone" typeId="mainZoneType6"/>
|
||||
<channel-group id="zone2" typeId="zone2type1"/>
|
||||
<channel-group id="zone3" typeId="zone3"/>
|
||||
<channel-group id="zone4" typeId="zone4"/>
|
||||
</channel-groups>
|
||||
|
||||
<properties>
|
||||
<property name="protocol">HEX</property>
|
||||
</properties>
|
||||
|
||||
<config-description-ref uri="thing-type:rotel:serial6"/>
|
||||
</thing-type>
|
||||
|
||||
</thing:thing-descriptions>
|
Loading…
Reference in New Issue
Block a user