]> git.basschouten.com Git - openhab-addons.git/commitdiff
[rotel] New channels to control random mode and repeat mode (CD players) (#13165)
authorlolodomo <lg.hc@free.fr>
Sat, 23 Jul 2022 15:26:09 +0000 (17:26 +0200)
committerGitHub <noreply@github.com>
Sat, 23 Jul 2022 15:26:09 +0000 (17:26 +0200)
Available for models CD11, CD14 and RCD-1572

Signed-off-by: Laurent Garnier <lg.hc@free.fr>
bundles/org.openhab.binding.rotel/README.md
bundles/org.openhab.binding.rotel/src/main/java/org/openhab/binding/rotel/internal/RotelBindingConstants.java
bundles/org.openhab.binding.rotel/src/main/java/org/openhab/binding/rotel/internal/RotelRepeatMode.java [new file with mode: 0644]
bundles/org.openhab.binding.rotel/src/main/java/org/openhab/binding/rotel/internal/communication/RotelCommand.java
bundles/org.openhab.binding.rotel/src/main/java/org/openhab/binding/rotel/internal/communication/RotelSimuConnector.java
bundles/org.openhab.binding.rotel/src/main/java/org/openhab/binding/rotel/internal/handler/RotelHandler.java
bundles/org.openhab.binding.rotel/src/main/resources/OH-INF/i18n/rotel.properties
bundles/org.openhab.binding.rotel/src/main/resources/OH-INF/thing/cd11.xml
bundles/org.openhab.binding.rotel/src/main/resources/OH-INF/thing/cd14.xml
bundles/org.openhab.binding.rotel/src/main/resources/OH-INF/thing/channels.xml
bundles/org.openhab.binding.rotel/src/main/resources/OH-INF/thing/rcd1572.xml

index edc946d4c8ad6c39a748ae9f1c12f2f20c5221bf..c63bd6576f527d65da01ecd563823e04997a43dd 100644 (file)
@@ -163,6 +163,8 @@ The following channels are available:
 | treble, mainZone#treble | Treble Adjustment     | Number    | Adjust the treble                                        | INCREASE, DECREASE, value          |
 | playControl    | Playback Control               | Player    | Control the playback                                     | PLAY, PAUSE, NEXT, PREVIOUS        |
 | track          | Current Track                  | Number    | The current CD track number                              |                                    |
+| random         | Random Mode                    | Switch    | The current random mode                                  |                                    |
+| repeat         | Repeat Mode                    | String    | The current repeat mode                                  | TRACK, DISC, OFF                   |
 | mainZone#line1 | Front Panel Line 1             | String    | The first line displayed on the device front panel       |                                    |
 | mainZone#line2 | Front Panel Line 2             | String    | The second line displayed on the device front panel      |                                    |
 | frequency      | Current Frequency              | Number    | The current frequency (in kHz) for digital source input  |                                    |
@@ -179,8 +181,8 @@ Here are the list of channels available for each thing type:
 | a11        | power, source, volume, mute, bass, treble, brightness, tcbypass, balance, speakera, speakerb            |
 | a12        | power, source, volume, mute, bass, treble, frequency, brightness, tcbypass, balance, speakera, speakerb |
 | a14        | power, source, volume, mute, bass, treble, frequency, brightness, tcbypass, balance, speakera, speakerb |
-| cd11       | power, playControl, track, brightness                                                                   |
-| cd14       | power, playControl, track, brightness                                                                   |
+| cd11       | power, playControl, track, random, repeat, brightness                                                   |
+| cd14       | power, playControl, track, random, repeat, brightness                                                   |
 | m8         | power, brightness                                                                                       |
 | p5         | power, source, volume, mute, bass, treble, frequency, brightness, tcbypass, balance                     |
 | ra11       | power, source, volume, mute, bass, treble, playControl, frequency, brightness, tcbypass, balance        |
@@ -193,7 +195,7 @@ Here are the list of channels available for each thing type:
 | rc1572     | power, source, volume, mute, bass, treble, frequency, brightness, tcbypass, balance                     |
 | rc1590     | power, source, volume, mute, bass, treble, frequency, brightness, tcbypass, balance                     |
 | rcd1570    | power, playControl, brightness                                                                          |
-| rcd1572    | power, playControl, track, brightness                                                                   |
+| rcd1572    | power, playControl, track, random, repeat, brightness                                                   |
 | rcx1500    | power, source, volume, mute, playControl                                                                |
 | rdd1580    | power, source, playControl, frequency                                                                   |
 | rdg1520    | power, source, playControl                                                                              |
index 8f2169fbe2801aca906b151edc32078d6e7de7eb..78e94b802eefea6852a9e79c38b7c5e2fe8e51ce 100644 (file)
@@ -136,6 +136,8 @@ public class RotelBindingConstants {
     public static final String CHANNEL_TREBLE = "treble";
     public static final String CHANNEL_PLAY_CONTROL = "playControl";
     public static final String CHANNEL_TRACK = "track";
+    public static final String CHANNEL_RANDOM = "random";
+    public static final String CHANNEL_REPEAT = "repeat";
     public static final String CHANNEL_FREQUENCY = "frequency";
     public static final String CHANNEL_LINE1 = "mainZone#line1";
     public static final String CHANNEL_LINE2 = "mainZone#line2";
@@ -259,6 +261,8 @@ public class RotelBindingConstants {
     public static final String KEY1_PLAY_STATUS = "play_status";
     public static final String KEY2_PLAY_STATUS = "status";
     public static final String KEY_TRACK = "track";
+    public static final String KEY_RANDOM = "rnd";
+    public static final String KEY_REPEAT = "rpt";
     public static final String KEY_DIMMER = "dimmer";
     public static final String KEY_FREQ = "freq";
     public static final String KEY_FREQ_ZONE1 = "freq_zone1";
@@ -306,6 +310,8 @@ public class RotelBindingConstants {
     public static final String PLAY = "play";
     public static final String PAUSE = "pause";
     public static final String STOP = "stop";
+    public static final String TRACK = "track";
+    public static final String DISC = "disc";
 
     public static final int MAX_NUMBER_OF_ZONES = 4;
 }
diff --git a/bundles/org.openhab.binding.rotel/src/main/java/org/openhab/binding/rotel/internal/RotelRepeatMode.java b/bundles/org.openhab.binding.rotel/src/main/java/org/openhab/binding/rotel/internal/RotelRepeatMode.java
new file mode 100644 (file)
index 0000000..96419af
--- /dev/null
@@ -0,0 +1,45 @@
+/**
+ * Copyright (c) 2010-2022 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;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+/**
+ * Represents the different repeat modes
+ *
+ * @author Laurent Garnier - Initial contribution
+ */
+@NonNullByDefault
+public enum RotelRepeatMode {
+    TRACK,
+    DISC,
+    OFF;
+
+    /**
+     * Get the repeat mode from its name
+     *
+     * @param name the searched name (case is ignored)
+     *
+     * @return the repeat mode associated to the searched name
+     *
+     * @throws RotelException - If no repeat mode is associated to the searched name
+     */
+    public static RotelRepeatMode getFromName(String name) throws RotelException {
+        for (RotelRepeatMode value : RotelRepeatMode.values()) {
+            if (value.name().equalsIgnoreCase(name)) {
+                return value;
+            }
+        }
+        throw new RotelException("Invalid name for a repeat mode: " + name);
+    }
+}
index 48cce171f789c5eb249ce51df0302df1ee9132f2..742e9fe108bfaa2f8a37e599dcdbeb9dc1a3b94e 100644 (file)
@@ -267,6 +267,10 @@ public enum RotelCommand {
     PAUSE("Pause Source", PRIMARY_CMD, (byte) 0x05, "pause", "pause"),
     CD_PLAY_STATUS("Request CD play status", "get_cd_play_status", null),
     PLAY_STATUS("Request source play status", "get_play_status", "status?"),
+    RANDOM_TOGGLE("Random Play Mode Toggle", PRIMARY_CMD, (byte) 0x25, "random", "rnd"),
+    RANDOM_MODE("Request current random play mode", null, "rnd?"),
+    REPEAT_TOGGLE("Repeat Play Mode Toggle", PRIMARY_CMD, (byte) 0x26, "repeat", "rpt"),
+    REPEAT_MODE("Request current repeat play mode", null, "rpt?"),
     TRACK_FORWARD("Track Forward", PRIMARY_CMD, (byte) 0x09, "track_fwd", "trkf"),
     TRACK_BACKWORD("Track Backward", PRIMARY_CMD, (byte) 0x08, "track_back", "trkb"),
     TRACK("Request current CD track number", null, "track?"),
index 1821d0294cf8a98352fe4680f86b48af0e2566a1..6e210d21fb371aa35e388a1dbe223c69c01a574b 100644 (file)
@@ -28,6 +28,7 @@ import org.eclipse.jdt.annotation.Nullable;
 import org.openhab.binding.rotel.internal.RotelException;
 import org.openhab.binding.rotel.internal.RotelModel;
 import org.openhab.binding.rotel.internal.RotelPlayStatus;
+import org.openhab.binding.rotel.internal.RotelRepeatMode;
 import org.openhab.binding.rotel.internal.protocol.RotelAbstractProtocolHandler;
 import org.openhab.binding.rotel.internal.protocol.RotelProtocol;
 import org.openhab.binding.rotel.internal.protocol.hex.RotelHexProtocolHandler;
@@ -71,6 +72,8 @@ public class RotelSimuConnector extends RotelConnector {
     private boolean speakerB = false;
     private RotelPlayStatus playStatus = RotelPlayStatus.STOPPED;
     private int track = 1;
+    private boolean randomMode;
+    private RotelRepeatMode repeatMode = RotelRepeatMode.OFF;
     private boolean selectingRecord;
     private int showZone;
     private int dimmer;
@@ -780,6 +783,30 @@ public class RotelSimuConnector extends RotelConnector {
                 case TRACK:
                     textAscii = buildTrackAsciiResponse();
                     break;
+                case RANDOM_TOGGLE:
+                    randomMode = !randomMode;
+                    textAscii = buildRandomModeAsciiResponse();
+                    break;
+                case RANDOM_MODE:
+                    textAscii = buildRandomModeAsciiResponse();
+                    break;
+                case REPEAT_TOGGLE:
+                    switch (repeatMode) {
+                        case TRACK:
+                            repeatMode = RotelRepeatMode.DISC;
+                            break;
+                        case DISC:
+                            repeatMode = RotelRepeatMode.OFF;
+                            break;
+                        case OFF:
+                            repeatMode = RotelRepeatMode.TRACK;
+                            break;
+                    }
+                    textAscii = buildRepeatModeAsciiResponse();
+                    break;
+                case REPEAT_MODE:
+                    textAscii = buildRepeatModeAsciiResponse();
+                    break;
                 case SOURCE_MULTI_INPUT:
                     multiinput = !multiinput;
                     text = "MULTI IN " + (multiinput ? "ON" : "OFF");
@@ -1174,6 +1201,26 @@ public class RotelSimuConnector extends RotelConnector {
         return buildAsciiResponse(KEY_TRACK, String.format("%03d", track));
     }
 
+    private String buildRandomModeAsciiResponse() {
+        return buildAsciiResponse(KEY_RANDOM, randomMode);
+    }
+
+    private String buildRepeatModeAsciiResponse() {
+        String mode = "";
+        switch (repeatMode) {
+            case TRACK:
+                mode = TRACK;
+                break;
+            case DISC:
+                mode = DISC;
+                break;
+            case OFF:
+                mode = MSG_VALUE_OFF;
+                break;
+        }
+        return buildAsciiResponse(KEY_REPEAT, mode);
+    }
+
     private String buildSourceAsciiResponse() {
         if (model.getNumberOfZones() > 1) {
             StringJoiner sj = new StringJoiner(",");
index 6a2d2392b4ed2670811f023f01bb6888dc6d1c82..518cc6a026dbafa9d38882c597d135954927d676 100644 (file)
@@ -29,6 +29,7 @@ import org.openhab.binding.rotel.internal.RotelBindingConstants;
 import org.openhab.binding.rotel.internal.RotelException;
 import org.openhab.binding.rotel.internal.RotelModel;
 import org.openhab.binding.rotel.internal.RotelPlayStatus;
+import org.openhab.binding.rotel.internal.RotelRepeatMode;
 import org.openhab.binding.rotel.internal.RotelStateDescriptionOptionProvider;
 import org.openhab.binding.rotel.internal.communication.RotelCommand;
 import org.openhab.binding.rotel.internal.communication.RotelConnector;
@@ -112,6 +113,8 @@ public class RotelHandler extends BaseThingHandler implements RotelMessageEventL
     private int[] trebles = { 0, 0, 0, 0, 0 };
     private RotelPlayStatus playStatus = RotelPlayStatus.STOPPED;
     private int track;
+    private boolean randomMode;
+    private RotelRepeatMode repeatMode = RotelRepeatMode.OFF;
     private double[] frequencies = { 0.0, 0.0, 0.0, 0.0, 0.0 };
     private String frontPanelLine1 = "";
     private String frontPanelLine2 = "";
@@ -790,6 +793,48 @@ public class RotelHandler extends BaseThingHandler implements RotelMessageEventL
                             logger.debug("Command {} from channel {} failed: invalid command value", command, channel);
                         }
                         break;
+                    case CHANNEL_RANDOM:
+                        if (!isPowerOn()) {
+                            success = false;
+                            logger.debug("Command {} from channel {} ignored: device in standby", command, channel);
+                        } else if (command instanceof OnOffType) {
+                            sendCommand(RotelCommand.RANDOM_TOGGLE);
+                        } else {
+                            success = false;
+                            logger.debug("Command {} from channel {} failed: invalid command value", command, channel);
+                        }
+                        break;
+                    case CHANNEL_REPEAT:
+                        if (!isPowerOn()) {
+                            success = false;
+                            logger.debug("Command {} from channel {} ignored: device in standby", command, channel);
+                        } else {
+                            RotelRepeatMode currentMode = repeatMode;
+                            RotelRepeatMode mode = RotelRepeatMode.OFF;
+                            try {
+                                mode = RotelRepeatMode.getFromName(command.toString());
+                                if (mode == currentMode) {
+                                    success = false;
+                                    logger.debug("Command {} from channel {} ignored: no change requested", command,
+                                            channel);
+                                }
+                            } catch (RotelException e) {
+                                success = false;
+                                logger.debug("Command {} from channel {} failed: invalid command value", command,
+                                        channel);
+                            }
+                            if (success) {
+                                // Toggle TRACK -> DISC -> OFF
+                                sendCommand(RotelCommand.REPEAT_TOGGLE);
+                                if ((mode == RotelRepeatMode.OFF && currentMode == RotelRepeatMode.TRACK)
+                                        || (mode == RotelRepeatMode.TRACK && currentMode == RotelRepeatMode.DISC)
+                                        || (mode == RotelRepeatMode.DISC && currentMode == RotelRepeatMode.OFF)) {
+                                    Thread.sleep(SLEEP_INTV);
+                                    sendCommand(RotelCommand.REPEAT_TOGGLE);
+                                }
+                            }
+                        }
+                        break;
                     case CHANNEL_BRIGHTNESS:
                     case CHANNEL_ALL_BRIGHTNESS:
                         if (!isPowerOn()) {
@@ -1455,6 +1500,31 @@ public class RotelHandler extends BaseThingHandler implements RotelMessageEventL
                         updateChannelState(CHANNEL_TRACK);
                     }
                     break;
+                case KEY_RANDOM:
+                    if (MSG_VALUE_ON.equalsIgnoreCase(value)) {
+                        randomMode = true;
+                        updateChannelState(CHANNEL_RANDOM);
+                    } else if (MSG_VALUE_OFF.equalsIgnoreCase(value)) {
+                        randomMode = false;
+                        updateChannelState(CHANNEL_RANDOM);
+                    } else {
+                        throw new RotelException("Invalid value");
+                    }
+                    break;
+                case KEY_REPEAT:
+                    if (TRACK.equalsIgnoreCase(value)) {
+                        repeatMode = RotelRepeatMode.TRACK;
+                        updateChannelState(CHANNEL_REPEAT);
+                    } else if (DISC.equalsIgnoreCase(value)) {
+                        repeatMode = RotelRepeatMode.DISC;
+                        updateChannelState(CHANNEL_REPEAT);
+                    } else if (MSG_VALUE_OFF.equalsIgnoreCase(value)) {
+                        repeatMode = RotelRepeatMode.OFF;
+                        updateChannelState(CHANNEL_REPEAT);
+                    } else {
+                        throw new RotelException("Invalid value");
+                    }
+                    break;
                 case KEY_FREQ:
                 case KEY_FREQ_ZONE1:
                 case KEY_FREQ_ZONE2:
@@ -1596,6 +1666,8 @@ public class RotelHandler extends BaseThingHandler implements RotelMessageEventL
         updateChannelState(CHANNEL_TREBLE);
         updateChannelState(CHANNEL_PLAY_CONTROL);
         updateChannelState(CHANNEL_TRACK);
+        updateChannelState(CHANNEL_RANDOM);
+        updateChannelState(CHANNEL_REPEAT);
         updateChannelState(CHANNEL_FREQUENCY);
         updateChannelState(CHANNEL_BRIGHTNESS);
         updateChannelState(CHANNEL_TCBYPASS);
@@ -1837,6 +1909,10 @@ public class RotelHandler extends BaseThingHandler implements RotelMessageEventL
                                 if (source != null && source.getName().equals("CD") && !model.hasSourceControl()) {
                                     sendCommand(RotelCommand.TRACK);
                                     Thread.sleep(SLEEP_INTV);
+                                    sendCommand(RotelCommand.RANDOM_MODE);
+                                    Thread.sleep(SLEEP_INTV);
+                                    sendCommand(RotelCommand.REPEAT_MODE);
+                                    Thread.sleep(SLEEP_INTV);
                                 }
                             }
                             if (model.hasDspControl()) {
@@ -2114,6 +2190,16 @@ public class RotelHandler extends BaseThingHandler implements RotelMessageEventL
                     state = new DecimalType(track);
                 }
                 break;
+            case CHANNEL_RANDOM:
+                if (isPowerOn()) {
+                    state = OnOffType.from(randomMode);
+                }
+                break;
+            case CHANNEL_REPEAT:
+                if (isPowerOn()) {
+                    state = new StringType(repeatMode.name());
+                }
+                break;
             case CHANNEL_PLAY_CONTROL:
                 if (isPowerOn()) {
                     switch (playStatus) {
index 80055551670656dc225c401600264caf0caa1a07..c60d8d3d6cf364cfe4f84a1bcc6c5f26b5947789 100644 (file)
@@ -11,6 +11,8 @@ thing-type.rotel.a12.label = A12 Integrated Amplifier
 thing-type.rotel.a12.description = Connection to the Rotel A12 or A12MKII integrated amplifier
 thing-type.rotel.a14.label = A14 Integrated Amplifier
 thing-type.rotel.a14.description = Connection to the Rotel A14 or A14MKII integrated amplifier
+thing-type.rotel.c8.label = C8 Distribution Amplifier
+thing-type.rotel.c8.description = Connection to the Rotel C8 or C8+ distribution amplifier
 thing-type.rotel.cd11.label = CD11 CD Player
 thing-type.rotel.cd11.description = Connection to the Rotel CD11 CD player
 thing-type.rotel.cd14.label = CD14 CD Player
@@ -112,8 +114,15 @@ channel-type.rotel.frequency.label = Current Frequency
 channel-type.rotel.frequency.description = The current frequency (in kHz) for digital source input
 channel-type.rotel.frontPanelLine.label = Front Panel Line
 channel-type.rotel.frontPanelLine.description = The line content displayed on the device front panel
+channel-type.rotel.random.label = Random Mode
+channel-type.rotel.random.description = The current random mode
 channel-type.rotel.recordSource.label = Record Source
 channel-type.rotel.recordSource.description = Select the source to be recorded
+channel-type.rotel.repeat.label = Repeat Mode
+channel-type.rotel.repeat.description = The current repeat mode
+channel-type.rotel.repeat.state.option.TRACK = Track
+channel-type.rotel.repeat.state.option.DISC = Disc
+channel-type.rotel.repeat.state.option.OFF = Off
 channel-type.rotel.source.label = Source Input
 channel-type.rotel.source.description = Select the source input
 channel-type.rotel.speakera.label = Speaker-A Adjustment
index 6a401b1d28d7d06844664dfce44a094ac2b9fdaa..634fa228cb65544ef01648d5f19557a4a97fcc9a 100644 (file)
@@ -13,6 +13,8 @@
                        <channel id="power" typeId="system.power"/>
                        <channel id="playControl" typeId="system.media-control"/>
                        <channel id="track" typeId="track"/>
+                       <channel id="random" typeId="random"/>
+                       <channel id="repeat" typeId="repeat"/>
                        <channel id="brightness" typeId="brightness"/>
                </channels>
 
index 4d0a2b907932928ecb9d48fcfa9e5e7179f33f2d..416501567112d790d158686a833c15cafbb37226 100644 (file)
@@ -13,6 +13,8 @@
                        <channel id="power" typeId="system.power"/>
                        <channel id="playControl" typeId="system.media-control"/>
                        <channel id="track" typeId="track"/>
+                       <channel id="random" typeId="random"/>
+                       <channel id="repeat" typeId="repeat"/>
                        <channel id="brightness" typeId="brightness"/>
                </channels>
 
index 8cdfe8a9ee491641a6088f87ad0d3d716cd36d0b..b0132fea9566e22304fab7f9b6b893dd729321c1 100644 (file)
                <state pattern="%d" readOnly="true"/>
        </channel-type>
 
+       <channel-type id="random" advanced="true">
+               <item-type>Switch</item-type>
+               <label>Random Mode</label>
+               <description>The current random mode</description>
+               <state readOnly="false"/>
+       </channel-type>
+
+       <channel-type id="repeat" advanced="true">
+               <item-type>String</item-type>
+               <label>Repeat Mode</label>
+               <description>The current repeat mode</description>
+               <state readOnly="false" pattern="%s">
+                       <options>
+                               <option value="TRACK">Track</option>
+                               <option value="DISC">Disc</option>
+                               <option value="OFF">Off</option>
+                       </options>
+               </state>
+       </channel-type>
+
        <channel-type id="frequency" advanced="true">
                <item-type>Number</item-type>
                <label>Current Frequency</label>
index 34932be3e25aafdd1054214519438c15826b0aaa..4a2ac1d8eaabc4753e96df60ef40ccddc6ecc216 100644 (file)
@@ -13,6 +13,8 @@
                        <channel id="power" typeId="system.power"/>
                        <channel id="playControl" typeId="system.media-control"/>
                        <channel id="track" typeId="track"/>
+                       <channel id="random" typeId="random"/>
+                       <channel id="repeat" typeId="repeat"/>
                        <channel id="brightness" typeId="brightness"/>
                </channels>