mirror of
https://github.com/openhab/openhab-addons.git
synced 2025-01-10 15:11:59 +01:00
[vizio] Vizio TV binding - Initial contribution (#13309)
Signed-off-by: Michael Lobstein <michael.lobstein@gmail.com>
This commit is contained in:
parent
a9d4244fd8
commit
fc529777e4
@ -358,6 +358,7 @@
|
|||||||
/bundles/org.openhab.binding.vesync/ @dag81
|
/bundles/org.openhab.binding.vesync/ @dag81
|
||||||
/bundles/org.openhab.binding.vigicrues/ @clinique
|
/bundles/org.openhab.binding.vigicrues/ @clinique
|
||||||
/bundles/org.openhab.binding.vitotronic/ @steand
|
/bundles/org.openhab.binding.vitotronic/ @steand
|
||||||
|
/bundles/org.openhab.binding.vizio/ @mlobstein
|
||||||
/bundles/org.openhab.binding.volvooncall/ @clinique @Jamstah
|
/bundles/org.openhab.binding.volvooncall/ @clinique @Jamstah
|
||||||
/bundles/org.openhab.binding.warmup/ @jamesmelville
|
/bundles/org.openhab.binding.warmup/ @jamesmelville
|
||||||
/bundles/org.openhab.binding.weathercompany/ @mhilbush
|
/bundles/org.openhab.binding.weathercompany/ @mhilbush
|
||||||
|
@ -1781,6 +1781,11 @@
|
|||||||
<artifactId>org.openhab.binding.vitotronic</artifactId>
|
<artifactId>org.openhab.binding.vitotronic</artifactId>
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.openhab.addons.bundles</groupId>
|
||||||
|
<artifactId>org.openhab.binding.vizio</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.openhab.addons.bundles</groupId>
|
<groupId>org.openhab.addons.bundles</groupId>
|
||||||
<artifactId>org.openhab.binding.volvooncall</artifactId>
|
<artifactId>org.openhab.binding.volvooncall</artifactId>
|
||||||
|
13
bundles/org.openhab.binding.vizio/NOTICE
Normal file
13
bundles/org.openhab.binding.vizio/NOTICE
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
This content is produced and maintained by the openHAB project.
|
||||||
|
|
||||||
|
* Project home: https://www.openhab.org
|
||||||
|
|
||||||
|
== Declared Project Licenses
|
||||||
|
|
||||||
|
This program and the accompanying materials are made available under the terms
|
||||||
|
of the Eclipse Public License 2.0 which is available at
|
||||||
|
https://www.eclipse.org/legal/epl-2.0/.
|
||||||
|
|
||||||
|
== Source Code
|
||||||
|
|
||||||
|
https://github.com/openhab/openhab-addons
|
181
bundles/org.openhab.binding.vizio/README.md
Normal file
181
bundles/org.openhab.binding.vizio/README.md
Normal file
@ -0,0 +1,181 @@
|
|||||||
|
# Vizio Binding
|
||||||
|
|
||||||
|
This binding connects Vizio TVs to openHAB.
|
||||||
|
The TV must support the Vizio SmartCast API that is found on 2016 and later models.
|
||||||
|
|
||||||
|
## Supported Things
|
||||||
|
|
||||||
|
There is currently only one supported thing type, which represents a Vizio TV using the `vizio_tv` id.
|
||||||
|
Multiple Things can be added if more than one Vizio TV is to be controlled.
|
||||||
|
|
||||||
|
## Discovery
|
||||||
|
|
||||||
|
Auto-discovery is supported if the Vizio TV can be located on the local network using mDNS.
|
||||||
|
Otherwise the thing must be manually added.
|
||||||
|
When the TV is discovered, a pairing process to obtain an authentication token from the TV must be completed using the openHAB console. See below for details.
|
||||||
|
|
||||||
|
## Thing Configuration
|
||||||
|
|
||||||
|
The thing has a few configuration parameters:
|
||||||
|
|
||||||
|
| Parameter | Description |
|
||||||
|
|-------------|--------------------------------------------------------------------------------------------------------------------------------------|
|
||||||
|
| hostName | The host name or IP address of the Vizio TV. Mandatory. |
|
||||||
|
| port | The port on the Vizio TV that listens for https connections. Default 7345; Use 9000 for older model TVs. |
|
||||||
|
| authToken | The token that is used to authenticate all commands sent to the TV. See below for instructions to obtain via the openHAB console. |
|
||||||
|
| appListJson | A JSON string that defines the apps that are available in the `activeApp` channel drop down. See below for instructions for editing. |
|
||||||
|
|
||||||
|
### Console Commands for Pairing:
|
||||||
|
|
||||||
|
To obtain an authorization token that enables openHAB to authenticate with the TV, the following console commands must be used while the TV is turned on.
|
||||||
|
The first command will send a pairing start request to the TV. This triggers the TV to display a 4-digit pairing code on screen that must be sent with the second command.
|
||||||
|
|
||||||
|
Start Pairing:
|
||||||
|
|
||||||
|
```
|
||||||
|
openhab:vizio <thingUID> start_pairing <deviceName>
|
||||||
|
```
|
||||||
|
|
||||||
|
Substitute `<thingUID>` with thing's id, ie: `vizio_tv:00bc3e711660`
|
||||||
|
Substitute `<deviceName>` the desired device name that will appear in the TV's settings, under Mobile Devices, ie: `Vizio-openHAB`
|
||||||
|
|
||||||
|
Submit Pairing Code:
|
||||||
|
|
||||||
|
```
|
||||||
|
openhab:vizio <thingUID> submit_code <pairingCode>
|
||||||
|
```
|
||||||
|
|
||||||
|
Substitute `<thingUID>` with the same thing id used above
|
||||||
|
Substitute `<pairingCode>` with the 4-digit pairing code displayed on the TV, ie: `1234`
|
||||||
|
|
||||||
|
The console should then indicate that pairing was successful (token will be displayed) and that the token was saved to the thing configuration.
|
||||||
|
If using file-based provisioning of the thing, the authorization token must be added to the thing configuration manually.
|
||||||
|
With an authorization token in place, the binding can now control the TV.
|
||||||
|
|
||||||
|
The authorization token text can be re-used in the event that it becomes necessary to setup the binding again.
|
||||||
|
By simply adding the token that is already recognized by the TV to the thing configuration, the pairing process can be bypassed.
|
||||||
|
|
||||||
|
## Channels
|
||||||
|
|
||||||
|
The following channels are available:
|
||||||
|
|
||||||
|
| Channel ID | Item Type | Description |
|
||||||
|
|-------------|-----------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||||
|
| power | Switch | Turn the power on the TV on or off. Note: TV may not turn on if power is switched off and the TV is configured for Eco mode. |
|
||||||
|
| volume | Dimmer | Control the volume on the TV (0-100%). |
|
||||||
|
| mute | Switch | Mute or unmute the volume on the TV. |
|
||||||
|
| source | String | Select the source input on the TV. The dropdown list is automatically populated from the TV. |
|
||||||
|
| activeApp | String | A dropdown containing a list of streaming apps defined by the `appListJson` config option that can be launched by the binding. An app started via remote control is automatically selected. |
|
||||||
|
| control | Player | Control Playback e.g. Play/Pause/Next/Previous/FForward/Rewind |
|
||||||
|
| button | String | Sends a remote control command the TV. See list of available commands below. |
|
||||||
|
|
||||||
|
### List of available button commands for Vizio TVs:
|
||||||
|
|
||||||
|
PowerOn
|
||||||
|
PowerOff
|
||||||
|
PowerToggle
|
||||||
|
VolumeUp
|
||||||
|
VolumeDown
|
||||||
|
MuteOn **(may only work as a toggle)**
|
||||||
|
MuteOff **(may only work as a toggle)**
|
||||||
|
MuteToggle
|
||||||
|
ChannelUp
|
||||||
|
ChannelDown
|
||||||
|
PreviousCh
|
||||||
|
InputToggle
|
||||||
|
SeekFwd
|
||||||
|
SeekBack
|
||||||
|
Play
|
||||||
|
Pause
|
||||||
|
Up
|
||||||
|
Down
|
||||||
|
Left
|
||||||
|
Right
|
||||||
|
Ok
|
||||||
|
Back
|
||||||
|
Info
|
||||||
|
Menu
|
||||||
|
Home
|
||||||
|
Exit
|
||||||
|
Smartcast
|
||||||
|
ccToggle
|
||||||
|
PictureMode
|
||||||
|
WideMode
|
||||||
|
WideToggle
|
||||||
|
|
||||||
|
### App List Configuration:
|
||||||
|
|
||||||
|
The Vizio API to launch and identify currently running apps on the TV is very complex.
|
||||||
|
To handle this, the binding maintains a JSON database of applications and their associated metadata in order to populate the `activeApp` dropdown with available apps.
|
||||||
|
|
||||||
|
When the thing is started for the first time, this JSON database is saved into the `appListJson` configuration parameter.
|
||||||
|
This list of apps can be edited via the script editor on the thing configuration.
|
||||||
|
By editing the JSON, apps that are not desired can be removed from the `activeApp` dropdown and newly discovered apps can be added.
|
||||||
|
|
||||||
|
An entry for an application has a `name` element and a `config` element containing `APP_ID`, `NAME_SPACE` and `MESSAGE` (null for most apps):
|
||||||
|
|
||||||
|
```
|
||||||
|
{
|
||||||
|
"name": "Crackle",
|
||||||
|
"config": {
|
||||||
|
"APP_ID": "5",
|
||||||
|
"NAME_SPACE": 4,
|
||||||
|
"MESSAGE": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
If an app is running that is not currently recognized by the binding, the `activeApp` channel will display a message that contains the `APP_ID` and `NAME_SPACE` which can be used to create the missing record for that app in the JSON.
|
||||||
|
|
||||||
|
If an app that is in the JSON database fails to start when selected, try adjusting the `NAME_SPACE` value for that app.
|
||||||
|
`NAME_SPACE` seems to be a version number and adjusting the number up or down may correct the mismatch between the TV and the binding.
|
||||||
|
|
||||||
|
A current list of `APP_ID`'s can be found at http://hometest.buddytv.netdna-cdn.com/appservice/vizio_apps_prod.json
|
||||||
|
and `NAME_SPACE` & `MESSAGE` values needed can be found at http://hometest.buddytv.netdna-cdn.com/appservice/app_availability_prod.json
|
||||||
|
|
||||||
|
If there is an error in the user supplied `appListJson`, the thing will fail to start and display a CONFIGURATION_PENDING message.
|
||||||
|
If all text in `appListJson` is removed (set to null) and the thing configuration saved, the binding will restore `appListJson` from the binding's JSON db.
|
||||||
|
|
||||||
|
## Full Example
|
||||||
|
|
||||||
|
vizio.things:
|
||||||
|
|
||||||
|
```
|
||||||
|
// Vizio TV
|
||||||
|
vizio:vizio_tv:mytv1 "My Vizio TV" [ hostName="192.168.10.1", port=7345, authToken="idspisp0pd" ]
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
vizio.items:
|
||||||
|
|
||||||
|
```
|
||||||
|
// Vizio TV items:
|
||||||
|
|
||||||
|
Switch TV_Power "Power" { channel="vizio:vizio_tv:mytv1:power" }
|
||||||
|
Dimmer TV_Volume "Volume [%d %%]" { channel="vizio:vizio_tv:mytv1:volume" }
|
||||||
|
Switch TV_Mute "Mute" { channel="vizio:vizio_tv:mytv1:mute" }
|
||||||
|
String TV_Source "Source Input [%s]" { channel="vizio:vizio_tv:mytv1:source" }
|
||||||
|
String TV_ActiveApp "Current App: [%s]" { channel="vizio:vizio_tv:mytv1:activeApp" }
|
||||||
|
Player TV_Control "Playback Control" { channel="vizio:vizio_tv:mytv1:control" }
|
||||||
|
String TV_Button "Send Command to TV" { channel="vizio:vizio_tv:mytv1:button" }
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
vizio.sitemap:
|
||||||
|
|
||||||
|
```
|
||||||
|
sitemap vizio label="Vizio" {
|
||||||
|
Frame label="My Vizio TV" {
|
||||||
|
Switch item=TV_Power
|
||||||
|
// Volume can be a Setpoint also
|
||||||
|
Slider item=TV_Volume minValue=0 maxValue=100 step=1 icon="soundvolume"
|
||||||
|
Switch item=TV_Mute icon="soundvolume_mute"
|
||||||
|
Selection item=TV_Source icon="screen"
|
||||||
|
Selection item=TV_ActiveApp icon="screen"
|
||||||
|
Default item=TV_Control
|
||||||
|
Selection item=TV_Button
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
17
bundles/org.openhab.binding.vizio/pom.xml
Normal file
17
bundles/org.openhab.binding.vizio/pom.xml
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>org.openhab.addons.bundles</groupId>
|
||||||
|
<artifactId>org.openhab.addons.reactor.bundles</artifactId>
|
||||||
|
<version>3.4.0-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>org.openhab.binding.vizio</artifactId>
|
||||||
|
|
||||||
|
<name>openHAB Add-ons :: Bundles :: Vizio Binding</name>
|
||||||
|
|
||||||
|
</project>
|
@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<features name="org.openhab.binding.vizio-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.4.0">
|
||||||
|
<repository>mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features</repository>
|
||||||
|
|
||||||
|
<feature name="openhab-binding-vizio" description="Vizio Binding" version="${project.version}">
|
||||||
|
<feature>openhab-runtime-base</feature>
|
||||||
|
<feature>openhab-transport-mdns</feature>
|
||||||
|
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.vizio/${project.version}</bundle>
|
||||||
|
</feature>
|
||||||
|
</features>
|
@ -0,0 +1,54 @@
|
|||||||
|
/**
|
||||||
|
* 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.vizio.internal;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.openhab.core.thing.ThingTypeUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link VizioBindingConstants} class defines common constants, which are
|
||||||
|
* used across the whole binding.
|
||||||
|
*
|
||||||
|
* @author Michael Lobstein - Initial contribution
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
public class VizioBindingConstants {
|
||||||
|
public static final String BINDING_ID = "vizio";
|
||||||
|
public static final String PROPERTY_UUID = "uuid";
|
||||||
|
public static final String PROPERTY_HOST_NAME = "hostName";
|
||||||
|
public static final String PROPERTY_PORT = "port";
|
||||||
|
public static final String PROPERTY_AUTH_TOKEN = "authToken";
|
||||||
|
public static final String PROPERTY_APP_LIST_JSON = "appListJson";
|
||||||
|
public static final String EMPTY = "";
|
||||||
|
public static final String MODIFY_STRING_SETTING_JSON = "{\"REQUEST\": \"MODIFY\",\"VALUE\": \"%s\",\"HASHVAL\": %d}";
|
||||||
|
public static final String MODIFY_INT_SETTING_JSON = "{\"REQUEST\": \"MODIFY\",\"VALUE\": %d,\"HASHVAL\": %d}";
|
||||||
|
public static final String UNKNOWN_APP_STR = "Unknown app_id: %d, name_space: %d";
|
||||||
|
public static final String ON = "ON";
|
||||||
|
public static final String OFF = "OFF";
|
||||||
|
|
||||||
|
// List of all Thing Type UIDs
|
||||||
|
public static final ThingTypeUID THING_TYPE_VIZIO_TV = new ThingTypeUID(BINDING_ID, "vizio_tv");
|
||||||
|
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Collections.singleton(THING_TYPE_VIZIO_TV);
|
||||||
|
|
||||||
|
// List of all Channel id's
|
||||||
|
public static final String POWER = "power";
|
||||||
|
public static final String VOLUME = "volume";
|
||||||
|
public static final String MUTE = "mute";
|
||||||
|
public static final String SOURCE = "source";
|
||||||
|
public static final String ACTIVE_APP = "activeApp";
|
||||||
|
public static final String CONTROL = "control";
|
||||||
|
public static final String BUTTON = "button";
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
/**
|
||||||
|
* 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.vizio.internal;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link VizioConfiguration} is the class used to match the
|
||||||
|
* thing configuration.
|
||||||
|
*
|
||||||
|
* @author Michael Lobstein - Initial contribution
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
public class VizioConfiguration {
|
||||||
|
public @Nullable String hostName;
|
||||||
|
public Integer port = 7345;
|
||||||
|
public @Nullable String authToken;
|
||||||
|
public @Nullable String appListJson;
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
/**
|
||||||
|
* 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.vizio.internal;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link VizioException} extends Exception
|
||||||
|
*
|
||||||
|
* @author Michael Lobstein - Initial contribution
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
public class VizioException extends Exception {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
public VizioException(String errorMessage) {
|
||||||
|
super(errorMessage);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,71 @@
|
|||||||
|
/**
|
||||||
|
* 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.vizio.internal;
|
||||||
|
|
||||||
|
import static org.openhab.binding.vizio.internal.VizioBindingConstants.SUPPORTED_THING_TYPES_UIDS;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
|
import org.eclipse.jetty.client.HttpClient;
|
||||||
|
import org.openhab.binding.vizio.internal.appdb.VizioAppDbService;
|
||||||
|
import org.openhab.binding.vizio.internal.handler.VizioHandler;
|
||||||
|
import org.openhab.core.io.net.http.HttpClientFactory;
|
||||||
|
import org.openhab.core.thing.Thing;
|
||||||
|
import org.openhab.core.thing.ThingTypeUID;
|
||||||
|
import org.openhab.core.thing.binding.BaseThingHandlerFactory;
|
||||||
|
import org.openhab.core.thing.binding.ThingHandler;
|
||||||
|
import org.openhab.core.thing.binding.ThingHandlerFactory;
|
||||||
|
import org.osgi.service.component.annotations.Activate;
|
||||||
|
import org.osgi.service.component.annotations.Component;
|
||||||
|
import org.osgi.service.component.annotations.Reference;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link VizioHandlerFactory} is responsible for creating things and thing
|
||||||
|
* handlers.
|
||||||
|
*
|
||||||
|
* @author Michael Lobstein - Initial contribution
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
@Component(service = ThingHandlerFactory.class, configurationPid = "binding.vizio")
|
||||||
|
public class VizioHandlerFactory extends BaseThingHandlerFactory {
|
||||||
|
|
||||||
|
private final HttpClient httpClient;
|
||||||
|
private final VizioStateDescriptionOptionProvider stateDescriptionProvider;
|
||||||
|
private final String vizioAppsJson;
|
||||||
|
|
||||||
|
@Activate
|
||||||
|
public VizioHandlerFactory(final @Reference HttpClientFactory httpClientFactory,
|
||||||
|
final @Reference VizioStateDescriptionOptionProvider provider,
|
||||||
|
final @Reference VizioAppDbService vizioAppDbService) {
|
||||||
|
this.httpClient = httpClientFactory.getCommonHttpClient();
|
||||||
|
this.stateDescriptionProvider = provider;
|
||||||
|
this.vizioAppsJson = vizioAppDbService.getVizioAppsJson();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean supportsThingType(ThingTypeUID thingTypeUID) {
|
||||||
|
return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected @Nullable ThingHandler createHandler(Thing thing) {
|
||||||
|
ThingTypeUID thingTypeUID = thing.getThingTypeUID();
|
||||||
|
|
||||||
|
if (SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID)) {
|
||||||
|
VizioHandler handler = new VizioHandler(thing, httpClient, stateDescriptionProvider, vizioAppsJson);
|
||||||
|
return handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,43 @@
|
|||||||
|
/**
|
||||||
|
* 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.vizio.internal;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.openhab.core.events.EventPublisher;
|
||||||
|
import org.openhab.core.thing.binding.BaseDynamicStateDescriptionProvider;
|
||||||
|
import org.openhab.core.thing.i18n.ChannelTypeI18nLocalizationService;
|
||||||
|
import org.openhab.core.thing.link.ItemChannelLinkRegistry;
|
||||||
|
import org.openhab.core.thing.type.DynamicStateDescriptionProvider;
|
||||||
|
import org.osgi.service.component.annotations.Activate;
|
||||||
|
import org.osgi.service.component.annotations.Component;
|
||||||
|
import org.osgi.service.component.annotations.Reference;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link VizioStateDescriptionOptionProvider} is a Dynamic provider of state options while leaving other state
|
||||||
|
* description fields as original.
|
||||||
|
*
|
||||||
|
* @author Michael Lobstein - Initial contribution
|
||||||
|
*/
|
||||||
|
@Component(service = { DynamicStateDescriptionProvider.class, VizioStateDescriptionOptionProvider.class })
|
||||||
|
@NonNullByDefault
|
||||||
|
public class VizioStateDescriptionOptionProvider extends BaseDynamicStateDescriptionProvider {
|
||||||
|
|
||||||
|
@Activate
|
||||||
|
public VizioStateDescriptionOptionProvider(final @Reference EventPublisher eventPublisher,
|
||||||
|
final @Reference ItemChannelLinkRegistry itemChannelLinkRegistry,
|
||||||
|
final @Reference ChannelTypeI18nLocalizationService channelTypeI18nLocalizationService) {
|
||||||
|
this.eventPublisher = eventPublisher;
|
||||||
|
this.itemChannelLinkRegistry = itemChannelLinkRegistry;
|
||||||
|
this.channelTypeI18nLocalizationService = channelTypeI18nLocalizationService;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,57 @@
|
|||||||
|
/**
|
||||||
|
* 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.vizio.internal.appdb;
|
||||||
|
|
||||||
|
import static org.openhab.binding.vizio.internal.VizioBindingConstants.*;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.osgi.service.component.annotations.Activate;
|
||||||
|
import org.osgi.service.component.annotations.Component;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link VizioAppDbService} class makes available a JSON list of known apps on Vizio TVs.
|
||||||
|
*
|
||||||
|
* @author Michael Lobstein - Initial Contribution
|
||||||
|
*/
|
||||||
|
|
||||||
|
@Component(service = VizioAppDbService.class)
|
||||||
|
@NonNullByDefault
|
||||||
|
public class VizioAppDbService {
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(VizioAppDbService.class);
|
||||||
|
private String vizioAppsJson;
|
||||||
|
|
||||||
|
@Activate
|
||||||
|
public VizioAppDbService() {
|
||||||
|
try {
|
||||||
|
InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream("/db/apps.json");
|
||||||
|
if (is != null) {
|
||||||
|
vizioAppsJson = new String(is.readAllBytes(), StandardCharsets.UTF_8);
|
||||||
|
} else {
|
||||||
|
vizioAppsJson = EMPTY;
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
logger.warn("Unable to load Vizio app list : {}", e.getMessage());
|
||||||
|
vizioAppsJson = EMPTY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getVizioAppsJson() {
|
||||||
|
return vizioAppsJson;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,293 @@
|
|||||||
|
/**
|
||||||
|
* 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.vizio.internal.communication;
|
||||||
|
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.concurrent.TimeoutException;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.eclipse.jetty.client.HttpClient;
|
||||||
|
import org.eclipse.jetty.client.api.ContentResponse;
|
||||||
|
import org.eclipse.jetty.client.api.Request;
|
||||||
|
import org.eclipse.jetty.client.util.StringContentProvider;
|
||||||
|
import org.eclipse.jetty.http.HttpHeader;
|
||||||
|
import org.eclipse.jetty.http.HttpMethod;
|
||||||
|
import org.openhab.binding.vizio.internal.VizioException;
|
||||||
|
import org.openhab.binding.vizio.internal.dto.PutResponse;
|
||||||
|
import org.openhab.binding.vizio.internal.dto.app.CurrentApp;
|
||||||
|
import org.openhab.binding.vizio.internal.dto.applist.VizioAppConfig;
|
||||||
|
import org.openhab.binding.vizio.internal.dto.audio.Audio;
|
||||||
|
import org.openhab.binding.vizio.internal.dto.input.CurrentInput;
|
||||||
|
import org.openhab.binding.vizio.internal.dto.inputlist.InputList;
|
||||||
|
import org.openhab.binding.vizio.internal.dto.pairing.PairingComplete;
|
||||||
|
import org.openhab.binding.vizio.internal.dto.pairing.PairingStart;
|
||||||
|
import org.openhab.binding.vizio.internal.dto.power.PowerMode;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import com.google.gson.GsonBuilder;
|
||||||
|
import com.google.gson.JsonSyntaxException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link VizioCommunicator} class contains methods for accessing the HTTP interface of Vizio TVs
|
||||||
|
*
|
||||||
|
* @author Michael Lobstein - Initial contribution
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
public class VizioCommunicator {
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(VizioCommunicator.class);
|
||||||
|
|
||||||
|
private static final String AUTH_HEADER = "AUTH";
|
||||||
|
private static final String JSON_CONTENT_TYPE = "application/json";
|
||||||
|
private static final String JSON_VALUE = "{\"VALUE\": %s}";
|
||||||
|
|
||||||
|
private final HttpClient httpClient;
|
||||||
|
private final Gson gson = new GsonBuilder().serializeNulls().create();
|
||||||
|
|
||||||
|
private final String authToken;
|
||||||
|
private final String urlPowerMode;
|
||||||
|
private final String urlCurrentAudio;
|
||||||
|
private final String urlCurrentInput;
|
||||||
|
private final String urlInputList;
|
||||||
|
private final String urlChangeVolume;
|
||||||
|
private final String urlCurrentApp;
|
||||||
|
private final String urlLaunchApp;
|
||||||
|
private final String urlKeyPress;
|
||||||
|
private final String urlStartPairing;
|
||||||
|
private final String urlSubmitPairingCode;
|
||||||
|
|
||||||
|
public VizioCommunicator(HttpClient httpClient, String host, int port, String authToken) {
|
||||||
|
this.httpClient = httpClient;
|
||||||
|
this.authToken = authToken;
|
||||||
|
|
||||||
|
final String baseUrl = "https://" + host + ":" + port;
|
||||||
|
urlPowerMode = baseUrl + "/state/device/power_mode";
|
||||||
|
urlCurrentAudio = baseUrl + "/menu_native/dynamic/tv_settings/audio";
|
||||||
|
urlChangeVolume = baseUrl + "/menu_native/dynamic/tv_settings/audio/volume";
|
||||||
|
urlCurrentInput = baseUrl + "/menu_native/dynamic/tv_settings/devices/current_input";
|
||||||
|
urlInputList = baseUrl + "/menu_native/dynamic/tv_settings/devices/name_input";
|
||||||
|
urlCurrentApp = baseUrl + "/app/current";
|
||||||
|
urlLaunchApp = baseUrl + "/app/launch";
|
||||||
|
urlKeyPress = baseUrl + "/key_command/";
|
||||||
|
urlStartPairing = baseUrl + "/pairing/start";
|
||||||
|
urlSubmitPairingCode = baseUrl + "/pairing/pair";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the current power state of the Vizio TV
|
||||||
|
*
|
||||||
|
* @return A PowerMode response object
|
||||||
|
* @throws VizioException
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public PowerMode getPowerMode() throws VizioException {
|
||||||
|
return fromJson(getCommand(urlPowerMode), PowerMode.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the current audio settings of the Vizio TV
|
||||||
|
*
|
||||||
|
* @return An Audio response object
|
||||||
|
* @throws VizioException
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public Audio getCurrentAudioSettings() throws VizioException {
|
||||||
|
return fromJson(getCommand(urlCurrentAudio), Audio.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Change the volume of the Vizio TV
|
||||||
|
*
|
||||||
|
* @param the command JSON for the desired volue
|
||||||
|
* @return A PutResponse response object
|
||||||
|
* @throws VizioException
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public PutResponse changeVolume(String commandJSON) throws VizioException {
|
||||||
|
return fromJson(putCommand(urlChangeVolume, commandJSON), PutResponse.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the currently selected input of the Vizio TV
|
||||||
|
*
|
||||||
|
* @return A CurrentInput response object
|
||||||
|
* @throws VizioException
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public CurrentInput getCurrentInput() throws VizioException {
|
||||||
|
return fromJson(getCommand(urlCurrentInput), CurrentInput.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Change the currently selected input of the Vizio TV
|
||||||
|
*
|
||||||
|
* @param the command JSON for the selected input
|
||||||
|
* @return A PutResponse response object
|
||||||
|
* @throws VizioException
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public PutResponse changeInput(String commandJSON) throws VizioException {
|
||||||
|
return fromJson(putCommand(urlCurrentInput, commandJSON), PutResponse.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the list of available source inputs from the Vizio TV
|
||||||
|
*
|
||||||
|
* @return An InputList response object
|
||||||
|
* @throws VizioException
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public InputList getSourceInputList() throws VizioException {
|
||||||
|
return fromJson(getCommand(urlInputList), InputList.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the id of the app currently running on the Vizio TV
|
||||||
|
*
|
||||||
|
* @return A CurrentApp response object
|
||||||
|
* @throws VizioException
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public CurrentApp getCurrentApp() throws VizioException {
|
||||||
|
return fromJson(getCommand(urlCurrentApp), CurrentApp.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Launch a given streaming app on the Vizio TV
|
||||||
|
*
|
||||||
|
* @param the VizioAppConfig data for the app to launch
|
||||||
|
* @return A PutResponse response object
|
||||||
|
* @throws VizioException
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public PutResponse launchApp(VizioAppConfig appConfig) throws VizioException {
|
||||||
|
return fromJson(putCommand(urlLaunchApp, String.format(JSON_VALUE, gson.toJson(appConfig))), PutResponse.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a key press command to the Vizio TV
|
||||||
|
*
|
||||||
|
* @param the command JSON for the key press
|
||||||
|
* @return A PutResponse response object
|
||||||
|
* @throws VizioException
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public PutResponse sendKeyPress(String commandJSON) throws VizioException {
|
||||||
|
return fromJson(putCommand(urlKeyPress, commandJSON), PutResponse.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start the pairing process to obtain an auth token from the TV
|
||||||
|
*
|
||||||
|
* @param the deviceName that is displayed in the TV settings after the device is registered
|
||||||
|
* @param the deviceId a unique number that identifies this pairing request
|
||||||
|
* @return A PairingStart response object
|
||||||
|
* @throws VizioException
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public PairingStart starPairing(String deviceName, int deviceId) throws VizioException {
|
||||||
|
return fromJson(
|
||||||
|
putCommand(urlStartPairing,
|
||||||
|
String.format("{ \"DEVICE_NAME\": \"%s\", \"DEVICE_ID\": \"%d\" }", deviceName, deviceId)),
|
||||||
|
PairingStart.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finish the pairing process by submitting the code that was displayed on the TV to obtain the auth token
|
||||||
|
*
|
||||||
|
* @param the same deviceId that was used by startPairing()
|
||||||
|
* @param the pairingCode that was displayed on the TV
|
||||||
|
* @param the pairingToken returned by startPairing()
|
||||||
|
* @return A PairingComplete response object
|
||||||
|
* @throws VizioException
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public PairingComplete submitPairingCode(int deviceId, String pairingCode, int pairingToken) throws VizioException {
|
||||||
|
return fromJson(putCommand(urlSubmitPairingCode, String.format(
|
||||||
|
"{\"DEVICE_ID\": \"%d\",\"CHALLENGE_TYPE\": 1,\"RESPONSE_VALUE\": \"%s\",\"PAIRING_REQ_TOKEN\": %d}",
|
||||||
|
deviceId, pairingCode, pairingToken)), PairingComplete.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends a GET request to the Vizio TV
|
||||||
|
*
|
||||||
|
* @param url The url used to retrieve status information from the Vizio TV
|
||||||
|
* @return The response content of the http request
|
||||||
|
* @throws VizioException
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private String getCommand(String url) throws VizioException {
|
||||||
|
try {
|
||||||
|
final Request request = httpClient.newRequest(url).method(HttpMethod.GET);
|
||||||
|
request.header(AUTH_HEADER, authToken);
|
||||||
|
request.header(HttpHeader.CONTENT_TYPE, JSON_CONTENT_TYPE);
|
||||||
|
|
||||||
|
final ContentResponse response = request.send();
|
||||||
|
|
||||||
|
logger.trace("GET url: {}, response: {}", url, response.getContentAsString());
|
||||||
|
return response.getContentAsString();
|
||||||
|
} catch (InterruptedException | TimeoutException | ExecutionException e) {
|
||||||
|
throw new VizioException("Error executing vizio GET command, URL: " + url + " " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends a PUT request to the Vizio TV
|
||||||
|
*
|
||||||
|
* @param url The url used to send a command to the Vizio TV
|
||||||
|
* @param commandJSON The JSON data needed to execute the command
|
||||||
|
* @return The response content of the http request
|
||||||
|
* @throws VizioException
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private String putCommand(String url, String commandJSON) throws VizioException {
|
||||||
|
try {
|
||||||
|
final Request request = httpClient.newRequest(url).method(HttpMethod.PUT);
|
||||||
|
if (!url.contains("pairing")) {
|
||||||
|
request.header(AUTH_HEADER, authToken);
|
||||||
|
}
|
||||||
|
request.content(new StringContentProvider(commandJSON), JSON_CONTENT_TYPE);
|
||||||
|
|
||||||
|
final ContentResponse response = request.send();
|
||||||
|
|
||||||
|
logger.trace("PUT url: {}, response: {}", url, response.getContentAsString());
|
||||||
|
return response.getContentAsString();
|
||||||
|
} catch (InterruptedException | TimeoutException | ExecutionException e) {
|
||||||
|
throw new VizioException("Error executing vizio PUT command, URL: " + url + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrapper for the Gson fromJson() method that encapsulates exception handling
|
||||||
|
*
|
||||||
|
* @param json The JSON string to be deserialized
|
||||||
|
* @param classOfT The type of class to be returned
|
||||||
|
* @return the deserialized object
|
||||||
|
* @throws VizioException
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private <T> T fromJson(String json, Class<T> classOfT) throws VizioException {
|
||||||
|
Object obj = null;
|
||||||
|
try {
|
||||||
|
obj = gson.fromJson(json, classOfT);
|
||||||
|
} catch (JsonSyntaxException e) {
|
||||||
|
throw new VizioException("Error Parsing JSON string: " + json + ", Exception: " + e.getMessage());
|
||||||
|
}
|
||||||
|
if (obj != null) {
|
||||||
|
return classOfT.cast(obj);
|
||||||
|
} else {
|
||||||
|
throw new VizioException("Error creating " + classOfT.getSimpleName() + " object for JSON string: " + json);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,59 @@
|
|||||||
|
/**
|
||||||
|
* 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.vizio.internal.communication;
|
||||||
|
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.security.cert.CertificateException;
|
||||||
|
|
||||||
|
import javax.net.ssl.X509ExtendedTrustManager;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.openhab.core.io.net.http.PEMTrustManager;
|
||||||
|
import org.openhab.core.io.net.http.TlsTrustManagerProvider;
|
||||||
|
import org.openhab.core.io.net.http.TrustAllTrustManager;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides a {@link PEMTrustManager} to allow secure connections to a Vizio TV that uses self signed
|
||||||
|
* certificates.
|
||||||
|
*
|
||||||
|
* @author Christoph Weitkamp - Initial Contribution
|
||||||
|
* @author Michael Lobstein - Adapted for Vizio binding
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
public class VizioTlsTrustManagerProvider implements TlsTrustManagerProvider {
|
||||||
|
private final String hostname;
|
||||||
|
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(VizioTlsTrustManagerProvider.class);
|
||||||
|
|
||||||
|
public VizioTlsTrustManagerProvider(String hostname) {
|
||||||
|
this.hostname = hostname;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getHostName() {
|
||||||
|
return hostname;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public X509ExtendedTrustManager getTrustManager() {
|
||||||
|
try {
|
||||||
|
logger.trace("Use self-signed certificate downloaded from Vizio TV.");
|
||||||
|
return PEMTrustManager.getInstanceFromServer("https://" + getHostName());
|
||||||
|
} catch (CertificateException | MalformedURLException e) {
|
||||||
|
logger.debug("An unexpected exception occurred - returning a TrustAllTrustManager: {}", e.getMessage(), e);
|
||||||
|
}
|
||||||
|
return TrustAllTrustManager.getInstance();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,183 @@
|
|||||||
|
/**
|
||||||
|
* 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.vizio.internal.console;
|
||||||
|
|
||||||
|
import static org.openhab.binding.vizio.internal.VizioBindingConstants.*;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.eclipse.jetty.client.HttpClient;
|
||||||
|
import org.openhab.binding.vizio.internal.VizioException;
|
||||||
|
import org.openhab.binding.vizio.internal.communication.VizioCommunicator;
|
||||||
|
import org.openhab.binding.vizio.internal.dto.pairing.PairingComplete;
|
||||||
|
import org.openhab.binding.vizio.internal.handler.VizioHandler;
|
||||||
|
import org.openhab.core.io.console.Console;
|
||||||
|
import org.openhab.core.io.console.extensions.AbstractConsoleCommandExtension;
|
||||||
|
import org.openhab.core.io.console.extensions.ConsoleCommandExtension;
|
||||||
|
import org.openhab.core.io.net.http.HttpClientFactory;
|
||||||
|
import org.openhab.core.thing.Thing;
|
||||||
|
import org.openhab.core.thing.ThingRegistry;
|
||||||
|
import org.openhab.core.thing.ThingUID;
|
||||||
|
import org.openhab.core.thing.binding.ThingHandler;
|
||||||
|
import org.osgi.service.component.annotations.Activate;
|
||||||
|
import org.osgi.service.component.annotations.Component;
|
||||||
|
import org.osgi.service.component.annotations.Reference;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link VizioCommandExtension} is responsible for handling console commands
|
||||||
|
*
|
||||||
|
* @author Michael Lobstein - Initial contribution
|
||||||
|
*/
|
||||||
|
|
||||||
|
@NonNullByDefault
|
||||||
|
@Component(service = ConsoleCommandExtension.class)
|
||||||
|
public class VizioCommandExtension extends AbstractConsoleCommandExtension {
|
||||||
|
private static final String START_PAIRING = "start_pairing";
|
||||||
|
private static final String SUBMIT_CODE = "submit_code";
|
||||||
|
|
||||||
|
private final ThingRegistry thingRegistry;
|
||||||
|
private final HttpClient httpClient;
|
||||||
|
|
||||||
|
@Activate
|
||||||
|
public VizioCommandExtension(final @Reference ThingRegistry thingRegistry,
|
||||||
|
final @Reference HttpClientFactory httpClientFactory) {
|
||||||
|
super("vizio", "Interact with the Vizio binding to get an authentication token from the TV.");
|
||||||
|
this.thingRegistry = thingRegistry;
|
||||||
|
this.httpClient = httpClientFactory.getCommonHttpClient();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(String[] args, Console console) {
|
||||||
|
if (args.length == 3) {
|
||||||
|
Thing thing = null;
|
||||||
|
try {
|
||||||
|
ThingUID thingUID = new ThingUID(args[0]);
|
||||||
|
thing = thingRegistry.get(thingUID);
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
thing = null;
|
||||||
|
}
|
||||||
|
ThingHandler thingHandler = null;
|
||||||
|
VizioHandler handler = null;
|
||||||
|
if (thing != null) {
|
||||||
|
thingHandler = thing.getHandler();
|
||||||
|
if (thingHandler instanceof VizioHandler) {
|
||||||
|
handler = (VizioHandler) thingHandler;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (thing == null) {
|
||||||
|
console.println("Bad thing id '" + args[0] + "'");
|
||||||
|
printUsage(console);
|
||||||
|
} else if (thingHandler == null) {
|
||||||
|
console.println("No handler initialized for the thing id '" + args[0] + "'");
|
||||||
|
printUsage(console);
|
||||||
|
} else if (handler == null) {
|
||||||
|
console.println("'" + args[0] + "' is not a Vizio thing id");
|
||||||
|
printUsage(console);
|
||||||
|
} else {
|
||||||
|
String host = (String) thing.getConfiguration().get(PROPERTY_HOST_NAME);
|
||||||
|
BigDecimal port = (BigDecimal) thing.getConfiguration().get(PROPERTY_PORT);
|
||||||
|
|
||||||
|
if (host == null || host.isEmpty() || port.signum() < 1) {
|
||||||
|
console.println(
|
||||||
|
"Error! Host Name and Port must be specified in thing configuration before paring.");
|
||||||
|
return;
|
||||||
|
} else if (host.contains(":")) {
|
||||||
|
// format for ipv6
|
||||||
|
host = "[" + host + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
VizioCommunicator communicator = new VizioCommunicator(httpClient, host, port.intValue(), EMPTY);
|
||||||
|
|
||||||
|
switch (args[1]) {
|
||||||
|
case START_PAIRING:
|
||||||
|
try {
|
||||||
|
Random rng = new Random();
|
||||||
|
|
||||||
|
int pairingDeviceId = rng.nextInt(100000);
|
||||||
|
int pairingToken = communicator.starPairing(args[2], pairingDeviceId).getItem()
|
||||||
|
.getPairingReqToken();
|
||||||
|
if (pairingToken != -1) {
|
||||||
|
handler.setPairingDeviceId(pairingDeviceId);
|
||||||
|
handler.setPairingToken(pairingToken);
|
||||||
|
|
||||||
|
console.println("Pairing has been started!");
|
||||||
|
console.println(
|
||||||
|
"Please note the 4 digit code displayed on the TV and substitute it into the following console command:");
|
||||||
|
console.println(
|
||||||
|
"openhab:vizio " + handler.getThing().getUID() + " " + SUBMIT_CODE + " <NNNN>");
|
||||||
|
} else {
|
||||||
|
console.println("Unable to obtain pairing token!");
|
||||||
|
}
|
||||||
|
} catch (VizioException e) {
|
||||||
|
console.println("Error! Unable to start pairing process.");
|
||||||
|
console.println("Exception was: " + e.getMessage());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SUBMIT_CODE:
|
||||||
|
try {
|
||||||
|
int pairingDeviceId = handler.getPairingDeviceId();
|
||||||
|
int pairingToken = handler.getPairingToken();
|
||||||
|
|
||||||
|
if (pairingDeviceId < 0 || pairingToken < 0) {
|
||||||
|
console.println("Error! '" + START_PAIRING + "' command must be completed first.");
|
||||||
|
console.println(
|
||||||
|
"Please issue the following command and substitute the desired device name.");
|
||||||
|
console.println("openhab:vizio " + handler.getThing().getUID() + " " + START_PAIRING
|
||||||
|
+ " <deviceName>");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Integer.valueOf(args[2]);
|
||||||
|
PairingComplete authTokenResp = communicator.submitPairingCode(pairingDeviceId, args[2],
|
||||||
|
pairingToken);
|
||||||
|
if (authTokenResp.getItem().getAuthToken() != EMPTY) {
|
||||||
|
console.println("Pairing complete!");
|
||||||
|
console.println("The auth token: " + authTokenResp.getItem().getAuthToken()
|
||||||
|
+ " was received and will be added to the thing configuration.");
|
||||||
|
console.println(
|
||||||
|
"If the thing is provisioned via a file, the token must be manually added to the thing configuration.");
|
||||||
|
|
||||||
|
handler.setPairingDeviceId(-1);
|
||||||
|
handler.setPairingToken(-1);
|
||||||
|
handler.saveAuthToken(authTokenResp.getItem().getAuthToken());
|
||||||
|
} else {
|
||||||
|
console.println("Unable to obtain auth token!");
|
||||||
|
}
|
||||||
|
} catch (NumberFormatException nfe) {
|
||||||
|
console.println(
|
||||||
|
"Error! Pairing code must be numeric. Check console command and try again.");
|
||||||
|
} catch (VizioException e) {
|
||||||
|
console.println("Error! Unable to complete pairing process.");
|
||||||
|
console.println("Exception was: " + e.getMessage());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printUsage(console);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
printUsage(console);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> getUsages() {
|
||||||
|
return List.of(new String[] {
|
||||||
|
buildCommandUsage("<thingUID> " + START_PAIRING + " <deviceName>", "start pairing process"),
|
||||||
|
buildCommandUsage("<thingUID> " + SUBMIT_CODE + " <pairingCode>", "submit pairing code") });
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,132 @@
|
|||||||
|
/**
|
||||||
|
* 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.vizio.internal.discovery;
|
||||||
|
|
||||||
|
import static org.openhab.binding.vizio.internal.VizioBindingConstants.*;
|
||||||
|
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import javax.jmdns.ServiceInfo;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
|
import org.openhab.core.config.discovery.DiscoveryResult;
|
||||||
|
import org.openhab.core.config.discovery.DiscoveryResultBuilder;
|
||||||
|
import org.openhab.core.config.discovery.mdns.MDNSDiscoveryParticipant;
|
||||||
|
import org.openhab.core.thing.Thing;
|
||||||
|
import org.openhab.core.thing.ThingTypeUID;
|
||||||
|
import org.openhab.core.thing.ThingUID;
|
||||||
|
import org.osgi.service.component.annotations.Component;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link VizioDiscoveryParticipant} is responsible processing the
|
||||||
|
* results of searches for mDNS services of type _viziocast._tcp.local.
|
||||||
|
*
|
||||||
|
* @author Michael Lobstein - Initial contribution
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
@Component(configurationPid = "discovery.vizio")
|
||||||
|
public class VizioDiscoveryParticipant implements MDNSDiscoveryParticipant {
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(VizioDiscoveryParticipant.class);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<ThingTypeUID> getSupportedThingTypeUIDs() {
|
||||||
|
return SUPPORTED_THING_TYPES_UIDS;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getServiceType() {
|
||||||
|
return "_viziocast._tcp.local.";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable DiscoveryResult createResult(ServiceInfo service) {
|
||||||
|
DiscoveryResult result = null;
|
||||||
|
|
||||||
|
ThingUID thingUid = getThingUID(service);
|
||||||
|
if (thingUid != null) {
|
||||||
|
InetAddress ip = getIpAddress(service);
|
||||||
|
if (ip == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
String inetAddress = ip.toString().substring(1); // trim leading slash
|
||||||
|
String label = service.getName();
|
||||||
|
int port = service.getPort();
|
||||||
|
|
||||||
|
result = DiscoveryResultBuilder.create(thingUid).withLabel(label).withRepresentationProperty(PROPERTY_UUID)
|
||||||
|
.withProperty(PROPERTY_UUID, thingUid.getId())
|
||||||
|
.withProperty(Thing.PROPERTY_MODEL_ID, service.getPropertyString("mdl"))
|
||||||
|
.withProperty(PROPERTY_HOST_NAME, inetAddress).withProperty(PROPERTY_PORT, port).build();
|
||||||
|
logger.debug("Created {} for Vizio TV at {}, name: '{}'", result, inetAddress, label);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see org.openhab.core.config.discovery.mdns.MDNSDiscoveryParticipant#getThingUID(javax.jmdns.ServiceInfo)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public @Nullable ThingUID getThingUID(ServiceInfo service) {
|
||||||
|
if (service.getType() != null && service.getType().equals(getServiceType())) {
|
||||||
|
String uidName = getUIDName(service);
|
||||||
|
return uidName != null ? new ThingUID(THING_TYPE_VIZIO_TV, uidName) : null;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the UID name from the mdns record txt info (mac address), fall back with IP address
|
||||||
|
*
|
||||||
|
* @param service the mdns service
|
||||||
|
* @return the UID name
|
||||||
|
*/
|
||||||
|
private @Nullable String getUIDName(ServiceInfo service) {
|
||||||
|
String uid = service.getPropertyString("eth");
|
||||||
|
|
||||||
|
if (uid == null || uid.endsWith("000") || uid.length() < 12) {
|
||||||
|
uid = service.getPropertyString("wifi");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (uid == null || uid.endsWith("000") || uid.length() < 12) {
|
||||||
|
InetAddress ip = getIpAddress(service);
|
||||||
|
if (ip == null) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
uid = ip.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return uid.replaceAll("[^A-Za-z0-9_]", "_");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link InetAddress} gets the IP address of the device in v4 or v6 format.
|
||||||
|
*
|
||||||
|
* @param ServiceInfo service
|
||||||
|
* @return InetAddress the IP address
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private @Nullable InetAddress getIpAddress(ServiceInfo service) {
|
||||||
|
InetAddress address = null;
|
||||||
|
for (InetAddress addr : service.getInet4Addresses()) {
|
||||||
|
return addr;
|
||||||
|
}
|
||||||
|
// Fall back for Inet6addresses
|
||||||
|
for (InetAddress addr : service.getInet6Addresses()) {
|
||||||
|
return addr;
|
||||||
|
}
|
||||||
|
return address;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,93 @@
|
|||||||
|
/**
|
||||||
|
* 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.vizio.internal.dto;
|
||||||
|
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link Item} class contains data from the Vizio TV JSON response
|
||||||
|
*
|
||||||
|
* @author Michael Lobstein - Initial contribution
|
||||||
|
*/
|
||||||
|
public class Item {
|
||||||
|
@SerializedName("HASHVAL")
|
||||||
|
private Long hashval;
|
||||||
|
@SerializedName("CNAME")
|
||||||
|
private String cname;
|
||||||
|
@SerializedName("NAME")
|
||||||
|
private String name = "";
|
||||||
|
@SerializedName("TYPE")
|
||||||
|
private String type;
|
||||||
|
@SerializedName("ENABLED")
|
||||||
|
private String enabled;
|
||||||
|
@SerializedName("READONLY")
|
||||||
|
private String readonly;
|
||||||
|
@SerializedName("VALUE")
|
||||||
|
private Value value = new Value();
|
||||||
|
|
||||||
|
public Long getHashval() {
|
||||||
|
return hashval;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHashval(Long hashval) {
|
||||||
|
this.hashval = hashval;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCname() {
|
||||||
|
return cname;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCname(String cname) {
|
||||||
|
this.cname = cname;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setType(String type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getEnabled() {
|
||||||
|
return enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEnabled(String enabled) {
|
||||||
|
this.enabled = enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getReadonly() {
|
||||||
|
return readonly;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setReadonly(String readonly) {
|
||||||
|
this.readonly = readonly;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Value getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValue(Value value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,53 @@
|
|||||||
|
/**
|
||||||
|
* 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.vizio.internal.dto;
|
||||||
|
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link Parameters} class contains data from the Vizio TV JSON response
|
||||||
|
*
|
||||||
|
* @author Michael Lobstein - Initial contribution
|
||||||
|
*/
|
||||||
|
public class Parameters {
|
||||||
|
@SerializedName("FLAT")
|
||||||
|
private String flat;
|
||||||
|
@SerializedName("HELPTEXT")
|
||||||
|
private String helptext;
|
||||||
|
@SerializedName("HASHONLY")
|
||||||
|
private String hashonly;
|
||||||
|
|
||||||
|
public String getFlat() {
|
||||||
|
return flat;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFlat(String flat) {
|
||||||
|
this.flat = flat;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getHelptext() {
|
||||||
|
return helptext;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHelptext(String helptext) {
|
||||||
|
this.helptext = helptext;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getHashonly() {
|
||||||
|
return hashonly;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHashonly(String hashonly) {
|
||||||
|
this.hashonly = hashonly;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,53 @@
|
|||||||
|
/**
|
||||||
|
* 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.vizio.internal.dto;
|
||||||
|
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link PutResponse} class maps the JSON data response from several Vizio TV endpoints
|
||||||
|
*
|
||||||
|
* @author Michael Lobstein - Initial contribution
|
||||||
|
*/
|
||||||
|
public class PutResponse {
|
||||||
|
@SerializedName("STATUS")
|
||||||
|
private Status status;
|
||||||
|
@SerializedName("URI")
|
||||||
|
private String uri;
|
||||||
|
@SerializedName("TIME")
|
||||||
|
private String time;
|
||||||
|
|
||||||
|
public Status getStatus() {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStatus(Status status) {
|
||||||
|
this.status = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUri() {
|
||||||
|
return uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUri(String uri) {
|
||||||
|
this.uri = uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTime() {
|
||||||
|
return time;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTime(String time) {
|
||||||
|
this.time = time;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,43 @@
|
|||||||
|
/**
|
||||||
|
* 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.vizio.internal.dto;
|
||||||
|
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link Status} class contains data from the Vizio TV JSON response
|
||||||
|
*
|
||||||
|
* @author Michael Lobstein - Initial contribution
|
||||||
|
*/
|
||||||
|
public class Status {
|
||||||
|
@SerializedName("RESULT")
|
||||||
|
private String result;
|
||||||
|
@SerializedName("DETAIL")
|
||||||
|
private String detail;
|
||||||
|
|
||||||
|
public String getResult() {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setResult(String result) {
|
||||||
|
this.result = result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDetail() {
|
||||||
|
return detail;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDetail(String detail) {
|
||||||
|
this.detail = detail;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,43 @@
|
|||||||
|
/**
|
||||||
|
* 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.vizio.internal.dto;
|
||||||
|
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link Value} class contains data from the Vizio TV JSON response
|
||||||
|
*
|
||||||
|
* @author Michael Lobstein - Initial contribution
|
||||||
|
*/
|
||||||
|
public class Value {
|
||||||
|
@SerializedName("NAME")
|
||||||
|
private String name = "";
|
||||||
|
@SerializedName("METADATA")
|
||||||
|
private String metadata;
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMetadata() {
|
||||||
|
return metadata;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMetadata(String metadata) {
|
||||||
|
this.metadata = metadata;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,56 @@
|
|||||||
|
/**
|
||||||
|
* 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.vizio.internal.dto.app;
|
||||||
|
|
||||||
|
import org.openhab.binding.vizio.internal.dto.Status;
|
||||||
|
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link CurrentApp} class maps the JSON data response from the Vizio TV endpoint:
|
||||||
|
* '/app/current'
|
||||||
|
*
|
||||||
|
* @author Michael Lobstein - Initial contribution
|
||||||
|
*/
|
||||||
|
public class CurrentApp {
|
||||||
|
@SerializedName("STATUS")
|
||||||
|
private Status status;
|
||||||
|
@SerializedName("ITEM")
|
||||||
|
private ItemApp item = new ItemApp();
|
||||||
|
@SerializedName("URI")
|
||||||
|
private String uri;
|
||||||
|
|
||||||
|
public Status getStatus() {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStatus(Status status) {
|
||||||
|
this.status = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ItemApp getItem() {
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setItem(ItemApp item) {
|
||||||
|
this.item = item;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUri() {
|
||||||
|
return uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUri(String uri) {
|
||||||
|
this.uri = uri;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,44 @@
|
|||||||
|
/**
|
||||||
|
* 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.vizio.internal.dto.app;
|
||||||
|
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link ItemApp} class contains data from the Vizio TV JSON response
|
||||||
|
*
|
||||||
|
* @author Michael Lobstein - Initial contribution
|
||||||
|
*/
|
||||||
|
public class ItemApp {
|
||||||
|
@SerializedName("TYPE")
|
||||||
|
private String type;
|
||||||
|
|
||||||
|
@SerializedName("VALUE")
|
||||||
|
private ItemAppValue value = new ItemAppValue();
|
||||||
|
|
||||||
|
public String getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setType(String type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ItemAppValue getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValue(ItemAppValue value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,53 @@
|
|||||||
|
/**
|
||||||
|
* 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.vizio.internal.dto.app;
|
||||||
|
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link ItemAppValue} class contains data from the Vizio TV JSON response
|
||||||
|
*
|
||||||
|
* @author Michael Lobstein - Initial contribution
|
||||||
|
*/
|
||||||
|
public class ItemAppValue {
|
||||||
|
@SerializedName("MESSAGE")
|
||||||
|
private String message;
|
||||||
|
@SerializedName("NAME_SPACE")
|
||||||
|
private Integer nameSpace = -1;
|
||||||
|
@SerializedName("APP_ID")
|
||||||
|
private String appId = "";
|
||||||
|
|
||||||
|
public String getMessage() {
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMessage(String message) {
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getNameSpace() {
|
||||||
|
return nameSpace;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNameSpace(Integer nameSpace) {
|
||||||
|
this.nameSpace = nameSpace;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAppId() {
|
||||||
|
return appId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAppId(String appId) {
|
||||||
|
this.appId = appId;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,43 @@
|
|||||||
|
/**
|
||||||
|
* 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.vizio.internal.dto.applist;
|
||||||
|
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link VizioApp} class contains the name and config data for an app that runs on a Vizio TV
|
||||||
|
*
|
||||||
|
* @author Michael Lobstein - Initial contribution
|
||||||
|
*/
|
||||||
|
public class VizioApp {
|
||||||
|
@SerializedName("name")
|
||||||
|
private String name = "";
|
||||||
|
@SerializedName("config")
|
||||||
|
private VizioAppConfig config = new VizioAppConfig();
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public VizioAppConfig getConfig() {
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setConfig(VizioAppConfig config) {
|
||||||
|
this.config = config;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,53 @@
|
|||||||
|
/**
|
||||||
|
* 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.vizio.internal.dto.applist;
|
||||||
|
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link VizioAppConfig} class maps the JSON data needed to launch an app on a Vizio TV
|
||||||
|
*
|
||||||
|
* @author Michael Lobstein - Initial contribution
|
||||||
|
*/
|
||||||
|
public class VizioAppConfig {
|
||||||
|
@SerializedName("NAME_SPACE")
|
||||||
|
private Integer nameSpace;
|
||||||
|
@SerializedName("APP_ID")
|
||||||
|
private String appId;
|
||||||
|
@SerializedName("MESSAGE")
|
||||||
|
private String message;
|
||||||
|
|
||||||
|
public Integer getNameSpace() {
|
||||||
|
return nameSpace;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNameSpace(Integer nameSpace) {
|
||||||
|
this.nameSpace = nameSpace;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAppId() {
|
||||||
|
return appId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAppId(String appId) {
|
||||||
|
this.appId = appId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMessage() {
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMessage(String message) {
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,36 @@
|
|||||||
|
/**
|
||||||
|
* 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.vizio.internal.dto.applist;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link VizioApps} class contains a list of VizioApp objects
|
||||||
|
*
|
||||||
|
* @author Michael Lobstein - Initial contribution
|
||||||
|
*/
|
||||||
|
public class VizioApps {
|
||||||
|
@SerializedName("Apps")
|
||||||
|
private List<VizioApp> apps = new ArrayList<VizioApp>();
|
||||||
|
|
||||||
|
public List<VizioApp> getApps() {
|
||||||
|
return apps;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setApps(List<VizioApp> apps) {
|
||||||
|
this.apps = apps;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,120 @@
|
|||||||
|
/**
|
||||||
|
* 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.vizio.internal.dto.audio;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.openhab.binding.vizio.internal.dto.Parameters;
|
||||||
|
import org.openhab.binding.vizio.internal.dto.Status;
|
||||||
|
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link Audio} class maps the JSON data response from the Vizio TV endpoint:
|
||||||
|
* '/menu_native/dynamic/tv_settings/audio'
|
||||||
|
*
|
||||||
|
* @author Michael Lobstein - Initial contribution
|
||||||
|
*/
|
||||||
|
public class Audio {
|
||||||
|
@SerializedName("STATUS")
|
||||||
|
private Status status;
|
||||||
|
@SerializedName("HASHLIST")
|
||||||
|
private List<Long> hashlist = new ArrayList<Long>();
|
||||||
|
@SerializedName("GROUP")
|
||||||
|
private String group;
|
||||||
|
@SerializedName("NAME")
|
||||||
|
private String name;
|
||||||
|
@SerializedName("PARAMETERS")
|
||||||
|
private Parameters parameters;
|
||||||
|
@SerializedName("ITEMS")
|
||||||
|
private List<ItemAudio> items = new ArrayList<ItemAudio>();
|
||||||
|
@SerializedName("URI")
|
||||||
|
private String uri;
|
||||||
|
@SerializedName("CNAME")
|
||||||
|
private String cname;
|
||||||
|
@SerializedName("TYPE")
|
||||||
|
private String type;
|
||||||
|
|
||||||
|
public Status getStatus() {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStatus(Status status) {
|
||||||
|
this.status = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Long> getHashlist() {
|
||||||
|
return hashlist;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHashlist(List<Long> hashlist) {
|
||||||
|
this.hashlist = hashlist;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getGroup() {
|
||||||
|
return group;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGroup(String group) {
|
||||||
|
this.group = group;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Parameters getParameters() {
|
||||||
|
return parameters;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setParameters(Parameters parameters) {
|
||||||
|
this.parameters = parameters;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ItemAudio> getItems() {
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setItems(List<ItemAudio> items) {
|
||||||
|
this.items = items;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUri() {
|
||||||
|
return uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUri(String uri) {
|
||||||
|
this.uri = uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCname() {
|
||||||
|
return cname;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCname(String cname) {
|
||||||
|
this.cname = cname;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setType(String type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,93 @@
|
|||||||
|
/**
|
||||||
|
* 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.vizio.internal.dto.audio;
|
||||||
|
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link ItemAudio} class contains data from the Vizio TV JSON response
|
||||||
|
*
|
||||||
|
* @author Michael Lobstein - Initial contribution
|
||||||
|
*/
|
||||||
|
public class ItemAudio {
|
||||||
|
@SerializedName("HASHVAL")
|
||||||
|
private Long hashval = 0L;
|
||||||
|
@SerializedName("CNAME")
|
||||||
|
private String cname;
|
||||||
|
@SerializedName("NAME")
|
||||||
|
private String name;
|
||||||
|
@SerializedName("TYPE")
|
||||||
|
private String type;
|
||||||
|
@SerializedName("ENABLED")
|
||||||
|
private String enabled;
|
||||||
|
@SerializedName("READONLY")
|
||||||
|
private String readonly;
|
||||||
|
@SerializedName("VALUE")
|
||||||
|
private String value = "";
|
||||||
|
|
||||||
|
public Long getHashval() {
|
||||||
|
return hashval;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHashval(Long hashval) {
|
||||||
|
this.hashval = hashval;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCname() {
|
||||||
|
return cname;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCname(String cname) {
|
||||||
|
this.cname = cname;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setType(String type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getEnabled() {
|
||||||
|
return enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEnabled(String enabled) {
|
||||||
|
this.enabled = enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getReadonly() {
|
||||||
|
return readonly;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setReadonly(String readonly) {
|
||||||
|
this.readonly = readonly;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValue(String value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,80 @@
|
|||||||
|
/**
|
||||||
|
* 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.vizio.internal.dto.input;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.openhab.binding.vizio.internal.dto.Parameters;
|
||||||
|
import org.openhab.binding.vizio.internal.dto.Status;
|
||||||
|
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link CurrentInput} class maps the JSON data response from the Vizio TV endpoint:
|
||||||
|
* '/menu_native/dynamic/tv_settings/devices/current_input'
|
||||||
|
*
|
||||||
|
* @author Michael Lobstein - Initial contribution
|
||||||
|
*/
|
||||||
|
public class CurrentInput {
|
||||||
|
@SerializedName("STATUS")
|
||||||
|
private Status status;
|
||||||
|
@SerializedName("ITEMS")
|
||||||
|
private List<ItemInput> items = new ArrayList<ItemInput>();
|
||||||
|
@SerializedName("HASHLIST")
|
||||||
|
private List<Long> hashlist = new ArrayList<Long>();
|
||||||
|
@SerializedName("URI")
|
||||||
|
private String uri;
|
||||||
|
@SerializedName("PARAMETERS")
|
||||||
|
private Parameters parameters;
|
||||||
|
|
||||||
|
public Status getStatus() {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStatus(Status status) {
|
||||||
|
this.status = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ItemInput> getItems() {
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setItems(List<ItemInput> items) {
|
||||||
|
this.items = items;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Long> getHashlist() {
|
||||||
|
return hashlist;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHashlist(List<Long> hashlist) {
|
||||||
|
this.hashlist = hashlist;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUri() {
|
||||||
|
return uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUri(String uri) {
|
||||||
|
this.uri = uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Parameters getParameters() {
|
||||||
|
return parameters;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setParameters(Parameters parameters) {
|
||||||
|
this.parameters = parameters;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,93 @@
|
|||||||
|
/**
|
||||||
|
* 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.vizio.internal.dto.input;
|
||||||
|
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link ItemInput} class contains data from the Vizio TV JSON response
|
||||||
|
*
|
||||||
|
* @author Michael Lobstein - Initial contribution
|
||||||
|
*/
|
||||||
|
public class ItemInput {
|
||||||
|
@SerializedName("HASHVAL")
|
||||||
|
private Long hashval = 0L;
|
||||||
|
@SerializedName("NAME")
|
||||||
|
private String name;
|
||||||
|
@SerializedName("ENABLED")
|
||||||
|
private String enabled;
|
||||||
|
@SerializedName("VALUE")
|
||||||
|
private String value = "";
|
||||||
|
@SerializedName("CNAME")
|
||||||
|
private String cname;
|
||||||
|
@SerializedName("HIDDEN")
|
||||||
|
private String hidden;
|
||||||
|
@SerializedName("TYPE")
|
||||||
|
private String type;
|
||||||
|
|
||||||
|
public Long getHashval() {
|
||||||
|
return hashval;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHashval(Long hashval) {
|
||||||
|
this.hashval = hashval;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getEnabled() {
|
||||||
|
return enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEnabled(String enabled) {
|
||||||
|
this.enabled = enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValue(String value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCname() {
|
||||||
|
return cname;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCname(String cname) {
|
||||||
|
this.cname = cname;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getHidden() {
|
||||||
|
return hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHidden(String hidden) {
|
||||||
|
this.hidden = hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setType(String type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,121 @@
|
|||||||
|
/**
|
||||||
|
* 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.vizio.internal.dto.inputlist;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.openhab.binding.vizio.internal.dto.Item;
|
||||||
|
import org.openhab.binding.vizio.internal.dto.Parameters;
|
||||||
|
import org.openhab.binding.vizio.internal.dto.Status;
|
||||||
|
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link InputList} class maps the JSON data response from the Vizio TV endpoint:
|
||||||
|
* '/menu_native/dynamic/tv_settings/devices/name_input'
|
||||||
|
*
|
||||||
|
* @author Michael Lobstein - Initial contribution
|
||||||
|
*/
|
||||||
|
public class InputList {
|
||||||
|
@SerializedName("STATUS")
|
||||||
|
private Status status;
|
||||||
|
@SerializedName("HASHLIST")
|
||||||
|
private List<Long> hashlist = new ArrayList<Long>();
|
||||||
|
@SerializedName("GROUP")
|
||||||
|
private String group;
|
||||||
|
@SerializedName("NAME")
|
||||||
|
private String name;
|
||||||
|
@SerializedName("PARAMETERS")
|
||||||
|
private Parameters parameters;
|
||||||
|
@SerializedName("ITEMS")
|
||||||
|
private List<Item> items = new ArrayList<Item>();
|
||||||
|
@SerializedName("URI")
|
||||||
|
private String uri;
|
||||||
|
@SerializedName("CNAME")
|
||||||
|
private String cname;
|
||||||
|
@SerializedName("TYPE")
|
||||||
|
private String type;
|
||||||
|
|
||||||
|
public Status getStatus() {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStatus(Status status) {
|
||||||
|
this.status = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Long> getHashlist() {
|
||||||
|
return hashlist;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHashlist(List<Long> hashlist) {
|
||||||
|
this.hashlist = hashlist;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getGroup() {
|
||||||
|
return group;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGroup(String group) {
|
||||||
|
this.group = group;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Parameters getParameters() {
|
||||||
|
return parameters;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setParameters(Parameters parameters) {
|
||||||
|
this.parameters = parameters;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Item> getItems() {
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setItems(List<Item> items) {
|
||||||
|
this.items = items;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUri() {
|
||||||
|
return uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUri(String uri) {
|
||||||
|
this.uri = uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCname() {
|
||||||
|
return cname;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCname(String cname) {
|
||||||
|
this.cname = cname;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setType(String type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
/**
|
||||||
|
* 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.vizio.internal.dto.pairing;
|
||||||
|
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link ItemAuthToken} class contains data from the Vizio TV in response to completing the pairing process
|
||||||
|
*
|
||||||
|
* @author Michael Lobstein - Initial contribution
|
||||||
|
*/
|
||||||
|
public class ItemAuthToken {
|
||||||
|
@SerializedName("AUTH_TOKEN")
|
||||||
|
private String authToken = "";
|
||||||
|
|
||||||
|
public String getAuthToken() {
|
||||||
|
return authToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAuthToken(String authToken) {
|
||||||
|
this.authToken = authToken;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,43 @@
|
|||||||
|
/**
|
||||||
|
* 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.vizio.internal.dto.pairing;
|
||||||
|
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link ItemPairing} class contains data from the Vizio TV in response to starting the pairing process
|
||||||
|
*
|
||||||
|
* @author Michael Lobstein - Initial contribution
|
||||||
|
*/
|
||||||
|
public class ItemPairing {
|
||||||
|
@SerializedName("PAIRING_REQ_TOKEN")
|
||||||
|
private Integer pairingReqToken = -1;
|
||||||
|
@SerializedName("CHALLENGE_TYPE")
|
||||||
|
private Integer challengeType = -1;
|
||||||
|
|
||||||
|
public Integer getPairingReqToken() {
|
||||||
|
return pairingReqToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPairingReqToken(Integer pairingReqToken) {
|
||||||
|
this.pairingReqToken = pairingReqToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getChallengeType() {
|
||||||
|
return challengeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setChallengeType(Integer challengeType) {
|
||||||
|
this.challengeType = challengeType;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
/**
|
||||||
|
* 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.vizio.internal.dto.pairing;
|
||||||
|
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link PairingComplete} class maps the JSON data response from the Vizio TV endpoint:
|
||||||
|
* '/pairing/pair'
|
||||||
|
*
|
||||||
|
* @author Michael Lobstein - Initial contribution
|
||||||
|
*/
|
||||||
|
public class PairingComplete {
|
||||||
|
@SerializedName("ITEM")
|
||||||
|
private ItemAuthToken item = new ItemAuthToken();
|
||||||
|
|
||||||
|
public ItemAuthToken getItem() {
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setItem(ItemAuthToken item) {
|
||||||
|
this.item = item;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
/**
|
||||||
|
* 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.vizio.internal.dto.pairing;
|
||||||
|
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link PairingStart} class maps the JSON data response from the Vizio TV endpoint:
|
||||||
|
* '/pairing/start'
|
||||||
|
*
|
||||||
|
* @author Michael Lobstein - Initial contribution
|
||||||
|
*/
|
||||||
|
public class PairingStart {
|
||||||
|
@SerializedName("ITEM")
|
||||||
|
private ItemPairing item = new ItemPairing();
|
||||||
|
|
||||||
|
public ItemPairing getItem() {
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setItem(ItemPairing item) {
|
||||||
|
this.item = item;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,63 @@
|
|||||||
|
/**
|
||||||
|
* 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.vizio.internal.dto.power;
|
||||||
|
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link ItemPower} class contains data from the Vizio TV JSON response
|
||||||
|
*
|
||||||
|
* @author Michael Lobstein - Initial contribution
|
||||||
|
*/
|
||||||
|
public class ItemPower {
|
||||||
|
@SerializedName("CNAME")
|
||||||
|
private String cname;
|
||||||
|
@SerializedName("TYPE")
|
||||||
|
private String type;
|
||||||
|
@SerializedName("NAME")
|
||||||
|
private String name;
|
||||||
|
@SerializedName("VALUE")
|
||||||
|
private int value;
|
||||||
|
|
||||||
|
public String getCname() {
|
||||||
|
return cname;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCname(String cname) {
|
||||||
|
this.cname = cname;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setType(String type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValue(int value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,59 @@
|
|||||||
|
/**
|
||||||
|
* 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.vizio.internal.dto.power;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.openhab.binding.vizio.internal.dto.Status;
|
||||||
|
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link PowerMode} class maps the JSON data response from the Vizio TV endpoint:
|
||||||
|
* '/state/device/power_mode'
|
||||||
|
*
|
||||||
|
* @author Michael Lobstein - Initial contribution
|
||||||
|
*/
|
||||||
|
public class PowerMode {
|
||||||
|
@SerializedName("STATUS")
|
||||||
|
private Status status;
|
||||||
|
@SerializedName("ITEMS")
|
||||||
|
private List<ItemPower> items = new ArrayList<ItemPower>();
|
||||||
|
@SerializedName("URI")
|
||||||
|
private String uri;
|
||||||
|
|
||||||
|
public Status getStatus() {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStatus(Status status) {
|
||||||
|
this.status = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ItemPower> getItems() {
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setItems(List<ItemPower> items) {
|
||||||
|
this.items = items;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUri() {
|
||||||
|
return uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUri(String uri) {
|
||||||
|
this.uri = uri;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,70 @@
|
|||||||
|
/**
|
||||||
|
* 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.vizio.internal.enums;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link KeyCommand} class provides enum values for remote control button press commands.
|
||||||
|
*
|
||||||
|
* @author Michael Lobstein - Initial contribution
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
public enum KeyCommand {
|
||||||
|
SEEKFWD(2, 0),
|
||||||
|
SEEKBACK(2, 1),
|
||||||
|
PAUSE(2, 2),
|
||||||
|
PLAY(2, 3),
|
||||||
|
DOWN(3, 0),
|
||||||
|
LEFT(3, 1),
|
||||||
|
OK(3, 2),
|
||||||
|
LEFT2(3, 4),
|
||||||
|
RIGHT(3, 7),
|
||||||
|
UP(3, 8),
|
||||||
|
BACK(4, 0),
|
||||||
|
SMARTCAST(4, 3),
|
||||||
|
CCTOGGLE(4, 4),
|
||||||
|
INFO(4, 6),
|
||||||
|
MENU(4, 8),
|
||||||
|
HOME(4, 15),
|
||||||
|
VOLUMEDOWN(5, 0),
|
||||||
|
VOLUMEUP(5, 1),
|
||||||
|
MUTEOFF(5, 2),
|
||||||
|
MUTEON(5, 3),
|
||||||
|
MUTETOGGLE(5, 4),
|
||||||
|
PICTUREMODE(6, 0),
|
||||||
|
WIDEMODE(6, 1),
|
||||||
|
WIDETOGGLE(6, 2),
|
||||||
|
INPUTTOGGLE(7, 1),
|
||||||
|
CHANNELDOWN(8, 0),
|
||||||
|
CHANNELUP(8, 1),
|
||||||
|
PREVIOUSCH(8, 2),
|
||||||
|
EXIT(9, 0),
|
||||||
|
POWEROFF(11, 0),
|
||||||
|
POWERON(11, 1),
|
||||||
|
POWERTOGGLE(11, 2);
|
||||||
|
|
||||||
|
private static final String KEY_COMMAND_STR = "{\"KEYLIST\": [{\"CODESET\": %d,\"CODE\": %d,\"ACTION\":\"KEYPRESS\"}]}";
|
||||||
|
|
||||||
|
private final int codeSet;
|
||||||
|
private final int code;
|
||||||
|
|
||||||
|
KeyCommand(int codeSet, int code) {
|
||||||
|
this.codeSet = codeSet;
|
||||||
|
this.code = code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getJson() {
|
||||||
|
return String.format(KEY_COMMAND_STR, codeSet, code);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,584 @@
|
|||||||
|
/**
|
||||||
|
* 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.vizio.internal.handler;
|
||||||
|
|
||||||
|
import static org.openhab.binding.vizio.internal.VizioBindingConstants.*;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.concurrent.ScheduledFuture;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
|
import org.eclipse.jetty.client.HttpClient;
|
||||||
|
import org.openhab.binding.vizio.internal.VizioConfiguration;
|
||||||
|
import org.openhab.binding.vizio.internal.VizioException;
|
||||||
|
import org.openhab.binding.vizio.internal.VizioStateDescriptionOptionProvider;
|
||||||
|
import org.openhab.binding.vizio.internal.communication.VizioCommunicator;
|
||||||
|
import org.openhab.binding.vizio.internal.communication.VizioTlsTrustManagerProvider;
|
||||||
|
import org.openhab.binding.vizio.internal.dto.app.CurrentApp;
|
||||||
|
import org.openhab.binding.vizio.internal.dto.applist.VizioApp;
|
||||||
|
import org.openhab.binding.vizio.internal.dto.applist.VizioApps;
|
||||||
|
import org.openhab.binding.vizio.internal.dto.audio.Audio;
|
||||||
|
import org.openhab.binding.vizio.internal.dto.audio.ItemAudio;
|
||||||
|
import org.openhab.binding.vizio.internal.dto.input.CurrentInput;
|
||||||
|
import org.openhab.binding.vizio.internal.dto.inputlist.InputList;
|
||||||
|
import org.openhab.binding.vizio.internal.dto.power.PowerMode;
|
||||||
|
import org.openhab.binding.vizio.internal.enums.KeyCommand;
|
||||||
|
import org.openhab.core.config.core.Configuration;
|
||||||
|
import org.openhab.core.io.net.http.TlsTrustManagerProvider;
|
||||||
|
import org.openhab.core.library.types.NextPreviousType;
|
||||||
|
import org.openhab.core.library.types.OnOffType;
|
||||||
|
import org.openhab.core.library.types.PercentType;
|
||||||
|
import org.openhab.core.library.types.PlayPauseType;
|
||||||
|
import org.openhab.core.library.types.RewindFastforwardType;
|
||||||
|
import org.openhab.core.library.types.StringType;
|
||||||
|
import org.openhab.core.thing.Channel;
|
||||||
|
import org.openhab.core.thing.ChannelUID;
|
||||||
|
import org.openhab.core.thing.Thing;
|
||||||
|
import org.openhab.core.thing.ThingStatus;
|
||||||
|
import org.openhab.core.thing.ThingStatusDetail;
|
||||||
|
import org.openhab.core.thing.binding.BaseThingHandler;
|
||||||
|
import org.openhab.core.types.Command;
|
||||||
|
import org.openhab.core.types.RefreshType;
|
||||||
|
import org.openhab.core.types.StateOption;
|
||||||
|
import org.openhab.core.types.UnDefType;
|
||||||
|
import org.osgi.framework.FrameworkUtil;
|
||||||
|
import org.osgi.framework.ServiceRegistration;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import com.google.gson.JsonSyntaxException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link VizioHandler} is responsible for handling commands, which are
|
||||||
|
* sent to one of the channels.
|
||||||
|
*
|
||||||
|
* @author Michael Lobstein - Initial contribution
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
public class VizioHandler extends BaseThingHandler {
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(VizioHandler.class);
|
||||||
|
private final HttpClient httpClient;
|
||||||
|
private final VizioStateDescriptionOptionProvider stateDescriptionProvider;
|
||||||
|
private final String dbAppsJson;
|
||||||
|
|
||||||
|
private @Nullable ServiceRegistration<?> serviceRegistration;
|
||||||
|
private @Nullable ScheduledFuture<?> refreshJob;
|
||||||
|
private @Nullable ScheduledFuture<?> metadataRefreshJob;
|
||||||
|
|
||||||
|
private VizioCommunicator communicator;
|
||||||
|
private List<VizioApp> userConfigApps = new ArrayList<VizioApp>();
|
||||||
|
private Object sequenceLock = new Object();
|
||||||
|
|
||||||
|
private int pairingDeviceId = -1;
|
||||||
|
private int pairingToken = -1;
|
||||||
|
private Long currentInputHash = 0L;
|
||||||
|
private Long currentVolumeHash = 0L;
|
||||||
|
private String currentApp = EMPTY;
|
||||||
|
private String currentInput = EMPTY;
|
||||||
|
private boolean currentMute = false;
|
||||||
|
private int currentVolume = -1;
|
||||||
|
private boolean powerOn = false;
|
||||||
|
private boolean debounce = true;
|
||||||
|
|
||||||
|
public VizioHandler(Thing thing, HttpClient httpClient,
|
||||||
|
VizioStateDescriptionOptionProvider stateDescriptionProvider, String vizioAppsJson) {
|
||||||
|
super(thing);
|
||||||
|
this.httpClient = httpClient;
|
||||||
|
this.stateDescriptionProvider = stateDescriptionProvider;
|
||||||
|
this.dbAppsJson = vizioAppsJson;
|
||||||
|
this.communicator = new VizioCommunicator(httpClient, EMPTY, -1, EMPTY);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialize() {
|
||||||
|
logger.debug("Initializing Vizio handler");
|
||||||
|
final Gson gson = new Gson();
|
||||||
|
VizioConfiguration config = getConfigAs(VizioConfiguration.class);
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
String host = config.hostName;
|
||||||
|
final @Nullable String authToken = config.authToken;
|
||||||
|
@Nullable
|
||||||
|
String appListJson = config.appListJson;
|
||||||
|
|
||||||
|
if (host == null || host.isEmpty()) {
|
||||||
|
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
|
||||||
|
"@text/offline.configuration-error-hostname");
|
||||||
|
return;
|
||||||
|
} else if (host.contains(":")) {
|
||||||
|
// format for ipv6
|
||||||
|
host = "[" + host + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
this.communicator = new VizioCommunicator(httpClient, host, config.port, authToken != null ? authToken : EMPTY);
|
||||||
|
|
||||||
|
// register trustmanager service to allow httpClient to accept self signed cert from the Vizio TV
|
||||||
|
VizioTlsTrustManagerProvider tlsTrustManagerProvider = new VizioTlsTrustManagerProvider(
|
||||||
|
host + ":" + config.port);
|
||||||
|
serviceRegistration = FrameworkUtil.getBundle(getClass()).getBundleContext()
|
||||||
|
.registerService(TlsTrustManagerProvider.class.getName(), tlsTrustManagerProvider, null);
|
||||||
|
|
||||||
|
if (authToken == null) {
|
||||||
|
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_PENDING,
|
||||||
|
"@text/offline.configuration-error-authtoken");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if app list is not supplied in thing configuration, populate it from the json db
|
||||||
|
if (appListJson == null) {
|
||||||
|
appListJson = dbAppsJson;
|
||||||
|
|
||||||
|
// Update thing configuration (persistent) - store app list from db into thing so the user can update it
|
||||||
|
Configuration configuration = this.getConfig();
|
||||||
|
configuration.put(PROPERTY_APP_LIST_JSON, appListJson);
|
||||||
|
this.updateConfiguration(configuration);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
VizioApps appsFromJson = gson.fromJson(appListJson, VizioApps.class);
|
||||||
|
if (appsFromJson != null && !appsFromJson.getApps().isEmpty()) {
|
||||||
|
userConfigApps = appsFromJson.getApps();
|
||||||
|
|
||||||
|
List<StateOption> appListOptions = new ArrayList<>();
|
||||||
|
userConfigApps.forEach(app -> {
|
||||||
|
appListOptions.add(new StateOption(app.getName(), app.getName()));
|
||||||
|
});
|
||||||
|
|
||||||
|
stateDescriptionProvider.setStateOptions(new ChannelUID(getThing().getUID(), ACTIVE_APP),
|
||||||
|
appListOptions);
|
||||||
|
}
|
||||||
|
} catch (JsonSyntaxException e) {
|
||||||
|
logger.debug("Invalid App List Configuration in thing configuration. Exception: {}", e.getMessage(), e);
|
||||||
|
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
|
||||||
|
"@text/offline.configuration-error-applist");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
updateStatus(ThingStatus.UNKNOWN);
|
||||||
|
|
||||||
|
startVizioStateRefresh();
|
||||||
|
startPeriodicRefresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start the job that queries the Vizio TV every 10 seconds to get its current status
|
||||||
|
*/
|
||||||
|
private void startVizioStateRefresh() {
|
||||||
|
ScheduledFuture<?> refreshJob = this.refreshJob;
|
||||||
|
if (refreshJob == null || refreshJob.isCancelled()) {
|
||||||
|
this.refreshJob = scheduler.scheduleWithFixedDelay(this::refreshVizioState, 5, 10, TimeUnit.SECONDS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get current status from the Vizio TV and update the channels
|
||||||
|
*/
|
||||||
|
private void refreshVizioState() {
|
||||||
|
synchronized (sequenceLock) {
|
||||||
|
try {
|
||||||
|
PowerMode polledPowerMode = communicator.getPowerMode();
|
||||||
|
|
||||||
|
if (debounce && !polledPowerMode.getItems().isEmpty()) {
|
||||||
|
int powerMode = polledPowerMode.getItems().get(0).getValue();
|
||||||
|
if (powerMode == 1) {
|
||||||
|
powerOn = true;
|
||||||
|
updateState(POWER, OnOffType.ON);
|
||||||
|
} else if (powerMode == 0) {
|
||||||
|
powerOn = false;
|
||||||
|
updateState(POWER, OnOffType.OFF);
|
||||||
|
} else {
|
||||||
|
logger.debug("Unknown power mode {}, for response object: {}", powerMode, polledPowerMode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
updateStatus(ThingStatus.ONLINE);
|
||||||
|
} catch (VizioException e) {
|
||||||
|
logger.debug("Unable to retrieve Vizio TV power mode info. Exception: {}", e.getMessage(), e);
|
||||||
|
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||||
|
"@text/offline.communication-error-get-power");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (powerOn && (isLinked(VOLUME) || isLinked(MUTE))) {
|
||||||
|
try {
|
||||||
|
Audio audioSettings = communicator.getCurrentAudioSettings();
|
||||||
|
|
||||||
|
Optional<ItemAudio> volumeItem = audioSettings.getItems().stream()
|
||||||
|
.filter(i -> VOLUME.equals(i.getCname())).findFirst();
|
||||||
|
if (debounce && volumeItem.isPresent()) {
|
||||||
|
currentVolumeHash = volumeItem.get().getHashval();
|
||||||
|
|
||||||
|
try {
|
||||||
|
int polledVolume = Integer.parseInt(volumeItem.get().getValue());
|
||||||
|
if (polledVolume != currentVolume) {
|
||||||
|
currentVolume = polledVolume;
|
||||||
|
updateState(VOLUME, new PercentType(BigDecimal.valueOf(currentVolume)));
|
||||||
|
}
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
logger.debug("Unable to parse volume value {} as int", volumeItem.get().getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Optional<ItemAudio> muteItem = audioSettings.getItems().stream()
|
||||||
|
.filter(i -> MUTE.equals(i.getCname())).findFirst();
|
||||||
|
if (debounce && muteItem.isPresent()) {
|
||||||
|
String polledMute = muteItem.get().getValue().toUpperCase(Locale.ENGLISH);
|
||||||
|
|
||||||
|
if (ON.equals(polledMute) || OFF.equals(polledMute)) {
|
||||||
|
if (ON.equals(polledMute) && !currentMute) {
|
||||||
|
updateState(MUTE, OnOffType.ON);
|
||||||
|
currentMute = true;
|
||||||
|
} else if (OFF.equals(polledMute) && currentMute) {
|
||||||
|
updateState(MUTE, OnOffType.OFF);
|
||||||
|
currentMute = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
logger.debug("Unknown mute mode {}, for response object: {}", polledMute, audioSettings);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (VizioException e) {
|
||||||
|
logger.debug("Unable to retrieve Vizio TV current audio settings. Exception: {}", e.getMessage(),
|
||||||
|
e);
|
||||||
|
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||||
|
"@text/offline.communication-error-get-audio");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (powerOn && isLinked(SOURCE)) {
|
||||||
|
try {
|
||||||
|
CurrentInput polledInputState = communicator.getCurrentInput();
|
||||||
|
|
||||||
|
if (debounce && !polledInputState.getItems().isEmpty()
|
||||||
|
&& !currentInput.equals(polledInputState.getItems().get(0).getValue())) {
|
||||||
|
currentInput = polledInputState.getItems().get(0).getValue();
|
||||||
|
currentInputHash = polledInputState.getItems().get(0).getHashval();
|
||||||
|
updateState(SOURCE, new StringType(currentInput));
|
||||||
|
}
|
||||||
|
} catch (VizioException e) {
|
||||||
|
logger.debug("Unable to retrieve Vizio TV current input. Exception: {}", e.getMessage(), e);
|
||||||
|
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||||
|
"@text/offline.communication-error-get-input");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (powerOn && isLinked(ACTIVE_APP)) {
|
||||||
|
try {
|
||||||
|
if (debounce) {
|
||||||
|
CurrentApp polledApp = communicator.getCurrentApp();
|
||||||
|
Optional<VizioApp> currentAppData = userConfigApps.stream()
|
||||||
|
.filter(a -> a.getConfig().getAppId().equals(polledApp.getItem().getValue().getAppId())
|
||||||
|
&& a.getConfig().getNameSpace()
|
||||||
|
.equals(polledApp.getItem().getValue().getNameSpace()))
|
||||||
|
.findFirst();
|
||||||
|
|
||||||
|
if (currentAppData.isPresent()) {
|
||||||
|
if (!currentApp.equals(currentAppData.get().getName())) {
|
||||||
|
currentApp = currentAppData.get().getName();
|
||||||
|
updateState(ACTIVE_APP, new StringType(currentApp));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
currentApp = EMPTY;
|
||||||
|
try {
|
||||||
|
int appId = Integer.parseInt(polledApp.getItem().getValue().getAppId());
|
||||||
|
updateState(ACTIVE_APP, new StringType(String.format(UNKNOWN_APP_STR, appId,
|
||||||
|
polledApp.getItem().getValue().getNameSpace())));
|
||||||
|
} catch (NumberFormatException nfe) {
|
||||||
|
// Non-numeric appId received, eg: hdmi1
|
||||||
|
updateState(ACTIVE_APP, UnDefType.UNDEF);
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.debug("Unknown app_id: {}, name_space: {}",
|
||||||
|
polledApp.getItem().getValue().getAppId(),
|
||||||
|
polledApp.getItem().getValue().getNameSpace());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (VizioException e) {
|
||||||
|
logger.debug("Unable to retrieve Vizio TV current running app. Exception: {}", e.getMessage(), e);
|
||||||
|
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||||
|
"@text/offline.communication-error-get-app");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
debounce = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start the job to periodically retrieve various metadata from the Vizio TV every 10 minutes
|
||||||
|
*/
|
||||||
|
private void startPeriodicRefresh() {
|
||||||
|
ScheduledFuture<?> metadataRefreshJob = this.metadataRefreshJob;
|
||||||
|
if (metadataRefreshJob == null || metadataRefreshJob.isCancelled()) {
|
||||||
|
this.metadataRefreshJob = scheduler.scheduleWithFixedDelay(this::refreshVizioMetadata, 1, 600,
|
||||||
|
TimeUnit.SECONDS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update source list (hashes) and other metadata from the Vizio TV
|
||||||
|
*/
|
||||||
|
private void refreshVizioMetadata() {
|
||||||
|
synchronized (sequenceLock) {
|
||||||
|
try {
|
||||||
|
InputList inputList = communicator.getSourceInputList();
|
||||||
|
|
||||||
|
List<StateOption> sourceListOptions = new ArrayList<>();
|
||||||
|
inputList.getItems().forEach(source -> {
|
||||||
|
sourceListOptions.add(new StateOption(source.getName(), source.getValue().getName()));
|
||||||
|
});
|
||||||
|
|
||||||
|
stateDescriptionProvider.setStateOptions(new ChannelUID(getThing().getUID(), SOURCE),
|
||||||
|
sourceListOptions);
|
||||||
|
} catch (VizioException e) {
|
||||||
|
logger.debug("Unable to retrieve the Vizio TV input list. Exception: {}", e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void dispose() {
|
||||||
|
ScheduledFuture<?> refreshJob = this.refreshJob;
|
||||||
|
if (refreshJob != null) {
|
||||||
|
refreshJob.cancel(true);
|
||||||
|
this.refreshJob = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
ScheduledFuture<?> metadataRefreshJob = this.metadataRefreshJob;
|
||||||
|
if (metadataRefreshJob != null) {
|
||||||
|
metadataRefreshJob.cancel(true);
|
||||||
|
this.metadataRefreshJob = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
ServiceRegistration<?> localServiceRegistration = serviceRegistration;
|
||||||
|
if (localServiceRegistration != null) {
|
||||||
|
// remove trustmanager service
|
||||||
|
localServiceRegistration.unregister();
|
||||||
|
serviceRegistration = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||||
|
if (command instanceof RefreshType) {
|
||||||
|
logger.debug("Unsupported refresh command: {}", command);
|
||||||
|
} else {
|
||||||
|
switch (channelUID.getId()) {
|
||||||
|
case POWER:
|
||||||
|
debounce = false;
|
||||||
|
synchronized (sequenceLock) {
|
||||||
|
try {
|
||||||
|
if (command == OnOffType.ON) {
|
||||||
|
communicator.sendKeyPress(KeyCommand.POWERON.getJson());
|
||||||
|
powerOn = true;
|
||||||
|
} else {
|
||||||
|
communicator.sendKeyPress(KeyCommand.POWEROFF.getJson());
|
||||||
|
powerOn = false;
|
||||||
|
}
|
||||||
|
} catch (VizioException e) {
|
||||||
|
logger.debug("Unable to send power {} command to the Vizio TV, Exception: {}", command,
|
||||||
|
e.getMessage());
|
||||||
|
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||||
|
"@text/offline.communication-error-set-power");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case VOLUME:
|
||||||
|
debounce = false;
|
||||||
|
synchronized (sequenceLock) {
|
||||||
|
try {
|
||||||
|
int volume = Integer.parseInt(command.toString());
|
||||||
|
|
||||||
|
// volume changed again before polling has run, get current volume hash from the TV first
|
||||||
|
if (currentVolumeHash.equals(0L)) {
|
||||||
|
Audio audioSettings = communicator.getCurrentAudioSettings();
|
||||||
|
|
||||||
|
Optional<ItemAudio> volumeItem = audioSettings.getItems().stream()
|
||||||
|
.filter(i -> VOLUME.equals(i.getCname())).findFirst();
|
||||||
|
if (volumeItem.isPresent()) {
|
||||||
|
currentVolumeHash = volumeItem.get().getHashval();
|
||||||
|
} else {
|
||||||
|
logger.debug("Unable to get current volume hash on the Vizio TV");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
communicator
|
||||||
|
.changeVolume(String.format(MODIFY_INT_SETTING_JSON, volume, currentVolumeHash));
|
||||||
|
currentVolumeHash = 0L;
|
||||||
|
} catch (VizioException e) {
|
||||||
|
logger.debug("Unable to set volume on the Vizio TV, command volume: {}, Exception: {}",
|
||||||
|
command, e.getMessage());
|
||||||
|
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||||
|
"@text/offline.communication-error-set-volume");
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
logger.debug("Unable to parse command volume value {} as int", command);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MUTE:
|
||||||
|
debounce = false;
|
||||||
|
synchronized (sequenceLock) {
|
||||||
|
try {
|
||||||
|
if (command == OnOffType.ON && !currentMute) {
|
||||||
|
communicator.sendKeyPress(KeyCommand.MUTETOGGLE.getJson());
|
||||||
|
currentMute = true;
|
||||||
|
} else if (command == OnOffType.OFF && currentMute) {
|
||||||
|
communicator.sendKeyPress(KeyCommand.MUTETOGGLE.getJson());
|
||||||
|
currentMute = false;
|
||||||
|
}
|
||||||
|
} catch (VizioException e) {
|
||||||
|
logger.debug("Unable to send mute {} command to the Vizio TV, Exception: {}", command,
|
||||||
|
e.getMessage());
|
||||||
|
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||||
|
"@text/offline.communication-error-set-mute");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SOURCE:
|
||||||
|
debounce = false;
|
||||||
|
synchronized (sequenceLock) {
|
||||||
|
try {
|
||||||
|
// if input changed again before polling has run, get current input hash from the TV
|
||||||
|
// first
|
||||||
|
if (currentInputHash.equals(0L)) {
|
||||||
|
CurrentInput polledInput = communicator.getCurrentInput();
|
||||||
|
if (!polledInput.getItems().isEmpty()) {
|
||||||
|
currentInputHash = polledInput.getItems().get(0).getHashval();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
communicator
|
||||||
|
.changeInput(String.format(MODIFY_STRING_SETTING_JSON, command, currentInputHash));
|
||||||
|
currentInputHash = 0L;
|
||||||
|
} catch (VizioException e) {
|
||||||
|
logger.debug("Unable to set current source on the Vizio TV, source: {}, Exception: {}",
|
||||||
|
command, e.getMessage());
|
||||||
|
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||||
|
"@text/offline.communication-error-set-source");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ACTIVE_APP:
|
||||||
|
debounce = false;
|
||||||
|
synchronized (sequenceLock) {
|
||||||
|
try {
|
||||||
|
Optional<VizioApp> selectedApp = userConfigApps.stream()
|
||||||
|
.filter(a -> command.toString().equals(a.getName())).findFirst();
|
||||||
|
|
||||||
|
if (selectedApp.isPresent()) {
|
||||||
|
communicator.launchApp(selectedApp.get().getConfig());
|
||||||
|
} else {
|
||||||
|
logger.debug("Unknown app name: '{}', check that it exists in App List configuration",
|
||||||
|
command);
|
||||||
|
}
|
||||||
|
} catch (VizioException e) {
|
||||||
|
logger.debug("Unable to launch app name: '{}' on the Vizio TV, Exception: {}", command,
|
||||||
|
e.getMessage());
|
||||||
|
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||||
|
"@text/offline.communication-error-launch-app");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CONTROL:
|
||||||
|
debounce = false;
|
||||||
|
synchronized (sequenceLock) {
|
||||||
|
try {
|
||||||
|
handleControlCommand(command);
|
||||||
|
} catch (VizioException e) {
|
||||||
|
logger.debug("Unable to send control command: '{}' to the Vizio TV, Exception: {}", command,
|
||||||
|
e.getMessage());
|
||||||
|
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||||
|
"@text/offline.communication-error-send-cmd");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case BUTTON:
|
||||||
|
synchronized (sequenceLock) {
|
||||||
|
try {
|
||||||
|
KeyCommand keyCommand = KeyCommand.valueOf(command.toString().toUpperCase(Locale.ENGLISH));
|
||||||
|
communicator.sendKeyPress(keyCommand.getJson());
|
||||||
|
} catch (IllegalArgumentException | VizioException e) {
|
||||||
|
logger.debug("Unable to send keypress to the Vizio TV, key: {}, Exception: {}", command,
|
||||||
|
e.getMessage());
|
||||||
|
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||||
|
"@text/offline.communication-error-send-key");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
logger.warn("Unknown channel: '{}'", channelUID.getId());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleControlCommand(Command command) throws VizioException {
|
||||||
|
if (command instanceof PlayPauseType) {
|
||||||
|
if (command == PlayPauseType.PLAY) {
|
||||||
|
communicator.sendKeyPress(KeyCommand.PLAY.getJson());
|
||||||
|
} else if (command == PlayPauseType.PAUSE) {
|
||||||
|
communicator.sendKeyPress(KeyCommand.PAUSE.getJson());
|
||||||
|
}
|
||||||
|
} else if (command instanceof NextPreviousType) {
|
||||||
|
if (command == NextPreviousType.NEXT) {
|
||||||
|
communicator.sendKeyPress(KeyCommand.RIGHT.getJson());
|
||||||
|
} else if (command == NextPreviousType.PREVIOUS) {
|
||||||
|
communicator.sendKeyPress(KeyCommand.LEFT.getJson());
|
||||||
|
}
|
||||||
|
} else if (command instanceof RewindFastforwardType) {
|
||||||
|
if (command == RewindFastforwardType.FASTFORWARD) {
|
||||||
|
communicator.sendKeyPress(KeyCommand.SEEKFWD.getJson());
|
||||||
|
} else if (command == RewindFastforwardType.REWIND) {
|
||||||
|
communicator.sendKeyPress(KeyCommand.SEEKBACK.getJson());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
logger.warn("Unknown control command: {}", command);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isLinked(String channelName) {
|
||||||
|
Channel channel = this.thing.getChannel(channelName);
|
||||||
|
if (channel != null) {
|
||||||
|
return isLinked(channel.getUID());
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The remaining methods are used by the console when obtaining the auth token from the TV.
|
||||||
|
public void saveAuthToken(String authToken) {
|
||||||
|
// Store the auth token in the configuration and restart the thing
|
||||||
|
Configuration configuration = this.getConfig();
|
||||||
|
configuration.put(PROPERTY_AUTH_TOKEN, authToken);
|
||||||
|
this.updateConfiguration(configuration);
|
||||||
|
this.thingUpdated(this.getThing());
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getPairingDeviceId() {
|
||||||
|
return pairingDeviceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPairingDeviceId(int pairingDeviceId) {
|
||||||
|
this.pairingDeviceId = pairingDeviceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getPairingToken() {
|
||||||
|
return pairingToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPairingToken(int pairingToken) {
|
||||||
|
this.pairingToken = pairingToken;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<binding:binding id="vizio" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xmlns:binding="https://openhab.org/schemas/binding/v1.0.0"
|
||||||
|
xsi:schemaLocation="https://openhab.org/schemas/binding/v1.0.0 https://openhab.org/schemas/binding-1.0.0.xsd">
|
||||||
|
|
||||||
|
<name>Vizio Binding</name>
|
||||||
|
<description>Controls Vizio TVs w/SmartCast API (2016+ Models)</description>
|
||||||
|
|
||||||
|
</binding:binding>
|
@ -0,0 +1,81 @@
|
|||||||
|
# binding
|
||||||
|
|
||||||
|
binding.vizio.name = Vizio Binding
|
||||||
|
binding.vizio.description = Controls Vizio TVs w/SmartCast API (2016+ Models)
|
||||||
|
|
||||||
|
# thing types
|
||||||
|
|
||||||
|
thing-type.vizio.vizio_tv.label = Vizio TV
|
||||||
|
thing-type.vizio.vizio_tv.description = A Vizio SmartCast TV
|
||||||
|
|
||||||
|
# thing types config
|
||||||
|
|
||||||
|
thing-type.config.vizio.vizio_tv.appListJson.label = App List Configuration
|
||||||
|
thing-type.config.vizio.vizio_tv.appListJson.description = The JSON configuration string for the list of apps available in the activeApp channel drop down
|
||||||
|
thing-type.config.vizio.vizio_tv.authToken.label = Auth Token
|
||||||
|
thing-type.config.vizio.vizio_tv.authToken.description = Auth Token that is obtained via the pairing process; See documentation for details
|
||||||
|
thing-type.config.vizio.vizio_tv.hostName.label = Host Name/IP Address
|
||||||
|
thing-type.config.vizio.vizio_tv.hostName.description = Host Name or IP Address of the Vizio TV
|
||||||
|
thing-type.config.vizio.vizio_tv.port.label = Port
|
||||||
|
thing-type.config.vizio.vizio_tv.port.description = Port for the Vizio TV
|
||||||
|
thing-type.config.vizio.vizio_tv.port.option.7345 = 7345 (Newer Models)
|
||||||
|
thing-type.config.vizio.vizio_tv.port.option.9000 = 9000 (Older Models)
|
||||||
|
|
||||||
|
# channel types
|
||||||
|
|
||||||
|
channel-type.vizio.activeApp.label = Active App
|
||||||
|
channel-type.vizio.activeApp.description = The currently running App on the TV
|
||||||
|
channel-type.vizio.buttonTv.label = Remote Button
|
||||||
|
channel-type.vizio.buttonTv.description = A Remote Button press to send to the TV
|
||||||
|
channel-type.vizio.buttonTv.state.option.PowerOn = Power On
|
||||||
|
channel-type.vizio.buttonTv.state.option.PowerOff = Power Off
|
||||||
|
channel-type.vizio.buttonTv.state.option.PowerToggle = Power Toggle
|
||||||
|
channel-type.vizio.buttonTv.state.option.VolumeUp = Volume Up
|
||||||
|
channel-type.vizio.buttonTv.state.option.VolumeDown = Volume Down
|
||||||
|
channel-type.vizio.buttonTv.state.option.MuteOn = Mute On
|
||||||
|
channel-type.vizio.buttonTv.state.option.MuteOff = Mute Off
|
||||||
|
channel-type.vizio.buttonTv.state.option.MuteToggle = Mute Toggle
|
||||||
|
channel-type.vizio.buttonTv.state.option.ChannelUp = Channel Up
|
||||||
|
channel-type.vizio.buttonTv.state.option.ChannelDown = Channel Down
|
||||||
|
channel-type.vizio.buttonTv.state.option.PreviousCh = Previous Channel
|
||||||
|
channel-type.vizio.buttonTv.state.option.InputToggle = Input Toggle
|
||||||
|
channel-type.vizio.buttonTv.state.option.SeekFwd = Seek Fwd
|
||||||
|
channel-type.vizio.buttonTv.state.option.SeekBack = Seek Back
|
||||||
|
channel-type.vizio.buttonTv.state.option.Play = Play
|
||||||
|
channel-type.vizio.buttonTv.state.option.Pause = Pause
|
||||||
|
channel-type.vizio.buttonTv.state.option.Up = Up
|
||||||
|
channel-type.vizio.buttonTv.state.option.Down = Down
|
||||||
|
channel-type.vizio.buttonTv.state.option.Left = Left
|
||||||
|
channel-type.vizio.buttonTv.state.option.Right = Right
|
||||||
|
channel-type.vizio.buttonTv.state.option.Ok = Ok
|
||||||
|
channel-type.vizio.buttonTv.state.option.Back = Back
|
||||||
|
channel-type.vizio.buttonTv.state.option.Info = Info
|
||||||
|
channel-type.vizio.buttonTv.state.option.Menu = Menu
|
||||||
|
channel-type.vizio.buttonTv.state.option.Home = Home
|
||||||
|
channel-type.vizio.buttonTv.state.option.Exit = Exit
|
||||||
|
channel-type.vizio.buttonTv.state.option.Smartcast = Smartcast
|
||||||
|
channel-type.vizio.buttonTv.state.option.ccToggle = CC Toggle
|
||||||
|
channel-type.vizio.buttonTv.state.option.PictureMode = Picture Mode
|
||||||
|
channel-type.vizio.buttonTv.state.option.WideMode = Wide Mode
|
||||||
|
channel-type.vizio.buttonTv.state.option.WideToggle = Wide Toggle
|
||||||
|
channel-type.vizio.control.label = Control
|
||||||
|
channel-type.vizio.control.description = Transport Controls e.g. Play/Pause/Next/Previous/FForward/Rewind
|
||||||
|
channel-type.vizio.source.label = Source Input
|
||||||
|
channel-type.vizio.source.description = Select the Source Input for the TV
|
||||||
|
|
||||||
|
# message strings
|
||||||
|
|
||||||
|
offline.configuration-error-hostname = Host Name must be specified
|
||||||
|
offline.configuration-error-authtoken = Auth Token must be specified, see documentation for details
|
||||||
|
offline.configuration-error-applist = Invalid App List Configuration in thing configuration
|
||||||
|
offline.communication-error-get-power = Unable to retrieve power mode info from TV
|
||||||
|
offline.communication-error-get-audio = Unable to retrieve current audio settings from TV
|
||||||
|
offline.communication-error-get-input = Unable to retrieve current input from TV
|
||||||
|
offline.communication-error-get-app = Unable to retrieve current running app from TV
|
||||||
|
offline.communication-error-set-power = Unable to send power command to the TV
|
||||||
|
offline.communication-error-set-volume = Unable to set volume on the TV
|
||||||
|
offline.communication-error-set-mute = Unable to send mute command to the TV
|
||||||
|
offline.communication-error-set-source = Unable to set current source on the TV
|
||||||
|
offline.communication-error-launch-app = Unable to launch app on the TV
|
||||||
|
offline.communication-error-send-cmd = Unable to send control command to the TV
|
||||||
|
offline.communication-error-send-key = Unable to send keypress to the TV
|
@ -0,0 +1,117 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<thing:thing-descriptions bindingId="vizio"
|
||||||
|
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">
|
||||||
|
|
||||||
|
<!-- Vizio TV Thing -->
|
||||||
|
<thing-type id="vizio_tv">
|
||||||
|
<label>Vizio TV</label>
|
||||||
|
<description>
|
||||||
|
A Vizio SmartCast TV
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<channels>
|
||||||
|
<channel id="power" typeId="system.power"/>
|
||||||
|
<channel id="volume" typeId="system.volume"/>
|
||||||
|
<channel id="mute" typeId="system.mute"/>
|
||||||
|
<channel id="source" typeId="source"/>
|
||||||
|
<channel id="activeApp" typeId="activeApp"/>
|
||||||
|
<channel id="control" typeId="control"/>
|
||||||
|
<channel id="button" typeId="buttonTv"/>
|
||||||
|
</channels>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<property name="modelId">unknown</property>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<representation-property>uuid</representation-property>
|
||||||
|
|
||||||
|
<config-description>
|
||||||
|
<parameter name="hostName" type="text" required="true">
|
||||||
|
<context>network-address</context>
|
||||||
|
<label>Host Name/IP Address</label>
|
||||||
|
<description>Host Name or IP Address of the Vizio TV</description>
|
||||||
|
</parameter>
|
||||||
|
<parameter name="port" type="integer" min="1" max="65535" required="true">
|
||||||
|
<label>Port</label>
|
||||||
|
<description>Port for the Vizio TV</description>
|
||||||
|
<default>7345</default>
|
||||||
|
<limitToOptions>true</limitToOptions>
|
||||||
|
<options>
|
||||||
|
<option value="7345">7345 (Newer Models)</option>
|
||||||
|
<option value="9000">9000 (Older Models)</option>
|
||||||
|
</options>
|
||||||
|
</parameter>
|
||||||
|
<parameter name="authToken" type="text" required="false">
|
||||||
|
<label>Auth Token</label>
|
||||||
|
<description>Auth Token that is obtained via the pairing process; See documentation for details</description>
|
||||||
|
</parameter>
|
||||||
|
<parameter name="appListJson" type="text" required="false">
|
||||||
|
<context>script</context>
|
||||||
|
<label>App List Configuration</label>
|
||||||
|
<description>The JSON configuration string for the list of apps available in the activeApp channel drop down</description>
|
||||||
|
</parameter>
|
||||||
|
</config-description>
|
||||||
|
</thing-type>
|
||||||
|
|
||||||
|
<channel-type id="source">
|
||||||
|
<item-type>String</item-type>
|
||||||
|
<label>Source Input</label>
|
||||||
|
<description>Select the Source Input for the TV</description>
|
||||||
|
</channel-type>
|
||||||
|
|
||||||
|
<channel-type id="activeApp">
|
||||||
|
<item-type>String</item-type>
|
||||||
|
<label>Active App</label>
|
||||||
|
<description>The currently running App on the TV</description>
|
||||||
|
</channel-type>
|
||||||
|
|
||||||
|
<channel-type id="control">
|
||||||
|
<item-type>Player</item-type>
|
||||||
|
<label>Control</label>
|
||||||
|
<description>Transport Controls e.g. Play/Pause/Next/Previous/FForward/Rewind</description>
|
||||||
|
<category>Player</category>
|
||||||
|
</channel-type>
|
||||||
|
|
||||||
|
<channel-type id="buttonTv">
|
||||||
|
<item-type>String</item-type>
|
||||||
|
<label>Remote Button</label>
|
||||||
|
<description>A Remote Button press to send to the TV</description>
|
||||||
|
<state>
|
||||||
|
<options>
|
||||||
|
<option value="PowerOn">Power On</option>
|
||||||
|
<option value="PowerOff">Power Off</option>
|
||||||
|
<option value="PowerToggle">Power Toggle</option>
|
||||||
|
<option value="VolumeUp">Volume Up</option>
|
||||||
|
<option value="VolumeDown">Volume Down</option>
|
||||||
|
<option value="MuteOn">Mute On</option>
|
||||||
|
<option value="MuteOff">Mute Off</option>
|
||||||
|
<option value="MuteToggle">Mute Toggle</option>
|
||||||
|
<option value="ChannelUp">Channel Up</option>
|
||||||
|
<option value="ChannelDown">Channel Down</option>
|
||||||
|
<option value="PreviousCh">Previous Channel</option>
|
||||||
|
<option value="InputToggle">Input Toggle</option>
|
||||||
|
<option value="SeekFwd">Seek Fwd</option>
|
||||||
|
<option value="SeekBack">Seek Back</option>
|
||||||
|
<option value="Play">Play</option>
|
||||||
|
<option value="Pause">Pause</option>
|
||||||
|
<option value="Up">Up</option>
|
||||||
|
<option value="Down">Down</option>
|
||||||
|
<option value="Left">Left</option>
|
||||||
|
<option value="Right">Right</option>
|
||||||
|
<option value="Ok">Ok</option>
|
||||||
|
<option value="Back">Back</option>
|
||||||
|
<option value="Info">Info</option>
|
||||||
|
<option value="Menu">Menu</option>
|
||||||
|
<option value="Home">Home</option>
|
||||||
|
<option value="Exit">Exit</option>
|
||||||
|
<option value="Smartcast">Smartcast</option>
|
||||||
|
<option value="ccToggle">CC Toggle</option>
|
||||||
|
<option value="PictureMode">Picture Mode</option>
|
||||||
|
<option value="WideMode">Wide Mode</option>
|
||||||
|
<option value="WideToggle">Wide Toggle</option>
|
||||||
|
</options>
|
||||||
|
</state>
|
||||||
|
</channel-type>
|
||||||
|
</thing:thing-descriptions>
|
@ -0,0 +1,228 @@
|
|||||||
|
{
|
||||||
|
"Apps": [
|
||||||
|
{
|
||||||
|
"name": "SmartCast Home",
|
||||||
|
"config": {
|
||||||
|
"APP_ID": "1",
|
||||||
|
"NAME_SPACE": 4,
|
||||||
|
"MESSAGE": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Apple TV+",
|
||||||
|
"config": {
|
||||||
|
"APP_ID": "4",
|
||||||
|
"NAME_SPACE": 3,
|
||||||
|
"MESSAGE": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "CBS News",
|
||||||
|
"config": {
|
||||||
|
"APP_ID": "42",
|
||||||
|
"NAME_SPACE": 4,
|
||||||
|
"MESSAGE": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Crackle",
|
||||||
|
"config": {
|
||||||
|
"APP_ID": "5",
|
||||||
|
"NAME_SPACE": 4,
|
||||||
|
"MESSAGE": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "discovery+",
|
||||||
|
"config": {
|
||||||
|
"APP_ID": "130",
|
||||||
|
"NAME_SPACE": 4,
|
||||||
|
"MESSAGE": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Disney+",
|
||||||
|
"config": {
|
||||||
|
"APP_ID": "75",
|
||||||
|
"NAME_SPACE": 4,
|
||||||
|
"MESSAGE": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "FilmRise",
|
||||||
|
"config": {
|
||||||
|
"APP_ID": "24",
|
||||||
|
"NAME_SPACE": 4,
|
||||||
|
"MESSAGE": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Haystack News",
|
||||||
|
"config": {
|
||||||
|
"APP_ID": "60",
|
||||||
|
"NAME_SPACE": 4,
|
||||||
|
"MESSAGE": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "HBO Max",
|
||||||
|
"config": {
|
||||||
|
"APP_ID": "128",
|
||||||
|
"NAME_SPACE": 4,
|
||||||
|
"MESSAGE": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Hulu",
|
||||||
|
"config": {
|
||||||
|
"APP_ID": "3",
|
||||||
|
"NAME_SPACE": 4,
|
||||||
|
"MESSAGE": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "iHeartRadio",
|
||||||
|
"config": {
|
||||||
|
"APP_ID": "6",
|
||||||
|
"NAME_SPACE": 4,
|
||||||
|
"MESSAGE": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Movies Anywhere",
|
||||||
|
"config": {
|
||||||
|
"APP_ID": "38",
|
||||||
|
"NAME_SPACE": 4,
|
||||||
|
"MESSAGE": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "NBC",
|
||||||
|
"config": {
|
||||||
|
"APP_ID": "10",
|
||||||
|
"NAME_SPACE": 4,
|
||||||
|
"MESSAGE": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Netflix",
|
||||||
|
"config": {
|
||||||
|
"APP_ID": "1",
|
||||||
|
"NAME_SPACE": 3,
|
||||||
|
"MESSAGE": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Newsy",
|
||||||
|
"config": {
|
||||||
|
"APP_ID": "15",
|
||||||
|
"NAME_SPACE": 4,
|
||||||
|
"MESSAGE": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Paramount+",
|
||||||
|
"config": {
|
||||||
|
"APP_ID": "37",
|
||||||
|
"NAME_SPACE": 4,
|
||||||
|
"MESSAGE": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Peacock",
|
||||||
|
"config": {
|
||||||
|
"APP_ID": "88",
|
||||||
|
"NAME_SPACE": 4,
|
||||||
|
"MESSAGE": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Plex",
|
||||||
|
"config": {
|
||||||
|
"APP_ID": "9",
|
||||||
|
"NAME_SPACE": 4,
|
||||||
|
"MESSAGE": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Pluto TV",
|
||||||
|
"config": {
|
||||||
|
"APP_ID": "E6F74C01",
|
||||||
|
"NAME_SPACE": 0,
|
||||||
|
"MESSAGE": "{\"CAST_NAMESPACE\": \"urn:x-cast:tv.pluto\",\"CAST_MESSAGE\": {\"command\": \"initializePlayback\",\"channel\": \"\",\"episode\": \"\",\"time\": 0}}"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Prime Video",
|
||||||
|
"config": {
|
||||||
|
"APP_ID": "3",
|
||||||
|
"NAME_SPACE": 3,
|
||||||
|
"MESSAGE": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Redbox",
|
||||||
|
"config": {
|
||||||
|
"APP_ID": "41",
|
||||||
|
"NAME_SPACE": 4,
|
||||||
|
"MESSAGE": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Starz",
|
||||||
|
"config": {
|
||||||
|
"APP_ID": "151",
|
||||||
|
"NAME_SPACE": 4,
|
||||||
|
"MESSAGE": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Vudu",
|
||||||
|
"config": {
|
||||||
|
"APP_ID": "31",
|
||||||
|
"NAME_SPACE": 4,
|
||||||
|
"MESSAGE": "https://my.vudu.com/castReceiver/index.html?launch-source=app-icon"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "XUMO",
|
||||||
|
"config": {
|
||||||
|
"APP_ID": "62",
|
||||||
|
"NAME_SPACE": 4,
|
||||||
|
"MESSAGE": "{\"CAST_NAMESPACE\": \"urn:x-cast:com.google.cast.media\",\"CAST_MESSAGE\": {\"type\": \"LOAD\",\"media\": {},\"autoplay\": true,\"currentTime\": 0,\"customData\": {}}}"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "YouTube",
|
||||||
|
"config": {
|
||||||
|
"APP_ID": "1",
|
||||||
|
"NAME_SPACE": 5,
|
||||||
|
"MESSAGE": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "YouTubeTV",
|
||||||
|
"config": {
|
||||||
|
"APP_ID": "3",
|
||||||
|
"NAME_SPACE": 5,
|
||||||
|
"MESSAGE": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "WatchFree Plus",
|
||||||
|
"config": {
|
||||||
|
"APP_ID": "3014",
|
||||||
|
"NAME_SPACE": 4,
|
||||||
|
"MESSAGE": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "WatchFree+ AVOD",
|
||||||
|
"config": {
|
||||||
|
"APP_ID": "145",
|
||||||
|
"NAME_SPACE": 4,
|
||||||
|
"MESSAGE": null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@ -390,6 +390,7 @@
|
|||||||
<module>org.openhab.binding.vesync</module>
|
<module>org.openhab.binding.vesync</module>
|
||||||
<module>org.openhab.binding.vigicrues</module>
|
<module>org.openhab.binding.vigicrues</module>
|
||||||
<module>org.openhab.binding.vitotronic</module>
|
<module>org.openhab.binding.vitotronic</module>
|
||||||
|
<module>org.openhab.binding.vizio</module>
|
||||||
<module>org.openhab.binding.volvooncall</module>
|
<module>org.openhab.binding.volvooncall</module>
|
||||||
<module>org.openhab.binding.warmup</module>
|
<module>org.openhab.binding.warmup</module>
|
||||||
<module>org.openhab.binding.weathercompany</module>
|
<module>org.openhab.binding.weathercompany</module>
|
||||||
|
Loading…
Reference in New Issue
Block a user