diff --git a/brewblox_devcon_spark/endpoints/http_blocks.py b/brewblox_devcon_spark/endpoints/http_blocks.py index 6a98696e..60a1a34e 100644 --- a/brewblox_devcon_spark/endpoints/http_blocks.py +++ b/brewblox_devcon_spark/endpoints/http_blocks.py @@ -7,7 +7,8 @@ from fastapi import APIRouter from .. import mqtt, spark_api, utils -from ..models import Block, BlockIdentity, BlockNameChange +from ..models import (Block, BlockIdentity, BlockNameChange, ServicePatchEvent, + ServicePatchEventData) LOGGER = logging.getLogger(__name__) @@ -18,18 +19,15 @@ def publish(changed: list[Block] = None, deleted: list[BlockIdentity] = None): config = utils.get_config() mqtt_client = mqtt.CV.get() - changed = [v.model_dump(mode='json') for v in changed] if changed else [] - deleted = [v.id for v in deleted] if deleted else [] + changed = changed or [] + deleted = [v.id for v in (deleted or [])] mqtt_client.publish(f'{config.state_topic}/{config.name}/patch', - { - 'key': config.name, - 'type': 'Spark.patch', - 'ttl': '1d', - 'data': { - 'changed': changed, - 'deleted': deleted, - }, - }) + ServicePatchEvent( + key=config.name, + data=ServicePatchEventData( + changed=changed, + deleted=deleted) + ).model_dump(mode='json')) @router.post('/create', status_code=201) diff --git a/brewblox_devcon_spark/endpoints/http_system.py b/brewblox_devcon_spark/endpoints/http_system.py index 9d222d09..fb27c642 100644 --- a/brewblox_devcon_spark/endpoints/http_system.py +++ b/brewblox_devcon_spark/endpoints/http_system.py @@ -10,7 +10,8 @@ from .. import (command, exceptions, mqtt, spark_api, state_machine, utils, ymodem) -from ..models import FirmwareFlashResponse, PingResponse, StatusDescription +from ..models import (FirmwareFlashResponse, PingResponse, ServiceUpdateEvent, + ServiceUpdateEventData, StatusDescription) ESP_URL_FMT = 'http://brewblox.blob.core.windows.net/firmware/{date}-{version}/brewblox-esp32.bin' @@ -105,13 +106,10 @@ def __init__(self, background_tasks: BackgroundTasks) -> None: def _notify(self, msg: str): LOGGER.info(msg) self.mqtt_client.publish(self.notify_topic, - { - 'key': self.config.name, - 'type': 'Spark.update', - 'data': { - 'log': [msg], - }, - }) + ServiceUpdateEvent( + key=self.config.name, + data=ServiceUpdateEventData(log=[msg]) + ).model_dump(mode='json')) async def run(self) -> FirmwareFlashResponse: # pragma: no cover desc = self.state.desc() diff --git a/brewblox_devcon_spark/models.py b/brewblox_devcon_spark/models.py index 7b0b6063..b6242440 100644 --- a/brewblox_devcon_spark/models.py +++ b/brewblox_devcon_spark/models.py @@ -584,6 +584,11 @@ class DatastoreEvent(BaseModel): deleted: list[DatastoreValue] = Field(default_factory=list) +class HistoryEvent(BaseModel): + key: str + data: dict + + class ServiceStateEventData(BaseModel): status: StatusDescription blocks: list[Block] @@ -597,6 +602,22 @@ class ServiceStateEvent(BaseModel): data: ServiceStateEventData -class HistoryEvent(BaseModel): +class ServicePatchEventData(BaseModel): + changed: list[Block] = Field(default_factory=list) + deleted: list[str] = Field(default_factory=list) + + +class ServicePatchEvent(BaseModel): key: str - data: dict + type: Literal['Spark.patch'] = 'Spark.patch' + data: ServicePatchEventData + + +class ServiceUpdateEventData(BaseModel): + log: list[str] + + +class ServiceUpdateEvent(BaseModel): + key: str + type: Literal['Spark.update'] = 'Spark.update' + data: ServiceUpdateEventData diff --git a/test/test_integration.py b/test/test_integration.py index adfb1f99..078661aa 100644 --- a/test/test_integration.py +++ b/test/test_integration.py @@ -150,6 +150,7 @@ async def test_invalid_input(client: AsyncClient, block_args: Block, mocker: Moc # We need to simulate some bugs now m = mocker.patch.object(api, 'create_block', autospec=True) + mocker.patch(endpoints.http_blocks.__name__ + '.publish') # 500 if output is invalid # This is a programming error @@ -190,6 +191,7 @@ async def test_invalid_input_prod(client: AsyncClient, block_args: Block, mocker # We need to simulate some bugs now m = mocker.patch.object(api, 'create_block', autospec=True) + mocker.patch(endpoints.http_blocks.__name__ + '.publish') # 500 if output is invalid # This is a programming error