apwelsh / hubitat

MIT License
26 stars 12 forks source link

Roku child apps are not launching, although the momentary switch turns on & then off #2

Closed ashokaiyar closed 5 years ago

ashokaiyar commented 5 years ago

This is a continuation of a issue described on "community.hubitat.com". The relevant post is linked to below:

Momentary switches are not turning Roku apps on

TV details are as follows: user-device-name : 40" TCL Roku TV serial-number : 2N005D674148 active-app : Roku vendor-name : TCL device-id : 4KK455674148 screen-size : 40

apwelsh commented 5 years ago

I just ran a test on my TVs and they are all working as expected. Please navigate to the following URL and add the Raw results to this ticket. (Feel free to delete private data)

http://1.2.3.4:8060/query/device-info http://1.2.3.4:8060/query/apps

Replace 1.2.3.4 with the TV’s IP address.

I need to see if you are getting the same type of info as I am.

ashokaiyar commented 5 years ago

As requested:

device-info

<device-info>
<udn>02780005-500a-1049-8064-b88687f9a731</udn>
<serial-number>2N005D674148</serial-number>
<device-id>4KK455674148</device-id>
<advertising-id>346bbce4-09d7-5cfb-ad12-4d8d8f4bcbed</advertising-id>
<vendor-name>TCL</vendor-name>
<model-name>TCL 40FS3800</model-name>
<model-number>5110X</model-number>
<model-region>US</model-region>
<is-tv>true</is-tv>
<is-stick>false</is-stick>
<screen-size>40</screen-size>
<panel-id>25</panel-id>
<tuner-type>ATSC</tuner-type>
<supports-ethernet>false</supports-ethernet>
<wifi-mac>b8:86:87:f9:a7:31</wifi-mac>
<wifi-driver>aardvark</wifi-driver>
<network-type>wifi</network-type>
<network-name>St. Jerome - 2.4NG</network-name>
<friendly-device-name>40" TCL Roku TV</friendly-device-name>
<friendly-model-name>TCL•Roku TV</friendly-model-name>
<default-device-name>TCL•Roku TV - 2N005D674148</default-device-name>
<user-device-name>40" TCL Roku TV</user-device-name>
<build-number>089.00E04148A</build-number>
<software-version>9.0.0</software-version>
<software-build>4148</software-build>
<secure-device>true</secure-device>
<language>en</language>
<country>US</country>
<locale>en_US</locale>
<time-zone-auto>true</time-zone-auto>
<time-zone>US/Central</time-zone>
<time-zone-name>United States/Central</time-zone-name>
<time-zone-tz>America/Chicago</time-zone-tz>
<time-zone-offset>-300</time-zone-offset>
<clock-format>12-hour</clock-format>
<uptime>29471</uptime>
<power-mode>Headless</power-mode>
<supports-suspend>true</supports-suspend>
<supports-find-remote>false</supports-find-remote>
<supports-audio-guide>true</supports-audio-guide>
<supports-rva>true</supports-rva>
<developer-enabled>false</developer-enabled>
<keyed-developer-id/>
<search-enabled>true</search-enabled>
<search-channels-enabled>true</search-channels-enabled>
<voice-search-enabled>true</voice-search-enabled>
<notifications-enabled>true</notifications-enabled>
<notifications-first-use>false</notifications-first-use>
<supports-private-listening>true</supports-private-listening>
<supports-private-listening-dtv>true</supports-private-listening-dtv>
<supports-warm-standby>true</supports-warm-standby>
<headphones-connected>false</headphones-connected>
<supports-ecs-textedit>true</supports-ecs-textedit>
<supports-ecs-microphone>true</supports-ecs-microphone>
<supports-wake-on-wlan>false</supports-wake-on-wlan>
<has-play-on-roku>true</has-play-on-roku>
<has-mobile-screensaver>false</has-mobile-screensaver>
<support-url>tclusa.com/support</support-url>
<grandcentral-version>2.1.22</grandcentral-version>
<trc-version>3.0</trc-version>
<trc-channel-version>2.0.19</trc-channel-version>
<davinci-version>2.0.12</davinci-version>
</device-info>

apps

<apps>
<app id="31012" type="menu" version="1.9.28">FandangoNOW Movies & TV</app>
<app id="tvinput.dtv" type="tvin" version="1.0.0">Antenna TV</app>
<app id="14295" subtype="rsga" type="appl" version="3.9.190423">Acorn TV</app>
<app id="143088" subtype="rsga" type="appl" version="2.17.515">BritBox</app>
<app id="13" subtype="ndka" type="appl" version="10.8.2019040917">Prime Video</app>
<app id="63344" subtype="rsga" type="appl" version="2.12.94">Comedy Central</app>
<app id="27181" subtype="rsga" type="appl" version="4.51.216">Sky News</app>
<app id="27536" subtype="rsga" type="appl" version="4.14.6">CBS News</app>
<app id="30547" subtype="rsga" type="appl" version="2.0.21">WeatherNation</app>
<app id="71845" subtype="rsga" type="appl" version="2.3.3">NewsON</app>
<app id="837" subtype="ndka" type="appl" version="1.0.80000286">YouTube</app>
<app id="2016" subtype="rsga" type="appl" version="6.1.2">Sony Crackle</app>
<app id="2213" subtype="sdka" type="appl" version="4.1.1609">Roku Media Player</app>
<app id="23353" subtype="rsga" type="appl" version="3.1.2">PBS</app>
<app id="151908" subtype="rsga" type="appl" version="2.0.19">The Roku Channel</app>
<app id="74519" subtype="rsga" type="appl" version="3.14.1197">Pluto TV - It's Free TV</app>
<app id="34376" subtype="rsga" type="appl" version="2.6.2019042400">ESPN</app>
<app id="12" subtype="ndka" type="appl" version="4.2.81115035">Netflix</app>
<app id="258944" subtype="rsga" type="appl" version="1.0.32">Watch TCM</app>
<app id="8518" subtype="rsga" type="appl" version="3.3.1">EWTN Global Catholic Network</app>
<app id="204413" subtype="rdpb" type="appl" version="1.30.33">Movies Plus TV</app>
<app id="28" subtype="rsga" type="appl" version="5.3.30">Pandora</app>
</apps>
apwelsh commented 5 years ago

You aren’t by any chance leaving the child device page open while issuing a refresh apps event, are you? Hubitat is fickle when it comes to managing devices that have been deleted and then added back in with the same ID. You have to navigate back out of the child device screen and enter into it from the main device list, or from the parent device. Each new device gets assigned a unique internal ID (like 1224) that is seen on the URL. If you are in an old page then the buttons won’t do anything.

apwelsh commented 5 years ago

All this output is exactly what I would have expected.

ashokaiyar commented 5 years ago

You aren’t by any chance leaving the child device page open while issuing a refresh apps event, are you?

No, I'm not doing that. So this is a mystery. Are any of my settings different from yours?

To add, On/Off and Volume Control with the parent device work perfectly.

apwelsh commented 5 years ago

I will look at the device info closely when I get home. I wonder if there is a setting in the TV that is preventing the activation of applications remotely. Will let you know.

apwelsh commented 5 years ago

Interesting. When you sent me the XML, was the TV powered on? It is reporting that it is in sleep mode in the XML.

I definitely want to get to the bottom of this.

This is a long shot,

  1. Make sure the TV has a an IP address that is reserved in the router, so it never changes
  2. On the Roku, go to Settings, System, Advance system settings, control by mobile apps and set the value to Permissive.

Also, I realized when I got home I have the 43 TCL 4k, not the 40 TCL. We are on the same version of Roku (9.0.0), and everything appears correct.

Do you have access to the CURL command line utility? If so, you can run the following to launch Amazon Prime Video app:

curl -d '' http://1.2.3.4:8060/launch/13

replace 1.2.3.4 with your TV ip address.

This is the Roku API command to launch an app. If your TV will accept this, then this DTH should work, as it does the same exact thing.

But if this works, and the DTH does not, I need to look closer at the code to see if I missed something that affects your TV. I suspect this is not the case, since this works on every Roku system I have tried, include my stand-alone Roku.

apwelsh commented 5 years ago

I updated the parent DTH "Roku TV" to send an empty body (as opposed to the default of no body) to see if this clears up the issue. I also implemented a few changes to ensure the refreshApps event is cleaner, and easier to monitor in the logs. Please update your Roku TV (parent) DTH and try again. When updating, please refresh the browser session after issuing the "refreshApps" event, prior to testing the application activation.

ashokaiyar commented 5 years ago

Do you have access to the CURL command line utility? If so, you can run the following to launch Amazon Prime Video app: curl -d '' http://1.2.3.4:8060/launch/13

This works perfectly. I will update the apps in 20 minutes.

ashokaiyar commented 5 years ago

So, I updated the parent app, and it still doesn't work. But I've addressed your questions below. Very puzzling:

When you sent me the XML, was the TV powered on? It is reporting that it is in sleep mode in the XML.

It was in sleep mode.

Make sure the TV has a an IP address that is reserved in the router, so it never changes

Already had a static address ....

On the Roku, go to Settings, System, Advance system settings, control by mobile apps and set the value to Permissive.

Already set to be permissive. Also, the curl command works from my Macbook.

So I went ahead and deleted the device (Bedroom TV) and re-created it, and all the child device apps (Prime, Netflix etc). Still no go.

ashokaiyar commented 5 years ago

Here's some more information. I used:

curl http://192.168.1.34:8060/query/apps

to retrieve the list of apps. I can launch any of the apps from the command line using the appropriate app id in the POST url that you suggested.

Since I've got a static IP address for the TV, I'm going to create virtual switches and rule machine rules with HTTP POST to launch the apps I need.

And I can use your app to turn on/off, control volume and mute!

ashokaiyar commented 5 years ago

Yup that works just fine. Very puzzling that http post from RM or the command line works, but not from within the app.

Anyway, I have a satisfactory solution for my needs - use the app for on/off/volume and RM to pick Roku apps with virtual momentary switches.

apwelsh commented 5 years ago

Are you in the latest version of Hubitat firmware?

ashokaiyar commented 5 years ago

Yes - I have the latest Hubitat firmware.

I figured out the problem, and have a solution. You’ll have to clean up the solution because the last I coded was 30 years ago, and I know nothing about Groovy. Anyway, here’s the problem with the code:

In roku-app-child.groovy, the appId is recovered using this line: def appId = device.deviceNetworkId.split("-")[1]

And then the parent app is called in the following line to launch the Roku app.

That makes the assumption that there are no other “-“ in the deviceNetworkId. Well, when I add my TVs to Hubitat, the deviceNetworkId has several other “-“ in it. For example, here’s the deviceNetworkId:

a528a3f3-ce28-479e-ba83-c65812f20e6c

So the appId recovered from roku-app-child.groovy is: “ce28-479e-ba83-c65812f20e6c-appId”

Hence, the appId recovered is erroneous, and the app isn’t launched. As I said, I don’t know the least thing about Groovy, so my solution might be wrong. However, it works. Here are the changes that I made this morning - my solution is to separate the appId from the deviceNetworkId using a colon (:) instead of a dash. I made two "diff" files with the changes because diff is what I used 30 years ago while programming in C as a graduate student :-)

roku-tv.diff

--- roku-tv.groovy  2019-06-06 10:48:05.333846764 -0500
+++ roku-tv-new.groovy  2019-06-06 10:25:23.093319024 -0500
@@ -22,7 +22,7 @@
 }

 metadata {
-   definition (name: "Roku TV", namespace: "apwelsh", author: "Armand Welsh") {
+   definition (name: "Roku TV New", namespace: "apwelsh", author: "Armand Welsh") {
        capability "TV"
        capability "AudioVolume"
        capability "Switch"
@@ -82,7 +82,7 @@
        //log.debug "child: ${child.deviceNetworkId} (${child.name})"
        def nodeExists = false
        body.app.each{ node ->
-           if ("${device.deviceNetworkId}-${node.attributes().id}" == child.deviceNetworkId)
+           if ("${device.deviceNetworkId}:${node.attributes().id}" == child.deviceNetworkId)
            nodeExists = true
        }
        if (!nodeExists) {
@@ -321,7 +321,7 @@

 private def getChild(String appId) {

-   def netId = "${device.deviceNetworkId}-${appId}"
+   def netId = "${device.deviceNetworkId}:${appId}"
     try {
        def result = null
         childDevices.each{ child ->
@@ -338,8 +338,8 @@

 private void createChildDevice(String appId, String appName) {
     try {
-       def netId = "${device.deviceNetworkId}-${appId}"
-        addChildDevice("Roku App", "${netId}",
+       def netId = "${device.deviceNetworkId}:${appId}"
+        addChildDevice("Roku App New", "${netId}",
             [label: "${device.displayName}-${appName}", 
              isComponent: false, name: "${appName}"])
        log.trace "Created child device: ${appName} (${netId})"
@@ -347,3 +347,6 @@
         log.error "Failed to create child device with exception: ${e}"
     }
 }
+

roku-app-child.diff

--- roku-app-child.groovy   2019-06-06 10:25:57.610037109 -0500
+++ roku-app-child-new.groovy   2019-06-06 10:24:45.116529558 -0500
@@ -19,7 +19,7 @@
  *-------------------------------------------------------------------------------------------------------------------
  **/
 metadata {
-   definition (name: "Roku App", namespace: "apwelsh", author: "Armand Welsh") {
+   definition (name: "Roku App New", namespace: "apwelsh", author: "Armand Welsh") {
        capability "Momentary"
        capability "Switch"
        capability "Actuator"
@@ -28,7 +28,7 @@

 def on() {
    sendEvent (name: "switch", value:"on")
-   def appId = device.deviceNetworkId.split("-")[1]
+   def appId = device.deviceNetworkId.split(":")[1]
    parent.launchApp(appId)

    runInMillis(3000, 'off')
@@ -45,5 +45,3 @@
 def parse(String description) {
     log.debug "parse(${description}) called"
 }
+
apwelsh commented 5 years ago

Doh! Good catch. I went off the assumption you would use an networkId if the parent app of something like “rokuLivingRoom” rather than the Roku’s GUID based network ID. Rather than change the delimiter (because there will always be conflicts) I will simply take the lay delimiter. A simple regular expression will work. Now that I know the cause, I can simulate it to test for the fix correctly.

ashokaiyar commented 5 years ago

Let me know when you upload the new device drivers, so I can update my installation. Thanks!

apwelsh commented 5 years ago

Please update your parent and child handlers. I made some changes that should fix the issue, but they are completely untested. I will run my full validation tonight when I get home. This is a best effort attempt at a formal fix (offline).

apwelsh commented 5 years ago

So this is frustrating. Hubitat's groovy does not support the Java standard RegEx matcher, so I need to change up my parser logic. I will notify you when I have completed all regression testing.

apwelsh commented 5 years ago

This was an interesting learning experience. Hubitat started auto-assigning network ID values using the GUID/UUID generation algorithm. This has the benefit is always create unique network IDs, but the my DTH was not designed for that. Based on your discovery, I have updated the code, and tested it with the new updated to hubitat. It now works with any parent device network ID, regardless of the existence of hyphens in the name. Thanks for you assistance. The new code has been posted.

apwelsh commented 5 years ago

It is up to date. I also have an experimental DTH that seems to be working as desired. It is in the feature-switch branch. Either one will work, but the switch one is what I had originally envisioned for this. When an app is running, that app is in the ON state. When an app is turned off, the TV returns to the Home Screen. This version has minimal network chatter, and improved response times. Only one app can be on at any given time with this other version, so turning on Hulu will turn off NetFlix (if that was the running app). This makes for some cool effects. Like, you can have a mood light that changes color based on the active application .

ashokaiyar commented 5 years ago

Nice!