mirror of
https://github.com/fmtr/haco.git
synced 2026-10-26 02:48:54 -04:00
Implement announce as control method and allow async methods
This commit is contained in:
parent
21100a5096
commit
caa19f016d
4 changed files with 46 additions and 27 deletions
|
|
@ -2,7 +2,6 @@ import aiomqtt
|
|||
import asyncio
|
||||
|
||||
from fmtr.tools import mqtt, Constants
|
||||
from fmtr.tools.json_tools import to_json
|
||||
from haco import constants
|
||||
from haco.obs import logger
|
||||
|
||||
|
|
@ -35,22 +34,16 @@ class ClientHaco(mqtt.Client):
|
|||
payload = message.payload.decode()
|
||||
logger.info(f"{message.topic.value}{Constants.ARROW}{payload}")
|
||||
topic_command = self.device.subscriptions[message.topic.value]
|
||||
echo_val = topic_command.wrap_back(message)
|
||||
echo_val = await topic_command.wrap_back(message)
|
||||
|
||||
|
||||
# Echo back as new state
|
||||
topic_state = topic_command.state
|
||||
if topic_state:
|
||||
await topic_state.wrap_back(echo_val)
|
||||
|
||||
async def start(self):
|
||||
while True:
|
||||
try:
|
||||
async with self:
|
||||
|
||||
for topic, data in self.device.announce.items():
|
||||
data_json = to_json(data)
|
||||
logger.info(f'Announcing {topic} with {data_json}')
|
||||
await self.publish(topic, payload=data_json, retain=True)
|
||||
await self.device.announce()
|
||||
|
||||
await self.publish(self.will.topic, self.ONLINE, retain=True)
|
||||
|
||||
|
|
|
|||
|
|
@ -3,8 +3,10 @@ from __future__ import annotations
|
|||
from dataclasses import dataclass, field
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from fmtr.tools.json_tools import to_json
|
||||
from haco.base import Base
|
||||
from haco.capabilities import Capability
|
||||
from haco.obs import logger
|
||||
from haco.utils import sanitize_name
|
||||
|
||||
if TYPE_CHECKING:
|
||||
|
|
@ -21,7 +23,7 @@ class Control(Base):
|
|||
unique_id: str | None = field(default=None, init=False)
|
||||
availability_topic: str | None = field(default=None, init=False)
|
||||
|
||||
announce: dict | None = field(default=None, metadata=dict(exclude=True))
|
||||
# announce: dict | None = field(default=None, metadata=dict(exclude=True))
|
||||
subscriptions: dict | None = field(default=None, metadata=dict(exclude=True), init=False)
|
||||
|
||||
def __post_init__(self):
|
||||
|
|
@ -36,7 +38,7 @@ class Control(Base):
|
|||
self.unique_id = self.get_unique_id()
|
||||
self.availability_topic = self.get_availability_topic()
|
||||
self.subscriptions = self.get_subscriptions()
|
||||
self.announce = self.get_announce()
|
||||
#self.announce = self.get_announce()
|
||||
|
||||
@property
|
||||
def parent(self):
|
||||
|
|
@ -47,7 +49,6 @@ class Control(Base):
|
|||
for cap in self.capabilities:
|
||||
data |= cap.announce
|
||||
|
||||
data = {self.announce_topic: data}
|
||||
return data
|
||||
|
||||
@classmethod
|
||||
|
|
@ -86,13 +87,16 @@ class Control(Base):
|
|||
async def initialise(self):
|
||||
...
|
||||
|
||||
async def announce2(self):
|
||||
async def announce(self):
|
||||
"""
|
||||
|
||||
Entities must be able to announce themselves to Home Assistant, e.g. when a pulldown changes its options, etc.
|
||||
|
||||
"""
|
||||
await self.device.client.publish(self.announce_topic, self.announce)
|
||||
topic = self.announce_topic
|
||||
data_json = to_json(self.get_announce())
|
||||
logger.info(f'Announcing {topic} with {data_json}')
|
||||
await self.device.client.publish(topic, data_json, retain=True)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ class Device(Base):
|
|||
controls: List[Control] = field(default_factory=list, metadata=dict(exclude=True))
|
||||
|
||||
parent: ClientHaco | None = field(metadata=dict(exclude=True), init=False)
|
||||
announce: dict | None = field(default=None, metadata=dict(exclude=True), init=False)
|
||||
# announce: dict | None = field(default=None, metadata=dict(exclude=True), init=False)
|
||||
subscriptions: dict | None = field(default=None, metadata=dict(exclude=True), init=False)
|
||||
|
||||
|
||||
|
|
@ -34,7 +34,7 @@ class Device(Base):
|
|||
|
||||
for control in self.controls:
|
||||
control.set_parent(self)
|
||||
self.announce = self.get_announce()
|
||||
#self.announce = self.get_announce()
|
||||
self.subscriptions = self.get_subscriptions()
|
||||
|
||||
self
|
||||
|
|
@ -47,12 +47,10 @@ class Device(Base):
|
|||
def name_san(self) -> str:
|
||||
return sanitize_name(self.name)
|
||||
|
||||
def get_announce(self):
|
||||
async def announce(self):
|
||||
for control in self.controls:
|
||||
await control.announce()
|
||||
|
||||
data = {}
|
||||
for capability in self.controls:
|
||||
data |= capability.announce
|
||||
return data
|
||||
|
||||
@property
|
||||
def client(self):
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ from dataclasses import dataclass, field
|
|||
from functools import cached_property
|
||||
from typing import ClassVar, TYPE_CHECKING
|
||||
|
||||
from fmtr.tools import aio
|
||||
from haco.obs import logger
|
||||
|
||||
if TYPE_CHECKING:
|
||||
|
|
@ -76,11 +77,19 @@ class AnnounceTopicState(AnnounceTopic):
|
|||
|
||||
async def wrap_back(self, value):
|
||||
method = getattr(self.capability.control, self.callback_name, None)
|
||||
is_async = aio.is_async(method)
|
||||
|
||||
# test
|
||||
|
||||
try:
|
||||
value_raw = method(value)
|
||||
|
||||
if is_async:
|
||||
value_raw = await method(value)
|
||||
else:
|
||||
value_raw = method(value)
|
||||
|
||||
except NotImplementedError:
|
||||
logger.warning(f'No method implemented for {self.topic}')
|
||||
logger.warning(f'No method implemented for {self.__class__.__name__}.{self.callback_name}: {self.topic}')
|
||||
return
|
||||
|
||||
await self.capability.control.device.client.publish(self.topic, value_raw)
|
||||
|
|
@ -94,16 +103,31 @@ class AnnounceTopicCommand(AnnounceTopic):
|
|||
def state(self):
|
||||
return self.capability.state
|
||||
|
||||
def wrap_back(self, message):
|
||||
async def wrap_back(self, message):
|
||||
method = getattr(self.capability.control, self.callback_name, None)
|
||||
|
||||
is_async = aio.is_async(method)
|
||||
|
||||
#test
|
||||
|
||||
try:
|
||||
value = method(message.payload.decode('utf-8'))
|
||||
|
||||
value = message.payload.decode('utf-8')
|
||||
|
||||
if is_async:
|
||||
value_raw = await method(value)
|
||||
else:
|
||||
value_raw = method(value)
|
||||
|
||||
except NotImplementedError:
|
||||
logger.warning(f'No method implemented for {self.topic}')
|
||||
return
|
||||
|
||||
return value
|
||||
# Echo back as new state
|
||||
topic_state = self.state
|
||||
if topic_state:
|
||||
await topic_state.wrap_back(value_raw)
|
||||
|
||||
|
||||
def get_subscriptions(self):
|
||||
return {self.topic: self}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue