Groovy Access to Dashboard JSON

Thanks @thebearmay, I'll mess about with this for a bit. Much appreciated.

2 Likes

Have you looked at Hubivue? www.hubivue.com. It may be easier formatting across devices

Hey @rlighgow1, more looking for the quickly copy the format across several dashboards than working across devices. Also trying to up (or better stated 'learn') my Groovy coding game. I will check it out though for other projects.

3 Likes

Thanks @thebearmay , I really appreciate the direction. I've done a lot of coding, but never in Groovy, and not on Hubitat. The pointers are much appreciated. And, sorry for the long post, just trying to be thorough in the example to make it easier to see what I've done.

I've got everything pretty much in line except for the two original issues, reading and writing the JSON. Here's what's going on. Seems the only accessToken that it likes is the dashboard specific token.

On the GET side:

Call Format 1:

uri: "http://127.0.0.1:8080/apps/api/$appId/dashboard/$childId/layout?access_token=$oAuth_accessToken"
        textParser: true,
		headers: [
			Cookie: state.cookie
		]
	  ]

Fail Response: groovyx.net.http.HttpResponseException: status code: 401, reason phrase: Unauthorized

Call Format 2:

"http://127.0.0.1:8080/apps/api/$childId/dashboard/0/layout?access_token=$oAuth_accessToken"

Fail Response: Dashboard token no longer valid! Either token was revoked or access removed.

Call Format 3:

"http://127.0.0.1:8080/apps/api/$childId/dashboard/0/layout?access_token=$dash_accessToken"

Success Response: ( [{"localization":"English","roundedCorners...) returns the JSON

Obviously, I would wish this could be done with the oAuth token and not the dashboard token. Not sure if possible, but I'm stuck here.

On the POST side:

Call Format 1:

        uri: "http://127.0.0.1:8080/apps/api/$id/dashboard/$childId/layout",
        //uri: "http://127.0.0.1:8080/apps/api/$childId/dashboard/0/layout",
        
        headers: [
            //Authorization: "${dash_accessToken}",
            Authorization: "${oAuth_accessToken}",
            requestContentType: 'application/json',
		    contentType: 'application/json',
			"Cookie": cookie,
			body: "$dshJson"
        ]
	]

Response: ( params: hubitat.scheduling.AsyncResponse@1aafc27 data: null )

Regardless of the mix-n-match of the uri and the authorization, the result is always the same (i.e., hubitat.scheduling) and the JSON for the dashboard is never updated.

Will keep messing with it, but am kind of lost.

Good news is, all other functions are coming together nicely!

1 Like

Legacy dashboard token seems to be required for both. In your response method try

log.debug "${resp.properties}"

That should give you a dump of the headers and response codes.

1 Like

That's a shame. i was so close! That pretty much defeats the "make it simple for the user" requirement. I'll research other options.

Thanks all for the help.

If you don't mind scraping the child app page it shouldn't be too difficult to grab it from one of the legacy links on the page.

I was looking into that but not sure the information is actually there (in a meaningful way), or it's above my current knowledge level.

To get the list of dashboards, I'm scraping (regex) the /installedapp/list. This gives me the Dashboard App Id, Dashboard (child) Name and Id, Child App Status URL (/installedapp/status/XX), Child App Config URL (installedapp/configure/XX).

The configure page is where I see the links for the dashboards, and manually hovering over the link does who the URL and the access token. Problem is, I don't see that same information in the HTML. So, to my knowledge (hoping for correction or confirmation), this means it's being loaded by JS directly into the page DOM, and therefore would only be readable the same way?

I guess what I'm saying is, while I can see the access token for the children, getting the HTML content (they way I know how) can't see the access token.

I hope that made sense.

Do your httpGet against the status page instead:

http://127.0.0.1:8080/installedapp/status/$dash_ID

So, it looks like to get the dashboard layout, it's a GET using the "Local LAN" access token.

http://127.0.0.1:8080/apps/api/${dashboardID}/dashboard/0/layout?access_token=${localLANAccessToken}

To write them is a POST using the "Legacy Local LAN" access token.

http://127.0.0.1:8080/apps/api/${mainDashboardAppID/dashboard/${dashboardID}/layout?access_token=${legacyLocalLANAccessToken}

I'm going to start calling the "legacy lan access code" the global code.

So, to get the global code, do a call against the main dashboard app status page and parse it out.
To get the dashboard specific code, do a call against the app status page for the dashboard and parse it out.

I didn't need to set a bearer token for the post operation. Still just used the access token in line of the URI.

EDIT: Maybe not. Just realized that the POST was successful, but nothing changed.

EDIT2: I later realized I had errors in the logs. It didn't like something about the background setting, but it does look like the POST was successful.

1 Like

Thanks a ton. Just reviewed the status page. Packed full of high hopes yet again. Will advise.

2 Likes

I'm seeing the same 'background' error
java.lang.NullPointerException: Cannot get property 'background' on null object on line 332 (method saveLayout)

Unfortunately, mine is not saving. I do get a 200 sucess code, and the response shows me template JSON, but it's the original, not what I changed. Still at it. Not sure if it's the error above or my JSON formatting.

I'm guessing that since the error is happening, the changes as a whole aren't being applied. I saw the same with the response, but I think that's a good sign that it's the right path!

The good news is, this is as close as I've been to success. Still grinding!

In case anyone is still trying to get the dashboard access token, I ran across it when looking for something else:

Dashboard Token
    params = [
            uri : "http://127.0.0.1:8080/hub2/hubData",
            headers: [Accept: "application/json"]
    ]
    httpGet(params) { resp ->
        state.dashAccessToken=resp.data.baseModel.dashboard.accessToken  
    }
3 Likes