#!/usr/bin/python3

#     Copyright 2021. FastyBird s.r.o.
#
#     Licensed under the Apache License, Version 2.0 (the "License");
#     you may not use this file except in compliance with the License.
#     You may obtain a copy of the License at
#
#         http://www.apache.org/licenses/LICENSE-2.0
#
#     Unless required by applicable law or agreed to in writing, software
#     distributed under the License is distributed on an "AS IS" BASIS,
#     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#     See the License for the specific language governing permissions and
#     limitations under the License.

"""
FastyBird MQTT connector consumers module devices messages consumer
"""

# Python base dependencies
import logging
import uuid
from typing import Dict, List, Union

# App dependencies
from devices_module.items import DeviceItem
from devices_module.repositories import (
    ChannelsRepository,
    DevicesControlsRepository,
    DevicesPropertiesRepository,
    DevicesRepository,
)
from exchange_plugin.dispatcher import EventDispatcher
from fb_mqtt_connector_plugin.consumers.consumer import IConsumer
from fb_mqtt_connector_plugin.consumers.entities import (
    BaseEntity,
    DeviceAttributeEntity,
    FirmwareEntity,
    HardwareEntity,
)
from kink import inject
from modules_metadata.devices_module import DeviceConnectionState, DevicePropertyName
from modules_metadata.types import DataType

# App libs
from miniserver_gateway.events.connectors import (
    ConnectorAddOrEditChannel,
    ConnectorAddOrEditDevice,
    ConnectorAddOrEditDeviceControl,
    ConnectorAddOrEditDeviceProperty,
    ConnectorDeleteChannel,
    ConnectorDeleteDeviceControl,
    ConnectorDeleteDeviceProperty,
    ConnectorDevicePropertyActualValueEvent,
)


@inject(alias=IConsumer)
class DeviceAttributeItemConsumer(IConsumer):  # pylint: disable=too-few-public-methods
    """
    Device attribute message consumer

    @package        FastyBird:MiniServer!
    @module         device

    @author         <NAME> <<EMAIL>>
    """

    __devices_repository: DevicesRepository
    __devices_properties_repository: DevicesPropertiesRepository
    __devices_controls_repository: DevicesControlsRepository
    __channels_repository: ChannelsRepository

    __event_dispatcher: EventDispatcher
    __logger: logging.Logger

    # -----------------------------------------------------------------------------

    def __init__(  # pylint: disable=too-many-arguments
        self,
        devices_repository: DevicesRepository,
        devices_properties_repository: DevicesPropertiesRepository,
        devices_controls_repository: DevicesControlsRepository,
        channels_repository: ChannelsRepository,
        event_dispatcher: EventDispatcher,
        logger: logging.Logger = logging.getLogger("dummy"),
    ) -> None:
        self.__devices_repository = devices_repository
        self.__devices_properties_repository = devices_properties_repository
        self.__devices_controls_repository = devices_controls_repository
        self.__channels_repository = channels_repository

        self.__event_dispatcher = event_dispatcher
        self.__logger = logger

    # -----------------------------------------------------------------------------

    def consume(self, entity: BaseEntity) -> None:
        """Consume received message"""
        if not isinstance(entity, DeviceAttributeEntity):
            return

        device_item = self.__devices_repository.get_by_identifier(device_identifier=entity.device)

        if device_item is None:
            self.__logger.error("Message is for unknown device %s", entity.device)

            return

        to_update: Dict[str, Union[str, bool, None]] = {}

        if entity.attribute == DeviceAttributeEntity.NAME:
            to_update["name"] = str(entity.value)

        if entity.attribute == DeviceAttributeEntity.STATE and DeviceConnectionState.has_value(str(entity.value)):
            self.__process_state(device_item=device_item, value=DeviceConnectionState(entity.value))

        if entity.attribute == DeviceAttributeEntity.PROPERTIES and isinstance(entity.value, list):
            self.__process_properties(device_item=device_item, values=entity.value)

        if entity.attribute == DeviceAttributeEntity.CHANNELS and isinstance(entity.value, list):
            self.__process_channels(device_item, entity.value)

        if entity.attribute == DeviceAttributeEntity.CONTROLS and isinstance(entity.value, list):
            self.__process_controls(device_item=device_item, values=entity.value)

        parent_device_item = (
            self.__devices_repository.get_by_identifier(device_identifier=entity.parent)
            if entity.parent is not None
            else None
        )

        if bool(to_update) or parent_device_item is not None:
            self.__event_dispatcher.dispatch(
                event_id=ConnectorAddOrEditDevice.EVENT_NAME,
                event=ConnectorAddOrEditDevice(
                    connector_id=device_item.connector_id,
                    device_id=device_item.device_id,
                    device_data=to_update,
                    parent_id=parent_device_item.device_id if parent_device_item is not None else None,
                ),
            )

        self.__logger.debug("Consumed device attribute message for: %s", device_item.identifier)

    # -----------------------------------------------------------------------------

    def __process_state(self, device_item: DeviceItem, value: DeviceConnectionState) -> None:
        device_property_item = self.__devices_properties_repository.get_by_identifier(
            device_id=device_item.device_id,
            property_identifier=DevicePropertyName.STATE.value,
        )

        if device_property_item is None:
            self.__event_dispatcher.dispatch(
                event_id=ConnectorAddOrEditDeviceProperty.EVENT_NAME,
                event=ConnectorAddOrEditDeviceProperty(
                    device_id=device_item.device_id,
                    property_id=None,
                    property_data={
                        "identifier": DevicePropertyName.STATE.value,
                        "key": None,
                        "settable": False,
                        "queryable": False,
                        "data_type": DataType.ENUM.value,
                        "unit": None,
                        "format": ",".join(
                            [
                                DeviceConnectionState.CONNECTED.value,
                                DeviceConnectionState.DISCONNECTED.value,
                                DeviceConnectionState.INIT.value,
                                DeviceConnectionState.READY.value,
                                DeviceConnectionState.RUNNING.value,
                                DeviceConnectionState.SLEEPING.value,
                                DeviceConnectionState.STOPPED.value,
                                DeviceConnectionState.LOST.value,
                                DeviceConnectionState.ALERT.value,
                                DeviceConnectionState.UNKNOWN.value,
                            ]
                        ),
                    },
                ),
            )

        else:
            self.__event_dispatcher.dispatch(
                event_id=ConnectorDevicePropertyActualValueEvent.EVENT_NAME,
                event=ConnectorDevicePropertyActualValueEvent(
                    property_id=device_property_item.property_id,
                    actual_value=value.value,
                ),
            )

    # -----------------------------------------------------------------------------

    def __process_properties(self, device_item: DeviceItem, values: List) -> None:
        for identifier in values:
            one_device_property_item = self.__devices_properties_repository.get_by_identifier(
                device_id=device_item.device_id,
                property_identifier=identifier,
            )

            if one_device_property_item is None:
                self.__event_dispatcher.dispatch(
                    event_id=ConnectorAddOrEditDeviceProperty.EVENT_NAME,
                    event=ConnectorAddOrEditDeviceProperty(
                        device_id=device_item.device_id,
                        property_id=None,
                        property_data={
                            "identifier": identifier,
                        },
                    ),
                )

        for device_property_item in self.__devices_properties_repository.get_all_by_device(
            device_id=device_item.device_id,
        ):
            if device_property_item.identifier not in values:
                self.__event_dispatcher.dispatch(
                    event_id=ConnectorDeleteDeviceProperty.EVENT_NAME,
                    event=ConnectorDeleteDeviceProperty(
                        property_id=device_property_item.property_id,
                    ),
                )

    # -----------------------------------------------------------------------------

    def __process_channels(self, device_item: DeviceItem, values: List) -> None:
        for identifier in values:
            channel_item = self.__channels_repository.get_by_identifier(
                device_id=device_item.device_id,
                channel_identifier=identifier,
            )

            if channel_item is None:
                self.__event_dispatcher.dispatch(
                    event_id=ConnectorAddOrEditChannel.EVENT_NAME,
                    event=ConnectorAddOrEditChannel(
                        device_id=device_item.device_id,
                        channel_id=None,
                        channel_data={
                            "identifier": identifier,
                        },
                    ),
                )

        for channel_item in self.__channels_repository.get_all_by_device(
            device_id=device_item.device_id,
        ):
            if channel_item.identifier not in values:
                self.__event_dispatcher.dispatch(
                    event_id=ConnectorDeleteChannel.EVENT_NAME,
                    event=ConnectorDeleteChannel(
                        channel_id=channel_item.channel_id,
                    ),
                )

    # -----------------------------------------------------------------------------

    def __process_controls(self, device_item: DeviceItem, values: List) -> None:
        for name in values:
            device_control = self.__devices_controls_repository.get_by_name(
                device_id=device_item.device_id,
                control_name=name,
            )

            if device_control is None:
                self.__event_dispatcher.dispatch(
                    event_id=ConnectorAddOrEditDeviceControl.EVENT_NAME,
                    event=ConnectorAddOrEditDeviceControl(
                        device_id=device_item.device_id,
                        control_id=uuid.uuid4(),
                        control_name=name,
                    ),
                )

        for device_control in self.__devices_controls_repository.get_all_by_device(device_id=device_item.device_id):
            if device_control.name not in values:
                self.__event_dispatcher.dispatch(
                    event_id=ConnectorDeleteDeviceControl.EVENT_NAME,
                    event=ConnectorDeleteDeviceControl(
                        control_id=device_control.control_id,
                    ),
                )


@inject(alias=IConsumer)
class DeviceHardwareItemConsumer(IConsumer):  # pylint: disable=too-few-public-methods
    """
    Device hardware info message consumer

    @package        FastyBird:MiniServer!
    @module         device

    @author         <NAME> <<EMAIL>>
    """

    __devices_repository: DevicesRepository

    __event_dispatcher: EventDispatcher
    __logger: logging.Logger

    # -----------------------------------------------------------------------------

    def __init__(
        self,
        devices_repository: DevicesRepository,
        event_dispatcher: EventDispatcher,
        logger: logging.Logger = logging.getLogger("dummy"),
    ) -> None:
        self.__devices_repository = devices_repository

        self.__event_dispatcher = event_dispatcher
        self.__logger = logger

    # -----------------------------------------------------------------------------

    def consume(self, entity: BaseEntity) -> None:
        """Consume received message"""
        if not isinstance(entity, HardwareEntity):
            return

        device_item = self.__devices_repository.get_by_identifier(device_identifier=entity.device)

        if device_item is None:
            self.__logger.error("Message is for unknown device %s", entity.device)

            return

        to_update: Dict[str, Union[str, bool, None]] = {}

        if entity.parameter == HardwareEntity.MAC_ADDRESS:
            to_update = {"hardware_mac_address": str(entity.value)}

        if entity.parameter == HardwareEntity.MANUFACTURER:
            to_update = {"hardware_manufacturer": str(entity.value)}

        if entity.parameter == HardwareEntity.MODEL:
            to_update = {"hardware_model": str(entity.value)}

        if entity.parameter == HardwareEntity.VERSION:
            to_update = {"hardware_version": str(entity.value)}

        if bool(to_update):
            self.__event_dispatcher.dispatch(
                event_id=ConnectorAddOrEditDevice.EVENT_NAME,
                event=ConnectorAddOrEditDevice(
                    connector_id=device_item.connector_id,
                    device_id=device_item.device_id,
                    device_data=to_update,
                ),
            )

        self.__logger.debug("Consumed device hardware info message for: %s", device_item.identifier)


@inject(alias=IConsumer)
class DeviceFirmwareItemConsumer(IConsumer):  # pylint: disable=too-few-public-methods
    """
    Device firmware info message consumer

    @package        FastyBird:MiniServer!
    @module         device

    @author         <NAME> <<EMAIL>>
    """

    __devices_repository: DevicesRepository

    __event_dispatcher: EventDispatcher
    __logger: logging.Logger

    # -----------------------------------------------------------------------------

    def __init__(
        self,
        devices_repository: DevicesRepository,
        event_dispatcher: EventDispatcher,
        logger: logging.Logger = logging.getLogger("dummy"),
    ) -> None:
        self.__devices_repository = devices_repository

        self.__event_dispatcher = event_dispatcher
        self.__logger = logger

    # -----------------------------------------------------------------------------

    def consume(self, entity: BaseEntity) -> None:
        """Consume received message"""
        if not isinstance(entity, FirmwareEntity):
            return

        device_item = self.__devices_repository.get_by_identifier(device_identifier=entity.device)

        if device_item is None:
            self.__logger.error("Message is for unknown device %s", entity.device)

            return

        to_update: Dict[str, Union[str, bool, None]] = {}

        if entity.parameter == FirmwareEntity.MANUFACTURER:
            to_update = {"firmware_manufacturer": entity.value}

        if entity.parameter == FirmwareEntity.VERSION:
            to_update = {"firmware_version": entity.value}

        if bool(to_update):
            self.__event_dispatcher.dispatch(
                event_id=ConnectorAddOrEditDevice.EVENT_NAME,
                event=ConnectorAddOrEditDevice(
                    connector_id=device_item.connector_id,
                    device_id=device_item.device_id,
                    device_data=to_update,
                ),
            )

        self.__logger.debug("Consumed device firmware info message for: %s", device_item.identifier)

#!/usr/bin/python3

#     Copyright 2021. FastyBird s.r.o.
#
#     Licensed under the Apache License, Version 2.0 (the "License");
#     you may not use this file except in compliance with the License.
#     You may obtain a copy of the License at
#
#         http://www.apache.org/licenses/LICENSE-2.0
#
#     Unless required by applicable law or agreed to in writing, software
#     distributed under the License is distributed on an "AS IS" BASIS,
#     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#     See the License for the specific language governing permissions and
#     limitations under the License.

"""
FastyBird MQTT connector consumers module devices messages consumer
"""

# Python base dependencies
import logging
import uuid
from typing import Dict, List, Union

# App dependencies
from devices_module.items import DeviceItem
from devices_module.repositories import (
    ChannelsRepository,
    DevicesControlsRepository,
    DevicesPropertiesRepository,
    DevicesRepository,
)
from exchange_plugin.dispatcher import EventDispatcher
from fb_mqtt_connector_plugin.consumers.consumer import IConsumer
from fb_mqtt_connector_plugin.consumers.entities import (
    BaseEntity,
    DeviceAttributeEntity,
    FirmwareEntity,
    HardwareEntity,
)
from kink import inject
from modules_metadata.devices_module import DeviceConnectionState, DevicePropertyName
from modules_metadata.types import DataType

# App libs
from miniserver_gateway.events.connectors import (
    ConnectorAddOrEditChannel,
    ConnectorAddOrEditDevice,
    ConnectorAddOrEditDeviceControl,
    ConnectorAddOrEditDeviceProperty,
    ConnectorDeleteChannel,
    ConnectorDeleteDeviceControl,
    ConnectorDeleteDeviceProperty,
    ConnectorDevicePropertyActualValueEvent,
)


@inject(alias=IConsumer)
class DeviceAttributeItemConsumer(IConsumer):  # pylint: disable=too-few-public-methods
    """
    Device attribute message consumer

    @package        FastyBird:MiniServer!
    @module         device

    @author         <NAME> <<EMAIL>>
    """

    __devices_repository: DevicesRepository
    __devices_properties_repository: DevicesPropertiesRepository
    __devices_controls_repository: DevicesControlsRepository
    __channels_repository: ChannelsRepository

    __event_dispatcher: EventDispatcher
    __logger: logging.Logger

    # -----------------------------------------------------------------------------

    def __init__(  # pylint: disable=too-many-arguments
        self,
        devices_repository: DevicesRepository,
        devices_properties_repository: DevicesPropertiesRepository,
        devices_controls_repository: DevicesControlsRepository,
        channels_repository: ChannelsRepository,
        event_dispatcher: EventDispatcher,
        logger: logging.Logger = logging.getLogger("dummy"),
    ) -> None:
        self.__devices_repository = devices_repository
        self.__devices_properties_repository = devices_properties_repository
        self.__devices_controls_repository = devices_controls_repository
        self.__channels_repository = channels_repository

        self.__event_dispatcher = event_dispatcher
        self.__logger = logger

    # -----------------------------------------------------------------------------

    def consume(self, entity: BaseEntity) -> None:
        """Consume received message"""
        if not isinstance(entity, DeviceAttributeEntity):
            return

        device_item = self.__devices_repository.get_by_identifier(device_identifier=entity.device)

        if device_item is None:
            self.__logger.error("Message is for unknown device %s", entity.device)

            return

        to_update: Dict[str, Union[str, bool, None]] = {}

        if entity.attribute == DeviceAttributeEntity.NAME:
            to_update["name"] = str(entity.value)

        if entity.attribute == DeviceAttributeEntity.STATE and DeviceConnectionState.has_value(str(entity.value)):
            self.__process_state(device_item=device_item, value=DeviceConnectionState(entity.value))

        if entity.attribute == DeviceAttributeEntity.PROPERTIES and isinstance(entity.value, list):
            self.__process_properties(device_item=device_item, values=entity.value)

        if entity.attribute == DeviceAttributeEntity.CHANNELS and isinstance(entity.value, list):
            self.__process_channels(device_item, entity.value)

        if entity.attribute == DeviceAttributeEntity.CONTROLS and isinstance(entity.value, list):
            self.__process_controls(device_item=device_item, values=entity.value)

        parent_device_item = (
            self.__devices_repository.get_by_identifier(device_identifier=entity.parent)
            if entity.parent is not None
            else None
        )

        if bool(to_update) or parent_device_item is not None:
            self.__event_dispatcher.dispatch(
                event_id=ConnectorAddOrEditDevice.EVENT_NAME,
                event=ConnectorAddOrEditDevice(
                    connector_id=device_item.connector_id,
                    device_id=device_item.device_id,
                    device_data=to_update,
                    parent_id=parent_device_item.device_id if parent_device_item is not None else None,
                ),
            )

        self.__logger.debug("Consumed device attribute message for: %s", device_item.identifier)

    # -----------------------------------------------------------------------------

    def __process_state(self, device_item: DeviceItem, value: DeviceConnectionState) -> None:
        device_property_item = self.__devices_properties_repository.get_by_identifier(
            device_id=device_item.device_id,
            property_identifier=DevicePropertyName.STATE.value,
        )

        if device_property_item is None:
            self.__event_dispatcher.dispatch(
                event_id=ConnectorAddOrEditDeviceProperty.EVENT_NAME,
                event=ConnectorAddOrEditDeviceProperty(
                    device_id=device_item.device_id,
                    property_id=None,
                    property_data={
                        "identifier": DevicePropertyName.STATE.value,
                        "key": None,
                        "settable": False,
                        "queryable": False,
                        "data_type": DataType.ENUM.value,
                        "unit": None,
                        "format": ",".join(
                            [
                                DeviceConnectionState.CONNECTED.value,
                                DeviceConnectionState.DISCONNECTED.value,
                                DeviceConnectionState.INIT.value,
                                DeviceConnectionState.READY.value,
                                DeviceConnectionState.RUNNING.value,
                                DeviceConnectionState.SLEEPING.value,
                                DeviceConnectionState.STOPPED.value,
                                DeviceConnectionState.LOST.value,
                                DeviceConnectionState.ALERT.value,
                                DeviceConnectionState.UNKNOWN.value,
                            ]
                        ),
                    },
                ),
            )

        else:
            self.__event_dispatcher.dispatch(
                event_id=ConnectorDevicePropertyActualValueEvent.EVENT_NAME,
                event=ConnectorDevicePropertyActualValueEvent(
                    property_id=device_property_item.property_id,
                    actual_value=value.value,
                ),
            )

    # -----------------------------------------------------------------------------

    def __process_properties(self, device_item: DeviceItem, values: List) -> None:
        for identifier in values:
            one_device_property_item = self.__devices_properties_repository.get_by_identifier(
                device_id=device_item.device_id,
                property_identifier=identifier,
            )

            if one_device_property_item is None:
                self.__event_dispatcher.dispatch(
                    event_id=ConnectorAddOrEditDeviceProperty.EVENT_NAME,
                    event=ConnectorAddOrEditDeviceProperty(
                        device_id=device_item.device_id,
                        property_id=None,
                        property_data={
                            "identifier": identifier,
                        },
                    ),
                )

        for device_property_item in self.__devices_properties_repository.get_all_by_device(
            device_id=device_item.device_id,
        ):
            if device_property_item.identifier not in values:
                self.__event_dispatcher.dispatch(
                    event_id=ConnectorDeleteDeviceProperty.EVENT_NAME,
                    event=ConnectorDeleteDeviceProperty(
                        property_id=device_property_item.property_id,
                    ),
                )

    # -----------------------------------------------------------------------------

    def __process_channels(self, device_item: DeviceItem, values: List) -> None:
        for identifier in values:
            channel_item = self.__channels_repository.get_by_identifier(
                device_id=device_item.device_id,
                channel_identifier=identifier,
            )

            if channel_item is None:
                self.__event_dispatcher.dispatch(
                    event_id=ConnectorAddOrEditChannel.EVENT_NAME,
                    event=ConnectorAddOrEditChannel(
                        device_id=device_item.device_id,
                        channel_id=None,
                        channel_data={
                            "identifier": identifier,
                        },
                    ),
                )

        for channel_item in self.__channels_repository.get_all_by_device(
            device_id=device_item.device_id,
        ):
            if channel_item.identifier not in values:
                self.__event_dispatcher.dispatch(
                    event_id=ConnectorDeleteChannel.EVENT_NAME,
                    event=ConnectorDeleteChannel(
                        channel_id=channel_item.channel_id,
                    ),
                )

    # -----------------------------------------------------------------------------

    def __process_controls(self, device_item: DeviceItem, values: List) -> None:
        for name in values:
            device_control = self.__devices_controls_repository.get_by_name(
                device_id=device_item.device_id,
                control_name=name,
            )

            if device_control is None:
                self.__event_dispatcher.dispatch(
                    event_id=ConnectorAddOrEditDeviceControl.EVENT_NAME,
                    event=ConnectorAddOrEditDeviceControl(
                        device_id=device_item.device_id,
                        control_id=uuid.uuid4(),
                        control_name=name,
                    ),
                )

        for device_control in self.__devices_controls_repository.get_all_by_device(device_id=device_item.device_id):
            if device_control.name not in values:
                self.__event_dispatcher.dispatch(
                    event_id=ConnectorDeleteDeviceControl.EVENT_NAME,
                    event=ConnectorDeleteDeviceControl(
                        control_id=device_control.control_id,
                    ),
                )


@inject(alias=IConsumer)
class DeviceHardwareItemConsumer(IConsumer):  # pylint: disable=too-few-public-methods
    """
    Device hardware info message consumer

    @package        FastyBird:MiniServer!
    @module         device

    @author         <NAME> <<EMAIL>>
    """

    __devices_repository: DevicesRepository

    __event_dispatcher: EventDispatcher
    __logger: logging.Logger

    # -----------------------------------------------------------------------------

    def __init__(
        self,
        devices_repository: DevicesRepository,
        event_dispatcher: EventDispatcher,
        logger: logging.Logger = logging.getLogger("dummy"),
    ) -> None:
        self.__devices_repository = devices_repository

        self.__event_dispatcher = event_dispatcher
        self.__logger = logger

    # -----------------------------------------------------------------------------

    def consume(self, entity: BaseEntity) -> None:
        """Consume received message"""
        if not isinstance(entity, HardwareEntity):
            return

        device_item = self.__devices_repository.get_by_identifier(device_identifier=entity.device)

        if device_item is None:
            self.__logger.error("Message is for unknown device %s", entity.device)

            return

        to_update: Dict[str, Union[str, bool, None]] = {}

        if entity.parameter == HardwareEntity.MAC_ADDRESS:
            to_update = {"hardware_mac_address": str(entity.value)}

        if entity.parameter == HardwareEntity.MANUFACTURER:
            to_update = {"hardware_manufacturer": str(entity.value)}

        if entity.parameter == HardwareEntity.MODEL:
            to_update = {"hardware_model": str(entity.value)}

        if entity.parameter == HardwareEntity.VERSION:
            to_update = {"hardware_version": str(entity.value)}

        if bool(to_update):
            self.__event_dispatcher.dispatch(
                event_id=ConnectorAddOrEditDevice.EVENT_NAME,
                event=ConnectorAddOrEditDevice(
                    connector_id=device_item.connector_id,
                    device_id=device_item.device_id,
                    device_data=to_update,
                ),
            )

        self.__logger.debug("Consumed device hardware info message for: %s", device_item.identifier)


@inject(alias=IConsumer)
class DeviceFirmwareItemConsumer(IConsumer):  # pylint: disable=too-few-public-methods
    """
    Device firmware info message consumer

    @package        FastyBird:MiniServer!
    @module         device

    @author         <NAME> <<EMAIL>>
    """

    __devices_repository: DevicesRepository

    __event_dispatcher: EventDispatcher
    __logger: logging.Logger

    # -----------------------------------------------------------------------------

    def __init__(
        self,
        devices_repository: DevicesRepository,
        event_dispatcher: EventDispatcher,
        logger: logging.Logger = logging.getLogger("dummy"),
    ) -> None:
        self.__devices_repository = devices_repository

        self.__event_dispatcher = event_dispatcher
        self.__logger = logger

    # -----------------------------------------------------------------------------

    def consume(self, entity: BaseEntity) -> None:
        """Consume received message"""
        if not isinstance(entity, FirmwareEntity):
            return

        device_item = self.__devices_repository.get_by_identifier(device_identifier=entity.device)

        if device_item is None:
            self.__logger.error("Message is for unknown device %s", entity.device)

            return

        to_update: Dict[str, Union[str, bool, None]] = {}

        if entity.parameter == FirmwareEntity.MANUFACTURER:
            to_update = {"firmware_manufacturer": entity.value}

        if entity.parameter == FirmwareEntity.VERSION:
            to_update = {"firmware_version": entity.value}

        if bool(to_update):
            self.__event_dispatcher.dispatch(
                event_id=ConnectorAddOrEditDevice.EVENT_NAME,
                event=ConnectorAddOrEditDevice(
                    connector_id=device_item.connector_id,
                    device_id=device_item.device_id,
                    device_data=to_update,
                ),
            )

        self.__logger.debug("Consumed device firmware info message for: %s", device_item.identifier)

#!/usr/bin/python3 #     Copyright 2021. FastyBird s.r.o. # #     Licensed under the Apache License, Version 2.0 (the "License"); #     you may not use this file except in compliance with the License. #     You may obtain a copy of the License at # #         http://www.apache.org/licenses/LICENSE-2.0 # #     Unless required by applicable law or agreed to in writing, software #     distributed under the License is distributed on an "AS IS" BASIS, #     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #     See the License for the specific language governing permissions and #     limitations under the License. FastyBird MQTT connector consumers module devices messages consumer # Python base dependencies # App dependencies # App libs # pylint: disable=too-few-public-methods Device attribute message consumer      @package        FastyBird:MiniServer!     @module         device      @author         <NAME> <<EMAIL>> # ----------------------------------------------------------------------------- # pylint: disable=too-many-arguments # ----------------------------------------------------------------------------- Consume received message # ----------------------------------------------------------------------------- # ----------------------------------------------------------------------------- # ----------------------------------------------------------------------------- # ----------------------------------------------------------------------------- # pylint: disable=too-few-public-methods Device hardware info message consumer      @package        FastyBird:MiniServer!     @module         device      @author         <NAME> <<EMAIL>> # ----------------------------------------------------------------------------- # ----------------------------------------------------------------------------- Consume received message # pylint: disable=too-few-public-methods Device firmware info message consumer      @package        FastyBird:MiniServer!     @module         device      @author         <NAME> <<EMAIL>> # ----------------------------------------------------------------------------- # ----------------------------------------------------------------------------- Consume received message