openrvdas.logger.readers.mqtt_reader

No module-level documentation available.
  1#!/usr/bin/env python3
  2
  3import logging
  4from queue import Queue
  5
  6# Don't barf if they don't have redis installed. Only complain if
  7# they actually try to use it, below
  8try:
  9    import paho.mqtt.client as mqtt  # import the client | $ pip installing paho-mqtt is necessary
 10    PAHO_ENABLED = True
 11
 12    # Check which paho version is being used
 13    from pkg_resources import get_distribution, packaging  # noqa: E402
 14    PAHO_VERSION = get_distribution('paho-mqtt').version
 15    if packaging.version.parse(PAHO_VERSION) >= packaging.version.parse('2.0.0'):
 16        USE_VERSION_FLAG = True
 17    else:
 18        USE_VERSION_FLAG = False
 19except ModuleNotFoundError:
 20    PAHO_ENABLED = False
 21
 22from logger.readers.reader import Reader  # noqa: E402
 23
 24
 25################################################################################
 26class MQTTReader(Reader):
 27    """
 28    Read messages from an mqtt broker
 29    """
 30
 31    def __init__(self, broker, channel, client_name,
 32                 port=1883, clean_start=None,
 33                 qos=0, return_as_bytes=False, **kwargs):
 34        """
 35        Read text records from the channel subscription.
 36        ```
 37
 38        broker       MQTT broker to connect, broker format[###.###.#.#]
 39        channel      MQTT channel to read from, channel format[@broker/path_of_subscripton]
 40        port         broker port, typically 1883
 41        clean_start  Request new session on first connection. Options: True, False,
 42                       or the default of mqtt.MQTT_CLEAN_START_FIRST_ONLY
 43        qos          Quality of service: 0 = at most once, 1 = at least once, 2 = exactly once
 44        return_as_bytes
 45                     If true, return message in bytes, otherwise convert to str
 46        ```
 47        Instructions on how to start an MQTT broker:
 48
 49        1. First install the Mosquitto Broker :
 50            ```
 51            sudo apt-get update
 52            sudo apt-get install mosquitto
 53            sudo apt-get install mosquitto-clients
 54            ```
 55        2. The mosquitto service starts automatically when downloaded but use :
 56            ```
 57            sudo service mosquitto start
 58            sudo service mosquitto stop
 59            ```
 60            to start and stop the service.
 61
 62        3. To test the install use:
 63            ```
 64            netstat -at
 65            ```
 66            and you should see the MQTT broker which is the port 1883
 67
 68        4. In order to manually subscribe to a client use :
 69            ```
 70            mosquitto_sub -t "example/topic"
 71            ```
 72            and publish a message by using
 73            ```
 74            mosquitto_pub -m "published message" -t "certain/channel"
 75            ```
 76        5. Mosquitto uses a configuration file "mosquitto.conf" which you can
 77           find in /etc/mosquitto 	folder
 78
 79        ```
 80        """
 81        if not PAHO_ENABLED:
 82            raise ModuleNotFoundError('MQTTReader(): paho-mqtt is not installed. Please '
 83                                      'try "pip install paho-mqtt" prior to use.')
 84        if qos not in [0, 1, 2]:
 85            raise ValueError('MQTTReader parameter qos must be integer value 0, 1 or 2. '
 86                             f'Found type "{type(qos).__name__}", value "{qos}".')
 87
 88        # Let's build it!
 89        super().__init__(**kwargs)
 90
 91        def on_connect(client, userdata, flags, rc, properties=None):
 92            logging.info(f'Connected With Result Code: {rc}')
 93
 94        def on_message(client, userdata, message):
 95            self.queue.put(message)
 96
 97        self.broker = broker
 98        self.channel = channel
 99        self.client_name = client_name
100        self.port = port
101        if clean_start is None:
102            clean_start = mqtt.MQTT_CLEAN_START_FIRST_ONLY
103        self.clean_start = clean_start
104        self.qos = qos
105        self.return_as_bytes = return_as_bytes
106        self.queue = Queue()
107
108        try:
109            if USE_VERSION_FLAG:
110                self.client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_name)
111            else:
112                self.client = mqtt.Client(client_name)
113
114            self.client.on_connect = on_connect
115            self.client.on_message = on_message
116
117            if USE_VERSION_FLAG:
118                self.client.connect(broker, port)
119                self.client.subscribe(channel, qos=self.qos)
120            else:
121                self.client.connect(broker, port, clean_start=clean_start)
122                self.client.subscribe(channel, options=SubscribeOptions(qos=qos))  # noqa: F821
123
124        except (mqtt.WebsocketConnectionError, ConnectionRefusedError) as e:
125            logging.error(f'Unable to connect to broker at {broker}:{port} {channel}')
126            raise e
127
128    ############################
129    def read(self):
130        while True:
131            try:
132                self.client.loop()
133                while not self.queue.empty():
134                    message = self.queue.get()
135                    if message is None:
136                        continue
137                    logging.debug('Got message "%s"', message.payload)
138                    if self.return_as_bytes:
139                        return message.payload
140                    else:
141                        return str(message.payload, 'utf-8')
142            except KeyboardInterrupt:
143                self.client.disconnect()
144                exit(0)
class MQTTReader(logger.readers.reader.Reader):
 27class MQTTReader(Reader):
 28    """
 29    Read messages from an mqtt broker
 30    """
 31
 32    def __init__(self, broker, channel, client_name,
 33                 port=1883, clean_start=None,
 34                 qos=0, return_as_bytes=False, **kwargs):
 35        """
 36        Read text records from the channel subscription.
 37        ```
 38
 39        broker       MQTT broker to connect, broker format[###.###.#.#]
 40        channel      MQTT channel to read from, channel format[@broker/path_of_subscripton]
 41        port         broker port, typically 1883
 42        clean_start  Request new session on first connection. Options: True, False,
 43                       or the default of mqtt.MQTT_CLEAN_START_FIRST_ONLY
 44        qos          Quality of service: 0 = at most once, 1 = at least once, 2 = exactly once
 45        return_as_bytes
 46                     If true, return message in bytes, otherwise convert to str
 47        ```
 48        Instructions on how to start an MQTT broker:
 49
 50        1. First install the Mosquitto Broker :
 51            ```
 52            sudo apt-get update
 53            sudo apt-get install mosquitto
 54            sudo apt-get install mosquitto-clients
 55            ```
 56        2. The mosquitto service starts automatically when downloaded but use :
 57            ```
 58            sudo service mosquitto start
 59            sudo service mosquitto stop
 60            ```
 61            to start and stop the service.
 62
 63        3. To test the install use:
 64            ```
 65            netstat -at
 66            ```
 67            and you should see the MQTT broker which is the port 1883
 68
 69        4. In order to manually subscribe to a client use :
 70            ```
 71            mosquitto_sub -t "example/topic"
 72            ```
 73            and publish a message by using
 74            ```
 75            mosquitto_pub -m "published message" -t "certain/channel"
 76            ```
 77        5. Mosquitto uses a configuration file "mosquitto.conf" which you can
 78           find in /etc/mosquitto 	folder
 79
 80        ```
 81        """
 82        if not PAHO_ENABLED:
 83            raise ModuleNotFoundError('MQTTReader(): paho-mqtt is not installed. Please '
 84                                      'try "pip install paho-mqtt" prior to use.')
 85        if qos not in [0, 1, 2]:
 86            raise ValueError('MQTTReader parameter qos must be integer value 0, 1 or 2. '
 87                             f'Found type "{type(qos).__name__}", value "{qos}".')
 88
 89        # Let's build it!
 90        super().__init__(**kwargs)
 91
 92        def on_connect(client, userdata, flags, rc, properties=None):
 93            logging.info(f'Connected With Result Code: {rc}')
 94
 95        def on_message(client, userdata, message):
 96            self.queue.put(message)
 97
 98        self.broker = broker
 99        self.channel = channel
100        self.client_name = client_name
101        self.port = port
102        if clean_start is None:
103            clean_start = mqtt.MQTT_CLEAN_START_FIRST_ONLY
104        self.clean_start = clean_start
105        self.qos = qos
106        self.return_as_bytes = return_as_bytes
107        self.queue = Queue()
108
109        try:
110            if USE_VERSION_FLAG:
111                self.client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_name)
112            else:
113                self.client = mqtt.Client(client_name)
114
115            self.client.on_connect = on_connect
116            self.client.on_message = on_message
117
118            if USE_VERSION_FLAG:
119                self.client.connect(broker, port)
120                self.client.subscribe(channel, qos=self.qos)
121            else:
122                self.client.connect(broker, port, clean_start=clean_start)
123                self.client.subscribe(channel, options=SubscribeOptions(qos=qos))  # noqa: F821
124
125        except (mqtt.WebsocketConnectionError, ConnectionRefusedError) as e:
126            logging.error(f'Unable to connect to broker at {broker}:{port} {channel}')
127            raise e
128
129    ############################
130    def read(self):
131        while True:
132            try:
133                self.client.loop()
134                while not self.queue.empty():
135                    message = self.queue.get()
136                    if message is None:
137                        continue
138                    logging.debug('Got message "%s"', message.payload)
139                    if self.return_as_bytes:
140                        return message.payload
141                    else:
142                        return str(message.payload, 'utf-8')
143            except KeyboardInterrupt:
144                self.client.disconnect()
145                exit(0)

Read messages from an mqtt broker

MQTTReader( broker, channel, client_name, port=1883, clean_start=None, qos=0, return_as_bytes=False, **kwargs)
 32    def __init__(self, broker, channel, client_name,
 33                 port=1883, clean_start=None,
 34                 qos=0, return_as_bytes=False, **kwargs):
 35        """
 36        Read text records from the channel subscription.
 37        ```
 38
 39        broker       MQTT broker to connect, broker format[###.###.#.#]
 40        channel      MQTT channel to read from, channel format[@broker/path_of_subscripton]
 41        port         broker port, typically 1883
 42        clean_start  Request new session on first connection. Options: True, False,
 43                       or the default of mqtt.MQTT_CLEAN_START_FIRST_ONLY
 44        qos          Quality of service: 0 = at most once, 1 = at least once, 2 = exactly once
 45        return_as_bytes
 46                     If true, return message in bytes, otherwise convert to str
 47        ```
 48        Instructions on how to start an MQTT broker:
 49
 50        1. First install the Mosquitto Broker :
 51            ```
 52            sudo apt-get update
 53            sudo apt-get install mosquitto
 54            sudo apt-get install mosquitto-clients
 55            ```
 56        2. The mosquitto service starts automatically when downloaded but use :
 57            ```
 58            sudo service mosquitto start
 59            sudo service mosquitto stop
 60            ```
 61            to start and stop the service.
 62
 63        3. To test the install use:
 64            ```
 65            netstat -at
 66            ```
 67            and you should see the MQTT broker which is the port 1883
 68
 69        4. In order to manually subscribe to a client use :
 70            ```
 71            mosquitto_sub -t "example/topic"
 72            ```
 73            and publish a message by using
 74            ```
 75            mosquitto_pub -m "published message" -t "certain/channel"
 76            ```
 77        5. Mosquitto uses a configuration file "mosquitto.conf" which you can
 78           find in /etc/mosquitto 	folder
 79
 80        ```
 81        """
 82        if not PAHO_ENABLED:
 83            raise ModuleNotFoundError('MQTTReader(): paho-mqtt is not installed. Please '
 84                                      'try "pip install paho-mqtt" prior to use.')
 85        if qos not in [0, 1, 2]:
 86            raise ValueError('MQTTReader parameter qos must be integer value 0, 1 or 2. '
 87                             f'Found type "{type(qos).__name__}", value "{qos}".')
 88
 89        # Let's build it!
 90        super().__init__(**kwargs)
 91
 92        def on_connect(client, userdata, flags, rc, properties=None):
 93            logging.info(f'Connected With Result Code: {rc}')
 94
 95        def on_message(client, userdata, message):
 96            self.queue.put(message)
 97
 98        self.broker = broker
 99        self.channel = channel
100        self.client_name = client_name
101        self.port = port
102        if clean_start is None:
103            clean_start = mqtt.MQTT_CLEAN_START_FIRST_ONLY
104        self.clean_start = clean_start
105        self.qos = qos
106        self.return_as_bytes = return_as_bytes
107        self.queue = Queue()
108
109        try:
110            if USE_VERSION_FLAG:
111                self.client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_name)
112            else:
113                self.client = mqtt.Client(client_name)
114
115            self.client.on_connect = on_connect
116            self.client.on_message = on_message
117
118            if USE_VERSION_FLAG:
119                self.client.connect(broker, port)
120                self.client.subscribe(channel, qos=self.qos)
121            else:
122                self.client.connect(broker, port, clean_start=clean_start)
123                self.client.subscribe(channel, options=SubscribeOptions(qos=qos))  # noqa: F821
124
125        except (mqtt.WebsocketConnectionError, ConnectionRefusedError) as e:
126            logging.error(f'Unable to connect to broker at {broker}:{port} {channel}')
127            raise e

Read text records from the channel subscription.


broker       MQTT broker to connect, broker format[###.###.#.#]
channel      MQTT channel to read from, channel format[@broker/path_of_subscripton]
port         broker port, typically 1883
clean_start  Request new session on first connection. Options: True, False,
               or the default of mqtt.MQTT_CLEAN_START_FIRST_ONLY
qos          Quality of service: 0 = at most once, 1 = at least once, 2 = exactly once
return_as_bytes
             If true, return message in bytes, otherwise convert to str

Instructions on how to start an MQTT broker:

  1. First install the Mosquitto Broker :

    sudo apt-get update
    sudo apt-get install mosquitto
    sudo apt-get install mosquitto-clients
    
  2. The mosquitto service starts automatically when downloaded but use :

    sudo service mosquitto start
    sudo service mosquitto stop
    

    to start and stop the service.

  3. To test the install use:

    netstat -at
    

    and you should see the MQTT broker which is the port 1883

  4. In order to manually subscribe to a client use :

    mosquitto_sub -t "example/topic"
    

    and publish a message by using

    mosquitto_pub -m "published message" -t "certain/channel"
    
  5. Mosquitto uses a configuration file "mosquitto.conf" which you can find in /etc/mosquitto folder

```

broker
channel
client_name
port
clean_start
qos
return_as_bytes
queue
def read(self):
130    def read(self):
131        while True:
132            try:
133                self.client.loop()
134                while not self.queue.empty():
135                    message = self.queue.get()
136                    if message is None:
137                        continue
138                    logging.debug('Got message "%s"', message.payload)
139                    if self.return_as_bytes:
140                        return message.payload
141                    else:
142                        return str(message.payload, 'utf-8')
143            except KeyboardInterrupt:
144                self.client.disconnect()
145                exit(0)

read() should return None when there are no more records.