Beispiel #1
0
def main():
    global args, write_api
    parser = ArgumentParser(description=__doc__)
    parser.add_argument("--host",
                        default='localhost',
                        help='hostname of mqtt broker')
    parser.add_argument(
        "-t",
        action='append',
        default=['velogen/raw'],
        help='MQTT topic to subscribe to. Can be put multiple times.')
    parser.add_argument("-d", action='store_true', help='enable debug output')
    parser.add_argument("--user", default=None, help="username")
    parser.add_argument("--pw", default=None, help="password")

    args = parser.parse_args()

    client = Client()
    client.on_connect = on_connect
    client.on_disconnect = on_disconnect
    client.on_message = on_message
    if args.user is not None and args.pw is not None:
        client.username_pw_set(args.user, args.pw)
    client.connect(args.host)

    # For influxdb2 only
    db = InfluxDBClient(url='http://localhost:8086', token=token, debug=args.d)
    write_api = db.write_api(write_options=SYNCHRONOUS)

    while True:
        client.loop(timeout=1.0)
Beispiel #2
0
def main():
    global args
    parser = ArgumentParser(description=__doc__)
    parser.add_argument(
        "--host", default='localhost',
        help='hostname of mqtt broker'
    )
    parser.add_argument(
        "--topic", default='velogen/raw',
        help='comma separated list of MQTT topics to subscribe to'
    )
    args = parser.parse_args()

    c = Client()
    c.on_connect = on_connect
    c.on_disconnect = on_disconnect
    c.on_message = on_message
    c.connect(args.host)

    atexit.register(commit)

    while True:
        ts = datetime.now().timestamp()
        for tp, rts in rx_ts_dict.items():
            if rts is not None:
                # dump to file after 30 s of silence
                if ts - rts > 30:
                    clean_write(tp)
                    rx_ts_dict[tp] = None
        c.loop(1.0)
Beispiel #3
0
    def execute(self, chat_id, args):
        client = Client(userdata=self.user_data)

        connect_result = client.connect(self.config["server"])
        if not connect_result == MQTT_ERR_SUCCESS:
            raise Exception(
                "Client connection error {}".format(connect_result))

        topics = self.get_topic_list()
        for topic in topics:
            (subs_result, subs_id) = client.subscribe(topic)

        client.on_message = self.on_message
        if not subs_result == MQTT_ERR_SUCCESS:
            raise Exception("Subscription error {}".format(subs_result))

        time_start = time.time()
        while True:
            client.loop()

            if self.user_data["messages_received"] >= len(topics):
                break

            if time.time() - time_start > 10:
                break

        self.bot.sendMessage(chat_id, self.format_output())
Beispiel #4
0
def run(mqtt_client: paho.Client) -> None:
    """ Reads any messages from the queue and publishing them to the MQTT broker. """

    # Keep batches small, only send the latest X messages. The rest will be trimmed (in case of delay).
    message_queue = queue.Message.objects.all().order_by(
        '-pk')[0:settings.DSMRREADER_MQTT_MAX_MESSAGES_IN_QUEUE]

    if not message_queue:
        return

    logger.debug('MQTT: Processing %d message(s)', len(message_queue))

    for current in message_queue:
        logger.debug('MQTT: Publishing queued message (#%s) for %s: %s',
                     current.pk, current.topic, current.payload)
        message_info = mqtt_client.publish(
            topic=current.topic,
            payload=current.payload,
            qos=settings.DSMRREADER_MQTT_QOS_LEVEL,
            retain=True)

        loop_result = mqtt_client.loop(0.1)

        # Detect any networking errors early.
        if loop_result != paho.MQTT_ERR_SUCCESS:
            signal_reconnect()
            raise RuntimeError(
                'MQTT: Client loop() failed, requesting restart...')

        # Always True when using QoS 0 (as designed). For QoS 1 and 2 however, this BLOCKS further processing and
        # message deletion below, until the broker acknowledges the message was received.
        # Networking errors should terminate this loop as well, along with a request for restart.
        while not message_info.is_published():
            logger.debug(
                'MQTT: Waiting for message (#%s) to be marked published by broker',
                current.pk)
            loop_result = mqtt_client.loop(0.5)

            # Prevents infinite loop on connection errors.
            if loop_result != paho.MQTT_ERR_SUCCESS:
                signal_reconnect()
                raise RuntimeError(
                    'MQTT: Client loop() failed, requesting restart to prevent waiting forever...'
                )

        logger.debug('MQTT: Deleting published message (#%s) from queue',
                     current.pk)
        current.delete()

    # Delete any overflow in messages.
    queue.Message.objects.all().delete()
def run_client(settings):
    def on_connect(*args, **kwargs):
        print("connected")

    def on_message(*args, **kwargs):
        print("message received", args, kwargs)

    client = MQTTClient()
    client.on_connect = on_connect
    client.on_message = on_message
    client.connect(server, settings["mqtt_settings"]["port"], 60)
    t0 = time.time()
    while True:
        time.sleep(1)
        client.loop()
        td = time.time() - t0
        f = lambda x: np.log(x / 10) * 10 + 50
        data = '{"meat_temp": %.1f, "oven_temp": %.1f}' % (f(td), f(td + 100))
        print("publishing data")
        client.publish("test_topic", data)
Beispiel #6
0
    def test_run_success(self, load_subscribed_topics_mock, isdir_mock):
        # mock function call to load subscribed topics
        load_subscribed_topics_mock.return_value = MagicMock()
        input = [0, 0, 1]
        isdir_mock.return_value = True
        loop_mock = MagicMock()
        loop_mock.side_effect = input

        client_mock = Client(MagicMock())
        client_mock.connect = MagicMock()
        client_mock.loop = loop_mock
        mqtt_client = MQTT(client_mock)
        mqtt_client.run()

        self.assertEqual(client_mock.connect.call_count, 1)
        self.assertEqual(client_mock.loop.call_count, len(input))
class HotWord(object):
    def __init__(self):
        self.received_lamp_state = None
        self.color_database = json.load(open('color.json'))
        self.client = Client(client_id='google_home')
        self.client.on_connect = self.on_connect
        self.client.connect('localhost', port=1883, keepalive=60)
        self._wait_for_lamp_state()
        self.client.loop_start()

    def _receive_lamp_state(self, client, userdata, message):
        print(message.payload)
        self.received_lamp_state = json.loads(message.payload.decode("utf-8"))

    def on_connect(self, client, userdata, flags, rc):
        client.message_callback_add('/lamp/changed', self._receive_lamp_state)
        client.subscribe('/lamp/changed', qos=1)

    def _wait_for_lamp_state(self):
        for i in range(10):
            if self.received_lamp_state:
                return
            self.client.loop(0.05)
        raise Exception("Timeout waiting for lamp state")

    def process_device_actions(self, event, device_id):
        if 'inputs' in event.args:
            for i in event.args['inputs']:
                if i['intent'] == 'action.devices.EXECUTE':
                    for c in i['payload']['commands']:
                        for device in c['devices']:
                            if device['id'] == device_id:
                                if 'execution' in c:
                                    for e in c['execution']:
                                        if 'params' in e:
                                            yield e['command'], e['params']
                                        else:
                                            yield e['command'], None

    def process_event(self, event, device_id):
        """Pretty prints events.

        Prints all events that occur with two spaces between each new
        conversation and a single space between turns of a conversation.

        Args:
            event(event.Event): The current event to process.
            device_id(str): The device ID of the new instance.
        """
        if event.type == EventType.ON_CONVERSATION_TURN_STARTED:
            print()

        print(event)

        if (event.type == EventType.ON_CONVERSATION_TURN_FINISHED
                and event.args and not event.args['with_follow_on_turn']):
            print()
        if event.type == EventType.ON_DEVICE_ACTION:
            for command, params in self.process_device_actions(
                    event, device_id):
                print('Do command', command, 'with params', str(params))
                if command == "action.devices.commands.OnOff":
                    if params['on']:
                        self.received_lamp_state['client'] = 'google_home'
                        self.received_lamp_state['on'] = True
                        print('Turning the LED on.')
                    else:
                        self.received_lamp_state['client'] = 'google_home'
                        self.received_lamp_state['on'] = False
                        print('Turning the LED off.')
                    self.client.publish('/lamp/set_config',
                                        json.dumps(self.received_lamp_state),
                                        qos=1)
                if command == "action.devices.commands.ColorAbsolute":
                    if params['color']:
                        print("hello it is me color")
                        color = params['color'].get('name')
                        hue = self.color_database[color]['hue']
                        saturation = self.color_database[color]['saturation']
                        self.received_lamp_state['color']['h'] = round(hue, 2)
                        self.received_lamp_state['color']['s'] = round(
                            saturation, 2)
                        self.received_lamp_state['client'] = 'google_home'
                        self.client.publish('/lamp/set_config',
                                            json.dumps(
                                                self.received_lamp_state),
                                            qos=1)
                if command == "action.devices.commands.BrightnessAbsolute":
                    if params['brightness']:
                        print("hello")
                        brightness = (params['brightness']) / 100
                        print(brightness)
                        self.received_lamp_state['brightness'] = brightness
                        self.received_lamp_state['client'] = 'google_home'
                        self.client.publish('/lamp/set_config',
                                            json.dumps(
                                                self.received_lamp_state),
                                            qos=1)
                sleep(0.1)
                self.client.loop_stop()

    def register_device(self, project_id, credentials, device_model_id,
                        device_id):
        """Register the device if needed.

        Registers a new assistant device if an instance with the given id
        does not already exists for this model.

        Args:
           project_id(str): The project ID used to register device instance.
           credentials(google.oauth2.credentials.Credentials): The Google
                    OAuth2 credentials of the user to associate the device
                    instance with.
           device_model_id(str): The registered device model ID.
           device_id(str): The device ID of the new instance.
        """
        base_url = '/'.join(
            [DEVICE_API_URL, 'projects', project_id, 'devices'])
        device_url = '/'.join([base_url, device_id])
        session = google.auth.transport.requests.AuthorizedSession(credentials)
        r = session.get(device_url)
        print(device_url, r.status_code)
        if r.status_code == 404:
            print('Registering....')
            r = session.post(base_url,
                             data=json.dumps({
                                 'id': device_id,
                                 'model_id': device_model_id,
                                 'client_type': 'SDK_LIBRARY'
                             }))
            if r.status_code != 200:
                raise Exception('failed to register device: ' + r.text)
            print('\rDevice registered.')

    def main(self):
        parser = argparse.ArgumentParser(
            formatter_class=argparse.RawTextHelpFormatter)
        parser.add_argument('--credentials',
                            type=existing_file,
                            metavar='OAUTH2_CREDENTIALS_FILE',
                            default=os.path.join(
                                os.path.expanduser('~/.config'),
                                'google-oauthlib-tool', 'credentials.json'),
                            help='Path to store and read OAuth2 credentials')
        parser.add_argument('--device_model_id',
                            type=str,
                            metavar='DEVICE_MODEL_ID',
                            required=True,
                            help='The device model ID registered with Google')
        parser.add_argument(
            '--project_id',
            type=str,
            metavar='PROJECT_ID',
            required=False,
            help='The project ID used to register device instances.')
        parser.add_argument('-v',
                            '--version',
                            action='version',
                            version='%(prog)s ' + Assistant.__version_str__())

        args = parser.parse_args()
        with open(args.credentials, 'r') as f:
            credentials = google.oauth2.credentials.Credentials(token=None,
                                                                **json.load(f))

        with Assistant(credentials, args.device_model_id) as assistant:
            events = assistant.start()

            print('device_model_id:',
                  args.device_model_id + '\n' + 'device_id:',
                  assistant.device_id + '\n')

            if args.project_id:
                register_device(args.project_id, credentials,
                                args.device_model_id, assistant.device_id)

            for event in events:
                self.process_event(event, assistant.device_id)
Beispiel #8
0
class MQTTClient:
    """ mqtt客户端的父类
    """

    def __init__(self, host, port,
                 client_id=None,
                 clean_session=False,
                 keepalive=60):

        self.client = Client()
        if client_id:
            self.client._client_id = client_id
            self.client._clean_session = False

        self.host = host
        self.port = port
        self.keepalive = keepalive

        self.connected = False

        self.client.on_connect = self._on_connect
        self.client.on_message = self._on_message
        self.client.on_log = self._on_log

    def connect(self, user='******', password='******'):
        rc = 1
        if self.connected:
            return 0

        self.client.username_pw_set(user, password)
        try:
            rc = self.client.connect(self.host, self.port, self.keepalive)
            assert rc == 0, ConnectionRefusedError
            self.connected = True

        except ConnectionRefusedError:
            log.error('Retry after 1 second.')

        return rc

    def disconnect(self):
        self.connected = False
        self.client.disconnect()

    def loop(self, timeout=None):
        if timeout:
            self.client.loop(timeout=timeout)
        else:
            self.client.loop_forever()

    def loop_start(self):
        return self.client.loop_start()

    def publish(self, topic, data={}, qos=1):
        (rc, final_mid) = self.client.publish(topic, json.dumps(data), qos=qos)
        return rc, final_mid

    def _on_connect(self, client, userdata, flags, rc):
        pass

    def _on_message(self, client, userdata, msg):
        pass

    def _on_log(self, client, userdata, level, buf):
        return buf
class JMSClient(object):
    """Class JMSClient
    """

    _mh = None
    _client = None
    _host = None
    _port = None
    _user = None
    _passw = None
    _verbose = None
    _is_connected = None
    _messages = []

    def __init__(self, verbose=False):
        """Class constructor

        Called when the object is initialized

        Args:                   
           verbose (bool): verbose mode

        """

        try:

            self._mh = MasterHead.get_head()

            self._client = Client()
            self._client.on_message = self._on_message

            self._verbose = verbose
            if (self._verbose):
                self._client.on_log = self._on_log

        except MQTTException as ex:
            self._mh.demsg('htk_on_error', ex, self._mh.fromhere())

    @property
    def client(self):
        """ MQTT client property getter """

        return self._client

    @property
    def host(self):
        """ server host property getter """

        return self._host

    @property
    def port(self):
        """ server port property getter """

        return self._port

    @property
    def user(self):
        """ username property getter """

        return self._user

    @property
    def passw(self):
        """ user password property getter """

        return self._passw

    @property
    def verbose(self):
        """ verbose property getter """

        return self._verbose

    @property
    def is_connected(self):
        """ is_connected property getter """

        return self._is_connected

    def _on_log(self, client, obj, level, string):
        """ Callback for on_log event """

        print(string)

    def _on_message(self, client, obj, msg):
        """ Callback for on_message event """

        self._messages.append(msg.payload.decode())

    def connect(self, host, port=1883, user=None, passw=None, timeout=10):
        """Method connects to server

        Args:
           host (str): hostname
           port (str): port
           user (str): username
           passw (str): password
           timeout (int): timeout

        Returns:
           bool: result

        Raises:
           event: jms_before_connect
           event: jms_after_connected            

        """

        try:

            msg = 'host:{0}, port:{1}, user:{2}, passw:{3}, timeout:{4}'.format(
                host, port, user, passw, timeout)
            self._mh.demsg('htk_on_debug_info', self._mh._trn.msg(
                'htk_jms_connecting', msg), self._mh.fromhere())

            ev = event.Event(
                'jms_before_connect', host, port, user, passw, timeout)
            if (self._mh.fire_event(ev) > 0):
                host = ev.argv(0)
                port = ev.argv(1)
                user = ev.argv(2)
                passw = ev.argv(3)
                timeout = ev.argv(4)

            self._host = host
            self._port = port
            self._user = user
            self._passw = passw

            if (ev.will_run_default()):
                if (self._user != None):
                    self._client.username_pw_set(self._user, self._passw)

                setdefaulttimeout(timeout)
                self._client.connect(self._host, self._port)
                self._is_connected = True

            self._mh.demsg('htk_on_debug_info', self._mh._trn.msg(
                'htk_jms_connected'), self._mh.fromhere())
            ev = event.Event('jms_after_connect')
            self._mh.fire_event(ev)

            return True

        except (MQTTException, error, ValueError) as ex:
            self._mh.demsg('htk_on_error', ex, self._mh.fromhere())
            return False

    def disconnect(self):
        """Method disconnects from server 

        Args:   
           none       

        Returns:
           bool: result

        """

        try:

            self._mh.demsg('htk_on_debug_info', self._mh._trn.msg(
                'htk_jms_disconnecting'), self._mh.fromhere())

            if (not self._is_connected):
                self._mh.demsg('htk_on_warning', self._mh._trn.msg(
                    'htk_jms_not_connected'), self._mh.fromhere())
                return False
            else:
                self._client.disconnect()
                self._is_connected = False
                self._mh.demsg('htk_on_debug_info', self._mh._trn.msg(
                    'htk_jms_disconnected'), self._mh.fromhere())
                return True

        except (MQTTException, error, ValueError) as ex:
            self._mh.demsg('htk_on_error', ex, self._mh.fromhere())
            return False

    def send(self, destination_name, message):
        """Method sends message

        Args:
           destination_name (str): topic name
           message (str): message

        Returns:
           bool: result

        Raises:
           event: jms_before_send
           event: jms_after_send             

        """

        try:

            msg = 'destination_name:{0}, message:{1}'.format(
                destination_name, message)
            self._mh.demsg('htk_on_debug_info', self._mh._trn.msg(
                'htk_jms_sending_msg', msg), self._mh.fromhere())

            if (not self._is_connected):
                self._mh.demsg('htk_on_warning', self._mh._trn.msg(
                    'htk_jms_not_connected'), self._mh.fromhere())
                return False

            ev = event.Event('jms_before_send', destination_name, message)
            if (self._mh.fire_event(ev) > 0):
                destination_name = ev.argv(0)
                message = ev.argv(1)

            if (ev.will_run_default()):
                res, id = self._client.publish(destination_name, message)

                if (res != 0):
                    self._mh.demsg('htk_on_error', self._mh._trn.msg(
                        'htk_jms_sending_error'), self._mh.fromhere())

            self._mh.demsg('htk_on_debug_info', self._mh._trn.msg(
                'htk_jms_msg_sent'), self._mh.fromhere())
            ev = event.Event('jms_after_send')
            self._mh.fire_event(ev)

            return True

        except (MQTTException, error, ValueError) as ex:
            self._mh.demsg('htk_on_error', ex, self._mh.fromhere())
            return False

    def receive(self, destination_name, cnt=1, timeout=10):
        """Method receives messages

        Args:
           destination_name (str): queue name
           cnt (int): count of messages
           timeout (int): timeout to receive message

        Returns:
           list:  messages

        Raises:
           event: jms_before_receive
           event: jms_after_receive             

        """

        try:

            msg = 'destination_name:{0}, count:{1}'.format(
                destination_name, cnt)
            self._mh.demsg('htk_on_debug_info', self._mh._trn.msg(
                'htk_jms_receiving_msg', msg), self._mh.fromhere())

            if (not self._is_connected):
                self._mh.demsg('htk_on_warning', self._mh._trn.msg(
                    'htk_jms_not_connected'), self._mh.fromhere())
                return None

            ev = event.Event('jms_before_receive', destination_name, cnt)
            if (self._mh.fire_event(ev) > 0):
                destination_name = ev.argv(0)
                cnt = ev.argv(1)

            if (ev.will_run_default()):
                res, id = self._client.subscribe(destination_name)
                if (res != 0):
                    self._mh.demsg('htk_on_error', self._mh._trn.msg(
                        'htk_jms_sending_error'), self._mh.fromhere())
                    return None

                res = 0
                cnt_before = 0
                start = time()
                while (res == 0):
                    res = self._client.loop()
                    cnt_after = len(self._messages)
                    if (cnt_after > cnt_before and cnt_after < cnt):
                        cnt_before = cnt_after
                    elif (cnt_after == cnt or time() > start + timeout):
                        res = -1

                messages = self._messages
                self._client.unsubscribe(destination_name)
                self._messages = []

            self._mh.demsg('htk_on_debug_info', self._mh._trn.msg(
                'htk_jms_msg_received', len(messages)), self._mh.fromhere())
            ev = event.Event('jms_after_receive')
            self._mh.fire_event(ev)

            return messages

        except (MQTTException, error, ValueError) as ex:
            self._mh.demsg('htk_on_error', ex, self._mh.fromhere())
            return None
Beispiel #10
0
import time
from paho.mqtt.client import Client
 
def on_message(c, userdata, mesg):
    print "message: %s %s %s" % (userdata, mesg.topic, mesg.payload)
 
client = Client(client_id="my_id", userdata="user1")
client.connect("172.27.246.86")
client.on_message = on_message
client.subscribe("temp_value")
while True:
    client.loop()
    time.sleep(1)
def IniciarVerificacaoDeAtualizacao(client: mqtt.Client):
    while True:
        client.loop()
        time.sleep(1)
Beispiel #12
0
class PipaMQTTClient(object): 

    def __init__(self, client_id, host, port=1883, **kwargs):
        self._logger = logging.getLogger("gsensors.PipaMQTTClient")
        self._host = host
        self._port = port
        self._mqtt_client = Client(client_id=client_id, clean_session=False)
        self._mqtt_client.on_connect = self.on_connect
        self._mqtt_client.on_disconnect = self.on_disconnect
        self._mqtt_client.on_message = self.on_message

        self.worker = None
        self.worker_runner = None
        self.topics_sources = {}
        self.running = False
        self.connected = False

    def publish(self, topic, payload=None, qos=0, retain=False):
        # check connected
        if not self.connected:
            raise RuntimeError("MQTT client not connected ! ")
        if not self.running:
            raise RuntimeError("MQTT client not running ! ")
        self._mqtt_client.publish(topic, payload=payload, qos=qos, retain=retain)

    def PublishAction(self, topic, payload=None, retain=False):
        if payload is None:
            def _action(source, value):
                data = "%s" % value
                self._logger.debug("publish %s: %s" % (topic, data))
                self.publish(topic, payload=data, retain=retain)
        else:
            def _action(*args, **kwargs):
                self._logger.debug("publish %s: %s" % (topic, payload))
                self.publish(topic, payload=payload, retain=retain)
        return _action

    def on_disconnect(self, client, userdata, rc):
        self._logger.error("Disconnected with result code: "+str(rc))
        self.connected = False
        self.connect()

    def on_connect(self, client, userdata, flags, rc):
        if rc == 0:
            self._logger.info("Connected to MQTT broker")
            self.connected = True
            # Subscribing in on_connect() means that if we lose the connection and
            # reconnect then subscriptions will be renewed.
            #client.subscribe("$SYS/#")
            #client.subscribe("#")
            for topic in self.topics_sources.keys():
                client.subscribe(topic)
        else:
            self._logger.error("Connection fail with error: %s" % rc)

    def on_message(self, client, userdata, msg):
        self._logger.debug("get a msg %s: %s" % (msg.topic, msg.payload))
        if msg.topic in self.topics_sources:
            source = self.topics_sources[msg.topic]
            source.update(msg)

    def register_source(self, source, topic):
        # check that topic has no wildcard
        assert "#" not in topic
        if topic in self.topics_sources:
            raise ValueError("topic already monitored")
        self.topics_sources[topic] = source
        self._mqtt_client.subscribe(topic)
        return source

    def connect(self):
        self.worker_runner = gevent.spawn(self._connect)

    def _connect(self):
        while not self.connected:
            try:
                #self._mqtt_client.reinitialise()
                self._mqtt_client.connect(host=self._host, port=self._port, keepalive=60)
            except socket.error as err:
                self._logger.error("Imposible to connect to MQTT: %s" % err)
                self._logger.info("Will retry in 2 seconds")
            gevent.sleep(2)

    def wait_connected(self):
        while not self.connected:
            gevent.sleep(1)

    def start(self):
        if self.running:
            return
        self.running = True
        self.worker = gevent.spawn(self._mqtt_loop)
        self.connect()

    def _mqtt_loop(self):
        while self.running:
            self._mqtt_client.loop(timeout=0.02)
            gevent.sleep(0.01)
Beispiel #13
0
class Mqtt(Abstract):
    def __init__(self, service_info=None):
        self.connected = False
        self.client = None
        self.queue = Queue()

        super().__init__(service_info)

    def start(self):
        self.connect()
        self.receive_msgs()

    def stop(self):
        self.stop_receiving_msgs()
        self.disconnect()

    def add_stream(self, stream):
        self.streams[stream.name] = stream

    def remove_stream(self, name):
        if name in self.streams.keys():
            self.streams.pop(name)

    def remove_all_streams(self):
        self.streams = {}

    def is_connected(self):
        if self.client and self.connected:
            return True

        return False

    def connect(self):
        if not self.client:
            host = self.service_info['host']
            port = self.service_info['port']

            self.client = Client()
            self.client.on_message = self.on_mqtt_msg
            self.client.on_connect = self.on_connect
            self.client.on_disconnect = self.on_disconnect
            self.client.connect(host, port, 60)

    def on_connect(self, client, userdata, flags, rc):
        self.connected = True

    def disconnect(self):
        if self.client:
            self.client.disconnect()

    def on_disconnect(self, client, userdata, rc):
        self.client = None
        self.connected = False

    def send_msg(self, msg, tx_info=None):
        if self.client:
            topic = None

            if tx_info:
                topic = tx_info['topic']
            elif self.service_info:
                topic = self.service_info['publish']['default_topic']

            if self.client and topic:
                self.client.publish(topic, msg)
        else:
            raise MqttError('Cannot send message without a client')

    def receive_msgs(self):
        topics = self.service_info['subscribe']['topics']

        if self.client:
            for t in topics:
                self.client.subscribe(t, 0)

            sub_type = self.service_info['subscribe']['type']

            if sub_type == 'blocking':
                self.client.loop_forever()
            elif sub_type == 'unblocking':
                self.client.loop_start()
            elif sub_type == 'polled':
                self.client.loop(self.service_info['subscribe']['loop_time'])
            else:
                self.client.loop(.1)

        else:
            raise MqttError('Cannot receive message without a client')

    def stop_receiving_msgs(self):
        topics = self.service_info['subscribe']['topics']

        if self.client:
            for t in topics:
                self.client.unsubscribe(t)

            self.client.loop_stop()

    def handle_msg(self):
        msg = self.queue.get()
        print(f'Received: {msg["topic"]}::{msg["msg"]}')
        data = super().handle_msg(msg)

        for k, s in self.streams.items():
            events = []

            for d in data:
                timestamp = d.timestamp
                sample = getattr(d, s.handle)
                events.append(Event(timestamp, sample))

            s.handle_msg(events)

    def on_mqtt_msg(self, client, userdata, msg):
        payload = {}
        payload['topic'] = msg.topic
        payload['msg'] = msg.payload

        self.queue.put(payload)
        self.handle_msg()
Beispiel #14
0
class Mqtt():

    def __init__(self, app=None):
        self.app = app
        self.client = Client()
        self.refresh_time = 1.0
        self.topics = []
        self.mqtt_thread = Thread(target=self._loop_forever)
        self.mqtt_thread.daemon = True

        if app is not None:
            self.init_app(app)

    def init_app(self, app):
        self.refresh_time = app.config.get('MQTT_REFRESH_TIME', 1.0)

        self._connect(
            username=app.config.get('MQTT_USERNAME'),
            password=app.config.get('MQTT_PASSWORD'),
            broker_url=app.config.get('MQTT_BROKER_URL', 'localhost'),
            broker_port=app.config.get('MQTT_BROKER_PORT', 1883)
        )

    def _connect(self, username, password, broker_url, broker_port):
        if not self.mqtt_thread.is_alive():

            if username is not None:
                self.client.username_pw_set(username, password)

            res = self.client.connect(broker_url, broker_port)

            if res == 0:
                self.mqtt_thread.start()

    def _disconnect(self):
        self.client.disconnect()

    def _loop_forever(self):
        while True:
            time.sleep(self.refresh_time)
            self.client.loop(timeout=1.0, max_packets=1)

    def on_topic(self, topic: str):
        """
        Decorator to add a callback function that is called when a certain
        topic has been published. The callback function is expected to have the
        following form: `handle_topic(client, userdata, message)`

        :parameter topic: a string specifying the subscription topic to subscribe to

        **Example usage:**

        ::

            @on_topic('home/mytopic')
            def handle_mytopic(client, userdata, message):
                print('Received message on topic {}: {}'
                      .format(message.topic, message.payload.decode()))

        """
        def decorator(handler):
            self.client.message_callback_add(topic, handler)
            return handler
        return decorator

    def subscribe(self, topic: str, qos: int=0):
        """
        Subscribe to a certain topic.

        :param topic: a string specifying the subscription topic to subscribe to.
        :param qos: the desired quality of service level for the subscription.
                    Defaults to 0.

        A topic is a UTF-8 string, which is used by the broker to filter
        messages for each connected client. A topic consists of one or more
        topic levels. Each topic level is separated by a forward slash
        (topic level separator).

        **Topic example:** `myhome/groundfloor/livingroom/temperature`

        """
        # TODO: add support for list of topics
        # don't subscribe if already subscribed
        if topic in self.topics:
            return

        # try to subscribe
        result, mid = self.client.subscribe(topic, qos)

        # if successful add to topics
        if result == MQTT_ERR_SUCCESS:
            self.topics.append(topic)

        return result

    def unsubscribe(self, topic: str):
        """
        Unsubscribe from a single topic.

        :param topic: a single string that is the subscription topic to
                      unsubscribe from

        """
        # don't unsubscribe if not in topics
        if topic not in self.topics:
            return

        result, mid = self.client.unsubscribe(topic)

        # if successful remove from topics
        if result == MQTT_ERR_SUCCESS:
            self.topics.remove(topic)

        return result

    def unsubscribe_all(self):
        """
        Unsubscribe from all topics.

        """
        topics = self.topics[:]
        for topic in topics:
            self.unsubscribe(topic)

    def publish(self, topic: str, payload: bytes=None, qos: int=0,
                retain: bool=False) -> Tuple[int, int]:
        """
        Send a message to the broker.

        :param topic: the topic that the message should be published on
        :param payload: the actual message to send. If not given, or set to
                        None a zero length message will be used. Passing an
                        int or float will result in the payload being
                        converted to a string representing that number.
                        If you wish to send a true int/float, use struct.pack()
                        to create the payload you require.
        :param qos: the quality of service level to use
        :param retain: if set to True, the message will be set as the
                       "last known good"/retained message for the topic

        :returns: Returns a tuple (result, mid), where result is
                  MQTT_ERR_SUCCESS to indicate success or MQTT_ERR_NO_CONN
                  if the client is not currently connected. mid is the message
                  ID for the publish request.

        """
        return self.client.publish(topic, payload, qos, retain)

    def on_message(self):
        """
        Decorator to handle all messages that have been subscribed.

        **Example Usage:**

        ::

            @mqtt.on_message()
            def handle_messages(client, userdata, message):
                print('Received message on topic {}: {}'
                      .format(message.topic, message.payload.decode()))

        """
        def decorator(handler):
            self.client.on_message = handler
            return handler
        return decorator