nebulous / infinitude

Open control of Carrier/Bryant thermostats
MIT License
225 stars 50 forks source link

Trying to ingest JSON status api into Telegraf #167

Closed mattster98 closed 1 year ago

mattster98 commented 1 year ago

Apologies for going incommunicado in #56 - that's where this started. I've come back around to this and here's what I'm hoping to do:

Telegraf has an http input which will call the status api which returns a nice JSON response. Telegraf parses this but ignores strings, which every response in the status API is, even the numbers.

While there appears to be hoops you can jump through to get the string numbers into Telegraf, those numbers would best just be numbers without the quotes in the json itself. I haven't been able to get Telegraf to ingest anything from the status api.

I'm not sure the best solution for this. I'm hoping there's a way to get Infinitude to output the numeric values (specifically rh, rt) without the quotes. A list of fields that should be presented without them in the config json seems like a reasonable solution without the software having to figure it out on its own.

mattster98 commented 1 year ago

Working on getting Telegraf to take the data as-is, it was also explained to me that the json values are all arrays.. so that further complicates things unnecessarily. Certainly arrays make sense for some of the values, but every value being inside a single-entity array seems unhelpful.

nebulous commented 1 year ago

You're right that the infinitude json is structured in a way that's not particularly ergonomic to human use, but it is structured this way with intent - not unnecessarily. The thermostat deals exclusively in xml and xml sucks to work with, especially in javascript. So infinitude translates the thermostat's xml into a json structure which can unambiguously be translated back into xml.

However(and actually due to your request in 2018), the api will attempt to dereference single value arrays and also return numeric values if the number appears numeric. So, to get rh for zone 3 for example: GET /api/status/3/rh

When looking into this again for this ticket I noticed a bug with that endpoint when using zone 0 though, a fix for which was just pushed.

mattster98 commented 1 year ago

Is there documentation about getting specific values like that? I know there's a good bit of documentation about pushing to the API (/config), but less about pulling. I forget where I first saw the /status api, (maybe from reading the code :) ) and I knew you could add a zone number after /status but I didn't notice the ability to request individual values like that. I appreciate the response and will take a look at the change you pushed.

With help from the Telegraf community, I was able to get the data ingested. Pasting here for posterity if anyone finds themselves in a similar situation because traversing those single-node JSON arrays in Telegraf is pretty tedious.

      [[inputs.http]]
        name_override = "HVAC_Upstairs"
          urls = [
            "http://XX.XX.XX.XX:3000/api/status"
          ]
        method = "GET"
        data_format = "json"
        timeout = "5s"
        tag_keys = ["name"]
        json_string_fields = ["zones_0_zone_0_rh_0","zones_0_zone_0_rt_0","oat_0","mode_0"]

      [[processors.converter]]
        order = 1
        [processors.converter.fields]
          float = ["zones_0_zone_0_rh_0","zones_0_zone_0_rt_0","idu_0_cfm_0","oat_0"]

      [[processors.enum]]
        order = 2
        [[processors.enum.mapping]]
          field = "mode_0"
          dest = "Mode"
          default = -1
          [processors.enum.mapping.value_mappings]
            off = 0
            cool = 1
            heat = 2

      [[processors.rename]]
        order = 3
        [[processors.rename.replace]]
          field = "zones_0_zone_0_rh_0"
          dest = "Inside_Humidity"

        [[processors.rename.replace]]
          field = "zones_0_zone_0_rt_0"
          dest = "Inside_Temp"

        [[processors.rename.replace]]
          field = "idu_0_cfm_0"
          dest = "Fan_CFM"

        [[processors.rename.replace]]
          field = "oat_0"
          dest = "Outside_Temp"
mattster98 commented 1 year ago

I made a Status API page on the wiki with what I know at this point. Will close this one out.