Need some help with XMLSlurper

I’m working on connecting my new Holmes WeMo Humidifier to SmartThings and I’m running into some issues parsing the information it’s sending me. I’m building on code from @kevintierney that uses XMLSlurper to parse the messages from the device. Here’s my code at the moment:

    def bodyString = new String(map.body.decodeBase64())
    def body = new XmlSlurper().parseText(bodyString)
    log.debug("map.body: ${map.body}")
    log.debug("map.body.decodeBase64(): ${map.body.decodeBase64()}")
    log.debug("bodyString: ${bodyString}")
    log.debug("body: ${body}")
    log.debug("body.text(): ${body.text()}")

    if(body.attribute.value) {
        def filterLife = body.attribute.value.text()
        log.trace "FILTER LIFE: ${filterLife}"
    }

And here’s what I see in the Live Logging page:

5ad3b428-6778-4358-b2cd-7d735e179115 6:08:58 PM: trace FILTER LIFE:
5ad3b428-6778-4358-b2cd-7d735e179115 6:08:58 PM: debug body.text(): FilterLife59204592051423350534
5ad3b428-6778-4358-b2cd-7d735e179115 6:08:58 PM: debug body: FilterLife59204592051423350534
5ad3b428-6778-4358-b2cd-7d735e179115 6:08:58 PM: debug bodyString: 

<attribute><name>FilterLife</name><value>59204</value><prevalue>59205</prevalue><ts>1423350534</ts></attribute>



5ad3b428-6778-4358-b2cd-7d735e179115 6:08:58 PM: debug map.body.decodeBase64(): [60, 101, 58, 112, 114, 111, 112, 101, 114, 116, 121, 115, 101, 116, 32, 120, 109, 108, 110, 115, 58, 101, 61, 34, 117, 114, 110, 58, 115, 99, 104, 101, 109, 97, 115, 45, 117, 112, 110, 112, 45, 111, 114, 103, 58, 101, 118, 101, 110, 116, 45, 49, 45, 48, 34, 62, 10, 60, 101, 58, 112, 114, 111, 112, 101, 114, 116, 121, 62, 10, 60, 97, 116, 116, 114, 105, 98, 117, 116, 101, 76, 105, 115, 116, 62, 38, 108, 116, 59, 97, 116, 116, 114, 105, 98, 117, 116, 101, 38, 103, 116, 59, 38, 108, 116, 59, 110, 97, 109, 101, 38, 103, 116, 59, 70, 105, 108, 116, 101, 114, 76, 105, 102, 101, 38, 108, 116, 59, 47, 110, 97, 109, 101, 38, 103, 116, 59, 38, 108, 116, 59, 118, 97, 108, 117, 101, 38, 103, 116, 59, 53, 57, 50, 48, 52, 38, 108, 116, 59, 47, 118, 97, 108, 117, 101, 38, 103, 116, 59, 38, 108, 116, 59, 112, 114, 101, 118, 97, 108, 117, 101, 38, 103, 116, 59, 53, 57, 50, 48, 53, 38, 108, 116, 59, 47, 112, 114, 101, 118, 97, 108, 117, 101, 38, 103, 116, 59, 38, 108, 116, 59, 116, 115, 38, 103, 116, 59, 49, 52, 50, 51, 51, 53, 48, 53, 51, 52, 38, 108, 116, 59, 47, 116, 115, 38, 103, 116, 59, 38, 108, 116, 59, 47, 97, 116, 116, 114, 105, 98, 117, 116, 101, 38, 103, 116, 59, 60, 47, 97, 116, 116, 114, 105, 98, 117, 116, 101, 76, 105, 115, 116, 62, 10, 60, 47, 101, 58, 112, 114, 111, 112, 101, 114, 116, 121, 62, 10, 60, 47, 101, 58, 112, 114, 111, 112, 101, 114, 116, 121, 115, 101, 116, 62, 10, 10, 13]
5ad3b428-6778-4358-b2cd-7d735e179115 6:08:58 PM: debug map.body: PGU6cHJvcGVydHlzZXQgeG1sbnM6ZT0idXJuOnNjaGVtYXMtdXBucC1vcmc6ZXZlbnQtMS0wIj4KPGU6cHJvcGVydHk+CjxhdHRyaWJ1dGVMaXN0PiZsdDthdHRyaWJ1dGUmZ3Q7Jmx0O25hbWUmZ3Q7RmlsdGVyTGlmZSZsdDsvbmFtZSZndDsmbHQ7dmFsdWUmZ3Q7NTkyMDQmbHQ7L3ZhbHVlJmd0OyZsdDtwcmV2YWx1ZSZndDs1OTIwNSZsdDsvcHJldmFsdWUmZ3Q7Jmx0O3RzJmd0OzE0MjMzNTA1MzQmbHQ7L3RzJmd0OyZsdDsvYXR0cmlidXRlJmd0OzwvYXR0cmlidXRlTGlzdD4KPC9lOnByb3BlcnR5Pgo8L2U6cHJvcGVydHlzZXQ+CgoN

Now, my question. I’m not using the safe navigation operator (?.) in the if() clause, so that must mean that node exists, right? If so, why isn’t filterText populated?

Thanks in advance for the extra eyes on this!

In your poll function, what is you “getXState” command. The cockpot was GetCrockpotState.

Replace cockpotstatè with your method and cookedTime with filterlife

body?.Body?.GetCrockpotStateResponse?.cookedTime?.text()

Are “GetCrockpotState” and “cookedTime” arbitrary, or are those keywords you had to get from the device somehow?

The filter life messages seem to be getting sent to ST once a minute without having to poll, as far as I can tell.

Your response is a little different then mine. I got both of those parameters from eventservice.xml on the crockpot.

When I call GetCrockpotState I get this

<u:GetCrockpotStateResponse xmlns:u="urn:Belkin:service:basicevent:1">
<mode>0</mode>
<time>0</time>
<cookedTime>0</cookedTime>
</u:GetCrockpotStateResponse>

Looking at this post on SO game me an idea

Try

  def body = new XmlSlurper().parseText(bodyString)
    
body.attribute.find {it.name == "Filter Life"}.value.text()
1 Like