2017-09-07 10 views
1

私は、私たちのデバイス用のAWS IoTデバイスシャドーアップデートをしばらく開発しています。私たちは、AWBのIoT PythonデバイスSDK(Yocto/Bitbake製)とPython 2.7.3(ARM用にYoctoを提供する弊社のハードウェアベンダーが提供する唯一のバージョンです)のhttps://github.com/aws/aws-iot-device-sdk-pythonにあるLinuxディストリビューションを使用していますボード)。AWS IoT PythonデバイスSDKシャドーアップデートタイムアウト

AWSリポジトリからサンプルのシャドウアップデートコードをダウンロードし、ニーズに合わせて変更し、デバイスビルドに配置しました。ほとんどの場合、うまくいっていますが、私はまだ不快感を感じています。このコードでは、デバイスの接続に時間がかかる場合に処理するために、 "OfflinePublishQueueing"設定を追加しました。これは私たちが得ていた "PublishQueueDisabled"エラーを防ぐために1つのサイトで推奨されていました。ここに初期化コードがあります。私は、使用している証明書が良いことを知っていると付け加えます。それ以外の場合は、これまで成功していません。

self.AWSIoTMQTTShadowClient = AWSIoTMQTTShadowClient("InCoIoTShadowUpdate") 
self.AWSIoTMQTTShadowClient.configureEndpoint(endpoint, 8883) 
self.AWSIoTMQTTShadowClient.configureCredentials(rootCAPath, privateKeyFile, 
jointCertificateFile) 
# AWSIoTMQTTShadowClient configuration 
self.AWSIoTMQTTShadowClient.configureAutoReconnectBackoffTime(1, 32, 20) 
self.AWSIoTMQTTShadowClient.configureConnectDisconnectTimeout(10) # 10 sec 
self.AWSIoTMQTTShadowClient.configureMQTTOperationTimeout(15) # 15 sec 
MQTTClient = self.AWSIoTMQTTShadowClient.getMQTTConnection() 
MQTTClient.configureOfflinePublishQueueing(5, DROP_OLDEST) 

以降に、影を更新するためのコード、ThingIdは、他の場所のローカルデバイスの設定から設定されていることを指摘しました。

def ConnectAndUpdate(self): 

    deviceState = InovaIoTDeviceState() 
    log = logging.getLogger("InovaIoTDeviceClient:connectAndUpdate") 

    # Connect and subscribe to AWS IoT 
    try: 
     self.AWSIoTMQTTShadowClient.connect() 
    except (connectError, connectTimeoutException): 
     log.error("Error connecting to AWS IoT service") 
     return False 

    # Create a deviceShadow with persistent subscription 
    updateBot = self.AWSIoTMQTTShadowClient.createShadowHandlerWithName(self.ThingId, True) 
    JSONPayload = deviceState.GetDeviceShadowDocument() 

    try: 
     updateBot.shadowUpdate(JSONPayload, self.ShadowUpdateCallback, 15) 
    # This is bad if these errors are thrown, probably either an initial device registration failure 
    # or global problem with Inova AWS IoT console configuration or lambda function 
    except (publishError, subscribeError): 

     log.error('Publish or subscribe error..') 
     return False 

    except (publishTimeoutException, subscribeTimeoutException): 

     # It is possible we are here due to a temporary snafu in AWS 
     log.error('Publish or subscribe timeout..') 
     return False 

    except publishQueueDisabledException: 

     # From time to time, AWS will randomly disconnect. 
     log.error('Publish Queue disabled..') 
     return False 

    while not self.ResponseReceived: 
     time.sleep(1) 

    # reset state 
    self.ResponseReceived = False 

    try: 
     self.AWSIoTMQTTShadowClient.disconnect() 
    except (disconnectError, disconnectTimeoutException): 
     log.error('Error attempting to disconnect') 

    return self.UpdateSuccess 

、最終的には、コールバックコードここ

# Custom MQTT message callback 
def ShadowUpdateCallback(self, payload, responseStatus, token): 
    log = logging.getLogger("InovaIoTDeviceClient:shadowUpdateCallback") 
    if responseStatus == "timeout": 
     log.info("Shadow update timeout") 
     self.UpdateSuccess = False 
    elif responseStatus == "accepted": 
     log.info("Shadow update successful") 
     self.successive_errors = 0 
     self.UpdateSuccess = True 
    elif responseStatus == "rejected": 
     log.info("Rejected shadow update") 
     self.UpdateSuccess = False 

    self.ResponseReceived = True 

は比較的一般的であり、我々が得る様々なエラー、です。影の更新の成功率は約60%に過ぎないと私は言います。ここではAWSから報告されたタイムアウトがあります:

2017-09-06 11:15:13: (INFO:AWSIoTPythonSDK.core.shadow.deviceShadow) 
Subscribed to update accepted/rejected topics for deviceShadow: 
qqpba4fgsfazl2zfgqq8zkavj (Line:372) 
2017-09-06 11:15:13: (INFO:AWSIoTPythonSDK.core.protocol.mqttCore) Offline 
publish request detected. (Line:343) 
2017-09-06 11:15:13: (INFO:AWSIoTPythonSDK.core.protocol.mqttCore) Try 
queueing up this request... (Line:347) 
2017-09-06 11:15:28: (INFO:AWSIoTPythonSDK.core.shadow.deviceShadow) Shadow 
request with token: InCoIoTShadowUpdate_qqpba4fgsfazl2zfgqq8zkavj_0_acbxa 
has timed out. (Line:202) 
2017-09-06 11:15:28: (INFO:InCoIoTDeviceClient:shadowUpdateCallback) Shadow 
update timeout (Line:188) 

はここで実際の影更新コール

2017-09-06 12:40:11: (INFO:AWSIoTPythonSDK.core.protocol.mqttCore) Connected 
to AWS IoT. (Line:302) 
2017-09-06 12:40:27: (ERROR:AWSIoTPythonSDK.core.protocol.mqttCore) No 
feedback detected for subscribe request 1. Timeout and failed. (Line:413) 
2017-09-06 12:40:27: (ERROR:InCoIoTDeviceClient:connectAndUpdate) Publish 
or subscribe timeout.. (Line:147) 
2017-09-06 12:40:27: (INFO:cycle) Unsuccessful shadow update... (Line:173) 

からのタイムアウトエラーですので、これらは基本的にすべてのエラーでタイムアウトが、あります。追加のしわとして、私たちはデバイスの接続をwiresharkedし、(TLS 1.2暗号化されているので)コンテンツを見るのではなく、接続の動作を見るために試行を公開します。 wiresharkの出力から見た動作は、AWSエンドポイントが少なくとも8つの異なるIPアドレスによって処理されるということです。タイムアウトの場合、接続はいつもどこかで行われます。シャドウアップデートトピックを購読してパブリッシュしてタイムアウトを受け取った場合、そのアドレスのいずれかにしか接続しません。サブスクライブまたはパブリッシュタイムアウトでは、3つの異なるアドレスが試行されます。

これはすべてAWSとパフォーマンスの最終段階ですが、誰かがこれを見て回避することができたかどうかは疑問でした。タイムアウト値を上回ることは役に立たないようです。

+0

他の誰かが最近のバージョンのPythonで成功している人は、それも関連しているかもしれません。何とか2.7.11にアップグレードする必要があるかもしれませんが、それはここでは非常に難しい作業です。あるいは、リクエストライブラリをどのようにアップグレードするかを考え出すこともできます。 –

+0

pythonリクエストをurllib3で2.18.4にアップグレードしました。行動に変化はない。 –

答えて

1

私たちはこれを理解しました。 A.)私たちは、最近リリースされた1.2.0 AWS IoT Python SDKにアップグレードしました.B)MQTT CONNACKが受信されたときにオンラインコールバックを使用できるバグが修正されたようです。だから私はこれに私のコードを変更:

try: 
     self.AWSIoTMQTTShadowClient.onOnline = self.onConnect 
     self.AWSIoTMQTTShadowClient.connect() 
    except (connectError, connectTimeoutException): 
     log.error("Error connecting to AWS IoT service") 
     return False 

    while not self.is_aws_connected: 
     self.seconds_waited_for_conn_aws += 1 
     if self.seconds_waited_for_conn_aws > 30: 
      log.error("Timeout waiting for connected status.") 
      return False 
     time.sleep(1) 

    # Create a deviceShadow with persistent subscription 
    updateBot = self.AWSIoTMQTTShadowClient.createShadowHandlerWithName(self.ThingId, True) 

    try: 
     updateBot.shadowUpdate(JSONPayload, self.ShadowUpdateCallback, 15) 
    # This is bad if these errors are thrown, probably either an initial device registration failure 
    # or global problem with Inova AWS IoT console configuration or lambda function 
    except (publishError, subscribeError): 

     log.error('Publish or subscribe error..') 
     return False 

    except (publishTimeoutException, subscribeTimeoutException): 

     # It is possible we are here due to a temporary snafu in AWS 
     log.error('Publish or subscribe timeout..') 
     return False 

    except publishQueueDisabledException: 

     # From time to time, AWS will randomly disconnect. 
     log.error('Publish Queue disabled..') 
     return False 

    while not self.ResponseReceived: 
     time.sleep(1) 

    # reset state 
    self.ResponseReceived = False 
    return self.UpdateSuccess 

def onConnect(self): 
    log = logging.getLogger("InovaIoTDeviceClient:onConnect") 
    log.info("Callback from AWS layer on connect.") 
    self.is_aws_connected = True 

def runOnce(self): 
    try: 
     log = logging.getLogger("cycle") 
     if not self.ConnectAndUpdate(): 
      log.info("Unsuccessful shadow update...") 
    finally: 
     # only here to make sure we disconnect 
     try: 
      self.AWSIoTMQTTShadowClient.disconnect() 
      self.is_aws_connected = False 
     except (disconnectError, disconnectTimeoutException): 
      log.error('additional error attempting to disconnect') 

見ての通り、私はコードの1行目に「onOnline」コールバックを設定していて、そのステータスが完了するのを待っています。それは前だったので、私は(AWS SDKでworkers.pyから)AWS SDKの基盤にSTABLEとしてマークするためのシステムを待つ処理にしばしば

def _dispatch_connack(self, mid, rc): 
    status = self._client_status.get_status() 
    self._logger.debug("Dispatching [connack] event") 
    if self._need_recover(): 
     if ClientStatus.STABLE != status: # To avoid multiple connack dispatching 
      self._logger.debug("Has recovery job") 
      clean_up_debt = Thread(target=self._clean_up_debt) 
      clean_up_debt.start() 
    else: 
     self._logger.debug("No need for recovery") 
     self._client_status.set_status(ClientStatus.STABLE) 

たどうやらあなたはMQTTシステム上でカウントすることはできませんconnect()コールの反対側で完全に接続され、準備が整っていますが、onOnlineイベントを待つことができます。このため、以前はconfigureOfflinePublishQueueing()を呼び出していました。そしてなぜ我々はログで​​これを見るだろう...

2017-09-19 14:45:13: (INFO:AWSIoTPythonSDK.core.protocol.mqtt_core) Offline request detected! (Line:313) 

ありがとうございます、これは現在、はるかに優れています。ちなみに、より高性能なプロセッサでは、旧式のコードがより成功していました(デスクトップLinux VMでは98%の成功率、小型のARMボードでは45%の成功率)ので、彼らの「オフラインパブリッシング」システムでは、プロセッサボード。

関連する問題