import appdaemon.adbase as appapi
import appdaemon.utils as utils
import asyncio
import inspect
import traceback


class Entities:

    def __get__(self, instance, owner):
        state = utils.StateAttrs(instance.ad.get_state(instance.namespace, None, None, None))
        return state


class Mqtt(appapi.ADBase):

    entities = Entities()

    def __init__(self, ad, name, logger, error, args, config, app_config, global_vars,):

        super(Mqtt, self).__init__(ad, name, logger, error, args, config, app_config, global_vars)

        self.AD = ad
        self.name = name
        self._logger = logger
        self._error = error
        self.args = args
        self.config = config
        self.app_config = app_config
        self.global_vars = global_vars
        self.loop = self.AD.loop

    #
    # service calls
    #
    def mqtt_publish(self, topic, payload = None, **kwargs):
        kwargs['topic'] = topic
        kwargs['payload'] = payload
        service = 'publish'
        result = self.call_service(service, **kwargs)
        return result

    def mqtt_subscribe(self, topic, **kwargs):
        kwargs['topic'] = topic
        service = 'subscribe'
        result = self.call_service(service, **kwargs)
        return result

    def mqtt_unsubscribe(self, topic, **kwargs):
        kwargs['topic'] = topic
        service = 'unsubscribe'
        result = self.call_service(service, **kwargs)
        return result

    def call_service(self, service, **kwargs):
        self.AD.log(
            "DEBUG",
            "call_service: {}, {}".format(service, kwargs)
        )
        
        namespace = self._get_namespace(**kwargs)

        if 'topic' in kwargs:
            if not self.AD.get_plugin(namespace).active(): #ensure mqtt plugin is connected
                self.log("Attempt to call Mqtt Service while disconnected: {!r}".format(service), level="WARNING")
                return None

            try:
                result = self.AD.get_plugin(namespace).mqtt_service(service, **kwargs)
                
            except Exception as e:
                config = self.AD.get_plugin(namespace).config
                if config['type'] == 'mqtt':
                    self.AD.log('DEBUG', 'Got the following Error {}, when trying to retrieve Mqtt Plugin'.format(e))
                    self.error('Got error with the following {}'.format(e))
                    return str(e)
                else:
                    self.AD.log('CRITICAL', 'Wrong Namespace {!r} selected for MQTT Service. Please use proper namespace before trying again'.format(namespace))
                    self.error('Could not execute Service Call, as wrong Namespace {!r} used'.format(namespace))
                    return 'ERR'
        else:
            self.AD.log('DEBUG', 'Topic not provided for Service Call {!r}.'.format(service))
            raise ValueError("Topic not provided, please provide Topic for Service Call")

        return result

@@ -795,16 +795,716 @@
 D.loop%0A%0A
+    #%0A    # Listen state stub here as super class doesn't know the namespace%0A    #%0A%0A    def listen_event(self, cb, event=None, **kwargs):%0A        namespace = self._get_namespace(**kwargs)%0A%0A        if 'wildcard' in kwargs:%0A            wildcard = kwargs%5B'wildcard'%5D%0A            if wildcard%5B-2:%5D == '/#' and len(wildcard.split('/')%5B0%5D) %3E= 1:%0A                self.AD.get_plugin(namespace).process_mqtt_wildcard(kwargs%5B'wildcard'%5D)%0A            else:%0A                self.log(%22Using %7B!r%7D as MQTT Wildcard for Event is not valid, use another. Listen Event will not be registered%22.format(wildcard), level=%22WARNING%22)%0A                return%0A%0A        return super(Mqtt, self).listen_event(cb, event, **kwargs)%0A%0A
     #%0A  

Update mqttapi.py