voorkant / voorkant-core

https://voorkant.org/
MIT License
2 stars 3 forks source link

ha backend/thread and uithread design #10

Closed cyclops1982 closed 2 months ago

cyclops1982 commented 6 months ago

The current implementation has a hathread and uithread, and these are quite tightly coupled. Moreover, the uithread currently uses the WSConn directly which we shouldn't be doing.

We want the UI to be disconnected from the websocket and preferably be generic and not home-assistant specific.

At startup, the ha-backend should setup the connection to HA using the WSConn. This should provide us with all states using the (get_states)[https://developers.home-assistant.io/docs/api/websocket/#fetching-states] call. Getting all states means we can build up a list of all entities, which we want to represent as a HAEntity object. This object should represent the current state of a entity in HA. The concept is thus that the ha-backend will keep the HAEntity up to date, the UI should then represent that state.

We currently also get the services for a specific domain, so a light has a on/off service and more. A entity has certain capabilities, so the HAEntity should also expose that so we can build generic UI for a lamp, and get the correct buttons/things available on the UI.

cyclops1982 commented 6 months ago
classDiagram
  Entity <|-- HAEntity
  HAEntity <|-- HAEntityLight
  Backend <|-- HABackend
  class Entity {
    ANY? Properties;
    getProperties();
  }
  class HAEntity {
    HAEntity(json statechange);
    HAServices[] GetServices();
  }
  class HAEntityLight {
    LightEntityFeature Features;
    On();
    Off();
  }
  class Backend {
    Backend();
  }
  class HABackend {
    -WSConn wc;
    -HAEntity[] entities;
    - void hathread();
    HABackend();
   HAEntity[] GetEntities();
  }

  class WSConn {
    WSConn();
  }

Notes/questions:

Habbie commented 6 months ago

@cyclops1982 did some refactoring work, which I then poked at until all frontends worked again. I made a few things slightly uglier in the process.

For the questions:

We probably want the HAEntityLight to expose the enum for it, so that we understand which capabilities we have. The methods on HAEntityLight can then check if the capability is there before executing.

yes, and a frontend may need this information for rendering. An RGB light looks different than a white dimmable light.

How do we make sure that a call to HAEntity (or it's children) causes a call on the websocket that only HABackend has?

I added WSConnSend to HABackend, because right now frontends create their own JSON objects, so we can just pass those through. Eventually that logic should move from frontends to entities. I'm not yet sure JSON should move all the way into HABackend, leaving just C++ objects in other places. It might be too inflexible.. or not.

If we want to do more than just home assistant, it makes sense to think about a abstract base class for Entity, Service and Backend. However, do those other systems work with an entity too? For Backend it's fairly clear and the WSConn needs to remain in HABackend, but what about GetEntities()? Let's make sure we have the abstract base class so that refactoring later on is less work.

I have a hard time imagining something flexible enough to support any other model. The one request we got for non-HA was OpenHab. We should look into its model and see if we can do something that fits both. That will likely leave us close-to-flexible-enough for other things.

Properties in HA can have various types, this is because they are using python and that's not a strictly typed. Not sure how that would work in c++.

Doesn't seem that bad - https://github.com/home-assistant/core/blob/3f1263a533bb9d2b3f566c4862b7f42271b33624/homeassistant/components/light/__init__.py#L863-L870

Maybe we can generate .hpp from this..

Habbie commented 6 months ago

OpenHab

https://www.openhab.org/docs/tutorial/model.html - did not really read it yet

Habbie commented 6 months ago

https://www.openhab.org/docs/tutorial/model.html - did not really read it yet

Locations are a hierarchy, which I don't think they are in HA. This feels like something we can fit in later.

The rest appears close enough to HA. Let's focus on HA for now.

Habbie commented 6 months ago

HAEntityLight (or perhaps HAEntity::Light?) will need a class definition in a header. I've been wondering if we can generate this header instead of typing it in. One source could be the Python code which appears to clearly define what an Entity is. Another potential source (might even be generated from that Python!) is get_services (see #27).

cyclops1982 commented 2 months ago

I think we've implemented most of this, and our design is slightly different.

If we want to document our design, then we should do that in .md files in the repo and not in issues. I'm voting to close this issue as it serves no value anymore.