mqtt + AWS AppSyn c: WebsocketConnectionError: ошибка рукопожатия WebSocket, соединение не обновлено - PullRequest
0 голосов
/ 02 мая 2020

Я использую библиотеку paho-mqtt Python для реализации подписок на AWS AppSyn c.

Вот код для подписки:


        postHeaders = {
            'Content-Type': 'application/json',
            **self._headers
        }

        payload = {
            "operationName": "onCommand",
            "query": """subscription onCommand($deviceId: ID!) {
                  onCommandCreated(deviceId: $deviceId) {
                    commandId
                    deviceId
                    command
                    arguments
                    status
                  }
                }
            """,
            "variables": {"deviceId": self._device_id}
        }

        r = requests.post(_ROOT_URL, headers=postHeaders, json=payload)
        try:
            r.raise_for_status()
        except Exception:
            self._exception('Could not subscribe to device commands, status %s, response %s', r.status_code, r.content)
            raise
        data = r.json()
        self._logger.info('Subscription response: %s', json.dumps(data, indent=3, sort_keys=True))

        # if data.get('errors'):
        #     raise ValueError('Error subscribing: {}'.format(data))
        client_id = data['extensions']['subscription']['mqttConnections'][0]['client']
        ws_url = r.json()['extensions']['subscription']['mqttConnections'][0]['url']
        topic = r.json()['extensions']['subscription']['mqttConnections'][0]['topics'][0]

        # noinspection PyUnusedLocal
        def on_connect(_client, _userdata, flags, rc):
            self._debug('Connected to subscription topic')
            client.subscribe(topic)
        urlparts = urlparse(ws_url)

        headers = {
            "Host": "{0:s}".format(urlparts.netloc),
        }

        client = mqtt.Client(client_id=client_id, transport="websockets")
        client.enable_logger(logging.getLogger('paho-mqtt'))
        client.on_connect = on_connect
        client.on_message = ...
        client.on_log = lambda *a, **kw: self._logger.info('On log', exc_info=True)
        client.ws_set_options(path="{}?{}".format(urlparts.path, urlparts.query), headers=headers)
        client.tls_set()

        self._debug('trying to connect now....')
        client.connect(urlparts.netloc, 443)
        try:
            client.loop_forever()
        except Exception:
            self._logger.exception('Error looping forever')
            raise
        finally:
            client.disconnect()

It работает довольно хорошо около 24 часов, после чего начинает отказывать, даже несмотря на попытки восстановить соединение. Мне удалось перехватить исключение, которое вызывает ошибку:

May 01 20:39:21 ip-10-0-1-121 test_chattyraspi[8022]:   File "/home/ubuntu/chattyraspi/lib/python3.6/site-packages/paho/mqtt/clie
May 01 20:39:21 ip-10-0-1-121 test_chattyraspi[8022]:     self.reconnect()
May 01 20:39:21 ip-10-0-1-121 test_chattyraspi[8022]:   File "/home/ubuntu/chattyraspi/lib/python3.6/site-packages/paho/mqtt/clie
May 01 20:39:21 ip-10-0-1-121 test_chattyraspi[8022]:     self._websocket_path, self._websocket_extra_headers)
May 01 20:39:21 ip-10-0-1-121 test_chattyraspi[8022]:   File "/home/ubuntu/chattyraspi/lib/python3.6/site-packages/paho/mqtt/clie
May 01 20:39:21 ip-10-0-1-121 test_chattyraspi[8022]:     self._do_handshake(extra_headers)
May 01 20:39:21 ip-10-0-1-121 test_chattyraspi[8022]:   File "/home/ubuntu/chattyraspi/lib/python3.6/site-packages/paho/mqtt/clie
May 01 20:39:21 ip-10-0-1-121 test_chattyraspi[8022]:     "WebSocket handshake error, connection not upgraded")
May 01 20:39:21 ip-10-0-1-121 test_chattyraspi[8022]: paho.mqtt.client.WebsocketConnectionError: WebSocket handshake error, conne
May 01 20:39:21 ip-10-0-1-121 test_chattyraspi[8022]: 2020-05-01 20:39:21,194 - paho-mqtt - DEBUG - Connection failed, retrying
May 01 20:39:23 ip-10-0-1-121 test_chattyraspi[8022]: 2020-05-01 20:39:23,207 - client.raspi.alexa.mirko.io - INFO - On log
May 01 20:39:23 ip-10-0-1-121 test_chattyraspi[8022]: Traceback (most recent call last):
May 01 20:39:23 ip-10-0-1-121 test_chattyraspi[8022]:   File "/home/ubuntu/chattyraspi/lib/python3.6/site-packages/paho/mqtt/clie
May 01 20:39:23 ip-10-0-1-121 test_chattyraspi[8022]:     self.reconnect()
May 01 20:39:23 ip-10-0-1-121 test_chattyraspi[8022]:   File "/home/ubuntu/chattyraspi/lib/python3.6/site-packages/paho/mqtt/clie
May 01 20:39:23 ip-10-0-1-121 test_chattyraspi[8022]:     self._websocket_path, self._websocket_extra_headers)
May 01 20:39:23 ip-10-0-1-121 test_chattyraspi[8022]:   File "/home/ubuntu/chattyraspi/lib/python3.6/site-packages/paho/mqtt/clie
May 01 20:39:23 ip-10-0-1-121 test_chattyraspi[8022]:     self._do_handshake(extra_headers)
May 01 20:39:23 ip-10-0-1-121 test_chattyraspi[8022]:   File "/home/ubuntu/chattyraspi/lib/python3.6/site-packages/paho/mqtt/clie
May 01 20:39:23 ip-10-0-1-121 test_chattyraspi[8022]:     "WebSocket handshake error, connection not upgraded")

Если я перезагружаю скрипт, он сразу же начинает получать уведомления.

Здесь вы можете найти полный код.

Я добавил еще несколько журналов, чтобы разобраться в проблеме. Кажется, что AWS AppSyn c возвращает connection: keep-alive, что вызывает взлом sh.

1 Ответ

1 голос
/ 05 мая 2020

IoT отключает соединение WebSocket и требует аутентификации каждые 24 часа. Вам нужно будет повторять подписку (в основном аутентификацию и подключение к предварительно подписанному URL) каждые 24 часа.

...