Trying to make an Home Assistant plugin

Posted on
Tue Jan 08, 2019 8:43 am
steinis offline
Posts: 80
Joined: Jul 17, 2015
Location: Oslo, NORWAY

Trying to make an Home Assistant plugin

For my own learning I'm trying to make a Home Assistant plugin to Indigo using the REST API.
I am not a programmer so bear with me, but like to learn:)

So far this is what I have and I would like to as a start to be able to make a device.sensor in indigo.

Code: Select all
      
      url = 'http://192.168.0.30:8123/api/states'
      r = requests.get(url, headers={'Authorization': 'Bearer "TOKEN"', 'content-type': 'application/json'})


      states = json.loads(r.content)
      self.logger.info("Print content:\n%s" % (states))



This is returning something like this:
[{u'entity_id': u'sensor.bad_taklys_kwh',
u'last_updated': u'2019-01-08T13:52:12.761034+00:00',
u'last_changed': u'2019-01-08T13:52:12.761034+00:00',
u'state': u'307.64',
u'context': {u'user_id': None, u'id': u'88ff02b8a17f4676b9a9fee4895de41d'},
u'attributes': {u'unit_of_measurement': u'Kwh', u'friendly_name': u'Bad taklys Kwh'}},
..........

So for each device I have following attributes: entity_id, state, last_changed and attributes.

My first question is how can I make alle "entity_id" that is starting with "sensor." available to add it as a sensor device in indigo?

Posted on
Tue Jan 08, 2019 10:09 am
jay (support) offline
Site Admin
User avatar
Posts: 15377
Joined: Mar 19, 2008
Location: Austin, Texas

Re: Trying to make an Home Assistant plugin

I don't understand the question - can you be more specific?

Jay (Indigo Support)
Twitter | Facebook | LinkedIn

Posted on
Tue Jan 08, 2019 10:50 am
steinis offline
Posts: 80
Joined: Jul 17, 2015
Location: Oslo, NORWAY

Re: Trying to make an Home Assistant plugin

I try:)

My goal is to make this plugin look for devices in Home Assistant and add them to Indigo.

The respond from JSON for the example above list every state for every device(sensor, light, switch etc.) in Home Assistant.

So for a start I would like to try to include a sensor value to Indigo., like you do with the Hue plugin. But the JSON response those not have any way to see if the state is from a light or a sensor without looking at the entity_id. I think I need to extract 'sensor' from entity_id.

After I would have list of sensor.devices that I can add to indigo to show the state, but how do I map this list to Indigo when creating a new device in Indigo.

Sorry if explained badly. I have looked at the HUE plugin, but for a beginner its complicated to understand.

Link to Home Assistant API: https://developers.home-assistant.io/docs/en/external_api_rest.html

Posted on
Tue Jan 08, 2019 1:47 pm
jay (support) offline
Site Admin
User avatar
Posts: 15377
Joined: Mar 19, 2008
Location: Austin, Texas

Re: Trying to make an Home Assistant plugin

To successfully develop a plugin, you're going to need to figure out several pieces (assuming you already know Python):

  • Gain a basic understanding of the IOM - start with the Plugin Developer's Guide then move on to the IOM Reference Guide.
  • Check out the SDK for example plugins for each of the device types Indigo supports. These might be a bit easier to digest as a starting point than the Hue plugin.
  • Your example script has the JSON reply converted to a Python list, so you'd need to cycle through that list looking at the "entity_id" to get the type. That is, however, not really the big challenge. Rather, how you design when and where in the plugin you perform the query to ha, what you do with the data, and how you keep them in sync. So, basically, how will the data flow in the plugin (including between ha and the plugin). At this point, you can look further at plugins like the Hue plugin or the Vera plugin (it might be somewhat simpler than the Hue plugin because it doesn't do as much).

I highly recommend that you do the first two before proceeding any further - I guarantee that you'll have a better experience (and be more successful) if you do.

Here's a specific example of doing what you're asking in the third one above:

Code: Select all
     
url = 'http://192.168.0.30:8123/api/states'
 r = requests.get(url, headers={'Authorization': 'Bearer "TOKEN"', 'content-type': 'application/json'})
ha_devices = r.json()
self.logger.info("Print content:\n{}".format(ha_devices)
for dev_dict in ha_devices:
    # Assuming that all entity_id values are of the form type.name, you can split those up into individual elements:
    type, dev_name = dev_dict[u"entity_id"].split(u'.', maxsplit=1)
    # now you have the type, you can create the device. I would caution against auto creating devices however
    # for a variety of reasons - instead I think I'd just ask for all devices, generate a list of each type, then when
    # the user creates a sensor device, show a popup list of all the possible sensor devices available.

Jay (Indigo Support)
Twitter | Facebook | LinkedIn

Posted on
Tue Jan 08, 2019 2:22 pm
steinis offline
Posts: 80
Joined: Jul 17, 2015
Location: Oslo, NORWAY

Re: Trying to make an Home Assistant plugin

Thanks for the detailed answer!

I will have a look at the examples and read the plugin documentation some more:)

Posted on
Tue Jan 08, 2019 3:28 pm
roussell offline
User avatar
Posts: 1094
Joined: Aug 18, 2008
Location: Alabama

Re: Trying to make an Home Assistant plugin

I’d urge you to consider the Greensky MQTT plugin for Indigo. Almost everything in Home Assistant can be reached via MQTT and the plugin already makes considerable progress toward exposing Indigo objects as MQTT topics.

The plugin needs some work but is pretty robust as it stands. Once I have the time I plan to contribute to its development and it might be worthwhile for you to see if extending it can fit your needs as well. (Probably easier than developing your own to start) I have a few issues to open for the plugin in github, just trying to get work sorted here at the start of the year and will then dive in.

Currently I’ve noticed that if the MQTT server restarts, the plugin will not reconnect without restarting it, the Indigo topics aren’t easily matched with HA topics, and some Indigo devices don’t update as one might expect (thermostats being a good example). Some of that could be solved with additional documentation, some of it will require code changes. Specifically for HA integration in Indigo, I would think a device/config area specifically to it would be cool. One of the things I’m looking at Tasmota device integration.

Terry


Sent from my iPhone using Tapatalk

Posted on
Tue Jan 08, 2019 3:45 pm
steinis offline
Posts: 80
Joined: Jul 17, 2015
Location: Oslo, NORWAY

Re: Trying to make an Home Assistant plugin

I'm currently using the Greensky MQTT, but as you said it needs some work. But for sure its a good plugin that works fine.

The problem with Home Assistant is that you need to restart it when you add devices etc. and since Greensky MQTT dosent support the retain option the lights dosent work from HA until the status change in indigo.
I would love a function to push all status with an action in Indigo after HA is restarting.
I have solved this solution with a paho-mqtt script but its a big job to set everything up and running with a lot of code and easy to misspell something.


Im doing this HA plugin a lot for my ovn learning BTW:)

Posted on
Mon Jan 14, 2019 11:33 am
steinis offline
Posts: 80
Joined: Jul 17, 2015
Location: Oslo, NORWAY

Re: Trying to make an Home Assistant plugin

I have finally managed to add binary sensor from HA to Indigo:)

Next step is to add relay devices. I think I have it, but struggle to find out how to implement a variable in following code line:


data='{"entity_id": "%s"}'

where %s = dev.address.
Since there are singel quotes(') and { }, I'm unsure how to handle this?

Posted on
Mon Jan 14, 2019 5:39 pm
jay (support) offline
Site Admin
User avatar
Posts: 15377
Joined: Mar 19, 2008
Location: Austin, Texas

Re: Trying to make an Home Assistant plugin

Am I missing something here:

Code: Select all
data='{"entity_id": dev.address}'


[EDIT] duh, cold is affecting my brain. I'm not sure what you're asking here either now that I look at what you typed:

Code: Select all
data='{"entity_id": "%s"}'


What are you trying to do with %s in this example? If you are trying to construct json, there are much better ways...

Jay (Indigo Support)
Twitter | Facebook | LinkedIn

Posted on
Tue Jan 15, 2019 1:38 am
steinis offline
Posts: 80
Joined: Jul 17, 2015
Location: Oslo, NORWAY

Re: Trying to make an Home Assistant plugin

Sorry, a little more context is always good:)

Here is my code for turning on switch in Home Assistant.

Code: Select all
      ###HA switch###
      if dev.deviceTypeId == u"HAswitchType":
         ###### TURN ON ######
         if action.deviceAction == indigo.kDeviceAction.TurnOn:
            # Command hardware module (dev) to turn ON here:

            url = 'http://''%s'':''%s''/api/services/switch/turn_on' % (self.SERVER_ADDRESS, self.SERVER_PORT)
            r = requests.post(url, headers={'Authorization': 'Bearer ''%s' % self.TOKEN, 'content-type': 'application/json'}, data='{"entity_id":  "switch.christmas_lights"}')


            self.debugLog("Device content url:\n{}".format(url))
            self.debugLog("Device content r:\n{}".format(r))

            sendSuccess = True  # Set to False if it failed.

            if sendSuccess:
               # If success then log that the command was successfully sent.
               indigo.server.log(u"sent \"%s\" %s" % (dev.name, "on"))

               # And then tell the Indigo Server to update the state.
               dev.updateStateOnServer("onOffState", True)
            else:
               # Else log failure but do NOT update state on Indigo Server.
               indigo.server.log(u"send \"%s\" %s failed" % (dev.name, "on"), isError=True)
"}')






Here is the setup for the JSON string:

Code: Select all
$ curl -X POST -H "Authorization: Bearer ABCDEFGH" \
       -H "Content-Type: application/json" \
       -d '{"entity_id": "switch.christmas_lights"}' \
       http://localhost:8123/api/services/switch/turn_on


So the switch.christmas_lights is the identity_id in Home Assistant and the dev.address in indigo.

Posted on
Tue Jan 15, 2019 12:26 pm
jay (support) offline
Site Admin
User avatar
Posts: 15377
Joined: Mar 19, 2008
Location: Austin, Texas

Re: Trying to make an Home Assistant plugin

You want to construct the POST data as a Python dictionary, then just convert that to JSON:

Code: Select all
      ###HA switch###
      if dev.deviceTypeId == u"HAswitchType":
         ###### TURN ON ######
         if action.deviceAction == indigo.kDeviceAction.TurnOn:
            # Command hardware module (dev) to turn ON here:

            url = 'http://''%s'':''%s''/api/services/switch/turn_on' % (self.SERVER_ADDRESS, self.SERVER_PORT)
           
            # On the following line, you can assemble the value to be passed as entity_id as necessary - for
            # instance if you don't actually store the type but just the name. For this example, let's say you
            # stored the HA name in a device state called "ha_name", this is what you could do:
            entity_id = "switch.{}".format(dev.states["ha_name"])
            post_data = {"entity_id": entity_id}
           
            # Then, use the json module (you need to import at the top of your plugin.py) to convert the
            # Python dictionary to JSON. This is a useful pattern to use since doing the JSON conversion
            # in some circumstances can be pretty painful. The module makes it a one liner for any data.
            r = requests.post(url, headers={'Authorization': 'Bearer ''%s' % self.TOKEN, 'content-type': 'application/json'}, data=json.dumps(post_data))


            self.debugLog("Device content url:\n{}".format(url))
            self.debugLog("Device content r:\n{}".format(r))

            sendSuccess = True  # Set to False if it failed.

            if sendSuccess:
               # If success then log that the command was successfully sent.
               indigo.server.log(u"sent \"%s\" %s" % (dev.name, "on"))

               # And then tell the Indigo Server to update the state.
               dev.updateStateOnServer("onOffState", True)
            else:
               # Else log failure but do NOT update state on Indigo Server.
               indigo.server.log(u"send \"%s\" %s failed" % (dev.name, "on"), isError=True)

Jay (Indigo Support)
Twitter | Facebook | LinkedIn

Posted on
Fri Jan 18, 2019 5:58 am
steinis offline
Posts: 80
Joined: Jul 17, 2015
Location: Oslo, NORWAY

Re: Trying to make an Home Assistant plugin

Thanks for the help, that worked and a nice way to handle JSON strings.

So I have uploaded my first plugin to GitHub: https://github.com/steinis123/IndigoHAplugin
I dont want to add it as a official plugin to Indigo yet, since its my first and will contain bugs.
But if someone wants to test it and give feedback I be happy!


To get started its easy. You only need the IP and PORT and also a HA access token.
After that you can add sensor, light and relays only pass your HA identity(ex: sensor.my_test) to the address field of your chosen device.


Something to be aware of is that the JSON part of the code is by far optimize so I think adding a lot og device may affect the performance. But I have set the polling time to 3 seconds for know.

Posted on
Thu Jan 24, 2019 11:47 am
SST offline
Posts: 4
Joined: Jul 18, 2018

Re: Trying to make an Home Assistant plugin

Great work! Is it possible to expose home assistant`s filter attributes to the device state in Indigo? An example for me would be to integrate a climate device (mill) and have the temperature display instead of heat.
Attachments
Skjermbilde 2019-01-24 kl. 18.38.44.png
Skjermbilde 2019-01-24 kl. 18.38.44.png (142.92 KiB) Viewed 531 times

Posted on
Thu Jan 24, 2019 1:58 pm
steinis offline
Posts: 80
Joined: Jul 17, 2015
Location: Oslo, NORWAY

Re: Trying to make an Home Assistant plugin

Thanks:)

I will have a look at it. It would be nice if the custom "HAsensor" device can fetch the attributes and make custom states in Indigo, else I need to add a "climate" specific device.

Maybe Jay can answer this? Is it possible to have dynamic state in a custom component in Indigo? So if I receive different attributes for different type of sensor I dont need to make an device for each.

Posted on
Thu Jan 24, 2019 2:22 pm
jay (support) offline
Site Admin
User avatar
Posts: 15377
Joined: Mar 19, 2008
Location: Austin, Texas

Re: Trying to make an Home Assistant plugin

Yes. Check out the source for the WeatherSnoop plugin for one instance (and there are some posts here on the forums about it as well). The key parts are the buildDynamicDeviceStates (the method defined in that plugin to generate the list of states), the getDeviceStateList method (which is a method defined in the plugin base class that normally just reads the states from the device's config xml, but can be overridden to provide a custom state list), and any call to stateListOrDisplayStateIdChanged (which will force a call to getDeviceStateList to update the states for the device), often called when the device starts up.

Jay (Indigo Support)
Twitter | Facebook | LinkedIn

Who is online

Users browsing this forum: No registered users and 0 guests