Help with json conversion

Posted on
Tue Feb 25, 2020 11:01 am
lvrouter offline
Posts: 18
Joined: Apr 17, 2016

Help with json conversion

I have to admit, up front, I'm a complete Python novice, almost no experience, old-school programmer. Maybe someone can push this old man in the right direction.

I have a script, as follows:

Code: Select all
import requests
import datetime
import json
url = 'http://10.0.1.96/index.php/pages/main/gaugeValues/2162'
indigo.server.log("Test Script Executed")
reply = requests.get(url, timeout=1.0)
indigo.server.log(reply.content)

result = json.loads(reply.text)
for item in result[0]:
   indigo.server.log(item)


Output to the log is:
Script Test Script Executed
Script [{"chanId":"","maxWatt":10161.8,"currWatt":1690,"minWatt":24,"unit":"W","netWatts":0,"tmpWatt":0}]
Script netWatts
Script chanId
Script currWatt
Script tmpWatt
Script maxWatt
Script unit
Script minWatt

What I want is the value of the item, not the item description, i.e. What is the value following "currWatt"? Probably real easy but I don't know how to do it.

Thank you.

Posted on
Tue Feb 25, 2020 11:12 am
FlyingDiver online
User avatar
Posts: 7217
Joined: Jun 07, 2014
Location: Southwest Florida, USA

Re: Help with json conversion

"for item in someDict" returns the keys of the dict, not the values. Try:

Code: Select all
import requests
import datetime
import json
url = 'http://10.0.1.96/index.php/pages/main/gaugeValues/2162'
indigo.server.log("Test Script Executed")
reply = requests.get(url, timeout=1.0)
indigo.server.log(reply.content)

result = json.loads(reply.text)
for key, value in result[0].iteritems():
   indigo.server.log("{} -> {}".format(key, value))


or
Code: Select all
result = json.loads(reply.text)
for key in result[0]:
   indigo.server.log("{} -> {}".format(key, result[0][key]))

joe (aka FlyingDiver)
my plugins: http://forums.indigodomo.com/viewforum.php?f=177

Posted on
Tue Feb 25, 2020 1:00 pm
lvrouter offline
Posts: 18
Joined: Apr 17, 2016

Re: Help with json conversion

Thank you so much!

First option didn't display values but the second option works perfectly.

Posted on
Tue Feb 25, 2020 1:19 pm
lvrouter offline
Posts: 18
Joined: Apr 17, 2016

Re: Help with json conversion

This code works and display, in the log, the key and the value:

Code: Select all
result = json.loads(reply.text)
for key in result[0]:
   indigo.server.log("{} -> {}".format(key, result[0][key]))


How do I assign a value of a specific key to an Indigo variable?

As I said in my post, a complete novice, long-time programmer, no python experience (or any other modern language) so these variable constructs completely overwhelm me. However, given an example, I can make things work.

And THANK YOU, in advance.

Posted on
Tue Feb 25, 2020 2:03 pm
FlyingDiver online
User avatar
Posts: 7217
Joined: Jun 07, 2014
Location: Southwest Florida, USA

Re: Help with json conversion

Here's the indigo method you need to call. First argument is the name or (preferred) the ID of the Indigo variable. Second argument is the value to set it to, which is pulled from the result dict.
Code: Select all
        indigo.variable.updateValue("currWatt", result[0]["currWatt"])


There's some really good on-line Python classes out there. Less than 10 hours will get you a good start.

joe (aka FlyingDiver)
my plugins: http://forums.indigodomo.com/viewforum.php?f=177

Posted on
Tue Feb 25, 2020 3:41 pm
jay (support) offline
Site Admin
User avatar
Posts: 18220
Joined: Mar 19, 2008
Location: Austin, Texas

Re: Help with json conversion

Can you post the actual JSON returned by the requests.get() call? I suspect that's going to shed some light on the confusion...

Jay (Indigo Support)
Twitter | Facebook | LinkedIn

Posted on
Tue Feb 25, 2020 3:57 pm
FlyingDiver online
User avatar
Posts: 7217
Joined: Jun 07, 2014
Location: Southwest Florida, USA

Re: Help with json conversion

jay (support) wrote:
Can you post the actual JSON returned by the requests.get() call? I suspect that's going to shed some light on the confusion...


It was buried in the original post:

Code: Select all
 [{"chanId":"","maxWatt":10161.8,"currWatt":1690,"minWatt":24,"unit":"W","netWatts":0,"tmpWatt":0}]

joe (aka FlyingDiver)
my plugins: http://forums.indigodomo.com/viewforum.php?f=177

Posted on
Wed Feb 26, 2020 3:37 am
Umtauscher offline
User avatar
Posts: 566
Joined: Oct 03, 2014
Location: Cologne, Germany

Re: Help with json conversion

Hi lvrouter,

well, this may be a bit off, but have you seen DaveL's GhostXML Plugin?
It does JSON very well.
Cheers
Wilhelm

Posted on
Wed Feb 26, 2020 8:33 am
lvrouter offline
Posts: 18
Joined: Apr 17, 2016

Re: Help with json conversion

When I do this:
Code: Select all
indigo.variable.updateValue("PowerString", reply.text)
It correctly sets the variable to the text returned by the server query (the json string)
Which is;
Code: Select all
[{"chanId":"","maxWatt":10222.3,"currWatt":2756,"minWatt":24,"unit":"W","netWatts":0,"tmpWatt":0}]

When I do this:
Code: Select all
indigo.variable.updateValue("PowerString", result[0]["currWatt"])

I get this error message:

Script Error embedded script: Python argument types in VariableCmds.updateValue(VariableCmds, str, int) did not match C++ signature:
updateValue(_VariableCmds {lvalue}, boost::python::api::object elem, CCString value)
Script Error Exception Traceback (most recent call shown last):

embedded script, line 17, at top level
ArgumentError: Python argument types in VariableCmds.updateValue(VariableCmds, str, int)did not match C++ signature:
updateValue(_VariableCmds {lvalue}, boost::python::api::object elem, CCString value)

Changing the reference to the Python Variable Id as follows:
Code: Select all
indigo.variable.updateValue(indigo.variables[424021792], result[0]['currWatt'])

Generates the exact same error message.

I have used GhostXML on older versions and when I set this up it doesn't return any values or error. It shows as "updated'. No error, just no values and I can't setup a virtual device as a result.

Posted on
Wed Feb 26, 2020 8:43 am
lvrouter offline
Posts: 18
Joined: Apr 17, 2016

Re: Help with json conversion

Well, I made progress. Variable type mismatch, this works:

Code: Select all
indigo.variable.updateValue("PowerString", str(result[0]["currWatt"]))

Posted on
Wed Feb 26, 2020 9:04 am
FlyingDiver online
User avatar
Posts: 7217
Joined: Jun 07, 2014
Location: Southwest Florida, USA

Re: Help with json conversion

My bad, I always forget that Indigo variables have to be strings. But then, I don't use them much.

joe (aka FlyingDiver)
my plugins: http://forums.indigodomo.com/viewforum.php?f=177

Posted on
Wed Feb 26, 2020 9:20 am
jay (support) offline
Site Admin
User avatar
Posts: 18220
Joined: Mar 19, 2008
Location: Austin, Texas

Re: Help with json conversion

FlyingDiver wrote:
It was buried in the original post:

Code: Select all
 [{"chanId":"","maxWatt":10161.8,"currWatt":1690,"minWatt":24,"unit":"W","netWatts":0,"tmpWatt":0}]


Oh, right, I should have seen that.

Note - you really should use variable IDs (or instances) rather than names in all method calls that take an Indigo object (variable, device, etc) since names can change but IDs can't. So:

Code: Select all
indigo.variable.updateValue(424021792, str(result[0]['currWatt']))


is the recommended approach.

I think a brief explanation of the JSON is appropriate. Here it is formatted so it's a little more readable:

Code: Select all
[
  {
    "chanId": "",
    "currWatt": 1690,
    "maxWatt": 10161.8,
    "minWatt": 24,
    "netWatts": 0,
    "tmpWatt": 0,
    "unit": "W"
  }
]


The brackets ([]) are an indication of a list. In this case, there is only one element, which is a dictionary. The dictionary is bounded by braces ({}). Each entry in the dictionary has a key (i.e. "currWatt") followed by a colon followed by the value (i.e. 1690).

So, you can say the "currWatt" value of the first dictionary in the list. Once you convert the JSON into native Python objects:

Code: Select all
import json
result = json.loads(reply.text)
# result is a list
# In your example, it has only 1 object, which is a dictionary
first_dict = result[0]
# first_dict has 7 entries, one being "currWatt"
curr_watt_value = first_dict["currWatt"]
# curr_watt_value is a number - you can tell by looking at the JSON where the value 1690 isn't enclosed in quotes,
# or in Python, use the type() function
print(type(curr_watt_value))

Jay (Indigo Support)
Twitter | Facebook | LinkedIn

Page 1 of 1

Who is online

Users browsing this forum: No registered users and 8 guests