Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

allow to specify session_id for connect() #226

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

vladak
Copy link
Contributor

@vladak vladak commented Nov 5, 2024

The ConnectionManager used by MiniMQTT disallows connecting to the same host/port combination multiple times. Sometimes it is actually handy to be able to create multiple connections, e.g. to test a MQTT broker implementation. This change allows for that by propagating the session_id parameter from connect() to the ConnectionManager.

Tested with CPython and a MQTT broker (called femtomqtt) running on localhost:

#!/usr/bin/env python3

try:
    import logging
except ImportError:
    import adafruit_logging as logging

try:
    from secrets import secrets
except ImportError:
    pass

import ssl
import sys

import adafruit_minimqtt.adafruit_minimqtt as MQTT


def main(session_id):
    logger = logging.getLogger(__name__)
    try:
        console_handler = logging.StreamHandler()
        logger.addHandler(console_handler)
    except Exception:
        pass
    logger.setLevel(logging.DEBUG)

    try:
        import wifi
        import socketpool

        logger.info("Connecting to wifi")
        wifi.radio.connect(secrets["SSID"], secrets["password"], timeout=10)
        logger.info("Connected to wifi")
        pool = socketpool.SocketPool(wifi.radio)
        host = secrets["broker"]
    except ImportError:
        import socket

        pool = socket
        host = "localhost"

    port = 1883
    mqtt_client = MQTT.MQTT(
        broker=host,
        port=port,
        socket_pool=pool,
        ssl_context=ssl.create_default_context(),
        connect_retries=1,
    )

    mqtt_client.logger = logger

    for i in range(2):
        logger.debug(f"connect #{i} with session_id = {session_id}")
        if session_id:
            session_id += f"{i}"
        mqtt_client.connect(session_id=session_id)


if __name__ == "__main__":
    session_id = None
    if len(sys.argv) > 1:
        session_id = sys.argv[1]
    try:
        main(session_id)
    except KeyboardInterrupt:
       pass

With no arguments the program ends with:

connect #0 with session_id = None
Attempting to connect to MQTT broker (attempt #0)
Attempting to establish MQTT connection...
Sending CONNECT to broker...
Fixed Header: bytearray(b'\x10\x14')
Variable Header: bytearray(b'\x00\x04MQTT\x04\x02\x00<')
Receiving CONNACK packet from broker
Got message type: 0x20 pkt: 0x20
Resetting reconnect backoff
connect #1 with session_id = None
Attempting to connect to MQTT broker (attempt #0)
Attempting to establish MQTT connection...
Closing socket
Socket error when connecting: Socket already connected to mqtt://localhost:1883
Traceback (most recent call last):
  File "/home/vkotal/Adafruit_CircuitPython_MiniMQTT/adafruit_minimqtt/adafruit_minimqtt.py", line 430, in connect
    ret = self._connect(
  File "/home/vkotal/Adafruit_CircuitPython_MiniMQTT/adafruit_minimqtt/adafruit_minimqtt.py", line 501, in _connect
    self._sock = self._connection_manager.get_socket(
  File "/home/vkotal/Adafruit_CircuitPython_MiniMQTT/venv/lib/python3.10/site-packages/adafruit_connection_manager.py", line 311, in get_socket
    raise RuntimeError(f"Socket already connected to {proto}//{host}:{port}")
RuntimeError: Socket already connected to mqtt://localhost:1883

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/home/vkotal/Adafruit_CircuitPython_MiniMQTT/./session_id.py", line 66, in <module>
    main(session_id)
  File "/home/vkotal/Adafruit_CircuitPython_MiniMQTT/./session_id.py", line 58, in main
    mqtt_client.connect(session_id=session_id)
  File "/home/vkotal/Adafruit_CircuitPython_MiniMQTT/adafruit_minimqtt/adafruit_minimqtt.py", line 464, in connect
    raise MMQTTException(exc_msg) from last_exception
adafruit_minimqtt.adafruit_minimqtt.MMQTTException: ('Connect failure', None)

with any argument 2 connections are created (verified with netstat):

connect #0 with session_id = foo
Attempting to connect to MQTT broker (attempt #0)
Attempting to establish MQTT connection...
Sending CONNECT to broker...
Fixed Header: bytearray(b'\x10\x13')
Variable Header: bytearray(b'\x00\x04MQTT\x04\x02\x00<')
Receiving CONNACK packet from broker
Got message type: 0x20 pkt: 0x20
Resetting reconnect backoff
connect #1 with session_id = foo0
Attempting to connect to MQTT broker (attempt #0)
Attempting to establish MQTT connection...
Sending CONNECT to broker...
Fixed Header: bytearray(b'\x10\x13')
Variable Header: bytearray(b'\x00\x04MQTT\x04\x02\x00<')
Receiving CONNACK packet from broker
Got message type: 0x20 pkt: 0x20
Resetting reconnect backoff

Also tested the same code on Adafruit CircuitPython 9.2.0 on 2024-10-28; Adafruit Feather ESP32S3 4MB Flash 2MB PSRAM with ESP32S3.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant