[samsungtv] Add artOrientatation channel (#17368)

* [samsungtv] add artOrientation channel

Signed-off-by: Nick Waterton <n.waterton@outlook.com>
pull/17365/head
Nick Waterton 2024-09-26 16:09:48 -04:00 committed by GitHub
parent d44d84eb43
commit 8332ab29c5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 106 additions and 16 deletions

View File

@ -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 TVs dont 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).

View File

@ -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";
}

View File

@ -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("");
}
}

View File

@ -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)));

View File

@ -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":

View File

@ -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 {}

View File

@ -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

View File

@ -55,6 +55,12 @@
<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>
@ -65,6 +71,12 @@
<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>

View File

@ -140,6 +140,12 @@
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>

View File

@ -32,10 +32,11 @@
<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>

View File

@ -30,6 +30,11 @@
<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>