mqtt + AWS AppSync:WebsocketConnectionError:WebSocket握手错误,连接未升级

时间:2020-05-02 16:59:45

标签: python amazon-web-services websocket aws-appsync

我正在使用paho-mqtt Python库来实现针对AWS AppSync的订阅。

这是订阅的代码:


        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()

它可以正常运行约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")

如果我重新启动脚本,它将立即开始立即接收通知。

Here,您可以找到完整的代码。

我添加了更多日志以深入研究问题。好像是 AWS AppSync返回connection: keep-alive,这将导致崩溃。

1 个答案:

答案 0 :(得分:1)

IoT会断开WebSocket连接,并需要每24小时进行身份验证。您将需要每24小时重新做一次Subscribe(基本上是身份验证并连接到预先签名的URL)。