Dynamically create HA entity

what is the best way to do this? a recent app from @Odianosen25 uses MQTT discovery, but I’m curious if there is another option.

the only way to create entities without mqtt is to use set_state()
but you only can create sensors with that.

it will always generate a warning the first time set_state is used. after that it just sets the state.

You can actually create ANYTHING with set_state. You can even make up a new domain like “food.rice”. HASS will accept it. The problem with anything other than a sensor is that HASS won’t handle the service calls for you. So, if you’re going to make, say, a switch… Then you’ll need to look for switch.turn_on and homeassistant.turn_on events and handle them appropriately.

@kylerw thanks for creating this, as I am beginning to learn some new ways of doing things. This is very interesting, as I have avoided using the self.set_state function for a while, and it totally skipped me it had the ability to create entities within HASS.

The reason I avoided it was initially when I started writing apps, I used it as usual. At a point when I was using it to control entities like input_numbers, which was used to in turn determine my media players’s volume level, I noticed some delays in execution time.

This got me to dig into the reason, and that was when I noticed the doc made mention of the fact it doesn’t change the state of the device, but just the state within Hass and it could be reverted back when the device is polled again. This also leads to it no longer reflects reality, and it was advised to be used for testing purposes…

Since then I just avoided using it, forgetting the fact it also stated it could be used to create entities within Hass if it doesn’t exist, as it doesn’t check for if it exist unlike the call service function.

I will need to play a bit more with it, so I could understand its limitation. HA’s docs does state one can create binary_sensors and sensors only using http requests (which I believe is what set_state does) in reference to what @ReneTode said . Now if one can use the self.set_state function to do more based on what @swiftlyfalling said, that will be very interesting.

Regards

yeah you are right. stuff gets created. but the behaviour from entities other then sensors is not like expected.
i tried to create switches on the fly long time ago, but when trying to use it it got buggy. for example you couldnt change the state from the switch in HA.
but thanks for saying it again, because i just got an idea to try out.

edit:
tried to create a switch. it is created, but as mentioned you cant change the state
tried to change the state by using a service_call but that doesnt work.

At one point, I was able to do this. I created a switch.test using “set_state” from AppDaemon, detected the switch toggle from the UI, and then performed a set_state again to show the change. Basically, I implemented “input_boolean” within AppDaemon that appeared as “switch.test” in HASS. I did it because I wanted to know if I could. The amount of code required was absurd and it was much easier to just make an actual input_boolean and react to it. I don’t remember all of the events I had to detect but, if I get some free time in the near future I’ll try to do it again just in case the code is useful to you.

the problem is that you cant change the state from the created switch in the HA GUI
i used self.set_state(“switch.test”, state = “on”) and the switch is there, but i cant set it to off in any way i try.

so yeah if you found a way i would love to know how.

I don’t have AppDaemon even running any more, but I was able to verify what I thought to be true using the API.

If I do: set_state(‘switch.testme’,‘on’) … then, in the UI, we see the switch. If I then toggle that switch in the UI, the following event it emitted.

{"event_type":"call_service","event":{"domain":"switch","service":"turn_off","service_data":{"entity_id":"switch.testme"}}}

So, based on the AppDaemon docs, I would need something like…

listen_event(my_call_back, event = "call_service")

then, in my_call_back… I would do…

def my_call_back(self,event_name,data, kwargs):
  if(data.domain == "switch" and data.service_data.entity_id == "switch.testme"):
    # yes... this is me... do the things
  else:
    # this was a service_call to something that isn't me... so ignore it.

Also, keep in mind, you’ll need to data.domain == “homeassistant” as well. For UI interaction, it’ll generally be switch.turn_off/turn_on. But, in automations, one might call homeassistant.turn_on/turn_off… so you need to catch them both.

Somewhere in the code of your call back, you need to make sure to self.set_state() back on if they turned the device on or off if they turned it off. If you’re doing something more than an input_boolean type behavior, generally you’d want to run the code to turn the thing on first, and then report back with the state saying that it’s on.

1 Like

the switch doesnt toggle. it stays to on no matter what i try. (or at least it immediatly switches back)
so i am not sure if the event will be triggered at all. (but i could try)
if the event is triggered then i would need to use set_state to set the switch to off after the event is triggered.

it is worth a try, it would only be 1 app for all “on the fly” entities
to make them work.

but i think it will create a circle.

if i try to switch the boolean in the UI, it would generate an event, then i need to use set_state and that would also generate an event.

tried it and it works. set_state doesnt trigger the event (or at least not the same)
so the app looks like:

import appdaemon.plugins.hass.hassapi as hass

class input_boolean(hass.Hass):

    def initialize(self):
        self.input_boolean = self.args["name"]
        if not self.entity_exists(self.input_boolean):
            self.set_state(self.input_boolean, state = "off")
        self.listen_event(self.change_state, event = "call_service")

    def change_state(self,event_name,data, kwargs):
        if(data["service"] == "turn_off" and data["service_data"]["entity_id"] == self.input_boolean):
            self.log(self.input_boolean + "switched off")
            self.set_state(self.input_boolean, state = "off")
        if(data["service"] == "turn_on" and data["service_data"]["entity_id"] == self.input_boolean):
            self.log(self.input_boolean + "switched on")
            self.set_state(self.input_boolean, state = "on")

with this app i can easy add new input booleans by just adding

rene:
  class: input_boolean
  module: input_boolean
  name: switch.rene

to the yaml and from that moment on i can use it in the gui and use listen_state in AD.

Thank you very much for that!!!

3 Likes

Absolutely. Glad to help.

Believe it or not, I made a climate entity with appdaemon way back in the day using this method. :slight_smile:

This is very interesting stuff. Thanks for sharing guys

did the climate entity also show like a climate entity in the gui from HA?
i tried to create a light, but it shows like a switch.
is it just a matter of adding attributes?

Yup!

Home Assistant is strange that way. The “domain” part of an entity ID (climate.myclimate or switch.myswitch) ONLY matters to the UI. Switches could be named somecrazything.mycrazything and as long as they trap the “switch.turn_on” service calls (and friends) then they’ll still WORK like a switch. But they won’t display like a switch in the UI.

At least this is how it SEEMED back when I was messing with it (I didn’t dig into HASS internals to confirm this, it just seemed to work that way when I tried it). Perhaps Home Assistant has been changed since then.

For lights, the UI responds to the “supported_features” attribute. I’m sure, in the code, it’s some kind of bitmask that ends up resulting in an integer. I’m not sure what all the values are, but, if you want a light with a brightness slider… try this… which works just fine for me and presents as a light with a brightness slider…

{
    "state": "on",
    "attributes": {
        "brightness": 255,
        "supported_features": 41
    }
}

If you want to do it “right”, you should dig into the code, find out what the bitmasks are for everything and set them accordingly. If you want to do it quickly, just find an existing light that has the features you want (RGB color, brightness, etc, etc) and copy the number from the existing entity.

and how do i find that number?

digging in the code and looking for bitmasks is hard, because i dont even know what bitmasks are :wink:

at this moment the switch on the fly is the thing i will use the most, but i might want to try other stuff too. (i know i will even just to be able to :wink: )

The easiest way to find the number is to find someone with a working, REAL, light device, have them look in dev-states and give you the number.

A quick look at source code shows this:

SUPPORT_BRIGHTNESS = 1
SUPPORT_COLOR_TEMP = 2
SUPPORT_EFFECT = 4
SUPPORT_FLASH = 8
SUPPORT_COLOR = 16
SUPPORT_TRANSITION = 32
SUPPORT_WHITE_VALUE = 128

Which would mean the light I used as an example (supported_features = 41) supports:
TRANSITION
FLASH
BRIGHTNESS

Basically… just add the numbers together for the things your device supports. For RGB and BRIGHTNESS, as example, then COLOR = 16, BRIGHTNESS = 1… so 17. For just brightness… then 1.

You’ll have to play with the numbers to see exactly which effects that enables in the UI. But that’s the gist of it.

1 Like

thanks. found where i need to look for the bitmasks.
i guess all i need to do is play around :wink:

you have played around with it.
so maybe you know if that is possible too:

is it possible to connect the created entity to a certain component from the outside?

I’m not sure what you mean by “connected component from the outside”. AppDaemon is not special in the way that it can set states and listen for events. Any application that connects to Hass’s websocket can do that. So, a NodeJS app, for instance, could do the same thing.

If you mean getting a switch that you made in AppDaemon to be handled automatically by HASS… no… that can’t be done. By setting the state of a non-existent entity, you circumvent anything automated that HASS would do for you. You can use MQTT Discovery and announce the new entity via MQTT and then home assistant will treat it like a more native switch/light/climate device.