]> git.basschouten.com Git - openhab-addons.git/commitdiff
[samsungtv] Add artOrientatation channel (#17368)
authorNick Waterton <NickWaterton@users.noreply.github.com>
Thu, 26 Sep 2024 20:09:48 +0000 (16:09 -0400)
committerGitHub <noreply@github.com>
Thu, 26 Sep 2024 20:09:48 +0000 (22:09 +0200)
* [samsungtv] add artOrientation channel

Signed-off-by: Nick Waterton <n.waterton@outlook.com>
bundles/org.openhab.binding.samsungtv/README.md
bundles/org.openhab.binding.samsungtv/src/main/java/org/openhab/binding/samsungtv/internal/SamsungTvBindingConstants.java
bundles/org.openhab.binding.samsungtv/src/main/java/org/openhab/binding/samsungtv/internal/config/SamsungTvConfiguration.java
bundles/org.openhab.binding.samsungtv/src/main/java/org/openhab/binding/samsungtv/internal/handler/SamsungTvHandler.java
bundles/org.openhab.binding.samsungtv/src/main/java/org/openhab/binding/samsungtv/internal/protocol/WebSocketArt.java
bundles/org.openhab.binding.samsungtv/src/main/java/org/openhab/binding/samsungtv/internal/service/RemoteControllerService.java
bundles/org.openhab.binding.samsungtv/src/main/java/org/openhab/binding/samsungtv/internal/service/SmartThingsApiService.java
bundles/org.openhab.binding.samsungtv/src/main/resources/OH-INF/config/config.xml
bundles/org.openhab.binding.samsungtv/src/main/resources/OH-INF/thing/channel-types.xml
bundles/org.openhab.binding.samsungtv/src/main/resources/OH-INF/thing/thing-types.xml
bundles/org.openhab.binding.samsungtv/src/main/resources/OH-INF/update/instructions.xml

index 54507e3d8cfa64af524f5751d8bbb33e1d6c5c61..d05142d81987d45dd8e6d68cd546d29f6ef353cd 100755 (executable)
@@ -16,17 +16,19 @@ Basic operation does not require any special configuration.
 
 The binding has the following configuration options, which can be set for "binding:samsungtv":
 
-| Parameter             | Name                      | Description                                                   | Required  |
-|-----------------------|---------------------------|---------------------------------------------------------------|-----------|
-| hostName              | Host Name                 | Network address of the Samsung TV                             | yes       |
-| port                  | TCP Port                  | TCP port of the Samsung TV                                    | no        |
-| macAddress            | MAC Address               | MAC Address of the Samsung TV                                 | no        |
-| refreshInterval       | Refresh Interval          | States how often a refresh shall occur in milliseconds        | no        |
-| protocol              | Remote Control Protocol   | The type of remote control protocol                           | yes       |
-| webSocketToken        | Websocket Token           | Security token for secure websocket connection                | no        |
-| subscription          | Subscribe to UPNP         | Reduces polling on UPNP devices                               | no        |
-| smartThingsApiKey     | Smartthings PAT           | Smartthings Personal Access Token                             | no        |
-| smartThingsDeviceId   | Smartthings Device ID     | Smartthings Device ID for this TV                             | no        |
+| Parameter              | Name                      | Description                                                   | Required  |
+|------------------------|---------------------------|---------------------------------------------------------------|-----------|
+| hostName               | Host Name                 | Network address of the Samsung TV                             | yes       |
+| port                   | TCP Port                  | TCP port of the Samsung TV                                    | no        |
+| macAddress             | MAC Address               | MAC Address of the Samsung TV                                 | no        |
+| refreshInterval        | Refresh Interval          | States how often a refresh shall occur in milliseconds        | no        |
+| protocol               | Remote Control Protocol   | The type of remote control protocol                           | yes       |
+| webSocketToken         | Websocket Token           | Security token for secure websocket connection                | no        |
+| subscription           | Subscribe to UPNP         | Reduces polling on UPNP devices, default false                | no        |
+| orientationKey         | Orientation Key           | Key press to send to rotate auto-rotation mount               | no        |
+| smartThingsApiKey      | Smartthings PAT           | Smartthings Personal Access Token                             | no        |
+| smartThingsDeviceId    | Smartthings Device ID     | Smartthings Device ID for this TV                             | no        |
+| smartThingsSubscription| Smarththings Subscription | Reduces polling on Smartthings channels, default true         | no        |
 
 ## Thing Configuration
 
@@ -89,6 +91,7 @@ TVs support the following channels:
 | artJson             | String   | RW         | Send/receive commands from the TV art websocket Channel                                                 |
 | artBrightness       | Dimmer   | RW         | ArtMode Brightness                                                                                      |
 | artColorTemperature | Number   | RW         | ArtMode Color temperature Minnimum value is -5 and maximum 5                                            |
+| artOrientation      | Switch   | RW         | TV orientation, Landscape (OFF) or Portrait (ON)                                                        |
 
 **NOTE:** channels: brightness, contrast, sharpness, colorTemperature don't work on newer TV's.  
 **NOTE:** channels: sourceName, sourceId, programTitle, channelName and stopBrowser may need additional configuration. 
@@ -218,6 +221,7 @@ Currently known working commands for 2021 and earlier TV's are:
     get_api_version
     get_artmode_status
     set_artmode_status "value" on or off
+    get_current_rotation "current_rotation_status" 1 is landscape, 2 is Portrait
     get_auto_rotation_status
     set_auto_rotation_status "type" is "slideshow" pr 'shuffelslideshow", "value" is off or duration in minutes "category_id" is a string representing the category
     get_device_info
@@ -244,6 +248,7 @@ Currently known working commands for 2022 and later TV's are:
     api_version
     get_artmode_status
     set_artmode_status "value" on or off
+    get_current_rotation "current_rotation_status" 1 is landscape, 2 is Portrait
     get_slideshow_status
     set_slideshow_status "type" is "slideshow" pr 'shuffelslideshow", "value" is off or duration in minutes "category_id" is a string representing the category
     get_device_info
@@ -303,6 +308,17 @@ You can use a `Setpoint` contol for this item in your `sitemap` eg:
 Setpoint item=TV_ArtColorTemperature minValue=-5 maxValue=5 step=1 visibility=[TV_ArtMode==ON]
 ```
 
+### artOrientation:
+
+`artOrientation` is a Switch channel, it reports the current orientation of the TV, OFF for Landscape, and ON for Portrait. This channel is polled. If you send an ON or OFF command to this channel, then the binding will send a long (4s) press of the key defined in the configuration for orientationKey.  
+For 2023- TV's `orientationKey` should be KEY_MULTI_VIEW (default), for 2024+ TV's this should be KEY_HOME.
+
+```java
+Switch item=TV_ArtOrientation mappings[OFF="Landscape", ON="Portrait"]
+```
+
+**NOTE:** You should only send commands to the `artOrientation` channel if you have the auto-rotation mount paired to the TV.
+
 ## Full Example
 
 ### samsungtv.things
@@ -334,6 +350,7 @@ Image   TV_ArtImage      "Current Art"                         (gLivingRoomTV)
 String  TV_ArtJson       "Art Json [%s]"                       (gLivingRoomTV)   { channel="samsungtv:tv:livingroom:artJson" }
 Dimmer  TV_ArtBri        "Art Brightness [%d%%]"               (gLivingRoomTV)   { channel="samsungtv:tv:livingroom:artBrightness" }
 Number  TV_ArtCT         "Art CT [%d]"                         (gLivingRoomTV)   { channel="samsungtv:tv:livingroom:artColorTemperature" }
+Switch  TV_ArtOrient     "Art Orientation [%s]"                (gLivingRoomTV)   { channel="samsungtv:tv:livingroom:artOrientation" }
 ```
 
 ## WOL
@@ -529,6 +546,11 @@ You can now link the `sourceName`, `sourceId`, `channel` and `channelName` chann
 
 **NOTE:** You may not get anything for `channelName`, as most TV’s don’t report it. You can only send commands to `channel`, `sourceName` and `sourceId`, `channelName` is read only.
 
+## Smartthings Subscriptions
+
+Smartthings Subscriptions are supported. This is a feature which reduces the polling of Smartthings channels (on by default).  
+If the Smarthings channels only update with the Smartthings app open, turn subscription off, and the channels will be polled instead. Channels are only polled when the TV is ON.
+
 ## UPnP Subscriptions
 
 UPnP Subscriptions are supported. This is an experimental feature which reduces the polling of UPnP services (off by default).
index 839086c435a95ab9e28e3881bec247dd849f450e..b1cca0fc4b665ab9721a092d146e410ffe8db735 100755 (executable)
@@ -60,4 +60,5 @@ public class SamsungTvBindingConstants {
     public static final String ART_JSON = "artJson";
     public static final String ART_BRIGHTNESS = "artBrightness";
     public static final String ART_COLOR_TEMPERATURE = "artColorTemperature";
+    public static final String ART_ORIENTATION = "artOrientation";
 }
index 87ee4d74e778869e9252fecf017a92346a7f6e13..5ff392c92ef093e00aff540d65556e206689a9c5 100755 (executable)
@@ -39,6 +39,8 @@ public class SamsungTvConfiguration {
     public static final String WEBSOCKET_TOKEN = "webSocketToken";
     public static final String SMARTTHINGS_API = "smartThingsApiKey";
     public static final String SMARTTHINGS_DEVICEID = "smartThingsDeviceId";
+    public static final String SMARTTHINGS_SUBSCRIPTION = "smartThingsSubscription";
+    public static final String ORIENTATION_KEY = "orientationKey";
     public static final int PORT_DEFAULT_LEGACY = 55000;
     public static final int PORT_DEFAULT_WEBSOCKET = 8001;
     public static final int PORT_DEFAULT_SECUREWEBSOCKET = 8002;
@@ -52,6 +54,8 @@ public class SamsungTvConfiguration {
     public String smartThingsApiKey;
     public String smartThingsDeviceId;
     public boolean subscription;
+    public boolean smartThingsSubscription;
+    public String orientationKey;
 
     public boolean isWebsocketProtocol() {
         return PROTOCOL_WEBSOCKET.equals(getProtocol()) || PROTOCOL_SECUREWEBSOCKET.equals(getProtocol());
@@ -92,4 +96,12 @@ public class SamsungTvConfiguration {
     public boolean getSubscription() {
         return Optional.ofNullable(subscription).orElse(false);
     }
+
+    public boolean getSmartThingsSubscription() {
+        return Optional.ofNullable(smartThingsSubscription).orElse(false);
+    }
+
+    public String getOrientationKey() {
+        return Optional.ofNullable(orientationKey).orElse("");
+    }
 }
index eb66d57705a1b32193aed0a13136588e421223fc..0fa24968072e3109e84990186aef50ffa3f365ad 100755 (executable)
@@ -560,7 +560,9 @@ public class SamsungTvHandler extends BaseThingHandler implements RegistryListen
     private void poll() {
         try {
             // Skip channels if service is not connected/started
-            services.stream().filter(service -> service.checkConnection())
+            // Only poll SmartThings if TV is ON (ie playing)
+            services.stream().filter(service -> service.checkConnection()).filter(
+                    service -> getPowerState() || !service.getServiceName().equals(SmartThingsApiService.SERVICE_NAME))
                     .forEach(service -> service.getSupportedChannelNames(true).stream()
                             .filter(channel -> isLinked(channel) && !isDuplicateChannel(channel))
                             .forEach(channel -> service.handleCommand(channel, RefreshType.REFRESH)));
index 2477ae621287a7b4f1e86f6e66ac2f74194588a7..b82cba06ef50c4bbeb2e6281d6195d29bc467f6b 100755 (executable)
@@ -45,6 +45,7 @@ import javax.net.ssl.X509TrustManager;
 import org.eclipse.jdt.annotation.NonNullByDefault;
 import org.eclipse.jdt.annotation.Nullable;
 import org.openhab.core.library.types.DecimalType;
+import org.openhab.core.library.types.OnOffType;
 import org.openhab.core.library.types.PercentType;
 import org.openhab.core.library.types.RawType;
 import org.openhab.core.library.types.StringType;
@@ -111,6 +112,7 @@ class WebSocketArt extends WebSocketBase {
             String current_content_id;
             String content_id;
             String category_id;
+            int current_rotation_status;
             String is_shown;
             String type;
             String file_type;
@@ -149,6 +151,10 @@ class WebSocketArt extends WebSocketBase {
                 return Optional.ofNullable(current_content_id).orElse("");
             }
 
+            public int getRotationStatus() {
+                return Optional.ofNullable(Integer.valueOf(current_rotation_status)).orElse(0);
+            }
+
             public String getType() {
                 return Optional.ofNullable(type).orElse("");
             }
@@ -357,6 +363,7 @@ class WebSocketArt extends WebSocketBase {
                     getArtmodeStatus("get_auto_rotation_status");
                     getArtmodeStatus("get_current_artwork");
                     getArtmodeStatus("get_color_temperature");
+                    getArtmodeStatus("get_current_rotation");
                     break;
                 case "ms.channel.clientConnect":
                     logger.debug("{}: Another Art client has connected", host);
@@ -434,6 +441,11 @@ class WebSocketArt extends WebSocketBase {
                         }
                     }
                     break;
+                case "current_rotation_status":
+                case "get_current_rotation":
+                    // Landscape = 1, Portrait = 2
+                    valueReceived(ART_ORIENTATION, OnOffType.from(data.getRotationStatus() == 2));
+                    break;
                 case "set_brightness":
                 case "brightness_changed":
                 case "brightness":
index 923c93c21c8d0bbbcba63bc22009e5057ea9cc27..6e6e694971829a7868ae3b04ab1019409116ea8f 100755 (executable)
@@ -63,9 +63,9 @@ public class RemoteControllerService implements SamsungTvService {
     private final List<String> supportedCommandsNonUpnp = Arrays.asList(KEY_CODE, VOLUME, MUTE, POWER, CHANNEL,
             BROWSER_URL, STOP_BROWSER, SOURCE_APP);
     private final List<String> supportedCommandsArt = Arrays.asList(ART_MODE, ART_JSON, ART_LABEL, ART_IMAGE,
-            ART_BRIGHTNESS, ART_COLOR_TEMPERATURE);
+            ART_BRIGHTNESS, ART_COLOR_TEMPERATURE, ART_ORIENTATION);
     private static final List<String> REFRESH_CHANNELS = Arrays.asList();
-    private static final List<String> refreshArt = Arrays.asList(ART_BRIGHTNESS);
+    private static final List<String> refreshArt = Arrays.asList(ART_BRIGHTNESS, ART_ORIENTATION);
     private static final List<String> refreshApps = Arrays.asList(SOURCE_APP);
     private static final List<String> art2022 = Arrays.asList(ART_MODE, SET_ART_MODE);
 
@@ -202,6 +202,9 @@ public class RemoteControllerService implements SamsungTvService {
                 case ART_COLOR_TEMPERATURE:
                     remoteController.getArtmodeStatus("get_color_temperature");
                     break;
+                case ART_ORIENTATION:
+                    remoteController.getArtmodeStatus("get_current_rotation");
+                    break;
             }
             return true;
         }
@@ -351,6 +354,16 @@ public class RemoteControllerService implements SamsungTvService {
                 }
                 break;
 
+            case ART_ORIENTATION:
+                if (command instanceof OnOffType) {
+                    String key = handler.configuration.getOrientationKey();
+                    if (!key.isBlank()) {
+                        sendKeys(KeyCode.valueOf(key), 4000);
+                        result = true;
+                    }
+                }
+                break;
+
             case KEY_CODE:
                 if (command instanceof StringType) {
                     // split on [, +], but not if encloded in "" or {}
index 09b721ccc02f04fcc838dd5cbe8deb799d27bfc4..23743b1b72c606dbc13141c08a24bfbe88a8c11a 100755 (executable)
@@ -94,6 +94,7 @@ public class SmartThingsApiService implements SamsungTvService {
     private String host = "";
     private String apiKey = "";
     private String deviceId = "";
+    private boolean subscriptionEnabled = true;
     private int RATE_LIMIT = 1000;
     private int TIMEOUT = 1000; // connection timeout in ms
     private long prevUpdate = 0;
@@ -115,6 +116,7 @@ public class SmartThingsApiService implements SamsungTvService {
         this.host = host;
         this.apiKey = handler.configuration.getSmartThingsApiKey();
         this.deviceId = handler.configuration.getSmartThingsDeviceId();
+        this.subscriptionEnabled = handler.configuration.getSmartThingsSubscription();
         logger.debug("{}: Creating a Samsung TV Smartthings Api service", host);
     }
 
@@ -868,7 +870,9 @@ public class SmartThingsApiService implements SamsungTvService {
     public void start() {
         online = true;
         errorCount = 0;
-        startSSE();
+        if (subscriptionEnabled) {
+            startSSE();
+        }
     }
 
     @Override
index 765892be44304f62ccdbc1a652d5a1354614a472..e2603c08569c3c079278990ad1283b5de0ed1153 100755 (executable)
                        <default>false</default>
                        <advanced>true</advanced>
                </parameter>
+               <parameter name="orientationKey" type="text">
+                       <label>Key code to send to rotate TV</label>
+                       <description>Only works with optional rotating mount</description>
+                       <default>KEY_MULTI_VIEW</default>
+                       <advanced>true</advanced>
+               </parameter>
                <parameter name="smartThingsApiKey" type="text" groupName="Cloud Connection">
                        <label>Smartthings PAT</label>
                        <description>Go to https://account.smartthings.com/tokens and obtain a Personal Access Token, enter it here.</description>
                        <description>Once your PAT is entered and saved, look in the log for the Device ID for this TV, enter it here.</description>
                        <advanced>true</advanced>
                </parameter>
+               <parameter name="smartThingsSubscription" type="boolean" groupName="Cloud Connection">
+                       <label>Subscribe to SmartThings</label>
+                       <description>Reduces polling on SmartThings, by subscribing to Device Events</description>
+                       <default>true</default>
+                       <advanced>true</advanced>
+               </parameter>
        </config-description>
 
 </config-description:config-descriptions>
index 98e3056ebef5d0344a582c2cecef478e5d7e9771..5fff9c9cb9ab8b4d2f4f9de5d8674accff85060f 100755 (executable)
                        maximum 5.</description>
        </channel-type>
 
+       <channel-type id="artworkorientation">
+               <item-type>Switch</item-type>
+               <label>Artwork Orientation</label>
+               <description>TV orientation, Landcape or Portrait</description>
+       </channel-type>
+
        <channel-type id="sourceapp" advanced="true">
                <item-type>String</item-type>
                <label>Application</label>
index 638d83222380c3ed02e6df5aecc48dd718ac1997..2487c03423f50f4c1e51a92bce02f3d65ca330f3 100755 (executable)
                        <channel id="artJson" typeId="artworkjson"/>
                        <channel id="artBrightness" typeId="artworkbrightness"/>
                        <channel id="artColorTemperature" typeId="artworkcolortemperature"/>
+                       <channel id="artOrientation" typeId="artworkorientation"/>
                </channels>
 
                <properties>
-                       <property name="thingTypeVersion">1</property>
+                       <property name="thingTypeVersion">2</property>
                </properties>
 
                <representation-property>hostName</representation-property>
index 3547215823efd98d59586e759cdd2fca2f38248f..79820de1cdaaa130f9dcfe3a57daa416af843676 100755 (executable)
                                <type>samsungtv:artworkcolortemperature</type>
                        </add-channel>
                </instruction-set>
+               <instruction-set targetVersion="2">
+                       <add-channel id="artOrientation">
+                               <type>samsungtv:artworkorientation</type>
+                       </add-channel>
+               </instruction-set>
        </thing-type>
 
 </update:update-descriptions>