Trying to parse an XML file returned from my ControlByWeb X410

I’m trying to extract the temperature from a Control By Web X410. When you go to the ips, it returns the following XML data:

F 63.5 0 0 0.0 External

I’ve written the following template in the Developer Tools/Template screen based on my research:

rest:

  • resource: “192.186.86.33/state.xml”
    scan_interval: 30
    sensor:
    • name: “Garage Exterior Temperature”
      unit_of_measurement: “°F”
      device_class: temperature
      state_class: measurement
      value_template: >
      {% set temp = value | regex_findall_index(‘([^<]+)’) %}
      {{ temp | float(0) }}

I keep getting the following result: IndexError: list index out of range

I’ve used AI to generate a number of other methods: scrape, command, etc. but no luck. Here’s an example of scrape:

sensor:

  • platform: scrape
    resource: “http://192.168.86.33/state.xml
    name: “Garage Exterior Temperature”
    unique_id: “garage_exterior_temp”
    select: “sensor1”
    json_attributes: - value
    value_template: ‘{{ value }}’
    unit_of_measurement: “°F”
    device_class: temperature
    scan_interval: 60

This generates the error: ‘value’ is undefined

Any ideas? FYI I’ve been a database programmer for 40 years and wrote my own first home automation software 25 years ago, but am new to HA.

Regards, Mark

That does not look like XML. Please use preformatted text for the XML and for the yaml code.

Sorry my original posting did not display the full xml. Here it is:

<datavalues>
  <units>F</units>
  <sensor1>63.5</sensor1>
  <s1Alrm>0</s1Alrm>
  <battery>0</battery>
  <batteryVoltage>0.0</batteryVoltage>
  <powersource>External</powersource>
</datavalues>

Your regex is very lacking. You should test out your template in Developer tools | Template.

You will see that

{{ '<datavalues>
  <units>F</units>
  <sensor1>63.5</sensor1>
  <s1Alrm>0</s1Alrm>
  <battery>0</battery>
  <batteryVoltage>0.0</batteryVoltage>
  <powersource>External</powersource>
</datavalues>' | regex_findall_index('([^<]+)') }}

Outputs

datavalues>

You can test out your regex in webpages like

You are basically saying ignore all characters up to and including the first < then give me the rest of the characters. Since you are not using global or multiline flags in the regex, it stops at the end of the first line.

ETA: Scratch that. I see regex_findall_index does indeed get all matches. But, your regex did not match to get the values.

Agree with Dujith to convert to json

First off all, do not do that. At least not with very strict parameters as it will be wrong most of the time. Its very outdated and makes wrong assumptions.

You will need to get the json path for the temperature
So convert to json then get the path by using these 2 sites:
https://www.freeformatter.com/xml-to-json-converter.html
https://jsonpathfinder.com/

That will give x.sensor1 (replace x with value.json) so no need for the regex stuff

Then use it in a value template:
value_template: "{{ value_json.sensor1 }}" within a REST sensor

I’m shaky with regex but the expresion your using looks like it would catch everyting after the opening <. I gave it a shot, and it may be rough, but this returns 63.5 for me.

{{ ('<datavalues>
      <units>F</units>
      <sensor1>63.5</sensor1>
      <s1Alrm>0</s1Alrm>
      <battery>0</battery>
      <batteryVoltage>0.0</batteryVoltage>
      <powersource>External</powersource>
    </datavalues>')|regex_findall_index('<.*?1>(.*?)<\/.*?>') }}

Here it is. You are not using findall_index correctly.

regex_findall_index(find='>(.+)<', index=1)

Index starts at 0. So your temperature is index=1

HappyCadaver’s works too!

1 Like

Nice, so much cleaner. Your example helped me understand it better and I managed to whittle mine down to regex_findall_index('1>(.+)<').

Right. So, after some reading…
regex_findall returns an array of the finds.
regex_findall_index returns the index of the array you put in the command.

If you get the regex down to only one find, you can leave off the index= as it uses 0.

It uses 0 if you only have 1 group () but you need to be prepared for it to be a list, so eventually you still would need to do value.0 to get the raw value or you end up with ['your_value'].

I finally was able to get data from my remote sensor with some other forum help. So here is the data that displays in the State* field under Developer tools/States for my Entity’s state:

{"datavalues":{"units":"F","sensor1":"58.1","s1Alrm":"0","battery":"0","batteryVoltage":"0.0","powersource":"External"}}

My question now is how do I parse out each piece of data so they’re individually accessible to use as triggers and/or conditions?