From 556fafb495cce875e3e11ea0a638009f6ddc37c9 Mon Sep 17 00:00:00 2001 From: Alfred Gedeon Date: Fri, 2 Feb 2024 07:38:47 -0800 Subject: [PATCH 01/12] Migratie your code from V1 to V2 Sdk --- documents/MIGRATION_GUIDE.md | 854 +++++++++++++++++++++++++++++++++++ 1 file changed, 854 insertions(+) create mode 100644 documents/MIGRATION_GUIDE.md diff --git a/documents/MIGRATION_GUIDE.md b/documents/MIGRATION_GUIDE.md new file mode 100644 index 00000000..ba6db21f --- /dev/null +++ b/documents/MIGRATION_GUIDE.md @@ -0,0 +1,854 @@ +grate from V1 to V2 of the AWS IoT SDK for Python + +The V2 AWS IoT SDK for Python is a major rewrite of the V1 code base built on top of Python 3.7+. It includes many updates, such as improved consistency, ease of use, more detailed information about client status, an offline operation queue control, etc. This guide describes the major features that are new in V2, and provides guidance on how to migrate your code to V2 from V1. + +## What’s new + +* V2 SDK client is truly async. Operations return `concurrent.futures.Future` objects. + Blocking calls can be emulated by waiting for the returned `Future` object to be resolved. +* V2 SDK provides implementation for MQTT5 protocol, the next step in evolution of the MQTT protocol. +* Public API terminology has changed. You `start()` or `stop()` the MQTT5 client rather than c`onnect` or d`isconnect` like in V1. This removes the semantic confusion with the connect/disconnect as the client-level controls vs. internal recurrent networking events. +* Support for Fleet Provisioning AWS IoT Core service. + +Public API for almost all actions and operations has changed significantly. For more details about the new features and to see specific code examples, refer to the other sections of this guide. + + +## How To Get Started with V2 SDK + +There are differences between IoT Python V1 SDK and IoT Python V2 SDK. Below are changes you need to make to use IoT Python V2 SDK features. For more information about MQTT5, visit [MQTT5 User Guide](https://github.com/aws/aws-iot-device-sdk-python-v2/blob/main/documents/MQTT5_Userguide.md) + + +### MQTT Protocol + +V1 SDK uses an MQTT version 3.1.1 client under the hood. + +V2 SDK provides MQTT version 3.1.1 and MQTT version 5.0 client implementations. This guide focuses on the MQTT5 since this version is significant improvement over MQTT3. See MQTT5 features section. + + +### Client Builder + +To access the AWS IoT service, you must initialize an MQTT client. + +In V1 SDK, the [`AWSIoTPythonSDK.MQTTLib.`AWSIotMqttClient](https://s3.amazonaws.com/aws-iot-device-sdk-python-docs/html/index.html#AWSIoTPythonSDK.MQTTLib.AWSIoTMQTTClient) class represents an MQTT client. You instantiate the client directly passing all the required parameters to the class constructor. It’s possible to change client settings after its creation using `configure*` methods, e.g. `configureMQTTOperationTimeout` or `configureConnectDisconnectTimeout`. + +In V2 SDK, the [awcrt.mqtt5.Client](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.Client) class represents an MQTT client, specifically MQTT5 protocol. V2 SDK provides an [awsiot.mqtt5_client_builder](https://aws.github.io/aws-iot-device-sdk-python-v2/awsiot/mqtt5_client_builder.html) designed to easily create common configuration types such as direct MQTT or WebSocket connections, the resulting MQTT5 client cannot have its settings modified. + +_Example of creating a client in V1_ + +``` +clientEndpoint = "-ats.iot..amazonaws.com" +clientId = "" +certificateFile = "" # X.509 based certificate file +privateKeyFile = "" # PEM encoded private key file +rootCAPath = "" + +client = AWSIoTMQTTClient(clientId) +client.configureEndpoint(host, port) +client.configureCredentials(rootCAPath, privateKeyFile, certificateFile) + +client.connect() + +``` + +_Example of creating a client in V2_ +V2 SDK supports different connection types. Given the same input parameters as in the V1 example above, the most suitable method to create an MQTT5 client will be [awsiot.mqtt5_client_builder.mtls_from_path](https://aws.github.io/aws-iot-device-sdk-python-v2/awsiot/mqtt5_client_builder.html#awsiot.mqtt5_client_builder.mtls_from_path). + +``` +from awsiot import mqtt5_client_builder + +clientEndpoint = "-ats.iot..amazonaws.com" +clientId = "" +certificateFile = "" # X.509 based certificate file +privateKeyFile = "" # PEM encoded private key file + +mqtt5_client = mqtt5_client_builder.mtls_from_path( + endpoint=clientEndpoint, + cert_filepath=certificateFile, + pri_key_filepath=privateKeyFile, + client_id=clientId, + clean_session=False, + keep_alive_secs=30) + +mqtt5_client.start() + +``` + +Refer to the [Connection Types and Features](https://quip-amazon.com/RUfpAM2x5mXr#temp:C:XVAe19c32f97575498c9c9ddc15a) section for other connection types supported by V2 SDK. + + +### Connection Types and Features + +V1 SDK supports two types of connections to connect to the AWS IoT service: MQTT with X.509 certificate and MQTT over Secure WebSocket with SigV4 authentication. + +V2 SDK adds a collection of connection types and cryptography formats (e.g. [PKCS #11](https://en.wikipedia.org/wiki/PKCS_11) and [Custom Authorizer](https://docs.aws.amazon.com/iot/latest/developerguide/custom-authentication.html)), credential providers (e.g. [Amazon Cognito](https://aws.amazon.com/cognito/) and [Windows Certificate Store](https://learn.microsoft.com/en-us/windows-hardware/drivers/install/certificate-stores)), and other connection-related features. +Refer to the “[How to setup MQTT5 builder based on desired connection method](https://github.com/aws/aws-iot-device-sdk-python-v2/blob/main/documents/MQTT5_Userguide.md#how-to-create-a-mqtt5-client-based-on-desired-connection-method)” section of the MQTT5 user guide for detailed information and code snippets on each connection type and connection feature. + +|Connection Type/Feature |V1 SDK |V2 SDK |User guide section | | +|--- |--- |--- |--- |--- | +| | | | | | +|MQTT over Secure WebSocket with AWS SigV4 authentication |✔ |✔ | | | +|MQTT with Java Keystore Method |✔ |✔ | |X.509 | +|MQTT (over TLS 1.2) with X.509 certificate based mutual authentication |✘ |✔ | |X.509 | +|MQTT with PKCS12 Method |✘ |✔✔*✔**** | |Container for X.509 | +|MQTT with Custom Key Operation Method |✔* |✔ | |X.509 | +|MQTT with Custom Authorizer Method |✔* |✔ | | | +|MQTT with Windows Certificate Store Method |✔* |✔ | |X.509 | +|MQTT with PKCS11 Method |✘ |✔ | |X.509 plus other formats | +|Websocket Connection with Cognito Authentication Method |✘ |✔ | | | +|HTTP Proxy |✔*** |✔ | | | + +✔* - one option to get this connection type work in V2 SDK, is to [import IOT Core key to a Java KeyStore and convert it to pkcs#12](https://github.com/aws/aws-iot-device-sdk-python-v2/blob/main/samples/pkcs12_connect.md). +✔** - In order to get this connection type work in V1 SDK, you need to implement the [Custom Authentication workflow](https://docs.aws.amazon.com/iot/latest/developerguide/custom-authorizer.html). +✔*** - Though V1 does not allow to specify HTTP proxy, it is possible to configure systemwide proxy. +✔**** - Available on MacOS only + + +### Lifecycle Events + +Both V1 and V2 SDKs provide lifecycle events for the MQTT clients. + +V1 SDK provides 2 lifecycle events: “on Online” and “on Offline”. You can supply a custom callback function via callbacks to `AWSIoTPythonSDK.MQTTLib.AWSIoTMQTTClient`. It is recommended to use lifecycle events callbacks to help determine the state of the MQTT client during operation. + +V2 SDK add 3 new lifecycle events, providing 5 lifecycle events in total: “on connection success”, “on connection failure”, “on disconnect”, “on stopped”, and “on attempting connect”. +Refer to the [MQTT5 user guide](https://github.com/aws/aws-iot-device-sdk-python-v2/blob/main/documents/MQTT5_Userguide.md#how-to-create-a-mqtt5-client-based-on-desired-connection-method) for the details. + +_Example of setting lifecycle events in V1_ + +``` +`def`` myConnectCallback``(``mid``,`` data``):` +` ``return` + +def myDisconnectCallback(mid, data): + return + +client = AWSIoTMQTTClient(clientId) +client.onOnline = on_online_callback +client.onOffline = on_offline_callback + +client.configureConnectDisconnectTimeout(10) # 10 sec +client.connect() + +``` + + +_Example of setting lifecycle events in V2_ + +``` +def on_lifecycle_connection_success( + lifecycle_connect_success_data: mqtt5.LifecycleConnectSuccessData): + return + +def on_lifecycle_connection_failure( + lifecycle_connection_failure: mqtt5.LifecycleConnectFailureData): + return + +def on_lifecycle_stopped( + lifecycle_stopped_data: mqtt5.LifecycleStoppedData): + return + +def on_lifecycle_disconnection( + lifecycle_disconnect_data: mqtt5.LifecycleDisconnectData): + return + +on_lifecycle_attempting_connect( + lifecycle_attempting_connect_data: mqtt5.LifecycleAttemptingConnectData): + return + +mqtt5_client = mqtt5_client_builder.mtls_from_path( + endpoint="-ats.iot..amazonaws.com", + cert_filepath="", + pri_key_filepath="", + on_lifecycle_connection_success=on_lifecycle_connection_success, + on_lifecycle_stopped=on_lifecycle_stopped, + on_lifecycle_attempting_connect=on_lifecycle_attempting_connect, + on_lifecycle_disconnection=on_lifecycle_disconnection, + on_lifecycle_connection_failure=on_lifecycle_connection_failure) +mqtt5_client.start() +``` + + + +### Publish + +V1 SDK provides two API calls for publishing: blocking and non-blocking. For the non-blocking version, the result of the publish operation is reported via a set of callbacks. If you try to publish to a topic that is not allowed by a policy, AWS IoT Core service will close the connection. + +V2 SDK provides only asynchronous non-blocking API. [PublishPacketBuilder](https://awslabs.github.io/aws-crt-java/software/amazon/awssdk/crt/mqtt5/packets/PublishPacket.PublishPacketBuilder.html) creates a [PublishPacket](https://awslabs.github.io/aws-crt-java/software/amazon/awssdk/crt/mqtt5/packets/PublishPacket.html) object containing a description of the PUBLISH packet. The [publish](https://awslabs.github.io/aws-crt-java/software/amazon/awssdk/crt/mqtt5/Mqtt5Client.html#publish(software.amazon.awssdk.crt.mqtt5.packets.PublishPacket)) operation takes a `PublishPacket` instance and returns a promise containing a [PublishResult](https://awslabs.github.io/aws-crt-java/software/amazon/awssdk/crt/mqtt5/PublishResult.html). The returned `PublishResult` will contain different data depending on the `QoS` used in the publish. + +* For QoS 0 (AT_MOST_ONCE): Calling `getValue` will return `null` and the promise will be complete as soon as the packet has been written to the socket. +* For QoS 1 (AT_LEAST_ONCE): Calling `getValue` will return a [PubAckPacket](https://awslabs.github.io/aws-crt-java/software/amazon/awssdk/crt/mqtt5/packets/PubAckPacket.html) and the promise will be complete as soon as the PUBACK is received from the broker. + +If the operation fails for any reason before these respective completion events, the promise is rejected with a descriptive error. You should always check the reason code of a [PubAckPacket](https://awslabs.github.io/aws-crt-java/software/amazon/awssdk/crt/mqtt5/packets/PubAckPacket.html) completion to determine if a QoS 1 publish operation actually succeeded. + +_Example of publishing in V1_ + +``` +# Blocking. +client.publish("my/topic", "hello", 0) +``` + +``` +# Non-blocking API. +`client.configureMQTTOperationTimeout`(30) # 30 Seconds +client.connect() + +def ack_callback(mid, data=data): + return + +client.publishAsync( + "my/topic", + "hello", + 1, + ackCallback=myPubackCallback) + +``` + +_Example of publishing in V2_ + +``` +publish_future,packet_id = client.publish(mqtt5.PublishPacket( + topic="my/topic", + payload=json.dumps("hello"), + qos=mqtt5.QoS.AT_LEAST_ONCE)) +publish_future.result(20) # 20 seconds +``` + + + +### Subscribe + +V1 provides blocking and non-blocking API for subscribing. To subscribe to topic in V1, you should provide an instance of [AWSIotTopic](http://aws-iot-device-sdk-java-docs.s3-website-us-east-1.amazonaws.com/com/amazonaws/services/iot/client/AWSIotTopic.html) to the [subscribe](https://s3.amazonaws.com/aws-iot-device-sdk-python-docs/html/index.html#AWSIoTPythonSDK.MQTTLib.AWSIoTMQTTClient.subscribe) operation. AWSIotTopic object (or, usually, an object of a children class) implements `onMessageReceived` method which will be called on receiving a new message. If you try to subscribe to a topic that is not allowed by a policy, AWS IoT Core service will close the connection. + +V2 SDK provides only asynchronous non-blocking API. First, you need to create a [SubscribePacket](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.SubscribePacket) object. If you specify multiple topics in the *Sequence[*[*Subscription*](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.Subscription)*]* parameter, V2 SDK will subscribe to all of these topics using one request. The [subscribe](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.Client.subscribe) operation takes a description of the `SubscribePacket` you wish to send and returns a promise that resolves successfully with the corresponding [SubAckPacket](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.SubackPacket) returned by the broker; the promise is rejected with an error if anything goes wrong before the `SubAckPacket` is received. You should always check the reason codes of a `SubAckPacket` completion to determine if the subscribe operation actually succeeded. + +In V2 SDK, if the MQTT5 client is going to subscribe and receive packets from the MQTT broker, it is important to also setup the `on_publish_callback_fn` callback. This callback is invoked whenever the client receives a message from the server on a topic the client is subscribed to. With this callback, you can process messages made to subscribed topics with its parameter [PublishReceivedData](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.PublishReceivedData). + +_Example of subscribing in V1_ + +``` +`client.configureMQTTOperationTimeout(30) # 30 Seconds + +def`` ackCallback``(``mid``,`` data``):` +` ``return` +` ` +`def`` messageCallback``(``client``,`` userdata``,`` message``):` +` ``return` +` ` +client.subscribe( + "myTopic/#", + 1, + ackCallback=mySubackCallback, + messageCallback=customMessageCallback) + +``` + +_Example of subscribing in V2_ + +``` +subscribe_future = client.subscribe( + subscribe_packet=mqtt5.SubscribePacket( + subscriptions=[mqtt5.Subscription( + topic_filter="my/own/topic", + qos=mqtt5.QoS.AT_LEAST_ONCE)])) + +suback = subscribe_future.result(20) + +``` + + + +### Unsubscribe + +V1 SDK provides blocking and non-blocking API for unsubscribing. To unsubscribe from topic in V1, you should provide a topic string to the [unsubscribe](https://s3.amazonaws.com/aws-iot-device-sdk-python-docs/html/index.html?highlight=unsubscribe#AWSIoTPythonSDK.MQTTLib.AWSIoTMQTTClient.unsubscribe) or [unsubscribeAsync](https://s3.amazonaws.com/aws-iot-device-sdk-python-docs/html/index.html?highlight=unsubscribe#AWSIoTPythonSDK.MQTTLib.AWSIoTMQTTClient.unsubscribeAsync) operation. The asynchronous operation takes a callback that determines success of failure + +V2 SDK provides only asynchronous non-blocking API. First, you need to create an [UnsubscribePacket](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.UnsubscribePacket) object.[](https://awslabs.github.io/aws-crt-java/software/amazon/awssdk/crt/mqtt5/packets/UnsubscribePacket.UnsubscribePacketBuilder.html) The [unsubscribe](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.Client.unsubscribe) operation takes a description of the [UnsubscribePacket](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.UnsubscribePacket) you wish to send and returns a promise that resolves successfully with the corresponding [UnsubAckPacket](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.UnsubackPacket) returned by the broker; the promise is rejected with an error if anything goes wrong before the [UnsubAckPacket](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.UnsubackPacket) is received. You should always check the reason codes of a [UnsubAckPacket](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.UnsubackPacket) completion to determine if the unsubscribe operation actually succeeded. +Similar to subscribing, you can unsubscribe from multiple topics in one request: just pass a list of topics to topic_filters (*Sequence[*[*str*](https://docs.python.org/3/library/stdtypes.html#str)*]) in *[*UnsubAckPacket*](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.UnsubackPacket) + +_Example of unsubscribing in V1_ + +``` +# Blocking API. +client.unsubscribe("my/topic") +client.unsubscribe("another/topic") + +``` + +``` +# Non-blocking API. +def unsuback_callback(mid): + return + +client.unsubscribeAsync("my/topic", ackCallback=unsuback_callback) + +``` + + +_Example of unsubscribing in V2_ + +``` +unsubscribe_future = mqtt5_client.unsubscribe( + unsubscribe_packet=mqtt5.UnsubscribePacket( + topic_filters=["my/topic"])) +unsuback = unsubscribe_future.result(60) # 60 Seconds +print("Unsubscribed with {}".format(unsuback.reason_codes)) + +``` + + + +### Client Stop + +In V1 SDK, the `disconnect` method in the `AWSIotMqttClient` class disconnects the client. Once disconnected, the client can connect again by calling `connect`. + +In V2 SDK, an MQTT5 client can stop a session by calling the [stop](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.Client.stop) method. You can provide an optional [DisconnectPacket](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.DisconnectPacket) parameter. A closed client can be started again by calling [start](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.Client.start). + +_Example of disconnecting a client in V1_ + +``` +client.disconnect(); +``` + +_Example of disconnecting a client in V2_ + +``` +mqtt5_client.stop( + disconnect_packet=mqtt5.DisconnectPacket( + reason_code=mqtt5.*DisconnectReasonCode**.**NORMAL_DISCONNECTION**, + session_expiry_interval_sec=3600*)) + +``` + + + +### Reconnects + +V1 has a maximum number of retry attempts for auto-reconnect. If you exhausted the maximum number of retries, V1 will throw a permanent error and you will not be able to use the same client instance again. + +V2 attempts to reconnect automatically until connection succeeds or `client.stop()` is called. The reconnection parameters, such as min/max delays and [jitter modes](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.ExponentialBackoffJitterMode), are configurable through [awsiot.mqtt5_client_builder](https://aws.github.io/aws-iot-device-sdk-python-v2/awsiot/mqtt5_client_builder.html#module-awsiot.mqtt5_client_builder). + + +_Example of tweaking reconnection settings in V1_ + +``` +*`baseReconnectQuietTimeSecond`*` ``=`` ``1 # Initial backoff time` +`maxReconnectQuiteTimeSecond ``=`` ``23 # maximum backoff time` +`stableConnectionTimeSecond ``=`` ``20 # the time the connection is considered stable` +`client``.``configureAutoReconnectBackoffTime``( + ``baseReconnectQuietTimeSecond``, + ``maxReconnectQuiteTimeSecond``, + ``stableConnectionTimeSecond``) + +` +``` + +_Example of tweaking reconnection settings in V2_ + +``` +mqtt5_client = mqtt5_client_builder.mtls_from_path( + endpoint="-ats.iot..amazonaws.com", + cert_filepath="", + pri_key_filepath="", + ... + max_reconnect_delay_ms=200, + min_reconnect_delay_ms=200, + min_connected_time_to_reset_reconnect_delay_ms=200, + retry_jitter_mode=mqtt5.ExponentialBackoffJitterMode.FULL) + +mqtt5_client.start() +``` + + + +### Offline Operations Queue + +In V1, if you’re having too many in-flight QoS 1 messages, you can encounter the `too many publishes in Progress` error on publishing messages. This is caused by the so-called in-flight publish limit. By default, V1 SDK supports a maximum of 20 in-flight operations. + +V2 does not limit the number of in-flight messages. Additionally, V2 provides a way to configure which kind of packets will be placed into the offline queue when the client is in the disconnected state. The following code snippet demonstrates how to enable storing all packets except QOS0 publish packets in the offline queue on disconnect: + +_Example of configuring the offline queue in V2_ + +``` +mqtt5_client = mqtt5_client_builder.mtls_from_path( + endpoint="-ats.iot..amazonaws.com", + cert_filepath="", + pri_key_filepath="", + ... + offline_queue_behavior= + mqtt5.ClientOperationQueueBehaviorType.FAIL_QOS0_PUBLISH_ON_DISCONNECT) + +mqtt5_client.start() +``` + +Note that AWS IoT Core [limits the number of allowed operations per second](https://docs.aws.amazon.com/general/latest/gr/iot-core.html#message-broker-limits). The [get_stats](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.Client.get_stats) method returns the current state of an `awscrt.mqtt5.Client` object’s queue of operations in [OperationStatisticsData](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.OperationStatisticsData), which may help with tracking the number of in-flight messages. + +``` +op_stats_data = mqtt5_client.get_stats() +print( + "Client operations queue statistics:\n" + + "incomplete_operation_count:" + op_stats_data.incomplete_operation_count() + "\n" + "incomplete_operation_size: " + op_stats_data.incomplete_operation_size() + "\n" + "unacked_operation_count: " + op_stats_data.unacked_operation_count() + "\n" + "unacked_operation_size: " + op_stats_data.unacked_operation_size() + "\n") + +``` + +See [withOfflineQueueBehavior documentation](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.ClientOptions) for more details. +See [ClientOfflineQueueBehavior types documentation](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.ClientOperationQueueBehaviorType) to find the list of the supported offline queue behaviors and their description. + + +### Operation Timeouts + +In V1 SDK, all operations (*publish*, *subscribe*, *unsubscribe*) will not timeout unless you define a timeout for them. If no timeout is defined, there is a possibility that an operation will wait forever for the server to respond and block the calling thread indefinitely. + +In V2 SDK, operations timeout is set for the MQTT5 client with the [ClientOptions](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.ClientOptions) class member `ack_timeout_sec`. The default value is no timeout. As in V1 SDK, failing to set a timeout can cause an operation to stuck forever, but it won’t block the client. +The [get_stats](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.Client.get_stats) method returns the current state of an` mqtt5.Client` object’s queue of operations, which may help with tracking operations. + +_Example of timeouts in V1_ + +``` +connectTimeoutSec = 10 +`client``.``configureConnectDisconnectTimeout`(connectTimeoutSec) +client.connect(); + + publishTimeoutMs = 20 +client.`configureMQTTOperationTimeout``(publishTimeoutMs)` +client.publish("my/topic", "hello", 1) + +``` + +_Example of timeouts in V2_ + +``` +mqtt5_client = mqtt5_client_builder.mtls_from_path( + endpoint="-ats.iot..amazonaws.com", + cert_filepath="", + pri_key_filepath="", + ack_timeout_sec=20 +) +``` + + + +### Logging + +V1 SDK uses `AWSIoTPythonSDK.core` custom logger logger for logging. + +V2 SDK uses a standard [logging facility](https://docs.python.org/3/howto/logging.html). + +_Example of using logging in V1_ + +``` +logger = logging.getLogger("AWSIoTPythonSDK.core") +logger.setLevel(logging.DEBUG) +streamHandler = logging.StreamHandler() +formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') +streamHandler.setFormatter(formatter) +logger.addHandler(streamHandler) + +logger.error("error log") +logger.info("info log") +``` + +_Example of using logging in V2_ + +``` +from awscrt import io +import logging + +io.init_logging(log_level=io.LogLevel.Trace, file_name='stderr') + +logger.debug("error log") + +``` + + + +### Client for Device Shadow Service + +V1 SDK is built with [AWS IoT device shadow support](http://docs.aws.amazon.com/iot/latest/developerguide/iot-thing-shadows.html), providing access to thing shadows (sometimes referred to as device shadows). It also supports a simplified shadow access model, which allows developers to exchange data with their shadows by just using getter and setter methods without having to serialize or deserialize any JSON documents. + +V2 SDK supports device shadow service as well, but with completely different API. +First, you subscribe to special topics to get data and feedback from a service. The service client provides API for that. For example, `subscribe_to_get_shadow_accepted` subscribes to a topic to which AWS IoT Core will publish a shadow document; and via the `subscribe_to_get_shadow_rejected` the server will notify you if it cannot send you a requested document. +After subscribing to all the required topics, the service client can start interacting with the server, for example update the status or request for data. These actions are also performed via client API calls. For example, `publish_get_shadow` sends a request to AWS IoT Core to get a shadow document. The requested Shadow document will be received in a callback specified in the `subscribe_to_get_shadow_accepted` call. + +AWS IoT Core [documentation for Device Shadow](https://docs.aws.amazon.com/iot/latest/developerguide/device-shadow-mqtt.html) service provides detailed descriptions for the topics used to interact with the service. + +_Example of creating a Device Shadow service client in V1_ + +``` +# Blocking and non-blocking API. +shadow_client= AWSIoTMQTTShadowClient(") +shadow_client.configureEndpoint("", port) +shadow_client.configureCredentials( + rootCAPath, + privateKeyPath, + certificatePath) +shadow_client.connect() +isPersistentSubscribe ** = True +deviceShadowHandler = shadow_client.createShadowHandlerWithName( + "", + *isPersistentSubscribe*) +``` + +_Example of creating a Device Shadow service client in V2_ + +``` +mqtt5_client.start() +shadow_client = iotshadow.IotShadowClient(mqtt5_client) +``` + +_Example of deleting a Device Shadow in V1_ + +``` +# Delete Shadow +def customShadowCallback_Delete(payload, responseStatus, token): + return +deviceShadowHandler.shadowDelete(customShadowCallback_Delete, 5) + +``` + +_Example of deleting a Classic Shadow in V2_ + +``` +def delete_accepted(DeleteShadowResponse response): + return +shadow_client.subscribe_to_delete_shadow_accepted(*request*, *qos*, *callback*) + +def delete_rejected(DeleteShadowResponse response): + return +shadow_client.subscribe_to_delete_shadow_rejected(*request*, *qos*, *callback*) + +iotshadow.DeleteShadowRequest req +req.client_token = "" +req.thing_name = "" + +shadow_future = shadow_client.publish_delete_shadow( + request=req, + qos=mqtt5.QoS.AT_LEAST_ONCE) + +``` + +_Example of updating a Classic Shadow in V1_ + +``` +# Update Shadow +def customShadowCallback_Update(payload, responseStatus, token): + return + +JSONPayload = '{"state":{"desired":{"property":' + str(3) + '}}}' +deviceShadowHandler.shadowUpdate( + JSONPayload, + customShadowCallback_Update, + 5) + +``` + +_Example of updating a Classic Shadow in V2_ + +``` +# Update shadow +def on_update_shadow_accepted(response): + return + update_accepted_subscribed_future, _ = + shadow_client.subscribe_to_update_shadow_accepted( + request=iotshadow.UpdateShadowSubscriptionRequest( + thing_name=shadow_thing_name), + qos=mqtt5.QoS.AT_LEAST_ONCE, + callback=on_update_shadow_accepted) + +def on_update_shadow_rejected(error): + return +update_rejected_subscribed_future, _ = + shadow_client.subscribe_to_update_shadow_rejected( + request=iotshadow.UpdateShadowSubscriptionRequest( + thing_name=shadow_thing_name), + qos=mqtt5.QoS.AT_LEAST_ONCE, + callback=on_update_shadow_rejected) + +request = iotshadow.UpdateShadowRequest( + thing_name="thing name", + state=iotshadow.ShadowState( + reported={color: 1}, + desired={color: 2},), + client_token="") + +future = shadow_client.publish_update_shadow( + request, + mqtt5.QoS.AT_LEAST_ONCE) + +``` + +_Example of subscribing to a delta Shadow events in V1_ + +``` +# Delta Events +shadow_client.connect() + +def customShadowCallback_Delta(payload, responseStatus, token): + return + +deviceShadowHandler = shadow_client.createShadowHandlerWithName( + "", + True) + +deviceShadowHandler.shadowRegisterDeltaCallback( + customShadowCallback_Delta) + +``` + +_Example of subscribing to a delta Shadow events in V2_ + +``` +# Delta Events +def on_shadow_delta_updated(delta): + return + +delta_subscribed_future, _ = shadow_client.subscribe_to_shadow_delta_updated_events( + request=iotshadow.ShadowDeltaUpdatedSubscriptionRequest( + thing_name=shadow_thing_name), + qos=mqtt5.QoS.AT_LEAST_ONCE, + callback=on_shadow_delta_updated) + +delta_subscribed_future.result() + +``` + + +See API documentation for V2 SDK [Device Shadow](https://aws.github.io/aws-iot-device-sdk-python-v2/awsiot/iotshadow.html) service client for more details. +Refer to the V2 SDK [Device Shadow](https://github.com/aws/aws-iot-device-sdk-python-v2/blob/main/samples/shadow_mqtt5.py) sample for code example. + + +### Client for Jobs Service + +V1 and V2 SDK offer support of AWS IoT Core services implementing a service client for the [Jobs](https://docs.aws.amazon.com/iot/latest/developerguide/iot-jobs.html) service which helps with defining a set of remote operations that can be sent to and run on one or more devices connected to AWS IoT. +V1 IotJobs APIs are defined [here](https://s3.amazonaws.com/aws-iot-device-sdk-python-docs/html/index.html#AWSIoTPythonSDK.MQTTLib.AWSIoTMQTTThingJobsClient), with its corresponding code [samples](https://github.com/aws/aws-iot-device-sdk-python/blob/master/samples/jobs/jobsSample.py) + +V2 SDK supports Jobs service as well, but with completely different API. +The Jobs service client provides API similar to API provided by [Client for Device Shadow Service](https://quip-amazon.com/RUfpAM2x5mXr#temp:C:XVAbbb7cff5d5884fdfb4dcf670f). First, you subscribe to special topics to get data and feedback from a service. The service client provides API for that. After subscribing to all the required topics, the service client can start interacting with the server, for example update the status or request for data. These actions are also performed via client API calls. + +AWS IoT Core documentation for [Jobs](https://docs.aws.amazon.com/iot/latest/developerguide/jobs-mqtt-api.html) service provides detailed descriptions for the topics used to interact with the service. + +See API documentation for V2 SDK [Jobs](https://aws.github.io/aws-iot-device-sdk-python-v2/awsiot/iotjobs.html) service clients for more details. +Refer to the V2 SDK [Jobs](https://github.com/aws/aws-iot-device-sdk-python-v2/blob/main/samples/jobs_mqtt5.py) samples for code examples. + +_V1 Jobs Example_ + +``` +jobs_client = AWSIoTMQTTThingJobsClient( + "", + "", + QoS=1, + awsIoTMQTTClient=mqtt5_client) + +jobsClient.connect() + +# Setup Callbacks +def newJobReceived(self, mqtt5_client, userdata, message): + return +jobs_client.createJobSubscription( + newJobReceived, + jobExecutionTopicType. + JOB_NOTIFY_NEXT_TOPIC) + +def startNextJobSuccessfullyInProgress(mqtt5_client, userdata, message): + return +jobs_client.createJobSubscription( + startNextJobSuccessfullyInProgress, + jobExecutionTopicType.JOB_START_NEXT_TOPIC, + jobExecutionTopicReplyType.JOB_ACCEPTED_REPLY_TYPE) + +def startNextRejected(mqtt5_client, userdata, message): + return +jobs_client.createJobSubscription( + startNextRejected, + jobExecutionTopicType.JOB_START_NEXT_TOPIC, + jobExecutionTopicReplyType.JOB_REJECTED_REPLY_TYPE) + +def updateJobSuccessful(mqtt5_client, userdata, message): + return +jobs_client.createJobSubscription( + updateJobSuccessful, + jobExecutionTopicType.JOB_UPDATE_TOPIC, + jobExecutionTopicReplyType.JOB_ACCEPTED_REPLY_TYPE, + '+') + +def updateJobRejected(mqtt5_client, userdata, message): + return +jobs_client.createJobSubscription( + updateJobRejected, + jobExecutionTopicType.JOB_UPDATE_TOPIC, + jobExecutionTopicReplyType.JOB_REJECTED_REPLY_TYPE, + '+') + +# start next job +statusDetails = + {'StartedBy': 'ClientToken: {} on {}'.format( + clientToken, + datetime.datetime.now().isoformat())} + +jobs_client.sendJobsStartNext( + statusDetails=statusDetails) + +# Update job status +jobs_cli.`sendJobsUpdate( + jobId="", + statusDetails=None, + `expectedersion=4, + executionNumber=3, + includeJobExecutionState=False, + includeJobDocument=False + stepTimeoutInMinutes=3) + +jobsClient.disconnect() + +``` + + +_V2 Jobs example_ + +``` +jobs_client = iotjobs.IotJobsClient(mqtt5_client) +get_jobs_request = iotjobs.GetPendingJobExecutionsRequest(thing_name=") + +# List pending jobs +def on_get_pending_job_executions_accepted(response): + return +jobs_request_future_accepted, _ = + jobs_client.subscribe_to_get_pending_job_executions_accepted + request=get_jobs_request, + qos=mqtt5.QoS.AT_LEAST_ONCE, + callback=on_get_pending_job_executions_accepted) + +def on_get_pending_job_executions_rejected(error): + return +jobs_request_future_rejected, _ = + jobs_client.subscribe_to_get_pending_job_executions_rejected( + request=get_jobs_request, + qos=mqtt5.QoS.AT_LEAST_ONCE, + callback=on_get_pending_job_executions_rejected) + +get_jobs_request_future = jobs_client.publish_get_pending_job_executions( + request=get_jobs_request, + qos=mqtt5.QoS.AT_LEAST_ONCE) + +# Subscribe to necessary topics +changed_subscription_request = iotjobs.NextJobExecutionChangedSubscriptionRequest( + thing_name="") + +def on_next_job_execution_changed(event): + return +subscribed_future, _ = jobs_client.subscribe_to_next_job_execution_changed_events( + request=changed_subscription_request, + qos=mqtt5.QoS.AT_LEAST_ONCE, + callback=on_next_job_execution_changed) + +start_subscription_request = iotjobs.StartNextPendingJobExecutionSubscriptionRequest( + thing_name="") + +def on_start_next_pending_job_execution_accepted(response): + return +subscribed_accepted_future, _ = + jobs_client.subscribe_to_start_next_pending_job_execution_accepted( + request=start_subscription_request, + qos=mqtt5.QoS.AT_LEAST_ONCE, + callback=on_start_next_pending_job_execution_accepted) + +def on_start_next_pending_job_execution_rejected(rejected): + return +subscribed_rejected_future, _ = + jobs_client.subscribe_to_start_next_pending_job_execution_rejected( + request=start_subscription_request, + qos=mqtt5.QoS.AT_LEAST_ONCE, + callback=on_start_next_pending_job_execution_rejected) + +# Note that we subscribe to "+", the MQTT wildcard, to receive +# responses about any job-ID. +update_subscription_request = iotjobs.UpdateJobExecutionSubscriptionRequest( + thing_name=jobs_thing_name, + job_id='+') + +def on_update_job_execution_accepted(response): + return +subscribed_accepted_future, _ = + jobs_client.subscribe_to_update_job_execution_accepted( + request=update_subscription_request, + qos=mqtt5.QoS.AT_LEAST_ONCE, + callback=on_update_job_execution_accepted) + +def on_update_job_execution_rejected(rejected): + return +subscribed_rejected_future, _ = + jobs_client.subscribe_to_update_job_execution_rejected( + request=update_subscription_request + qos=mqtt5.QoS.AT_LEAST_ONCE, + callback=on_update_job_execution_rejected) + +# Start next Job +request = iotjobs.StartNextPendingJobExecutionRequest( + thing_name=") +publish_future = jobs_client.publish_start_next_pending_job_execution( + request, + mqtt5.QoS.AT_LEAST_ONCE) +publish_future.add_done_callback( + on_publish_start_next_pending_job_execution) + +``` + + + +### Client for Fleet Provisioning Service + +Another IoT service that V2 SDK provides access to is [Fleet Provisioning](https://docs.aws.amazon.com/iot/latest/developerguide/provision-wo-cert.html) (also known as Identity Service). By using AWS IoT fleet provisioning, AWS IoT can generate and securely deliver device certificates and private keys to your devices when they connect to AWS IoT for the first time. + +The Fleet Provisioning service client provides API similar to API provided by [Client for Device Shadow Service](https://quip-amazon.com/RUfpAM2x5mXr#temp:C:XVAbbb7cff5d5884fdfb4dcf670f). First, you subscribe to special topics to get data and feedback from a service. The service client provides API for that. After subscribing to all the required topics, the service client can start interacting with the server, for example update the status or request for data. These actions are also performed via client API calls. + +AWS IoT Core documentation for [Fleet Provisioning](https://docs.aws.amazon.com/iot/latest/developerguide/fleet-provision-api.html) service provides detailed descriptions for the topics used to interact with the service. + +See API documentation for V2 SDK [Fleet Provisioning](https://aws.github.io/aws-iot-device-sdk-python-v2/awsiot/iotidentity.html) service client for more details. +Refer to the V2 SDK [Fleet Provisioning](https://github.com/aws/aws-iot-device-sdk-python-v2/blob/main/samples/fleetprovisioning.md) samples for code examples. + + +### Example + +It’s always helpful to look at a working example to see how new functionality works, to be able to tweak different options, to compare with existing code. For that reasons, we implemented a [Publish/Subscribe example](https://github.com/aws/aws-iot-device-sdk-python-v2/blob/main/samples/mqtt5_pubsub.md) ([source code](https://github.com/aws/aws-iot-device-sdk-python-v2/blob/main/samples/mqtt5_pubsub.py)) in V2 SDK similar to a sample provided by V1 SDK (see a corresponding [readme section](https://github.com/aws/aws-iot-device-sdk-python/blob/master/README.rst#basicpubsub) and [source code](https://github.com/aws/aws-iot-device-sdk-python/blob/master/samples/basicPubSub/basicPubSub.py)). + +## How to get help + +For any migration related questions or feedback, you can contact us at [discussion](https://github.com/aws/aws-iot-device-sdk-python-v2/discussions) by submitting an issue with a label `label:migration`. + +## Appendix + +### MQTT5 Features + +**Clean Start and Session Expiry** +You can use Clean Start and Session Expiry to handle your persistent sessions with more flexibility. +Refer to [awscrt.mqtt5.ClientSessionBehaviorType](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.ClientSessionBehaviorType) enum and [NegotiatedSettings.session_expiry_interval_sec](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.NegotiatedSettings) method for details. + +**Reason Code on all ACKs** +You can debug or process error messages more easily using the reason codes. Reason codes are returned by the message broker based on the type of interaction with the broker (Subscribe, Publish, Acknowledge). +See [PubAckReasonCode](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.PubackReasonCode), [SubAckReasonCode](https://awslabs.github.io/aws-crt-java/software/amazon/awssdk/crt/mqtt5/packets/SubAckPacket.SubAckReasonCode.html), [UnsubAckReasonCode](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.SubackReasonCode), [ConnectReasonCode](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.ConnectReasonCode), [DisconnectReasonCode](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.DisconnectReasonCode). + +**Topic Aliases** +You can substitute a topic name with a topic alias, which is a two-byte integer. +Use [mqtt5.TopicAliasingOptions](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.TopicAliasingOptions) with [mqtt5.ClientOptions](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.ClientOptions), and when creating a [PUBLISH packet](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.PublishPacket) use the parameter topic_alias(int). + +**Message Expiry** +You can add message expiry values to published messages. Use [message_expiry_interval_sec](https://awslabs.github.io/aws-crt-java/software/amazon/awssdk/crt/mqtt5/packets/PublishPacket.PublishPacketBuilder.html#withMessageExpiryIntervalSeconds(java.lang.Long)) variable when creating a [PUBLISH packet](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.PublishPacket). + +**Server disconnect** +When a disconnection happens, the server can proactively send the client a DISCONNECT to notify connection closure with a reason code for disconnection. +Refer to [DisconnectPacket](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.DisconnectPacket) class for details. + +**Request/Response** +Publishers can request a response be sent by the receiver to a publisher-specified topic upon reception. Use `response_topic` method in [PublishPacket](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.PublishPacket) class. + +**Maximum Packet Size** +Client and Server can independently specify the maximum packet size that they support. See [ConnectPacket.maximum_packet_size(int)](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.ConnectPacket), [NegotiatedSettings.maximum_packet_size_to_server](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.NegotiatedSettings), and [ConnAckPacket.maximum_packet_size](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.ConnackPacket) methods. + +**Payload format and content type** +You can specify the payload format (binary, text) and content type when a message is published. These are forwarded to the receiver of the message. Use content_type(str) method in [PublishPacket](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.PublishPacket) class. + +**Shared Subscriptions** +Shared Subscriptions allow multiple clients to share a subscription to a topic and only one client will receive messages published to that topic using a random distribution. +Refer to a [shared subscription sample](https://github.com/aws/aws-iot-device-sdk-python-v2/blob/main/samples/mqtt5_shared_subscription.md) in V2 SDK. +**NOTE** AWS IoT Core provides this functionality for MQTT3 as well. + From 26e575510eb7311c0e56e46a67e01baeacdd3a11 Mon Sep 17 00:00:00 2001 From: Alfred Gedeon Date: Thu, 8 Feb 2024 21:04:15 -0800 Subject: [PATCH 02/12] apply various reviews --- documents/MIGRATION_GUIDE.md | 664 +++++++++++++++++++++++------------ 1 file changed, 433 insertions(+), 231 deletions(-) diff --git a/documents/MIGRATION_GUIDE.md b/documents/MIGRATION_GUIDE.md index ba6db21f..c555c968 100644 --- a/documents/MIGRATION_GUIDE.md +++ b/documents/MIGRATION_GUIDE.md @@ -1,41 +1,92 @@ -grate from V1 to V2 of the AWS IoT SDK for Python - -The V2 AWS IoT SDK for Python is a major rewrite of the V1 code base built on top of Python 3.7+. It includes many updates, such as improved consistency, ease of use, more detailed information about client status, an offline operation queue control, etc. This guide describes the major features that are new in V2, and provides guidance on how to migrate your code to V2 from V1. - -## What’s new - -* V2 SDK client is truly async. Operations return `concurrent.futures.Future` objects. +# Migrate from v1 to v2 of the AWS IoT SDK for Python + +The AWS IoT SDK for Python v2 is a major rewrite of the v1 SDK code base built on top of Python 3.7+. +It includes many updates, such as improved consistency, ease of use, more detailed information about client status, +an offline operation queue control, etc. This guide describes the major features that are new in the v2 SDK, +and provides guidance on how to migrate your code to v2 from v1 of the AWS IoT SDK for Python. + +>[!NOTE] +> If you can't find the information you need in this guide, visit the [Hot to get help](#how-to-get-help) section for +> more help and guidance. + + +* [What's new in AWS IoT Device SDK for Python v2](#whats-new-in-aws-iot-device-sdk-for-python-v2) +* [How to get started with AWS IoT Device SDK for Python v2](#how-to-get-started-with-aws-iot-device-sdk-for-python-v2) + * [Package name change](#package-name-change) + * [MQTT protocol](#mqtt-protocol) + * [Client builder](#client-builder) + * [Connection types and features](#connection-types-and-features) + * [Lifecycle events](#lifecycle-events) + * [Publish](#publish) + * [Subscribe](#subscribe) + * [Unsubscribe](#unsubscribe) + * [Client stop](#client-stop) + * [Client shutdown](#client-shutdown) + * [Reconnects](#reconnects) + * [Offline operations queue](#offline-operations-queue) + * [Operation timeouts](#operation-timeouts) + * [Logging](#logging) + * [Client for AWS IoT Device Shadow](#client-for-aws-iot-device-shadow) + * [Client for AWS IoT Jobs](#client-for-aws-iot-jobs) + * [Client for AWS IoT fleet provisioning](#client-for-aws-iot-fleet-provisioning) + * [Example](#example) +* [How to get help](#how-to-get-help) +* [Appendix](#appendix) + * [MQTT5 features](#mqtt5-features) + + +## What's new in AWS IoT Devide SDK for Python v2 + +* The v2 SDK client is truly async. Operations return `concurrent.futures.Future` objects. Blocking calls can be emulated by waiting for the returned `Future` object to be resolved. * V2 SDK provides implementation for MQTT5 protocol, the next step in evolution of the MQTT protocol. -* Public API terminology has changed. You `start()` or `stop()` the MQTT5 client rather than c`onnect` or d`isconnect` like in V1. This removes the semantic confusion with the connect/disconnect as the client-level controls vs. internal recurrent networking events. -* Support for Fleet Provisioning AWS IoT Core service. +* Public API terminology has changed. You `start()` or `stop()` the MQTT5 client + rather than c`onnect` or d`isconnect` as in the v1 SDK. This removes the semantic confusion between client-level + controls and internval recurrent networking events related to connection and disconnection. +* The v2 SDK supports AWS Iot services such as Fleet Provisioning. -Public API for almost all actions and operations has changed significantly. For more details about the new features and to see specific code examples, refer to the other sections of this guide. +Public APIs for almost all actions and operations has changed significantly. +For more information about the new features and specific code examples, refer to the +[How to get started with AWS IoT Device SDK for Python v2](#how-to-get-started-with-aws-iot-device-sdk-for-python-v2) +section of this guide. -## How To Get Started with V2 SDK +## How To Get Started with AWS Iot Device SDK for python v2 -There are differences between IoT Python V1 SDK and IoT Python V2 SDK. Below are changes you need to make to use IoT Python V2 SDK features. For more information about MQTT5, visit [MQTT5 User Guide](https://github.com/aws/aws-iot-device-sdk-python-v2/blob/main/documents/MQTT5_Userguide.md) +There are differences between the v1 SDK and the v2 SDK. This section describes the changes you need to apply to your +project witht the v1 SDK to start using the v2 SDK. +For more information about MQTT5, visit [MQTT5 User Guide](https://github.com/aws/aws-iot-device-sdk-python-v2/blob/main/documents/MQTT5_Userguide.md) ### MQTT Protocol -V1 SDK uses an MQTT version 3.1.1 client under the hood. +The v1 SDK uses an MQTT version 3.1.1 client under the hood. -V2 SDK provides MQTT version 3.1.1 and MQTT version 5.0 client implementations. This guide focuses on the MQTT5 since this version is significant improvement over MQTT3. See MQTT5 features section. +The v2 SDK provides MQTT version 3.1.1 and MQTT version 5.0 client implementations. +This guide focuses on the MQTT5 because this version is a significant improvement over MQTT3. +For more information, see the [MQTT5 features](#mqtt5-features) section. ### Client Builder -To access the AWS IoT service, you must initialize an MQTT client. +To access AWS IoT services, you must initialize an MQTT client. -In V1 SDK, the [`AWSIoTPythonSDK.MQTTLib.`AWSIotMqttClient](https://s3.amazonaws.com/aws-iot-device-sdk-python-docs/html/index.html#AWSIoTPythonSDK.MQTTLib.AWSIoTMQTTClient) class represents an MQTT client. You instantiate the client directly passing all the required parameters to the class constructor. It’s possible to change client settings after its creation using `configure*` methods, e.g. `configureMQTTOperationTimeout` or `configureConnectDisconnectTimeout`. +In the v1 SDK, the [AWSIoTPythonSDK.MQTTLib.AWSIotMqttClient](https://s3.amazonaws.com/aws-iot-device-sdk-python-docs/html/index.html#AWSIoTPythonSDK.MQTTLib.AWSIoTMQTTClient) +class represents an MQTT client. You instantiate the client directly passing all the required parameters +to the class constructor. +It's possible to change client settings after its creation using `configure*` methods, +like `configureMQTTOperationTimeout` or `configureConnectDisconnectTimeout`. -In V2 SDK, the [awcrt.mqtt5.Client](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.Client) class represents an MQTT client, specifically MQTT5 protocol. V2 SDK provides an [awsiot.mqtt5_client_builder](https://aws.github.io/aws-iot-device-sdk-python-v2/awsiot/mqtt5_client_builder.html) designed to easily create common configuration types such as direct MQTT or WebSocket connections, the resulting MQTT5 client cannot have its settings modified. +In the v2 SDK, the [awcrt.mqtt5.Client](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.Client) +class represents an MQTT client, +specifically for MQTT5 protocol. +The v2 SDK provides an [awsiot.mqtt5_client_builder](https://aws.github.io/aws-iot-device-sdk-python-v2/awsiot/mqtt5_client_builder.html) +designed to easily create common configuration types such as direct MQTT or WebSocket connections. After and MQTT5 +client is built and finalized, the settings of the resulting MQTT5 client cannot be modified. -_Example of creating a client in V1_ +#### Example of creating a client in the v1 SDK -``` +```python clientEndpoint = "-ats.iot..amazonaws.com" clientId = "" certificateFile = "" # X.509 based certificate file @@ -50,12 +101,12 @@ client.connect() ``` -_Example of creating a client in V2_ -V2 SDK supports different connection types. Given the same input parameters as in the V1 example above, the most suitable method to create an MQTT5 client will be [awsiot.mqtt5_client_builder.mtls_from_path](https://aws.github.io/aws-iot-device-sdk-python-v2/awsiot/mqtt5_client_builder.html#awsiot.mqtt5_client_builder.mtls_from_path). +#### Example of creating a client in the v2 SDK -``` -from awsiot import mqtt5_client_builder +The V2 SDK supports different connection types. Given the same input parameters as in the V1 example above, +the most suitable method to create an MQTT5 client will be [awsiot.mqtt5_client_builder.mtls_from_path](https://aws.github.io/aws-iot-device-sdk-python-v2/awsiot/mqtt5_client_builder.html#awsiot.mqtt5_client_builder.mtls_from_path). +```python clientEndpoint = "-ats.iot..amazonaws.com" clientId = "" certificateFile = "" # X.509 based certificate file @@ -72,51 +123,62 @@ mqtt5_client = mqtt5_client_builder.mtls_from_path( mqtt5_client.start() ``` - -Refer to the [Connection Types and Features](https://quip-amazon.com/RUfpAM2x5mXr#temp:C:XVAe19c32f97575498c9c9ddc15a) section for other connection types supported by V2 SDK. +For more information, refer to the [Connection Types and Features](#connection-types-and-features) section for other +connection types supported by the v2 SDK ### Connection Types and Features -V1 SDK supports two types of connections to connect to the AWS IoT service: MQTT with X.509 certificate and MQTT over Secure WebSocket with SigV4 authentication. - -V2 SDK adds a collection of connection types and cryptography formats (e.g. [PKCS #11](https://en.wikipedia.org/wiki/PKCS_11) and [Custom Authorizer](https://docs.aws.amazon.com/iot/latest/developerguide/custom-authentication.html)), credential providers (e.g. [Amazon Cognito](https://aws.amazon.com/cognito/) and [Windows Certificate Store](https://learn.microsoft.com/en-us/windows-hardware/drivers/install/certificate-stores)), and other connection-related features. -Refer to the “[How to setup MQTT5 builder based on desired connection method](https://github.com/aws/aws-iot-device-sdk-python-v2/blob/main/documents/MQTT5_Userguide.md#how-to-create-a-mqtt5-client-based-on-desired-connection-method)” section of the MQTT5 user guide for detailed information and code snippets on each connection type and connection feature. - -|Connection Type/Feature |V1 SDK |V2 SDK |User guide section | | -|--- |--- |--- |--- |--- | -| | | | | | -|MQTT over Secure WebSocket with AWS SigV4 authentication |✔ |✔ | | | -|MQTT with Java Keystore Method |✔ |✔ | |X.509 | -|MQTT (over TLS 1.2) with X.509 certificate based mutual authentication |✘ |✔ | |X.509 | -|MQTT with PKCS12 Method |✘ |✔✔*✔**** | |Container for X.509 | -|MQTT with Custom Key Operation Method |✔* |✔ | |X.509 | -|MQTT with Custom Authorizer Method |✔* |✔ | | | -|MQTT with Windows Certificate Store Method |✔* |✔ | |X.509 | -|MQTT with PKCS11 Method |✘ |✔ | |X.509 plus other formats | -|Websocket Connection with Cognito Authentication Method |✘ |✔ | | | -|HTTP Proxy |✔*** |✔ | | | - -✔* - one option to get this connection type work in V2 SDK, is to [import IOT Core key to a Java KeyStore and convert it to pkcs#12](https://github.com/aws/aws-iot-device-sdk-python-v2/blob/main/samples/pkcs12_connect.md). -✔** - In order to get this connection type work in V1 SDK, you need to implement the [Custom Authentication workflow](https://docs.aws.amazon.com/iot/latest/developerguide/custom-authorizer.html). -✔*** - Though V1 does not allow to specify HTTP proxy, it is possible to configure systemwide proxy. -✔**** - Available on MacOS only +The v1 SDK supports two types of connections to the AWS IoT service: +MQTT with X.509 certificate and MQTT over Secure WebSocket with SigV4 authentication. + +The v2 SDK adds a collection of connection types and cryptography formats +(e.g. [PKCS #11](https://en.wikipedia.org/wiki/PKCS_11) and +[Custom Authorizer](https://docs.aws.amazon.com/iot/latest/developerguide/custom-authentication.html)), +credential providers (e.g. [Amazon Cognito](https://aws.amazon.com/cognito/) and +[Windows Certificate Store](https://learn.microsoft.com/en-us/windows-hardware/drivers/install/certificate-stores)), +and other connection-related features. + +For more information, refer to the [How to setup MQTT5 builder based on desired connection method](https://github.com/aws/aws-iot-device-sdk-python-v2/blob/main/documents/MQTT5_Userguide.md#how-to-create-a-mqtt5-client-based-on-desired-connection-method) +section fo the MQTT5 user guide for detailed information and code snippets on each connection type and connection +feature. + +| Connection type/feature | v1 SDK | v2 SDK | User guide | +|--------------------------------------------------------|---------------------------------------|------------------------------------|:----------:| +|MQTT over Secure WebSocket with AWS SigV4 authentication|$${\Large\color{green}✔}$$ |$${\Large\color{green}✔}$$ |[link](https://github.com/aws/aws-iot-device-sdk-python-v2/blob/main/documents/MQTT5_Userguide.md#mqtt-over-websockets-with-sigv4-authentication)| +|MQTT with Java Keystore Method |$${\Large\color{red}✘}$$ |$${\Large\color{orange}✔\*}$$ |[link](https://github.com/aws/aws-iot-device-sdk-python-v2/blob/main/samples/pkcs12_connect.md#how-to-setup-and-run)| +|Websocket Connection with Cognito Authentication Method |$${\Large\color{red}✘}$$ |$${\Large\color{green}✔}$$ |[link](https://github.com/aws/aws-iot-device-sdk-python-v2/blob/main/documents/MQTT5_Userguide.md#mqtt-over-websockets-with-cognito-authentication)| +|MQTT with X.509 certificate based mutual authentication |$${\Large\color{red}✘}$$ |$${\Large\color{green}✔}$$ |[link](https://github.com/aws/aws-iot-device-sdk-python-v2/blob/main/documents/MQTT5_Userguide.md#direct-mqtt-with-x509-based-mutual-tls)| +|MQTT with PKCS12 Method |$${\Large\color{red}✘}$$ |$${\Large\color{green}✔}$$ |[link](https://github.com/aws/aws-iot-device-sdk-python-v2/blob/main/documents/MQTT5_Userguide.md#direct-mqtt-with-pkcs12-method) | +|MQTT with Custom Authorizer Method |$${\Large\color{orange}✔\*\*}$$ |$${\Large\color{green}✔}$$ |[link](https://github.com/aws/aws-iot-device-sdk-python-v2/blob/main/documents/MQTT5_Userguide.md#direct-mqtt-with-custom-authentication)| +|MQTT with Windows Certificate Store Method |$${\Large\color{red}✘}$$ |$${\Large\color{green}✔}$$ |[link](TODO: PR to be merged)| +|MQTT with PKCS11 Method |$${\Large\color{red}✘}$$ |$${\Large\color{green}✔}$$ |[link](https://github.com/aws/aws-iot-device-sdk-python-v2/blob/main/documents/MQTT5_Userguide.md#direct-mqtt-with-pkcs11-method)| +|HTTP Proxy |$${\Large\color{orange}✔\*\*\*}$$|$${\Large\color{green}✔}$$ |[link](https://github.com/aws/aws-iot-device-sdk-python-v2/blob/main/documents/MQTT5_Userguide.md#adding-an-http-proxy)| + +$${\Large\color{orange}✔\*}$$ To get this connection type to work in the V2 SDK, you need to convert the Java Key store key into a PKSC#11 key + [import IOT Core key to a Java KeyStore and convert it to pkcs#12](https://github.com/aws/aws-iot-device-sdk-python-v2/blob/main/samples/pkcs12_connect.md#how-to-setup-and-run).\ +$${\Large\color{orange}✔\*}$$ - To get this connection type work in V1 SDK, you need to implement the [Custom Authentication workflow](https://docs.aws.amazon.com/iot/latest/developerguide/custom-authorizer.html).\ +$${\Large\color{orange}✔\*\*}$$ - The v1 SDK does not allow to specify HTTP proxy, it is possible to configure systemwide proxy. ### Lifecycle Events -Both V1 and V2 SDKs provide lifecycle events for the MQTT clients. +Both the v1 and the v2 SDKs provide lifecycle events for the MQTT clients. -V1 SDK provides 2 lifecycle events: “on Online” and “on Offline”. You can supply a custom callback function via callbacks to `AWSIoTPythonSDK.MQTTLib.AWSIoTMQTTClient`. It is recommended to use lifecycle events callbacks to help determine the state of the MQTT client during operation. +The v1 SDK provides 2 lifecycle events: “on Online” and “on Offline”. You can supply a custom callback function via +callbacks to `AWSIoTPythonSDK.MQTTLib.AWSIoTMQTTClient`. +It is recommended to use lifecycle events callbacks to help determine the state of the MQTT client during operation. -V2 SDK add 3 new lifecycle events, providing 5 lifecycle events in total: “on connection success”, “on connection failure”, “on disconnect”, “on stopped”, and “on attempting connect”. -Refer to the [MQTT5 user guide](https://github.com/aws/aws-iot-device-sdk-python-v2/blob/main/documents/MQTT5_Userguide.md#how-to-create-a-mqtt5-client-based-on-desired-connection-method) for the details. +The v2 SDK adds 3 new lifecycle events, providing 5 lifecycle events in total: “on connection success”, +“on connection failure”, “on disconnect”, “on stopped”, and “on attempting connect”. -_Example of setting lifecycle events in V1_ +For more information, refer to the [MQTT5 user guide](https://github.com/aws/aws-iot-device-sdk-python-v2/blob/main/documents/MQTT5_Userguide.md#how-to-create-a-mqtt5-client-based-on-desired-connection-method). -``` -`def`` myConnectCallback``(``mid``,`` data``):` -` ``return` +#### Example of setting lifecycle events in the v1 SDK + +```python +def myConnectCallback(mid, data): + return def myDisconnectCallback(mid, data): return @@ -130,10 +192,9 @@ client.connect() ``` +#### Example of setting lifecycle events in the v2 SDK -_Example of setting lifecycle events in V2_ - -``` +```python def on_lifecycle_connection_success( lifecycle_connect_success_data: mqtt5.LifecycleConnectSuccessData): return @@ -164,29 +225,43 @@ mqtt5_client = mqtt5_client_builder.mtls_from_path( on_lifecycle_disconnection=on_lifecycle_disconnection, on_lifecycle_connection_failure=on_lifecycle_connection_failure) mqtt5_client.start() -``` +``` ### Publish -V1 SDK provides two API calls for publishing: blocking and non-blocking. For the non-blocking version, the result of the publish operation is reported via a set of callbacks. If you try to publish to a topic that is not allowed by a policy, AWS IoT Core service will close the connection. +The v1 SDK provides two API calls for publishing: blocking and non-blocking. +For the non-blocking version, the result of the publish operation is reported via a set of callbacks. +If you try to publish to a topic that is not allowed by a policy, AWS IoT Core service will close the connection. -V2 SDK provides only asynchronous non-blocking API. [PublishPacketBuilder](https://awslabs.github.io/aws-crt-java/software/amazon/awssdk/crt/mqtt5/packets/PublishPacket.PublishPacketBuilder.html) creates a [PublishPacket](https://awslabs.github.io/aws-crt-java/software/amazon/awssdk/crt/mqtt5/packets/PublishPacket.html) object containing a description of the PUBLISH packet. The [publish](https://awslabs.github.io/aws-crt-java/software/amazon/awssdk/crt/mqtt5/Mqtt5Client.html#publish(software.amazon.awssdk.crt.mqtt5.packets.PublishPacket)) operation takes a `PublishPacket` instance and returns a promise containing a [PublishResult](https://awslabs.github.io/aws-crt-java/software/amazon/awssdk/crt/mqtt5/PublishResult.html). The returned `PublishResult` will contain different data depending on the `QoS` used in the publish. +The v2 SDK provides only asynchronous non-blocking API. +[awscrt.mqtt5.PublishPacket](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.PublishPacket) +object that contains a description of the PUBLISH packet. +The [publish](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.Client.publish) +operation takes a `PublishPacket` instance and returns a promise that contains a +[awscrt.mqtt5.PublishCompletionData](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.PublishCompletionData). +The returned `PublishCompletionData` will contain different data depending on the `QoS` used in the publish. -* For QoS 0 (AT_MOST_ONCE): Calling `getValue` will return `null` and the promise will be complete as soon as the packet has been written to the socket. -* For QoS 1 (AT_LEAST_ONCE): Calling `getValue` will return a [PubAckPacket](https://awslabs.github.io/aws-crt-java/software/amazon/awssdk/crt/mqtt5/packets/PubAckPacket.html) and the promise will be complete as soon as the PUBACK is received from the broker. +* For QoS 0 (AT\_MOST\_ONCE): Calling `getValue` will return `null` + and the promise will be complete as soon as the packet has been written to the socket. +* For QoS 1 (AT\_LEAST\_ONCE): Calling `getValue` will return a + [awscrt.mqtt5.PubAckPacket](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.PubackPacket) + and the promise will be complete as soon as the PUBACK is received from the broker. -If the operation fails for any reason before these respective completion events, the promise is rejected with a descriptive error. You should always check the reason code of a [PubAckPacket](https://awslabs.github.io/aws-crt-java/software/amazon/awssdk/crt/mqtt5/packets/PubAckPacket.html) completion to determine if a QoS 1 publish operation actually succeeded. +If the operation fails for any reason before these respective completion events, +the promise is rejected with a descriptive error. You should always check the reason code of a +[awscrt.mqtt5.PubAckPacket](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.PubackPacket) +completion to determine if a QoS 1 publish operation actually succeeded. -_Example of publishing in V1_ +#### Example of publishing in the v1 SDK -``` +```python # Blocking. client.publish("my/topic", "hello", 0) ``` -``` +```python # Non-blocking API. `client.configureMQTTOperationTimeout`(30) # 30 Seconds client.connect() @@ -202,48 +277,75 @@ client.publishAsync( ``` -_Example of publishing in V2_ +#### Example of publishing in the v2 SDK -``` -publish_future,packet_id = client.publish(mqtt5.PublishPacket( - topic="my/topic", - payload=json.dumps("hello"), - qos=mqtt5.QoS.AT_LEAST_ONCE)) +```python +publish_future,packet_id = client.publish( + mqtt5.PublishPacket( + topic="my/topic", + payload=json.dumps("hello"), + qos=mqtt5.QoS.AT_LEAST_ONCE)) publish_future.result(20) # 20 seconds ``` - - ### Subscribe -V1 provides blocking and non-blocking API for subscribing. To subscribe to topic in V1, you should provide an instance of [AWSIotTopic](http://aws-iot-device-sdk-java-docs.s3-website-us-east-1.amazonaws.com/com/amazonaws/services/iot/client/AWSIotTopic.html) to the [subscribe](https://s3.amazonaws.com/aws-iot-device-sdk-python-docs/html/index.html#AWSIoTPythonSDK.MQTTLib.AWSIoTMQTTClient.subscribe) operation. AWSIotTopic object (or, usually, an object of a children class) implements `onMessageReceived` method which will be called on receiving a new message. If you try to subscribe to a topic that is not allowed by a policy, AWS IoT Core service will close the connection. - -V2 SDK provides only asynchronous non-blocking API. First, you need to create a [SubscribePacket](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.SubscribePacket) object. If you specify multiple topics in the *Sequence[*[*Subscription*](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.Subscription)*]* parameter, V2 SDK will subscribe to all of these topics using one request. The [subscribe](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.Client.subscribe) operation takes a description of the `SubscribePacket` you wish to send and returns a promise that resolves successfully with the corresponding [SubAckPacket](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.SubackPacket) returned by the broker; the promise is rejected with an error if anything goes wrong before the `SubAckPacket` is received. You should always check the reason codes of a `SubAckPacket` completion to determine if the subscribe operation actually succeeded. - -In V2 SDK, if the MQTT5 client is going to subscribe and receive packets from the MQTT broker, it is important to also setup the `on_publish_callback_fn` callback. This callback is invoked whenever the client receives a message from the server on a topic the client is subscribed to. With this callback, you can process messages made to subscribed topics with its parameter [PublishReceivedData](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.PublishReceivedData). - -_Example of subscribing in V1_ +The v1 SDK provides blocking and non-blocking API for subscribing. +To subscribe to a topic in the v1 SDK, you should provide a `topic` string to the +[subscribe](https://s3.amazonaws.com/aws-iot-device-sdk-python-docs/html/index.html#AWSIoTPythonSDK.MQTTLib.AWSIoTMQTTClient.subscribe) +and [subscribeAsync](https://s3.amazonaws.com/aws-iot-device-sdk-python-docs/html/index.html?highlight=subscribe#AWSIoTPythonSDK.MQTTLib.AWSIoTMQTTClient.subscribeAsync) +operations. A callback parameter function will be called on receiving a new message. +If you try to subscribe to a topic that is not allowed by a policy, AWS IoT Core service will close the connection. + +The v2 SDK provides only asynchronous non-blocking API. First, you need to create a +[SubscribePacket](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.SubscribePacket) object. +If you specify multiple topics in the [*Sequence*\[*Subscription*\]](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.Subscription) +parameter, the v2 SDK will subscribe to all of these topics using one request. +The [subscribe](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.Client.subscribe) operation takes a +description of the `SubscribePacket` +you wish to send and returns a promise that resolves successfully with the +corresponding [SubAckPacket](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.SubackPacket) +returned by the broker. The promise is rejected with an error if anything goes wrong before +the `SubAckPacket` is received. +You should always check the reason codes of a `SubAckPacket` completion to determine if +the subscribe operation actually succeeded. + +In the v2 SDK, if the MQTT5 client is going to subscribe and receive packets from the MQTT broker, +it is important to also setup the `on_publish_callback_fn` callback int the `ClientOptions`. +This callback is invoked whenever the client receives a message from the server on a topic the client is subscribed to. +With this callback, you can process messages made to subscribed topics with its parameter +[PublishReceivedData](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.PublishReceivedData). + +#### Example of subscribing in the v1 SDK + +```python + +client.configureMQTTOperationTimeout(30) # 30 Seconds + +def ackCallback(mid, data): + return -``` -`client.configureMQTTOperationTimeout(30) # 30 Seconds +def messageCallback(client, userdata, message): + return -def`` ackCallback``(``mid``,`` data``):` -` ``return` -` ` -`def`` messageCallback``(``client``,`` userdata``,`` message``):` -` ``return` -` ` +# blocking client.subscribe( "myTopic/#", 1, - ackCallback=mySubackCallback, - messageCallback=customMessageCallback) + callback=messageCallback) + +# Non blocking +client.subscribeAsync( + "myTopic/#", + 1, + ackCallback=ackCallback, + messageCallback=messageCallback) ``` -_Example of subscribing in V2_ +#### Example of subscribing in the v2 SDK -``` +```python subscribe_future = client.subscribe( subscribe_packet=mqtt5.SubscribePacket( subscriptions=[mqtt5.Subscription( @@ -254,25 +356,39 @@ suback = subscribe_future.result(20) ``` - - ### Unsubscribe -V1 SDK provides blocking and non-blocking API for unsubscribing. To unsubscribe from topic in V1, you should provide a topic string to the [unsubscribe](https://s3.amazonaws.com/aws-iot-device-sdk-python-docs/html/index.html?highlight=unsubscribe#AWSIoTPythonSDK.MQTTLib.AWSIoTMQTTClient.unsubscribe) or [unsubscribeAsync](https://s3.amazonaws.com/aws-iot-device-sdk-python-docs/html/index.html?highlight=unsubscribe#AWSIoTPythonSDK.MQTTLib.AWSIoTMQTTClient.unsubscribeAsync) operation. The asynchronous operation takes a callback that determines success of failure - -V2 SDK provides only asynchronous non-blocking API. First, you need to create an [UnsubscribePacket](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.UnsubscribePacket) object.[](https://awslabs.github.io/aws-crt-java/software/amazon/awssdk/crt/mqtt5/packets/UnsubscribePacket.UnsubscribePacketBuilder.html) The [unsubscribe](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.Client.unsubscribe) operation takes a description of the [UnsubscribePacket](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.UnsubscribePacket) you wish to send and returns a promise that resolves successfully with the corresponding [UnsubAckPacket](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.UnsubackPacket) returned by the broker; the promise is rejected with an error if anything goes wrong before the [UnsubAckPacket](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.UnsubackPacket) is received. You should always check the reason codes of a [UnsubAckPacket](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.UnsubackPacket) completion to determine if the unsubscribe operation actually succeeded. -Similar to subscribing, you can unsubscribe from multiple topics in one request: just pass a list of topics to topic_filters (*Sequence[*[*str*](https://docs.python.org/3/library/stdtypes.html#str)*]) in *[*UnsubAckPacket*](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.UnsubackPacket) - -_Example of unsubscribing in V1_ - -``` +The v1 SDK provides blocking and non-blocking API for unsubscribing. To unsubscribe from a topic in the v1 SDK, +you should provide a topic string to the +[unsubscribe](https://s3.amazonaws.com/aws-iot-device-sdk-python-docs/html/index.html?highlight=unsubscribe#AWSIoTPythonSDK.MQTTLib.AWSIoTMQTTClient.unsubscribe) +or [unsubscribeAsync](https://s3.amazonaws.com/aws-iot-device-sdk-python-docs/html/index.html?highlight=unsubscribe#AWSIoTPythonSDK.MQTTLib.AWSIoTMQTTClient.unsubscribeAsync) +operation. The asynchronous operation call the passed callback which determines success of failure. + +The v2 SDK provides only asynchronous non-blocking API. +First, you need to create an [UnsubscribePacket](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.UnsubscribePacket) +object. The [unsubscribe](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.Client.unsubscribe) +operation takes a description of the [UnsubscribePacket](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.UnsubscribePacket) +you wish to send and returns a promise that resolves successfully with the corresponding +[UnsubAckPacket](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.UnsubackPacket) +returned by the broker. The promise is rejected with an error if anything goes wrong before +the [UnsubAckPacket](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.UnsubackPacket) is received. +You should always check the reason codes of +a [UnsubAckPacket](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.UnsubackPacket) completion +to determine if the unsubscribe operation actually succeeded. + +Similar to subscribing, you can unsubscribe from multiple topics in one request by passing +a list of topics to topic\_filters (*Sequence[str**]) in *[*UnsubAckPacket*](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.UnsubackPacket) + +#### Example of unsubscribing in the v1 SDK + +```python # Blocking API. client.unsubscribe("my/topic") client.unsubscribe("another/topic") ``` -``` +```python # Non-blocking API. def unsuback_callback(mid): return @@ -281,10 +397,9 @@ client.unsubscribeAsync("my/topic", ackCallback=unsuback_callback) ``` +#### Example of unsubscribing in the v2 SDK -_Example of unsubscribing in V2_ - -``` +```python unsubscribe_future = mqtt5_client.unsubscribe( unsubscribe_packet=mqtt5.UnsubscribePacket( topic_filters=["my/topic"])) @@ -293,23 +408,28 @@ print("Unsubscribed with {}".format(unsuback.reason_codes)) ``` - - ### Client Stop -In V1 SDK, the `disconnect` method in the `AWSIotMqttClient` class disconnects the client. Once disconnected, the client can connect again by calling `connect`. +In the v1 SDK, the `disconnect` method in the `AWSIotMqttClient` class disconnects the client. Once disconnected, +the client can connect again by calling `connect`. -In V2 SDK, an MQTT5 client can stop a session by calling the [stop](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.Client.stop) method. You can provide an optional [DisconnectPacket](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.DisconnectPacket) parameter. A closed client can be started again by calling [start](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.Client.start). +In the v2 SDK, an MQTT5 client can stop a session by calling the +[stop](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.Client.stop) method. +You can provide an optional [DisconnectPacket](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.DisconnectPacket) +parameter. A closed client can be started again by calling +[start](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.Client.start). -_Example of disconnecting a client in V1_ -``` +#### Example of disconnecting a client in the v1 SDK + +```python client.disconnect(); + ``` -_Example of disconnecting a client in V2_ +#### Example of disconnecting a client in the v2 SDK -``` +```python mqtt5_client.stop( disconnect_packet=mqtt5.DisconnectPacket( reason_code=mqtt5.*DisconnectReasonCode**.**NORMAL_DISCONNECTION**, @@ -317,32 +437,33 @@ mqtt5_client.stop( ``` - - ### Reconnects -V1 has a maximum number of retry attempts for auto-reconnect. If you exhausted the maximum number of retries, V1 will throw a permanent error and you will not be able to use the same client instance again. +The v1 SDK attempts to reconnect automatically using a [Progressive Reconnect Back Off](https://github.com/aws/aws-iot-device-sdk-python/blob/master/README.rst#progressive-reconnect-back-off) +until connection succeeds or `client.disconnect()` is called. -V2 attempts to reconnect automatically until connection succeeds or `client.stop()` is called. The reconnection parameters, such as min/max delays and [jitter modes](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.ExponentialBackoffJitterMode), are configurable through [awsiot.mqtt5_client_builder](https://aws.github.io/aws-iot-device-sdk-python-v2/awsiot/mqtt5_client_builder.html#module-awsiot.mqtt5_client_builder). +The v2 SDK attempts to reconnect automatically until the connection succeeds or `client.stop()` is called. +The reconnection parameters, such as min/max delays and +[jitter modes](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.ExponentialBackoffJitterMode), +are configurable through [awsiot.mqtt5\_client\_builder](https://aws.github.io/aws-iot-device-sdk-python-v2/awsiot/mqtt5_client_builder.html#module-awsiot.mqtt5_client_builder). -_Example of tweaking reconnection settings in V1_ +#### Example of tweaking reconnection settings in v1 -``` -*`baseReconnectQuietTimeSecond`*` ``=`` ``1 # Initial backoff time` -`maxReconnectQuiteTimeSecond ``=`` ``23 # maximum backoff time` -`stableConnectionTimeSecond ``=`` ``20 # the time the connection is considered stable` -`client``.``configureAutoReconnectBackoffTime``( +```python +baseReconnectQuietTimeSecond = 1 # Initial backoff time +maxReconnectQuiteTimeSecond = 23 # maximum backoff time +stableConnectionTimeSecond = 20 # the time the connection is considered stable +client``.``configureAutoReconnectBackoffTime``( ``baseReconnectQuietTimeSecond``, ``maxReconnectQuiteTimeSecond``, ``stableConnectionTimeSecond``) -` ``` -_Example of tweaking reconnection settings in V2_ +#### Example of tweaking reconnection settings in the v2 SDK -``` +```python mqtt5_client = mqtt5_client_builder.mtls_from_path( endpoint="-ats.iot..amazonaws.com", cert_filepath="", @@ -354,19 +475,23 @@ mqtt5_client = mqtt5_client_builder.mtls_from_path( retry_jitter_mode=mqtt5.ExponentialBackoffJitterMode.FULL) mqtt5_client.start() -``` - +``` ### Offline Operations Queue -In V1, if you’re having too many in-flight QoS 1 messages, you can encounter the `too many publishes in Progress` error on publishing messages. This is caused by the so-called in-flight publish limit. By default, V1 SDK supports a maximum of 20 in-flight operations. +In the v1 SDK, if you're having too many in-flight QoS 1 messages, you can encounter the `too many publishes in Progress` error +on publishing messages. This is caused by the so-called in-flight publish limit. By default, V1 SDK supports +a maximum of 20 in-flight operations. -V2 does not limit the number of in-flight messages. Additionally, V2 provides a way to configure which kind of packets will be placed into the offline queue when the client is in the disconnected state. The following code snippet demonstrates how to enable storing all packets except QOS0 publish packets in the offline queue on disconnect: +The v2 SDK does not limit the number of in-flight messages. +Additionally, the v2 SDK provides a way to configure which kind of packets will be placed into the offline queue +when the client is in the disconnected state. The following code snippet demonstrates how to enable storing all packets +except QOS0 publish packets in the offline queue on disconnect: -_Example of configuring the offline queue in V2_ +#### Example of configuring the offline queue in the v2 SDK -``` +```python mqtt5_client = mqtt5_client_builder.mtls_from_path( endpoint="-ats.iot..amazonaws.com", cert_filepath="", @@ -376,11 +501,17 @@ mqtt5_client = mqtt5_client_builder.mtls_from_path( mqtt5.ClientOperationQueueBehaviorType.FAIL_QOS0_PUBLISH_ON_DISCONNECT) mqtt5_client.start() + ``` -Note that AWS IoT Core [limits the number of allowed operations per second](https://docs.aws.amazon.com/general/latest/gr/iot-core.html#message-broker-limits). The [get_stats](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.Client.get_stats) method returns the current state of an `awscrt.mqtt5.Client` object’s queue of operations in [OperationStatisticsData](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.OperationStatisticsData), which may help with tracking the number of in-flight messages. +> [!NOTE] +> AWS IoT Core [limits the number of allowed operations per second](https://docs.aws.amazon.com/general/latest/gr/iot-core.html#message-broker-limits). +> The [get_stats](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.Client.get_stats) method returns +> the current state of an `awscrt.mqtt5.Client` object's queue of operations in +> [OperationStatisticsData](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.OperationStatisticsData), +> which may help with tracking the number of in-flight messages. -``` +``` python op_stats_data = mqtt5_client.get_stats() print( "Client operations queue statistics:\n" + @@ -391,20 +522,30 @@ print( ``` -See [withOfflineQueueBehavior documentation](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.ClientOptions) for more details. -See [ClientOfflineQueueBehavior types documentation](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.ClientOperationQueueBehaviorType) to find the list of the supported offline queue behaviors and their description. +For more information, see [withOfflineQueueBehavior documentation](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.ClientOptions). + +For the list of the supported offline queue behaviors and their descriptions, +see [ClientOfflineQueueBehavior types documentation](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.ClientOperationQueueBehaviorType). ### Operation Timeouts -In V1 SDK, all operations (*publish*, *subscribe*, *unsubscribe*) will not timeout unless you define a timeout for them. If no timeout is defined, there is a possibility that an operation will wait forever for the server to respond and block the calling thread indefinitely. +In the v1 SDK, all operations (*publish*, *subscribe*, *unsubscribe*) will not timeout unless you define a timeout for them. +If no timeout is defined, there is a possibility that an operation will wait forever for the server to respond and +block the calling thread indefinitely. -In V2 SDK, operations timeout is set for the MQTT5 client with the [ClientOptions](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.ClientOptions) class member `ack_timeout_sec`. The default value is no timeout. As in V1 SDK, failing to set a timeout can cause an operation to stuck forever, but it won’t block the client. -The [get_stats](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.Client.get_stats) method returns the current state of an` mqtt5.Client` object’s queue of operations, which may help with tracking operations. +In the v2 SDK, operations timeout is set for the MQTT5 client with the +[ClientOptions](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.ClientOptions) +class member `ack_timeout_sec`. +The default value is no timeout. As in the v1 SDK, failing to set a timeout can cause an operation to stuck forever, +but it won't block the client. -_Example of timeouts in V1_ +The [get\_stats](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.Client.get_stats) method returns +the current state of an` mqtt5.Client` object's queue of operations, which may help with tracking operations. -``` +#### Example of timeouts in the v1 SDK + +```python connectTimeoutSec = 10 `client``.``configureConnectDisconnectTimeout`(connectTimeoutSec) client.connect(); @@ -415,26 +556,24 @@ client.publish("my/topic", "hello", 1) ``` -_Example of timeouts in V2_ +### Example of timeouts in the v2 SDK -``` +```python mqtt5_client = mqtt5_client_builder.mtls_from_path( endpoint="-ats.iot..amazonaws.com", cert_filepath="", pri_key_filepath="", - ack_timeout_sec=20 -) -``` - + ack_timeout_sec=20) +``` ### Logging -V1 SDK uses `AWSIoTPythonSDK.core` custom logger logger for logging. +The v1 SDK uses `AWSIoTPythonSDK.core` custom logger logger for logging. -V2 SDK uses a standard [logging facility](https://docs.python.org/3/howto/logging.html). +The v2 SDK uses a standard [logging facility](https://docs.python.org/3/howto/logging.html). -_Example of using logging in V1_ +#### Example of using logging in the v1 SDK ``` logger = logging.getLogger("AWSIoTPythonSDK.core") @@ -446,9 +585,10 @@ logger.addHandler(streamHandler) logger.error("error log") logger.info("info log") + ``` -_Example of using logging in V2_ +#### Example of using logging in the v2 SDK ``` from awscrt import io @@ -460,21 +600,27 @@ logger.debug("error log") ``` +### Client for AWS IoT Device Shadow +The v1 SDK is built with [AWS IoT device shadow support](http://docs.aws.amazon.com/iot/latest/developerguide/iot-thing-shadows.html), +which provides access to thing shadows (sometimes referred to as device shadows). -### Client for Device Shadow Service - -V1 SDK is built with [AWS IoT device shadow support](http://docs.aws.amazon.com/iot/latest/developerguide/iot-thing-shadows.html), providing access to thing shadows (sometimes referred to as device shadows). It also supports a simplified shadow access model, which allows developers to exchange data with their shadows by just using getter and setter methods without having to serialize or deserialize any JSON documents. +The v2 SDK also supports device shadow service as well, but with a completely different APIs. +First, you subscribe to special topics to get data and feedback from a service. +The service client provides API for that. For example, `subscribe_to_get_shadow_accepted` subscribes to a topic +to which AWS IoT Core will publish a shadow document. The server will notify you if it cannot send you a +requested documen via the `subscribe_to_get_shadow_rejected`.\ +After subscribing to all the required topics, the service client can start interacting with the server, +for example update the status or request for data. These actions are also performed via client API calls. +For example, `publish_get_shadow` sends a request to AWS IoT Core to get a shadow document. +The requested Shadow document will be received in a callback specified in the `subscribe_to_get_shadow_accepted` call. -V2 SDK supports device shadow service as well, but with completely different API. -First, you subscribe to special topics to get data and feedback from a service. The service client provides API for that. For example, `subscribe_to_get_shadow_accepted` subscribes to a topic to which AWS IoT Core will publish a shadow document; and via the `subscribe_to_get_shadow_rejected` the server will notify you if it cannot send you a requested document. -After subscribing to all the required topics, the service client can start interacting with the server, for example update the status or request for data. These actions are also performed via client API calls. For example, `publish_get_shadow` sends a request to AWS IoT Core to get a shadow document. The requested Shadow document will be received in a callback specified in the `subscribe_to_get_shadow_accepted` call. +AWS IoT Core [documentation for Device Shadow](https://docs.aws.amazon.com/iot/latest/developerguide/device-shadow-mqtt.html) +service provides detailed descriptions for the topics used to interact with the service. -AWS IoT Core [documentation for Device Shadow](https://docs.aws.amazon.com/iot/latest/developerguide/device-shadow-mqtt.html) service provides detailed descriptions for the topics used to interact with the service. +#### Example of creating a Device Shadow service client in the v1 SDK -_Example of creating a Device Shadow service client in V1_ - -``` +```python # Blocking and non-blocking API. shadow_client= AWSIoTMQTTShadowClient(") shadow_client.configureEndpoint("", port) @@ -487,18 +633,20 @@ isPersistentSubscribe ** = True deviceShadowHandler = shadow_client.createShadowHandlerWithName( "", *isPersistentSubscribe*) + ``` -_Example of creating a Device Shadow service client in V2_ +#### Example of creating a Device Shadow service client in the v2 SDK -``` +```python mqtt5_client.start() shadow_client = iotshadow.IotShadowClient(mqtt5_client) + ``` -_Example of deleting a Device Shadow in V1_ +#### Example of deleting a Device Shadow in the v1 SDK -``` +```python # Delete Shadow def customShadowCallback_Delete(payload, responseStatus, token): return @@ -506,9 +654,9 @@ deviceShadowHandler.shadowDelete(customShadowCallback_Delete, 5) ``` -_Example of deleting a Classic Shadow in V2_ +#### Example of deleting a Classic Shadow in the v2 SDK -``` +```python def delete_accepted(DeleteShadowResponse response): return shadow_client.subscribe_to_delete_shadow_accepted(*request*, *qos*, *callback*) @@ -527,9 +675,9 @@ shadow_future = shadow_client.publish_delete_shadow( ``` -_Example of updating a Classic Shadow in V1_ +#### Example of updating a Classic Shadow in the v1 SDK -``` +```python # Update Shadow def customShadowCallback_Update(payload, responseStatus, token): return @@ -542,9 +690,9 @@ deviceShadowHandler.shadowUpdate( ``` -_Example of updating a Classic Shadow in V2_ +#### Example of updating a Classic Shadow in the v2 SDK -``` +```python # Update shadow def on_update_shadow_accepted(response): return @@ -577,9 +725,9 @@ future = shadow_client.publish_update_shadow( ``` -_Example of subscribing to a delta Shadow events in V1_ +#### Example of subscribing to a delta Shadow events in the v1 SDK -``` +```python # Delta Events shadow_client.connect() @@ -595,9 +743,9 @@ deviceShadowHandler.shadowRegisterDeltaCallback( ``` -_Example of subscribing to a delta Shadow events in V2_ +#### Example of subscribing to a delta Shadow events in the v2 SDK -``` +```python # Delta Events def on_shadow_delta_updated(delta): return @@ -612,27 +760,37 @@ delta_subscribed_future.result() ``` +For more information, see API documentation for the v2 SDK +[Device Shadow](https://aws.github.io/aws-iot-device-sdk-python-v2/awsiot/iotshadow.html). +service client for more details. +For code examples, see the v2 SDK [Device Shadow](https://github.com/aws/aws-iot-device-sdk-python-v2/blob/main/samples/shadow_mqtt5.py) -See API documentation for V2 SDK [Device Shadow](https://aws.github.io/aws-iot-device-sdk-python-v2/awsiot/iotshadow.html) service client for more details. -Refer to the V2 SDK [Device Shadow](https://github.com/aws/aws-iot-device-sdk-python-v2/blob/main/samples/shadow_mqtt5.py) sample for code example. +### Client for AWS IoT Jobs -### Client for Jobs Service +The v1 SDK and the v2 SDK offer support of AWS IoT Core services implementing a service client for the +[Jobs](https://docs.aws.amazon.com/iot/latest/developerguide/iot-jobs.html) service which helps with defining a set of +remote operations that can be sent to and run on one or more devices connected to AWS IoT. -V1 and V2 SDK offer support of AWS IoT Core services implementing a service client for the [Jobs](https://docs.aws.amazon.com/iot/latest/developerguide/iot-jobs.html) service which helps with defining a set of remote operations that can be sent to and run on one or more devices connected to AWS IoT. -V1 IotJobs APIs are defined [here](https://s3.amazonaws.com/aws-iot-device-sdk-python-docs/html/index.html#AWSIoTPythonSDK.MQTTLib.AWSIoTMQTTThingJobsClient), with its corresponding code [samples](https://github.com/aws/aws-iot-device-sdk-python/blob/master/samples/jobs/jobsSample.py) +For more information about the v1 SDK, see [AWS Iot Jobs APIs](https://s3.amazonaws.com/aws-iot-device-sdk-python-docs/html/index.html#AWSIoTPythonSDK.MQTTLib.AWSIoTMQTTThingJobsClient). +For code examples, see [AWS IoT Jobs samples](https://github.com/aws/aws-iot-device-sdk-python/blob/master/samples/jobs/jobsSample.py) -V2 SDK supports Jobs service as well, but with completely different API. -The Jobs service client provides API similar to API provided by [Client for Device Shadow Service](https://quip-amazon.com/RUfpAM2x5mXr#temp:C:XVAbbb7cff5d5884fdfb4dcf670f). First, you subscribe to special topics to get data and feedback from a service. The service client provides API for that. After subscribing to all the required topics, the service client can start interacting with the server, for example update the status or request for data. These actions are also performed via client API calls. +The v2 SDK supports Jobs service as well, but with completely different API. +The Jobs service client provides API similar to API provided by [Client for Device Shadow Service](#client-for-device-shadow-service). +First, you subscribe to special topics to get data and feedback from a service. +The service client provides API for that. After subscribing to all the required topics, +the service client can start interacting with the server, for example update the status or request for data. +These actions are also performed via client API calls. -AWS IoT Core documentation for [Jobs](https://docs.aws.amazon.com/iot/latest/developerguide/jobs-mqtt-api.html) service provides detailed descriptions for the topics used to interact with the service. +AWS IoT Core documentation for [AWS Iot Jobs](https://docs.aws.amazon.com/iot/latest/developerguide/jobs-mqtt-api.html) service +provides detailed descriptions for the topics used to interact with the service. -See API documentation for V2 SDK [Jobs](https://aws.github.io/aws-iot-device-sdk-python-v2/awsiot/iotjobs.html) service clients for more details. -Refer to the V2 SDK [Jobs](https://github.com/aws/aws-iot-device-sdk-python-v2/blob/main/samples/jobs_mqtt5.py) samples for code examples. +For API documentation for the v2 SDK, see [AWS Iot Jobs API](https://aws.github.io/aws-iot-device-sdk-python-v2/awsiot/iotjobs.html) +For code examples, see [AWS Iot Jobs](https://github.com/aws/aws-iot-device-sdk-python-v2/blob/main/samples/jobs_mqtt5.py) samples. -_V1 Jobs Example_ +#### AWS IoT Jobs Example in the v1 SDK -``` +```python jobs_client = AWSIoTMQTTThingJobsClient( "", "", @@ -702,8 +860,7 @@ jobsClient.disconnect() ``` - -_V2 Jobs example_ +#### AWS IoT Jobs Example in the v2 SDK ``` jobs_client = iotjobs.IotJobsClient(mqtt5_client) @@ -794,61 +951,106 @@ publish_future.add_done_callback( ``` +### Client for AWS IoT fleet provisioning -### Client for Fleet Provisioning Service +[Fleet Provisioning](https://docs.aws.amazon.com/iot/latest/developerguide/provision-wo-cert.html) +(also known as Identity Service) is another AWS IoT service that the v2 SDK provides access to. +By using AWS IoT fleet provisioning, AWS IoT can generate and securely deliver device certificates and private keys +to your devices when they connect to AWS IoT for the first time. -Another IoT service that V2 SDK provides access to is [Fleet Provisioning](https://docs.aws.amazon.com/iot/latest/developerguide/provision-wo-cert.html) (also known as Identity Service). By using AWS IoT fleet provisioning, AWS IoT can generate and securely deliver device certificates and private keys to your devices when they connect to AWS IoT for the first time. +The Fleet Provisioning service client provides APIs similar to the APIs provided by +[Client for Device Shadow Service](#client-for-device-shadow-service). +First, you subscribe to special topics to get data and feedback from a service. +The service client provides APIs for that. After subscribing to all the required topics, +the service client can start interacting with the server, for example update the status or request for data. +These actions are also performed via client API calls. -The Fleet Provisioning service client provides API similar to API provided by [Client for Device Shadow Service](https://quip-amazon.com/RUfpAM2x5mXr#temp:C:XVAbbb7cff5d5884fdfb4dcf670f). First, you subscribe to special topics to get data and feedback from a service. The service client provides API for that. After subscribing to all the required topics, the service client can start interacting with the server, for example update the status or request for data. These actions are also performed via client API calls. +For detailed descriptions for the topics used to interact with the Fleet Provisioning service, see +AWS IoT Core documentation for [Fleet Provisioning](https://docs.aws.amazon.com/iot/latest/developerguide/fleet-provision-api.html) -AWS IoT Core documentation for [Fleet Provisioning](https://docs.aws.amazon.com/iot/latest/developerguide/fleet-provision-api.html) service provides detailed descriptions for the topics used to interact with the service. +For more information about the Fleet Provisioning service client, See API documentation for the v2 SDK +[Fleet Provisioning](https://aws.github.io/aws-iot-device-sdk-python-v2/awsiot/iotidentity.html). -See API documentation for V2 SDK [Fleet Provisioning](https://aws.github.io/aws-iot-device-sdk-python-v2/awsiot/iotidentity.html) service client for more details. -Refer to the V2 SDK [Fleet Provisioning](https://github.com/aws/aws-iot-device-sdk-python-v2/blob/main/samples/fleetprovisioning.md) samples for code examples. +For code examples, see the v2 SDK [Fleet Provisioning](https://github.com/aws/aws-iot-device-sdk-python-v2/blob/main/samples/fleetprovisioning.md) +samples. ### Example -It’s always helpful to look at a working example to see how new functionality works, to be able to tweak different options, to compare with existing code. For that reasons, we implemented a [Publish/Subscribe example](https://github.com/aws/aws-iot-device-sdk-python-v2/blob/main/samples/mqtt5_pubsub.md) ([source code](https://github.com/aws/aws-iot-device-sdk-python-v2/blob/main/samples/mqtt5_pubsub.py)) in V2 SDK similar to a sample provided by V1 SDK (see a corresponding [readme section](https://github.com/aws/aws-iot-device-sdk-python/blob/master/README.rst#basicpubsub) and [source code](https://github.com/aws/aws-iot-device-sdk-python/blob/master/samples/basicPubSub/basicPubSub.py)). +It's always helpful to look at a working example to see how new functionality works, to be able to tweak different options, +to compare with existing code. For that reason, we implemented a +[Publish/Subscribe example](https://github.com/aws/aws-iot-device-sdk-python-v2/blob/main/samples/mqtt5_pubsub.md) +([source code](https://github.com/aws/aws-iot-device-sdk-python-v2/blob/main/samples/mqtt5_pubsub.py)) +in the v2 SDK similar to a sample provided by the v1 SDK (see a corresponding +[readme section](https://github.com/aws/aws-iot-device-sdk-python/blob/master/README.rst#basicpubsub) and +[source code](https://github.com/aws/aws-iot-device-sdk-python/blob/master/samples/basicPubSub/basicPubSub.py)). ## How to get help -For any migration related questions or feedback, you can contact us at [discussion](https://github.com/aws/aws-iot-device-sdk-python-v2/discussions) by submitting an issue with a label `label:migration`. +Questions? you can look for an answer in the +[discussion](https://github.com/aws/aws-iot-device-sdk-python-v2/discussions) page. +Or, you can always open a [new discussion](https://github.com/aws/aws-iot-device-sdk-python-v2/discussions/new?category=q-a&labels=migration), +and we will be happy to help you. ## Appendix ### MQTT5 Features -**Clean Start and Session Expiry** +**Clean Start and Session Expiry**\ You can use Clean Start and Session Expiry to handle your persistent sessions with more flexibility. -Refer to [awscrt.mqtt5.ClientSessionBehaviorType](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.ClientSessionBehaviorType) enum and [NegotiatedSettings.session_expiry_interval_sec](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.NegotiatedSettings) method for details. - -**Reason Code on all ACKs** -You can debug or process error messages more easily using the reason codes. Reason codes are returned by the message broker based on the type of interaction with the broker (Subscribe, Publish, Acknowledge). -See [PubAckReasonCode](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.PubackReasonCode), [SubAckReasonCode](https://awslabs.github.io/aws-crt-java/software/amazon/awssdk/crt/mqtt5/packets/SubAckPacket.SubAckReasonCode.html), [UnsubAckReasonCode](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.SubackReasonCode), [ConnectReasonCode](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.ConnectReasonCode), [DisconnectReasonCode](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.DisconnectReasonCode). - -**Topic Aliases** +For more information, see the [awscrt.mqtt5.ClientSessionBehaviorType](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.ClientSessionBehaviorType) +enum and the [NegotiatedSettings.session_expiry_interval_sec](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.NegotiatedSettings) +method. + +**Reason Code on all ACKs**\ +You can debug or process error messages more easily using the reason codes. +Reason codes are returned by the message broker based on the type of interaction with the broker +(Subscribe, Publish, Acknowledge). +For more information, see [PubAckReasonCode](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.PubackReasonCode), +[SubAckReasonCode](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.SubackReasonCode), +[UnsubAckReasonCode](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.SubackReasonCode), +[ConnectReasonCode](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.ConnectReasonCode), +[DisconnectReasonCode](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.DisconnectReasonCode). + +**Topic Aliases**\ You can substitute a topic name with a topic alias, which is a two-byte integer. -Use [mqtt5.TopicAliasingOptions](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.TopicAliasingOptions) with [mqtt5.ClientOptions](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.ClientOptions), and when creating a [PUBLISH packet](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.PublishPacket) use the parameter topic_alias(int). - -**Message Expiry** -You can add message expiry values to published messages. Use [message_expiry_interval_sec](https://awslabs.github.io/aws-crt-java/software/amazon/awssdk/crt/mqtt5/packets/PublishPacket.PublishPacketBuilder.html#withMessageExpiryIntervalSeconds(java.lang.Long)) variable when creating a [PUBLISH packet](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.PublishPacket). - -**Server disconnect** -When a disconnection happens, the server can proactively send the client a DISCONNECT to notify connection closure with a reason code for disconnection. -Refer to [DisconnectPacket](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.DisconnectPacket) class for details. - -**Request/Response** -Publishers can request a response be sent by the receiver to a publisher-specified topic upon reception. Use `response_topic` method in [PublishPacket](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.PublishPacket) class. - -**Maximum Packet Size** -Client and Server can independently specify the maximum packet size that they support. See [ConnectPacket.maximum_packet_size(int)](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.ConnectPacket), [NegotiatedSettings.maximum_packet_size_to_server](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.NegotiatedSettings), and [ConnAckPacket.maximum_packet_size](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.ConnackPacket) methods. - -**Payload format and content type** -You can specify the payload format (binary, text) and content type when a message is published. These are forwarded to the receiver of the message. Use content_type(str) method in [PublishPacket](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.PublishPacket) class. - -**Shared Subscriptions** -Shared Subscriptions allow multiple clients to share a subscription to a topic and only one client will receive messages published to that topic using a random distribution. -Refer to a [shared subscription sample](https://github.com/aws/aws-iot-device-sdk-python-v2/blob/main/samples/mqtt5_shared_subscription.md) in V2 SDK. -**NOTE** AWS IoT Core provides this functionality for MQTT3 as well. +Use [mqtt5.TopicAliasingOptions](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.TopicAliasingOptions) +with [mqtt5.ClientOptions](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.ClientOptions), +when creating a [PUBLISH](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.PublishPacket) packet, +use the parameter `topic\_alias(int)`. + +**Message Expiry**\ +You can add message expiry values to published messages. Use `message_expiry_interval_sec` +variable when creating a [PUBLISH packet](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.PublishPacket). + +**Server disconnect**\ +When a disconnection happens, the server can proactively send the client a `DISCONNECT` to notify connection closure +with a reason code for disconnection.\ +For more information, see the [DisconnectPacket](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.DisconnectPacket) +class. + +**Request/Response**\ +Publishers can request a response be sent by the receiver to a publisher-specified topic upon reception. +Use `response_topic` method in [PublishPacket](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.PublishPacket) class. + +**Maximum Packet Size**\ +Client and Server can independently specify the maximum packet size that they support. +For more information, see [ConnectPacket.maximum_packet_size(int)](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.ConnectPacket), +the [NegotiatedSettings.maximum_packet_size_to_server](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.NegotiatedSettings), +and the [ConnAckPacket.maximum_packet_size](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.ConnackPacket) methods. + +**Payload format and content type**\ +You can specify the payload format (binary, text) and content type when a message is published. +These are forwarded to the receiver of the message. Use content_type(str) method in +[PublishPacket](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.PublishPacket) class. + +**Shared Subscriptions**\ +Shared Subscriptions allow multiple clients to share a subscription to a topic and only one client will receive messages +published to that topic using a random distribution. +Refer to a [shared subscription sample](https://github.com/aws/aws-iot-device-sdk-python-v2/blob/main/samples/mqtt5_shared_subscription.md) in the v2 SDK. + +> [!NOTE] +> AWS IoT Core supports Shared Subscriptions for both MQTT3 and MQTT5. For more information, +> see [Shared Subscriptions](https://docs.aws.amazon.com/iot/latest/developerguide/mqtt.html#mqtt5-shared-subscription) +> from the AWS IoT Core developer guide. From ad4d104ae7847bef0bc6271c4114cd7f72aebcaa Mon Sep 17 00:00:00 2001 From: Alfred Gedeon Date: Thu, 8 Feb 2024 21:13:40 -0800 Subject: [PATCH 03/12] Fix various rendering issues --- documents/MIGRATION_GUIDE.md | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/documents/MIGRATION_GUIDE.md b/documents/MIGRATION_GUIDE.md index c555c968..2e514b1e 100644 --- a/documents/MIGRATION_GUIDE.md +++ b/documents/MIGRATION_GUIDE.md @@ -21,7 +21,6 @@ and provides guidance on how to migrate your code to v2 from v1 of the AWS IoT S * [Subscribe](#subscribe) * [Unsubscribe](#unsubscribe) * [Client stop](#client-stop) - * [Client shutdown](#client-shutdown) * [Reconnects](#reconnects) * [Offline operations queue](#offline-operations-queue) * [Operation timeouts](#operation-timeouts) @@ -155,10 +154,9 @@ feature. |MQTT with PKCS11 Method |$${\Large\color{red}✘}$$ |$${\Large\color{green}✔}$$ |[link](https://github.com/aws/aws-iot-device-sdk-python-v2/blob/main/documents/MQTT5_Userguide.md#direct-mqtt-with-pkcs11-method)| |HTTP Proxy |$${\Large\color{orange}✔\*\*\*}$$|$${\Large\color{green}✔}$$ |[link](https://github.com/aws/aws-iot-device-sdk-python-v2/blob/main/documents/MQTT5_Userguide.md#adding-an-http-proxy)| -$${\Large\color{orange}✔\*}$$ To get this connection type to work in the V2 SDK, you need to convert the Java Key store key into a PKSC#11 key - [import IOT Core key to a Java KeyStore and convert it to pkcs#12](https://github.com/aws/aws-iot-device-sdk-python-v2/blob/main/samples/pkcs12_connect.md#how-to-setup-and-run).\ +$${\Large\color{orange}✔\*}$$ - To get this connection type to work in the V2 SDK, you need to convert the Java Key store key into a PKSC#11 key [import IOT Core key to a Java KeyStore and convert it to pkcs#12](https://github.com/aws/aws-iot-device-sdk-python-v2/blob/main/samples/pkcs12_connect.md#how-to-setup-and-run).\ $${\Large\color{orange}✔\*}$$ - To get this connection type work in V1 SDK, you need to implement the [Custom Authentication workflow](https://docs.aws.amazon.com/iot/latest/developerguide/custom-authorizer.html).\ -$${\Large\color{orange}✔\*\*}$$ - The v1 SDK does not allow to specify HTTP proxy, it is possible to configure systemwide proxy. +$${\Large\color{orange}✔\*\*}$$ - The v1 SDK does not allow to specify HTTP proxy, it is possible to configure systemwide proxy. ### Lifecycle Events @@ -575,7 +573,7 @@ The v2 SDK uses a standard [logging facility](https://docs.python.org/3/howto/l #### Example of using logging in the v1 SDK -``` +```python logger = logging.getLogger("AWSIoTPythonSDK.core") logger.setLevel(logging.DEBUG) streamHandler = logging.StreamHandler() @@ -590,7 +588,7 @@ logger.info("info log") #### Example of using logging in the v2 SDK -``` +```python from awscrt import io import logging @@ -862,7 +860,7 @@ jobsClient.disconnect() #### AWS IoT Jobs Example in the v2 SDK -``` +```python jobs_client = iotjobs.IotJobsClient(mqtt5_client) get_jobs_request = iotjobs.GetPendingJobExecutionsRequest(thing_name=") From fe494261d861e9d100daca0309b5297717087666 Mon Sep 17 00:00:00 2001 From: Alfred Gedeon Date: Thu, 8 Feb 2024 21:15:48 -0800 Subject: [PATCH 04/12] Fix typo --- documents/MIGRATION_GUIDE.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/documents/MIGRATION_GUIDE.md b/documents/MIGRATION_GUIDE.md index 2e514b1e..a0127ff2 100644 --- a/documents/MIGRATION_GUIDE.md +++ b/documents/MIGRATION_GUIDE.md @@ -12,7 +12,6 @@ and provides guidance on how to migrate your code to v2 from v1 of the AWS IoT S * [What's new in AWS IoT Device SDK for Python v2](#whats-new-in-aws-iot-device-sdk-for-python-v2) * [How to get started with AWS IoT Device SDK for Python v2](#how-to-get-started-with-aws-iot-device-sdk-for-python-v2) - * [Package name change](#package-name-change) * [MQTT protocol](#mqtt-protocol) * [Client builder](#client-builder) * [Connection types and features](#connection-types-and-features) @@ -34,7 +33,7 @@ and provides guidance on how to migrate your code to v2 from v1 of the AWS IoT S * [MQTT5 features](#mqtt5-features) -## What's new in AWS IoT Devide SDK for Python v2 +## What's new in AWS IoT Device SDK for Python v2 * The v2 SDK client is truly async. Operations return `concurrent.futures.Future` objects. Blocking calls can be emulated by waiting for the returned `Future` object to be resolved. From 583c5e6ba3550eb4f06a66d813fd2b6f6967d737 Mon Sep 17 00:00:00 2001 From: Alfred Gedeon Date: Thu, 8 Feb 2024 21:19:33 -0800 Subject: [PATCH 05/12] Fix table legends --- documents/MIGRATION_GUIDE.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/documents/MIGRATION_GUIDE.md b/documents/MIGRATION_GUIDE.md index a0127ff2..60371d9c 100644 --- a/documents/MIGRATION_GUIDE.md +++ b/documents/MIGRATION_GUIDE.md @@ -153,10 +153,9 @@ feature. |MQTT with PKCS11 Method |$${\Large\color{red}✘}$$ |$${\Large\color{green}✔}$$ |[link](https://github.com/aws/aws-iot-device-sdk-python-v2/blob/main/documents/MQTT5_Userguide.md#direct-mqtt-with-pkcs11-method)| |HTTP Proxy |$${\Large\color{orange}✔\*\*\*}$$|$${\Large\color{green}✔}$$ |[link](https://github.com/aws/aws-iot-device-sdk-python-v2/blob/main/documents/MQTT5_Userguide.md#adding-an-http-proxy)| -$${\Large\color{orange}✔\*}$$ - To get this connection type to work in the V2 SDK, you need to convert the Java Key store key into a PKSC#11 key [import IOT Core key to a Java KeyStore and convert it to pkcs#12](https://github.com/aws/aws-iot-device-sdk-python-v2/blob/main/samples/pkcs12_connect.md#how-to-setup-and-run).\ -$${\Large\color{orange}✔\*}$$ - To get this connection type work in V1 SDK, you need to implement the [Custom Authentication workflow](https://docs.aws.amazon.com/iot/latest/developerguide/custom-authorizer.html).\ -$${\Large\color{orange}✔\*\*}$$ - The v1 SDK does not allow to specify HTTP proxy, it is possible to configure systemwide proxy. - +${\Large\color{orange}✔\*}$ - To get this connection type to work in the V2 SDK, you need to convert the Java Key store key into a PKSC#11 key [import IOT Core key to a Java KeyStore and convert it to pkcs#12](https://github.com/aws/aws-iot-device-sdk-python-v2/blob/main/samples/pkcs12_connect.md#how-to-setup-and-run).\ +${\Large\color{orange}✔\*}$ - To get this connection type work in V1 SDK, you need to implement the [Custom Authentication workflow](https://docs.aws.amazon.com/iot/latest/developerguide/custom-authorizer.html).\ +${\Large\color{orange}✔\*\*}$ - The v1 SDK does not allow to specify HTTP proxy, it is possible to configure systemwide proxy. ### Lifecycle Events From e5f20b1e952a08f6209852e5af2c5196276b572e Mon Sep 17 00:00:00 2001 From: Alfred Gedeon Date: Thu, 8 Feb 2024 21:21:12 -0800 Subject: [PATCH 06/12] Fix typo --- documents/MIGRATION_GUIDE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/documents/MIGRATION_GUIDE.md b/documents/MIGRATION_GUIDE.md index 60371d9c..9f7c07aa 100644 --- a/documents/MIGRATION_GUIDE.md +++ b/documents/MIGRATION_GUIDE.md @@ -153,7 +153,7 @@ feature. |MQTT with PKCS11 Method |$${\Large\color{red}✘}$$ |$${\Large\color{green}✔}$$ |[link](https://github.com/aws/aws-iot-device-sdk-python-v2/blob/main/documents/MQTT5_Userguide.md#direct-mqtt-with-pkcs11-method)| |HTTP Proxy |$${\Large\color{orange}✔\*\*\*}$$|$${\Large\color{green}✔}$$ |[link](https://github.com/aws/aws-iot-device-sdk-python-v2/blob/main/documents/MQTT5_Userguide.md#adding-an-http-proxy)| -${\Large\color{orange}✔\*}$ - To get this connection type to work in the V2 SDK, you need to convert the Java Key store key into a PKSC#11 key [import IOT Core key to a Java KeyStore and convert it to pkcs#12](https://github.com/aws/aws-iot-device-sdk-python-v2/blob/main/samples/pkcs12_connect.md#how-to-setup-and-run).\ +${\Large\color{orange}✔\*}$ - To get this connection type to work in the V2 SDK, you need to convert the Java Key store key into a PKSC#12 key [import IOT Core key to a Java KeyStore and convert it to pkcs#12](https://github.com/aws/aws-iot-device-sdk-python-v2/blob/main/samples/pkcs12_connect.md#how-to-setup-and-run).\ ${\Large\color{orange}✔\*}$ - To get this connection type work in V1 SDK, you need to implement the [Custom Authentication workflow](https://docs.aws.amazon.com/iot/latest/developerguide/custom-authorizer.html).\ ${\Large\color{orange}✔\*\*}$ - The v1 SDK does not allow to specify HTTP proxy, it is possible to configure systemwide proxy. From fa47e0fc35082a861ef6b9fc83b9623c0ce5b0bd Mon Sep 17 00:00:00 2001 From: Alfred Gedeon Date: Fri, 9 Feb 2024 09:27:34 -0800 Subject: [PATCH 07/12] add link after merged PR --- documents/MIGRATION_GUIDE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/documents/MIGRATION_GUIDE.md b/documents/MIGRATION_GUIDE.md index 9f7c07aa..a4225053 100644 --- a/documents/MIGRATION_GUIDE.md +++ b/documents/MIGRATION_GUIDE.md @@ -149,7 +149,7 @@ feature. |MQTT with X.509 certificate based mutual authentication |$${\Large\color{red}✘}$$ |$${\Large\color{green}✔}$$ |[link](https://github.com/aws/aws-iot-device-sdk-python-v2/blob/main/documents/MQTT5_Userguide.md#direct-mqtt-with-x509-based-mutual-tls)| |MQTT with PKCS12 Method |$${\Large\color{red}✘}$$ |$${\Large\color{green}✔}$$ |[link](https://github.com/aws/aws-iot-device-sdk-python-v2/blob/main/documents/MQTT5_Userguide.md#direct-mqtt-with-pkcs12-method) | |MQTT with Custom Authorizer Method |$${\Large\color{orange}✔\*\*}$$ |$${\Large\color{green}✔}$$ |[link](https://github.com/aws/aws-iot-device-sdk-python-v2/blob/main/documents/MQTT5_Userguide.md#direct-mqtt-with-custom-authentication)| -|MQTT with Windows Certificate Store Method |$${\Large\color{red}✘}$$ |$${\Large\color{green}✔}$$ |[link](TODO: PR to be merged)| +|MQTT with Windows Certificate Store Method |$${\Large\color{red}✘}$$ |$${\Large\color{green}✔}$$ |[link](https://github.com/aws/aws-iot-device-sdk-python-v2/blob/main/documents/MQTT5_Userguide.md#direct-mqtt-with-windows-certificate-store-method)| |MQTT with PKCS11 Method |$${\Large\color{red}✘}$$ |$${\Large\color{green}✔}$$ |[link](https://github.com/aws/aws-iot-device-sdk-python-v2/blob/main/documents/MQTT5_Userguide.md#direct-mqtt-with-pkcs11-method)| |HTTP Proxy |$${\Large\color{orange}✔\*\*\*}$$|$${\Large\color{green}✔}$$ |[link](https://github.com/aws/aws-iot-device-sdk-python-v2/blob/main/documents/MQTT5_Userguide.md#adding-an-http-proxy)| From e3f0472334fa1a856148a13a6cd24e9eaa04cdc3 Mon Sep 17 00:00:00 2001 From: Alfred Gedeon Date: Fri, 16 Feb 2024 19:22:02 -0800 Subject: [PATCH 08/12] sync with the CPP doc --- README.md | 1 + documents/MIGRATION_GUIDE.md | 409 +++++++++++++++++++++++++---------- 2 files changed, 301 insertions(+), 109 deletions(-) diff --git a/README.md b/README.md index 6810da82..c08f7041 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,7 @@ This document provides information about the AWS IoT Device SDK v2 for Python. T * [FAQ](./documents/FAQ.md) * [API Docs](https://aws.github.io/aws-iot-device-sdk-python-v2/) * [MQTT5 User Guide](./documents/MQTT5_Userguide.md) +* [Migration Guide from the AWS IoT SDK for Python v1](./documents/MIGRATION_GUIDE.md) ## Installation diff --git a/documents/MIGRATION_GUIDE.md b/documents/MIGRATION_GUIDE.md index a4225053..bda25f53 100644 --- a/documents/MIGRATION_GUIDE.md +++ b/documents/MIGRATION_GUIDE.md @@ -14,6 +14,7 @@ and provides guidance on how to migrate your code to v2 from v1 of the AWS IoT S * [How to get started with AWS IoT Device SDK for Python v2](#how-to-get-started-with-aws-iot-device-sdk-for-python-v2) * [MQTT protocol](#mqtt-protocol) * [Client builder](#client-builder) + * [Client Start](#client-start) * [Connection types and features](#connection-types-and-features) * [Lifecycle events](#lifecycle-events) * [Publish](#publish) @@ -37,25 +38,16 @@ and provides guidance on how to migrate your code to v2 from v1 of the AWS IoT S * The v2 SDK client is truly async. Operations return `concurrent.futures.Future` objects. Blocking calls can be emulated by waiting for the returned `Future` object to be resolved. -* V2 SDK provides implementation for MQTT5 protocol, the next step in evolution of the MQTT protocol. -* Public API terminology has changed. You `start()` or `stop()` the MQTT5 client - rather than c`onnect` or d`isconnect` as in the v1 SDK. This removes the semantic confusion between client-level - controls and internval recurrent networking events related to connection and disconnection. +* The v2 SDK provides implementation for MQTT5 protocol, the next step in evolution of the MQTT protocol. * The v2 SDK supports AWS Iot services such as Fleet Provisioning. -Public APIs for almost all actions and operations has changed significantly. -For more information about the new features and specific code examples, refer to the -[How to get started with AWS IoT Device SDK for Python v2](#how-to-get-started-with-aws-iot-device-sdk-for-python-v2) -section of this guide. - - ## How To Get Started with AWS Iot Device SDK for python v2 +Public APIs for almost all actions and operations has changed significantly. There are differences between the v1 SDK and the v2 SDK. This section describes the changes you need to apply to your -project witht the v1 SDK to start using the v2 SDK. +project witht the v1 SDK to start using the v2 SDK.\ For more information about MQTT5, visit [MQTT5 User Guide](https://github.com/aws/aws-iot-device-sdk-python-v2/blob/main/documents/MQTT5_Userguide.md) - ### MQTT Protocol The v1 SDK uses an MQTT version 3.1.1 client under the hood. @@ -64,7 +56,6 @@ The v2 SDK provides MQTT version 3.1.1 and MQTT version 5.0 client implementatio This guide focuses on the MQTT5 because this version is a significant improvement over MQTT3. For more information, see the [MQTT5 features](#mqtt5-features) section. - ### Client Builder To access AWS IoT services, you must initialize an MQTT client. @@ -76,11 +67,10 @@ It's possible to change client settings after its creation using `configure*` me like `configureMQTTOperationTimeout` or `configureConnectDisconnectTimeout`. In the v2 SDK, the [awcrt.mqtt5.Client](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.Client) -class represents an MQTT client, -specifically for MQTT5 protocol. +class represents an MQTT client, specifically for MQTT5 protocol. The v2 SDK provides an [awsiot.mqtt5_client_builder](https://aws.github.io/aws-iot-device-sdk-python-v2/awsiot/mqtt5_client_builder.html) -designed to easily create common configuration types such as direct MQTT or WebSocket connections. After and MQTT5 -client is built and finalized, the settings of the resulting MQTT5 client cannot be modified. +designed to easily create common configuration types such as direct MQTT or WebSocket connections. +After and MQTT5 client is built and finalized, the settings of the resulting MQTT5 client cannot be modified. #### Example of creating a client in the v1 SDK @@ -101,8 +91,8 @@ client.connect() #### Example of creating a client in the v2 SDK -The V2 SDK supports different connection types. Given the same input parameters as in the V1 example above, -the most suitable method to create an MQTT5 client will be [awsiot.mqtt5_client_builder.mtls_from_path](https://aws.github.io/aws-iot-device-sdk-python-v2/awsiot/mqtt5_client_builder.html#awsiot.mqtt5_client_builder.mtls_from_path). +The v2 SDK supports different connection types. Given the same input parameters as in the v1 example above, +the most recommended method to create an MQTT5 client will be [awsiot.mqtt5_client_builder.mtls_from_path](https://aws.github.io/aws-iot-device-sdk-python-v2/awsiot/mqtt5_client_builder.html#awsiot.mqtt5_client_builder.mtls_from_path). ```python clientEndpoint = "-ats.iot..amazonaws.com" @@ -124,17 +114,38 @@ mqtt5_client.start() For more information, refer to the [Connection Types and Features](#connection-types-and-features) section for other connection types supported by the v2 SDK +### Client Start + +To connect to the server in the v1 SDK, you call the `connect` method on an `MQTTClient` instance. + +The v2 SDK changed API terminology. You `Start` the MQTT5 client rather than `Connect` as in the v1 SDK. This removes +the semantinc confusion between client-level controls and internal recurrent networking events related to connection. + +#### Example of connecting to a server in the v1 SDK + +```python +client = AWSIoTMQTTClient(clientId) +client.connect() + +``` + +#### Example of connecting to a server in the v2 SDK + +```python +mqtt5_client = mqtt5_client_builder.mtls_from_path( ... ) +mqtt5_client.start() + +``` ### Connection Types and Features -The v1 SDK supports two types of connections to the AWS IoT service: -MQTT with X.509 certificate and MQTT over Secure WebSocket with SigV4 authentication. +The v1 SDK supports three types of connections to the AWS IoT service: +MQTT with X.509 certificate, [Amazon Cognito](https://aws.amazon.com/cognito/), and MQTT over Secure WebSocket with SigV4 authentication. The v2 SDK adds a collection of connection types and cryptography formats (e.g. [PKCS #11](https://en.wikipedia.org/wiki/PKCS_11) and [Custom Authorizer](https://docs.aws.amazon.com/iot/latest/developerguide/custom-authentication.html)), -credential providers (e.g. [Amazon Cognito](https://aws.amazon.com/cognito/) and -[Windows Certificate Store](https://learn.microsoft.com/en-us/windows-hardware/drivers/install/certificate-stores)), +credential providers (e.g. [Windows Certificate Store](https://learn.microsoft.com/en-us/windows-hardware/drivers/install/certificate-stores)), and other connection-related features. For more information, refer to the [How to setup MQTT5 builder based on desired connection method](https://github.com/aws/aws-iot-device-sdk-python-v2/blob/main/documents/MQTT5_Userguide.md#how-to-create-a-mqtt5-client-based-on-desired-connection-method) @@ -145,17 +156,20 @@ feature. |--------------------------------------------------------|---------------------------------------|------------------------------------|:----------:| |MQTT over Secure WebSocket with AWS SigV4 authentication|$${\Large\color{green}✔}$$ |$${\Large\color{green}✔}$$ |[link](https://github.com/aws/aws-iot-device-sdk-python-v2/blob/main/documents/MQTT5_Userguide.md#mqtt-over-websockets-with-sigv4-authentication)| |MQTT with Java Keystore Method |$${\Large\color{red}✘}$$ |$${\Large\color{orange}✔\*}$$ |[link](https://github.com/aws/aws-iot-device-sdk-python-v2/blob/main/samples/pkcs12_connect.md#how-to-setup-and-run)| -|Websocket Connection with Cognito Authentication Method |$${\Large\color{red}✘}$$ |$${\Large\color{green}✔}$$ |[link](https://github.com/aws/aws-iot-device-sdk-python-v2/blob/main/documents/MQTT5_Userguide.md#mqtt-over-websockets-with-cognito-authentication)| -|MQTT with X.509 certificate based mutual authentication |$${\Large\color{red}✘}$$ |$${\Large\color{green}✔}$$ |[link](https://github.com/aws/aws-iot-device-sdk-python-v2/blob/main/documents/MQTT5_Userguide.md#direct-mqtt-with-x509-based-mutual-tls)| +|Websocket Connection with Cognito Authentication Method |$${\Large\color{green}✔}$$ |$${\Large\color{green}✔}$$ |[link](https://github.com/aws/aws-iot-device-sdk-python-v2/blob/main/documents/MQTT5_Userguide.md#mqtt-over-websockets-with-cognito-authentication)| +|MQTT with X.509 certificate based mutual authentication |$${\Large\color{green}✔}$$ |$${\Large\color{green}✔}$$ |[link](https://github.com/aws/aws-iot-device-sdk-python-v2/blob/main/documents/MQTT5_Userguide.md#direct-mqtt-with-x509-based-mutual-tls)| |MQTT with PKCS12 Method |$${\Large\color{red}✘}$$ |$${\Large\color{green}✔}$$ |[link](https://github.com/aws/aws-iot-device-sdk-python-v2/blob/main/documents/MQTT5_Userguide.md#direct-mqtt-with-pkcs12-method) | |MQTT with Custom Authorizer Method |$${\Large\color{orange}✔\*\*}$$ |$${\Large\color{green}✔}$$ |[link](https://github.com/aws/aws-iot-device-sdk-python-v2/blob/main/documents/MQTT5_Userguide.md#direct-mqtt-with-custom-authentication)| |MQTT with Windows Certificate Store Method |$${\Large\color{red}✘}$$ |$${\Large\color{green}✔}$$ |[link](https://github.com/aws/aws-iot-device-sdk-python-v2/blob/main/documents/MQTT5_Userguide.md#direct-mqtt-with-windows-certificate-store-method)| |MQTT with PKCS11 Method |$${\Large\color{red}✘}$$ |$${\Large\color{green}✔}$$ |[link](https://github.com/aws/aws-iot-device-sdk-python-v2/blob/main/documents/MQTT5_Userguide.md#direct-mqtt-with-pkcs11-method)| |HTTP Proxy |$${\Large\color{orange}✔\*\*\*}$$|$${\Large\color{green}✔}$$ |[link](https://github.com/aws/aws-iot-device-sdk-python-v2/blob/main/documents/MQTT5_Userguide.md#adding-an-http-proxy)| -${\Large\color{orange}✔\*}$ - To get this connection type to work in the V2 SDK, you need to convert the Java Key store key into a PKSC#12 key [import IOT Core key to a Java KeyStore and convert it to pkcs#12](https://github.com/aws/aws-iot-device-sdk-python-v2/blob/main/samples/pkcs12_connect.md#how-to-setup-and-run).\ -${\Large\color{orange}✔\*}$ - To get this connection type work in V1 SDK, you need to implement the [Custom Authentication workflow](https://docs.aws.amazon.com/iot/latest/developerguide/custom-authorizer.html).\ -${\Large\color{orange}✔\*\*}$ - The v1 SDK does not allow to specify HTTP proxy, it is possible to configure systemwide proxy. +${\Large\color{orange}✔\*}$ - To get this connection type to work in the v2 SDK, you need to convert + the Java Key store key into a PKSC#12 key [import IOT Core key to a Java KeyStore and convert it to pkcs#12](https://github.com/aws/aws-iot-device-sdk-python-v2/blob/main/samples/pkcs12_connect.md#how-to-setup-and-run).\ +${\Large\color{orange}✔\*\*}$ - To get this connection type work in the v1 SDK, you need to implement + the [Custom Authentication workflow](https://docs.aws.amazon.com/iot/latest/developerguide/custom-authorizer.html).\ +${\Large\color{orange}✔\*\*\*}$ - The v1 SDK does not allow to specify HTTP proxy, + it is possible to configure systemwide proxy. ### Lifecycle Events @@ -239,6 +253,11 @@ operation takes a `PublishPacket` instance and returns a promise that contains a [awscrt.mqtt5.PublishCompletionData](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.PublishCompletionData). The returned `PublishCompletionData` will contain different data depending on the `QoS` used in the publish. +> [!NOTE] +> If you try to publish with the v2 MQTT5 client to a topic that is not allowed by a policy, you do not get the +> connection +> closed but instead receive a PUBACK with a reason code. + * For QoS 0 (AT\_MOST\_ONCE): Calling `getValue` will return `null` and the promise will be complete as soon as the packet has been written to the socket. * For QoS 1 (AT\_LEAST\_ONCE): Calling `getValue` will return a @@ -282,6 +301,7 @@ publish_future,packet_id = client.publish( payload=json.dumps("hello"), qos=mqtt5.QoS.AT_LEAST_ONCE)) publish_future.result(20) # 20 seconds + ``` ### Subscribe @@ -306,10 +326,15 @@ the `SubAckPacket` is received. You should always check the reason codes of a `SubAckPacket` completion to determine if the subscribe operation actually succeeded. +> [!NOTE] +> If you try to subscribe with the v2 MQTT5 client to a topic that is not allowed by a policy, you do not get the +> connection +> closed but instead receive a SUBACK with a reason code. + In the v2 SDK, if the MQTT5 client is going to subscribe and receive packets from the MQTT broker, it is important to also setup the `on_publish_callback_fn` callback int the `ClientOptions`. This callback is invoked whenever the client receives a message from the server on a topic the client is subscribed to. -With this callback, you can process messages made to subscribed topics with its parameter +With this callback, you can process messages made to subscribed topics through its `message` parameter [PublishReceivedData](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.PublishReceivedData). #### Example of subscribing in the v1 SDK @@ -354,11 +379,11 @@ suback = subscribe_future.result(20) ### Unsubscribe -The v1 SDK provides blocking and non-blocking API for unsubscribing. To unsubscribe from a topic in the v1 SDK, +The v1 SDK provides blocking and non-blocking APIs for unsubscribing. To unsubscribe from a topic in the v1 SDK, you should provide a topic string to the [unsubscribe](https://s3.amazonaws.com/aws-iot-device-sdk-python-docs/html/index.html?highlight=unsubscribe#AWSIoTPythonSDK.MQTTLib.AWSIoTMQTTClient.unsubscribe) or [unsubscribeAsync](https://s3.amazonaws.com/aws-iot-device-sdk-python-docs/html/index.html?highlight=unsubscribe#AWSIoTPythonSDK.MQTTLib.AWSIoTMQTTClient.unsubscribeAsync) -operation. The asynchronous operation call the passed callback which determines success of failure. +operations. The asynchronous operation call the passed callback which determines success of failure. The v2 SDK provides only asynchronous non-blocking API. First, you need to create an [UnsubscribePacket](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.UnsubscribePacket) @@ -373,7 +398,7 @@ a [UnsubAckPacket](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscr to determine if the unsubscribe operation actually succeeded. Similar to subscribing, you can unsubscribe from multiple topics in one request by passing -a list of topics to topic\_filters (*Sequence[str**]) in *[*UnsubAckPacket*](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.UnsubackPacket) +a list of topics to topic\_filters (\*Sequence[str\*\*]) in \*[\*UnsubAckPacket\*](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.UnsubackPacket) #### Example of unsubscribing in the v1 SDK @@ -477,7 +502,7 @@ mqtt5_client.start() ### Offline Operations Queue In the v1 SDK, if you're having too many in-flight QoS 1 messages, you can encounter the `too many publishes in Progress` error -on publishing messages. This is caused by the so-called in-flight publish limit. By default, V1 SDK supports +on publishing messages. This is caused by the so-called in-flight publish limit. By default, ther v1 SDK supports a maximum of 20 in-flight operations. The v2 SDK does not limit the number of in-flight messages. @@ -523,12 +548,11 @@ For more information, see [withOfflineQueueBehavior documentation](https://awsla For the list of the supported offline queue behaviors and their descriptions, see [ClientOfflineQueueBehavior types documentation](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.ClientOperationQueueBehaviorType). - ### Operation Timeouts -In the v1 SDK, all operations (*publish*, *subscribe*, *unsubscribe*) will not timeout unless you define a timeout for them. -If no timeout is defined, there is a possibility that an operation will wait forever for the server to respond and -block the calling thread indefinitely. +In the v1 SDK, all operations (*publish*, *subscribe*, *unsubscribe*) will not timeout unless +you define a timeout for them. If no timeout is defined, there is a possibility that an operation will wait forever +for the server to respond and block the calling thread indefinitely. In the v2 SDK, operations timeout is set for the MQTT5 client with the [ClientOptions](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.ClientOptions) @@ -758,8 +782,8 @@ delta_subscribed_future.result() For more information, see API documentation for the v2 SDK [Device Shadow](https://aws.github.io/aws-iot-device-sdk-python-v2/awsiot/iotshadow.html). -service client for more details. -For code examples, see the v2 SDK [Device Shadow](https://github.com/aws/aws-iot-device-sdk-python-v2/blob/main/samples/shadow_mqtt5.py) + +For code examples, see the v2 SDK [Device Shadow](https://github.com/aws/aws-iot-device-sdk-python-v2/blob/main/samples/shadow_mqtt5.py). ### Client for AWS IoT Jobs @@ -768,8 +792,6 @@ The v1 SDK and the v2 SDK offer support of AWS IoT Core services implementing a [Jobs](https://docs.aws.amazon.com/iot/latest/developerguide/iot-jobs.html) service which helps with defining a set of remote operations that can be sent to and run on one or more devices connected to AWS IoT. -For more information about the v1 SDK, see [AWS Iot Jobs APIs](https://s3.amazonaws.com/aws-iot-device-sdk-python-docs/html/index.html#AWSIoTPythonSDK.MQTTLib.AWSIoTMQTTThingJobsClient). -For code examples, see [AWS IoT Jobs samples](https://github.com/aws/aws-iot-device-sdk-python/blob/master/samples/jobs/jobsSample.py) The v2 SDK supports Jobs service as well, but with completely different API. The Jobs service client provides API similar to API provided by [Client for Device Shadow Service](#client-for-device-shadow-service). @@ -778,110 +800,109 @@ The service client provides API for that. After subscribing to all the required the service client can start interacting with the server, for example update the status or request for data. These actions are also performed via client API calls. -AWS IoT Core documentation for [AWS Iot Jobs](https://docs.aws.amazon.com/iot/latest/developerguide/jobs-mqtt-api.html) service -provides detailed descriptions for the topics used to interact with the service. - -For API documentation for the v2 SDK, see [AWS Iot Jobs API](https://aws.github.io/aws-iot-device-sdk-python-v2/awsiot/iotjobs.html) -For code examples, see [AWS Iot Jobs](https://github.com/aws/aws-iot-device-sdk-python-v2/blob/main/samples/jobs_mqtt5.py) samples. -#### AWS IoT Jobs Example in the v1 SDK +#### Example creating a jobs client in the v1 SDK ```python jobs_client = AWSIoTMQTTThingJobsClient( "", "", QoS=1, - awsIoTMQTTClient=mqtt5_client) + awsIoTMQTTClient=mqtt_client) jobsClient.connect() -# Setup Callbacks -def newJobReceived(self, mqtt5_client, userdata, message): +``` + +#### Example creating a jobs client in the v2 SDK + +```python +mqtt5_client.start() + +jobs_client = iotjobs.IotJobsClient(mqtt5_client) + +``` + +#### Example subscribing to jobs topics in the v1 SDK + +```python +# Blocking API +def newJobReceived(mqtt_client, userdata, message): return + jobs_client.createJobSubscription( newJobReceived, jobExecutionTopicType. JOB_NOTIFY_NEXT_TOPIC) -def startNextJobSuccessfullyInProgress(mqtt5_client, userdata, message): +def startNextJobSuccessfullyInProgress(mqtt_client, userdata, message): return + jobs_client.createJobSubscription( startNextJobSuccessfullyInProgress, jobExecutionTopicType.JOB_START_NEXT_TOPIC, jobExecutionTopicReplyType.JOB_ACCEPTED_REPLY_TYPE) -def startNextRejected(mqtt5_client, userdata, message): +def startNextRejected(mqtt_client, userdata, message): return + jobs_client.createJobSubscription( startNextRejected, jobExecutionTopicType.JOB_START_NEXT_TOPIC, jobExecutionTopicReplyType.JOB_REJECTED_REPLY_TYPE) -def updateJobSuccessful(mqtt5_client, userdata, message): +def updateJobSuccessful(mqtt_client, userdata, message): return + jobs_client.createJobSubscription( updateJobSuccessful, jobExecutionTopicType.JOB_UPDATE_TOPIC, jobExecutionTopicReplyType.JOB_ACCEPTED_REPLY_TYPE, '+') -def updateJobRejected(mqtt5_client, userdata, message): +def updateJobRejected(mqtt_client, userdata, message): return + jobs_client.createJobSubscription( updateJobRejected, jobExecutionTopicType.JOB_UPDATE_TOPIC, jobExecutionTopicReplyType.JOB_REJECTED_REPLY_TYPE, '+') -# start next job -statusDetails = - {'StartedBy': 'ClientToken: {} on {}'.format( - clientToken, - datetime.datetime.now().isoformat())} - -jobs_client.sendJobsStartNext( - statusDetails=statusDetails) - -# Update job status -jobs_cli.`sendJobsUpdate( - jobId="", - statusDetails=None, - `expectedersion=4, - executionNumber=3, - includeJobExecutionState=False, - includeJobDocument=False - stepTimeoutInMinutes=3) +def describeTopic(mqtt_client, userdata, message): + return -jobsClient.disconnect() +jobs_client.createJobSubscription( + describeTopic, + jobExecutionTopicType.JOB_DESCRIBE_TOPIC, + jobExecutionTopicReplyType.JOB_REJECTED_REPLY_TYPE, + jobId) ``` -#### AWS IoT Jobs Example in the v2 SDK - ```python -jobs_client = iotjobs.IotJobsClient(mqtt5_client) -get_jobs_request = iotjobs.GetPendingJobExecutionsRequest(thing_name=") +# Non blocking API -# List pending jobs -def on_get_pending_job_executions_accepted(response): +def ackCallback(mid, data): return -jobs_request_future_accepted, _ = - jobs_client.subscribe_to_get_pending_job_executions_accepted - request=get_jobs_request, - qos=mqtt5.QoS.AT_LEAST_ONCE, - callback=on_get_pending_job_executions_accepted) -def on_get_pending_job_executions_rejected(error): +def cllback(client, userdata, message): return -jobs_request_future_rejected, _ = - jobs_client.subscribe_to_get_pending_job_executions_rejected( - request=get_jobs_request, - qos=mqtt5.QoS.AT_LEAST_ONCE, - callback=on_get_pending_job_executions_rejected) -get_jobs_request_future = jobs_client.publish_get_pending_job_executions( - request=get_jobs_request, - qos=mqtt5.QoS.AT_LEAST_ONCE) +packet_id = jobs_client.createJobSubscriptionAsync( + ackCallback=ackCallback, + callback=callback, + jobExecutionType=jobExecutionTopicType.JOB_WILDCARD_TOPIC, + jobReplyType=jobExecutionTopicReplyType.JOB_REQUEST_TYPE, + jobId=None) + +``` + +#### Example subscribing to jobs topics in the v2 SDK + +More subscriptions will be listed with their corresponding API + +```python # Subscribe to necessary topics changed_subscription_request = iotjobs.NextJobExecutionChangedSubscriptionRequest( @@ -889,16 +910,46 @@ changed_subscription_request = iotjobs.NextJobExecutionChangedSubscriptionReques def on_next_job_execution_changed(event): return + subscribed_future, _ = jobs_client.subscribe_to_next_job_execution_changed_events( request=changed_subscription_request, qos=mqtt5.QoS.AT_LEAST_ONCE, callback=on_next_job_execution_changed) -start_subscription_request = iotjobs.StartNextPendingJobExecutionSubscriptionRequest( +changed_subscription_request = iotjobs.JobExecutionChangedSubscriptionRequest( thing_name="") +def on_job_execution_changed(event): + return + +subscribed_future, _ jobs_client.subscribe_to_job_executions_changed_events( + request=changed_subscription_request, + qos=mqtt5.QoS.AT_LEAST_ONCE, + callback=on_job_execution_changed) + +``` + +#### Example of execution of the next pending job in the v1 SDK + +```python +# start next job +statusDetails = + {'StartedBy': 'ClientToken: {} on {}'.format( + clientToken, + datetime.datetime.now().isoformat())} + +jobs_client.sendJobsStartNext( + statusDetails=statusDetails) +``` + +#### Example of execution of the next pending job in the v2 SDK + +```python +start_subscription_request = iotjobs.StartNextPendingJobExecutionSubscriptionRequest(thing_name="thing name") + def on_start_next_pending_job_execution_accepted(response): return + subscribed_accepted_future, _ = jobs_client.subscribe_to_start_next_pending_job_execution_accepted( request=start_subscription_request, @@ -907,20 +958,100 @@ subscribed_accepted_future, _ = def on_start_next_pending_job_execution_rejected(rejected): return + subscribed_rejected_future, _ = jobs_client.subscribe_to_start_next_pending_job_execution_rejected( request=start_subscription_request, qos=mqtt5.QoS.AT_LEAST_ONCE, callback=on_start_next_pending_job_execution_rejected) -# Note that we subscribe to "+", the MQTT wildcard, to receive -# responses about any job-ID. +execution_request = iotjobs.StartNextPendingJobExecutionRequest( + thing_name="thing_name") + +publish_future = jobs_client.publish_start_next_pending_job_execution( + request=execution_request, + mqtt.QoS.AT_LEAST_ONCE) + +publish_future.add_done_callback(on_publish_start_next_pending_job_execution) + +``` + +#### Example of getting detailed information about a job in the v1 SDK + +```python +# get info for specific job id +jobs_client.sendJobsDescribe(jobId = "job id", executionNumber=1, includeJobDocument=True) + +# or for the next job id +jobs_client.sendJobsDescribe(jobId = '$next', executionNumber=1, includeJobDocument=True) + +``` + +#### Example of getting detailed information about a job in the v2 SDK + +```python +def accepted_callback(response) # DescribeJobExecutionResponse + # job details received + return + +def rejected_callback(RejectedError response) # RejectedError + # error getting job details + return + +iotjobs.DescribeJobExecutionSubscriptionRequest request; +request.job_id = "job id" +request.thing_name = "thing name" + +jobs_client.subscribe_to_describe_job_execution_accepted( + request=request, + qos=mqtt5.QoS.AT_LEAST_ONCE, + callback=acceted_callback) + +jobs_client.subscribe_to_describe_job_execution_rejected( + request=request, + qos=mqtt5.QoS.AT_LEAST_ONCE, + callback=rejected_callback) + +describe_request = iotjobs.DescribeJobExecutionRequest( + client_token="client token", + execution_number=23, + include_job_document=false, + job_id="job id", + thing_name="thing name") + +jobs_client.publish_describe_job_execution( + request=describe_request, + qos=mqtt5.QoS.AT_LEAST_ONCE) + +``` + +#### Example updating status of a job on the v1 SDK + +```python +statusDetails = {'HandledBy': 'aws iot sdk'} + +jobs_client.sendJobsUpdate( + jobId="", + status=jobExecutionStatus.JOB_EXECUTION_SUCCEEDED, + statusDetails=statusDetails, + expectedersion=4, + executionNumber=3, + includeJobExecutionState=False, + includeJobDocument=False + stepTimeoutInMinutes=3) + +``` + +#### Example updating status of a job in the v2 SDK + +```python update_subscription_request = iotjobs.UpdateJobExecutionSubscriptionRequest( thing_name=jobs_thing_name, job_id='+') def on_update_job_execution_accepted(response): return + subscribed_accepted_future, _ = jobs_client.subscribe_to_update_job_execution_accepted( request=update_subscription_request, @@ -929,23 +1060,80 @@ subscribed_accepted_future, _ = def on_update_job_execution_rejected(rejected): return + subscribed_rejected_future, _ = jobs_client.subscribe_to_update_job_execution_rejected( request=update_subscription_request qos=mqtt5.QoS.AT_LEAST_ONCE, callback=on_update_job_execution_rejected) -# Start next Job -request = iotjobs.StartNextPendingJobExecutionRequest( - thing_name=") -publish_future = jobs_client.publish_start_next_pending_job_execution( - request, - mqtt5.QoS.AT_LEAST_ONCE) -publish_future.add_done_callback( - on_publish_start_next_pending_job_execution) +update_job_execution_request = iotjobs.UpdateJobExecutionRequest( + client_token="client_token", + excution_number=32, + expected_version=23, + include_job_document=true, + include_job_execution_state=true, + job_id="job id", + status=IN_PROGRESS, + status_details={"key":"val"}, + step_timeout_in_minutes=23, + thing_name="thing name") + +jobs_client.publish_update_job_execution( + request=update_job_execution_request, + qos=mqtt5.QoS.AT_LEAST_ONCE) + +``` + +#### Example of getting job info in the v1 SDK + +```python +# describe next job +jobs_client.sendJobsQuery(jobExecutionTopicType.JOB_DESCRIBE_TOPIC, '$next') + +# get list of pendig jobs +jobs_client.sendJobsQuery(jobExecutionTopicType.JOB_GET_PENDING_TOPIC) + +``` + +#### Example of getting job info in the v2 SDK + +```python +def on_get_pending_job_executions_accepted(response): + return + +jobs_request_future_accepted, _ = + jobs_client.subscribe_to_get_pending_job_executions_accepted + request=get_jobs_request, + qos=mqtt5.QoS.AT_LEAST_ONCE, + callback=on_get_pending_job_executions_accepted) + +def on_get_pending_job_executions_rejected(error): + return + +jobs_request_future_rejected, _ = + jobs_client.subscribe_to_get_pending_job_executions_rejected( + request=get_jobs_request, + qos=mqtt5.QoS.AT_LEAST_ONCE, + callback=on_get_pending_job_executions_rejected) + +get_jobs_request = iotjobs.GetPendingJobExecutionsRequest(thing_name=") + +get_jobs_request_future = jobs_client.publish_get_pending_job_executions( + request=get_jobs_request, + qos=mqtt5.QoS.AT_LEAST_ONCE) ``` +For detailed descriptions for the topics used to interact with the service, see AWS IoT Core documentation for the +[Jobs](https://docs.aws.amazon.com/iot/latest/developerguide/jobs-mqtt-api.html) service. + +For more information about the service clients, see API documentation for the v2 SDK +[Jobs](https://aws.github.io/aws-iot-device-sdk-python-v2/awsiot/iotjobs.html). + +For code examles, see [Jobs](https://github.com/aws/aws-iot-device-sdk-python/blob/master/samples/jobs/jobsSample.py) +samples. + ### Client for AWS IoT fleet provisioning @@ -1027,23 +1215,26 @@ class. **Request/Response**\ Publishers can request a response be sent by the receiver to a publisher-specified topic upon reception. -Use `response_topic` method in [PublishPacket](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.PublishPacket) class. +Use `response_topic` method in +[PublishPacket](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.PublishPacket) class. **Maximum Packet Size**\ -Client and Server can independently specify the maximum packet size that they support. +Client and Server can independently specify the maximum packet size that they support.\ For more information, see [ConnectPacket.maximum_packet_size(int)](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.ConnectPacket), the [NegotiatedSettings.maximum_packet_size_to_server](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.NegotiatedSettings), and the [ConnAckPacket.maximum_packet_size](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.ConnackPacket) methods. **Payload format and content type**\ You can specify the payload format (binary, text) and content type when a message is published. -These are forwarded to the receiver of the message. Use content_type(str) method in +These are forwarded to the receiver of the message. Use content\_type(str) method in [PublishPacket](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.PublishPacket) class. **Shared Subscriptions**\ Shared Subscriptions allow multiple clients to share a subscription to a topic and only one client will receive messages -published to that topic using a random distribution. -Refer to a [shared subscription sample](https://github.com/aws/aws-iot-device-sdk-python-v2/blob/main/samples/mqtt5_shared_subscription.md) in the v2 SDK. +published to that topic using a random distribution.\ +For more infromation, see a +[shared subscription sample](https://github.com/aws/aws-iot-device-sdk-python-v2/blob/main/samples/mqtt5_shared_subscription.md) +in the v2 SDK. > [!NOTE] > AWS IoT Core supports Shared Subscriptions for both MQTT3 and MQTT5. For more information, From 78f01eb4b8dfa10cce8efaba3d923adfbbc45dc7 Mon Sep 17 00:00:00 2001 From: Alfred Gedeon Date: Fri, 23 Feb 2024 17:19:55 -0800 Subject: [PATCH 09/12] fix comments --- documents/MIGRATION_GUIDE.md | 80 ++++++++++++++++++------------------ 1 file changed, 40 insertions(+), 40 deletions(-) diff --git a/documents/MIGRATION_GUIDE.md b/documents/MIGRATION_GUIDE.md index bda25f53..a220c109 100644 --- a/documents/MIGRATION_GUIDE.md +++ b/documents/MIGRATION_GUIDE.md @@ -14,7 +14,7 @@ and provides guidance on how to migrate your code to v2 from v1 of the AWS IoT S * [How to get started with AWS IoT Device SDK for Python v2](#how-to-get-started-with-aws-iot-device-sdk-for-python-v2) * [MQTT protocol](#mqtt-protocol) * [Client builder](#client-builder) - * [Client Start](#client-start) + * [Client start](#client-start) * [Connection types and features](#connection-types-and-features) * [Lifecycle events](#lifecycle-events) * [Publish](#publish) @@ -114,7 +114,7 @@ mqtt5_client.start() For more information, refer to the [Connection Types and Features](#connection-types-and-features) section for other connection types supported by the v2 SDK -### Client Start +### Client start To connect to the server in the v1 SDK, you call the `connect` method on an `MQTTClient` instance. @@ -155,20 +155,17 @@ feature. | Connection type/feature | v1 SDK | v2 SDK | User guide | |--------------------------------------------------------|---------------------------------------|------------------------------------|:----------:| |MQTT over Secure WebSocket with AWS SigV4 authentication|$${\Large\color{green}✔}$$ |$${\Large\color{green}✔}$$ |[link](https://github.com/aws/aws-iot-device-sdk-python-v2/blob/main/documents/MQTT5_Userguide.md#mqtt-over-websockets-with-sigv4-authentication)| -|MQTT with Java Keystore Method |$${\Large\color{red}✘}$$ |$${\Large\color{orange}✔\*}$$ |[link](https://github.com/aws/aws-iot-device-sdk-python-v2/blob/main/samples/pkcs12_connect.md#how-to-setup-and-run)| |Websocket Connection with Cognito Authentication Method |$${\Large\color{green}✔}$$ |$${\Large\color{green}✔}$$ |[link](https://github.com/aws/aws-iot-device-sdk-python-v2/blob/main/documents/MQTT5_Userguide.md#mqtt-over-websockets-with-cognito-authentication)| |MQTT with X.509 certificate based mutual authentication |$${\Large\color{green}✔}$$ |$${\Large\color{green}✔}$$ |[link](https://github.com/aws/aws-iot-device-sdk-python-v2/blob/main/documents/MQTT5_Userguide.md#direct-mqtt-with-x509-based-mutual-tls)| +|MQTT with Custom Authorizer Method |$${\Large\color{orange}✔\*}$$ |$${\Large\color{green}✔}$$ |[link](https://github.com/aws/aws-iot-device-sdk-python-v2/blob/main/documents/MQTT5_Userguide.md#direct-mqtt-with-custom-authentication)| +|HTTP Proxy |$${\Large\color{orange}✔\*\*}$$ |$${\Large\color{green}✔}$$ |[link](https://github.com/aws/aws-iot-device-sdk-python-v2/blob/main/documents/MQTT5_Userguide.md#adding-an-http-proxy)| |MQTT with PKCS12 Method |$${\Large\color{red}✘}$$ |$${\Large\color{green}✔}$$ |[link](https://github.com/aws/aws-iot-device-sdk-python-v2/blob/main/documents/MQTT5_Userguide.md#direct-mqtt-with-pkcs12-method) | -|MQTT with Custom Authorizer Method |$${\Large\color{orange}✔\*\*}$$ |$${\Large\color{green}✔}$$ |[link](https://github.com/aws/aws-iot-device-sdk-python-v2/blob/main/documents/MQTT5_Userguide.md#direct-mqtt-with-custom-authentication)| |MQTT with Windows Certificate Store Method |$${\Large\color{red}✘}$$ |$${\Large\color{green}✔}$$ |[link](https://github.com/aws/aws-iot-device-sdk-python-v2/blob/main/documents/MQTT5_Userguide.md#direct-mqtt-with-windows-certificate-store-method)| |MQTT with PKCS11 Method |$${\Large\color{red}✘}$$ |$${\Large\color{green}✔}$$ |[link](https://github.com/aws/aws-iot-device-sdk-python-v2/blob/main/documents/MQTT5_Userguide.md#direct-mqtt-with-pkcs11-method)| -|HTTP Proxy |$${\Large\color{orange}✔\*\*\*}$$|$${\Large\color{green}✔}$$ |[link](https://github.com/aws/aws-iot-device-sdk-python-v2/blob/main/documents/MQTT5_Userguide.md#adding-an-http-proxy)| -${\Large\color{orange}✔\*}$ - To get this connection type to work in the v2 SDK, you need to convert - the Java Key store key into a PKSC#12 key [import IOT Core key to a Java KeyStore and convert it to pkcs#12](https://github.com/aws/aws-iot-device-sdk-python-v2/blob/main/samples/pkcs12_connect.md#how-to-setup-and-run).\ -${\Large\color{orange}✔\*\*}$ - To get this connection type work in the v1 SDK, you need to implement +${\Large\color{orange}✔\*}$ - To get this connection type work in the v1 SDK, you need to implement the [Custom Authentication workflow](https://docs.aws.amazon.com/iot/latest/developerguide/custom-authorizer.html).\ -${\Large\color{orange}✔\*\*\*}$ - The v1 SDK does not allow to specify HTTP proxy, +${\Large\color{orange}✔\*\*}$ - The v1 SDK does not allow to specify HTTP proxy, it is possible to configure systemwide proxy. ### Lifecycle Events @@ -258,9 +255,9 @@ The returned `PublishCompletionData` will contain different data depending on th > connection > closed but instead receive a PUBACK with a reason code. -* For QoS 0 (AT\_MOST\_ONCE): Calling `getValue` will return `null` +* For QoS 0 (AT\_MOST\_ONCE): Calling `get_result` will return with no data and the promise will be complete as soon as the packet has been written to the socket. -* For QoS 1 (AT\_LEAST\_ONCE): Calling `getValue` will return a +* For QoS 1 (AT\_LEAST\_ONCE): Calling `get_result` will return a [awscrt.mqtt5.PubAckPacket](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.PubackPacket) and the promise will be complete as soon as the PUBACK is received from the broker. @@ -320,10 +317,10 @@ parameter, the v2 SDK will subscribe to all of these topics using one request. The [subscribe](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.Client.subscribe) operation takes a description of the `SubscribePacket` you wish to send and returns a promise that resolves successfully with the -corresponding [SubAckPacket](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.SubackPacket) +corresponding [SubackPacket](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.SubackPacket) returned by the broker. The promise is rejected with an error if anything goes wrong before -the `SubAckPacket` is received. -You should always check the reason codes of a `SubAckPacket` completion to determine if +the `SubackPacket` is received. +You should always check the reason codes of a `SubackPacket` completion to determine if the subscribe operation actually succeeded. > [!NOTE] @@ -332,7 +329,7 @@ the subscribe operation actually succeeded. > closed but instead receive a SUBACK with a reason code. In the v2 SDK, if the MQTT5 client is going to subscribe and receive packets from the MQTT broker, -it is important to also setup the `on_publish_callback_fn` callback int the `ClientOptions`. +it is important to also setup the `on_publish_received` callback int the `ClientOptions`. This callback is invoked whenever the client receives a message from the server on a topic the client is subscribed to. With this callback, you can process messages made to subscribed topics through its `message` parameter [PublishReceivedData](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.PublishReceivedData). @@ -340,7 +337,13 @@ With this callback, you can process messages made to subscribed topics through i #### Example of subscribing in the v1 SDK ```python +def on_publish_received(publish_received_data): + return + +client_options = mqtt5.ClientOptions( ... ) +client_options.on_publish_received = on_publish_received +client = mqtt5.Client(client_options) client.configureMQTTOperationTimeout(30) # 30 Seconds def ackCallback(mid, data): @@ -390,15 +393,15 @@ First, you need to create an [UnsubscribePacket](https://awslabs.github.io/aws-c object. The [unsubscribe](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.Client.unsubscribe) operation takes a description of the [UnsubscribePacket](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.UnsubscribePacket) you wish to send and returns a promise that resolves successfully with the corresponding -[UnsubAckPacket](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.UnsubackPacket) +[UnsubackPacket](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.UnsubackPacket) returned by the broker. The promise is rejected with an error if anything goes wrong before -the [UnsubAckPacket](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.UnsubackPacket) is received. +the [UnsubackPacket](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.UnsubackPacket) is received. You should always check the reason codes of -a [UnsubAckPacket](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.UnsubackPacket) completion +a [UnsubackPacket](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.UnsubackPacket) completion to determine if the unsubscribe operation actually succeeded. Similar to subscribing, you can unsubscribe from multiple topics in one request by passing -a list of topics to topic\_filters (\*Sequence[str\*\*]) in \*[\*UnsubAckPacket\*](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.UnsubackPacket) +a list of topics to topic\_filters (\*Sequence[str\*\*]) in \*[\*UnsubackPacket\*](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.UnsubackPacket) #### Example of unsubscribing in the v1 SDK @@ -429,7 +432,7 @@ print("Unsubscribed with {}".format(unsuback.reason_codes)) ``` -### Client Stop +### Client stop In the v1 SDK, the `disconnect` method in the `AWSIotMqttClient` class disconnects the client. Once disconnected, the client can connect again by calling `connect`. @@ -453,8 +456,8 @@ client.disconnect(); ```python mqtt5_client.stop( disconnect_packet=mqtt5.DisconnectPacket( - reason_code=mqtt5.*DisconnectReasonCode**.**NORMAL_DISCONNECTION**, - session_expiry_interval_sec=3600*)) + reason_code=mqtt5.DisconnectReasonCode.NORMAL_DISCONNECTION, + session_expiry_interval_sec=3600)) ``` @@ -475,10 +478,10 @@ are configurable through [awsiot.mqtt5\_client\_builder](https://aws.github.io/a baseReconnectQuietTimeSecond = 1 # Initial backoff time maxReconnectQuiteTimeSecond = 23 # maximum backoff time stableConnectionTimeSecond = 20 # the time the connection is considered stable -client``.``configureAutoReconnectBackoffTime``( - ``baseReconnectQuietTimeSecond``, - ``maxReconnectQuiteTimeSecond``, - ``stableConnectionTimeSecond``) +client.configureAutoReconnectBackoffTime( + baseReconnectQuietTimeSecond, + maxReconnectQuiteTimeSecond, + stableConnectionTimeSecond) ``` @@ -550,9 +553,7 @@ see [ClientOfflineQueueBehavior types documentation](https://awslabs.github.io/a ### Operation Timeouts -In the v1 SDK, all operations (*publish*, *subscribe*, *unsubscribe*) will not timeout unless -you define a timeout for them. If no timeout is defined, there is a possibility that an operation will wait forever -for the server to respond and block the calling thread indefinitely. +In the v1 SDK, all operations (*publish*, *subscribe*, *unsubscribe*) will take a timeout for all of them. In the v2 SDK, operations timeout is set for the MQTT5 client with the [ClientOptions](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.ClientOptions) @@ -567,11 +568,11 @@ the current state of an` mqtt5.Client` object's queue of operations, which may h ```python connectTimeoutSec = 10 -`client``.``configureConnectDisconnectTimeout`(connectTimeoutSec) +client.configureConnectDisconnectTimeout(connectTimeoutSec) client.connect(); publishTimeoutMs = 20 -client.`configureMQTTOperationTimeout``(publishTimeoutMs)` +client.configureMQTTOperationTimeout(publishTimeoutMs) client.publish("my/topic", "hello", 1) ``` @@ -589,7 +590,7 @@ mqtt5_client = mqtt5_client_builder.mtls_from_path( ### Logging -The v1 SDK uses `AWSIoTPythonSDK.core` custom logger logger for logging. +The v1 SDK uses `AWSIoTPythonSDK.core` custom logger for logging. The v2 SDK uses a standard [logging facility](https://docs.python.org/3/howto/logging.html). @@ -612,7 +613,6 @@ logger.info("info log") ```python from awscrt import io -import logging io.init_logging(log_level=io.LogLevel.Trace, file_name='stderr') @@ -625,7 +625,7 @@ logger.debug("error log") The v1 SDK is built with [AWS IoT device shadow support](http://docs.aws.amazon.com/iot/latest/developerguide/iot-thing-shadows.html), which provides access to thing shadows (sometimes referred to as device shadows). -The v2 SDK also supports device shadow service as well, but with a completely different APIs. +The v2 SDK also supports device shadow service, but with a completely different APIs. First, you subscribe to special topics to get data and feedback from a service. The service client provides API for that. For example, `subscribe_to_get_shadow_accepted` subscribes to a topic to which AWS IoT Core will publish a shadow document. The server will notify you if it cannot send you a @@ -679,11 +679,11 @@ deviceShadowHandler.shadowDelete(customShadowCallback_Delete, 5) ```python def delete_accepted(DeleteShadowResponse response): return -shadow_client.subscribe_to_delete_shadow_accepted(*request*, *qos*, *callback*) +shadow_client.subscribe_to_delete_shadow_accepted(request, qos, callback) def delete_rejected(DeleteShadowResponse response): return -shadow_client.subscribe_to_delete_shadow_rejected(*request*, *qos*, *callback*) +shadow_client.subscribe_to_delete_shadow_rejected(request, qos, callback) iotshadow.DeleteShadowRequest req req.client_token = "" @@ -793,7 +793,7 @@ The v1 SDK and the v2 SDK offer support of AWS IoT Core services implementing a remote operations that can be sent to and run on one or more devices connected to AWS IoT. -The v2 SDK supports Jobs service as well, but with completely different API. +The v2 SDK Jobs service APIs are completely different than the v1 SDK APIs. The Jobs service client provides API similar to API provided by [Client for Device Shadow Service](#client-for-device-shadow-service). First, you subscribe to special topics to get data and feedback from a service. The service client provides API for that. After subscribing to all the required topics, @@ -922,7 +922,7 @@ changed_subscription_request = iotjobs.JobExecutionChangedSubscriptionRequest( def on_job_execution_changed(event): return -subscribed_future, _ jobs_client.subscribe_to_job_executions_changed_events( +subscribed_future, _ = jobs_client.subscribe_to_job_executions_changed_events( request=changed_subscription_request, qos=mqtt5.QoS.AT_LEAST_ONCE, callback=on_job_execution_changed) @@ -1191,8 +1191,8 @@ You can debug or process error messages more easily using the reason codes. Reason codes are returned by the message broker based on the type of interaction with the broker (Subscribe, Publish, Acknowledge). For more information, see [PubAckReasonCode](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.PubackReasonCode), -[SubAckReasonCode](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.SubackReasonCode), -[UnsubAckReasonCode](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.SubackReasonCode), +[SubackReasonCode](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.SubackReasonCode), +[UnsubackReasonCode](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.SubackReasonCode), [ConnectReasonCode](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.ConnectReasonCode), [DisconnectReasonCode](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.DisconnectReasonCode). From 4b28d1b524b043a3f86e39783fc30186f0a97a05 Mon Sep 17 00:00:00 2001 From: Alfred Gedeon Date: Fri, 23 Feb 2024 17:43:24 -0800 Subject: [PATCH 10/12] fix indentation --- documents/MIGRATION_GUIDE.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/documents/MIGRATION_GUIDE.md b/documents/MIGRATION_GUIDE.md index a220c109..048a5a6e 100644 --- a/documents/MIGRATION_GUIDE.md +++ b/documents/MIGRATION_GUIDE.md @@ -233,7 +233,6 @@ mqtt5_client = mqtt5_client_builder.mtls_from_path( on_lifecycle_connection_failure=on_lifecycle_connection_failure) mqtt5_client.start() - ``` ### Publish @@ -275,7 +274,7 @@ client.publish("my/topic", "hello", 0) ```python # Non-blocking API. -`client.configureMQTTOperationTimeout`(30) # 30 Seconds +client.configureMQTTOperationTimeout(30) # 30 Seconds client.connect() def ack_callback(mid, data=data): @@ -571,7 +570,7 @@ connectTimeoutSec = 10 client.configureConnectDisconnectTimeout(connectTimeoutSec) client.connect(); - publishTimeoutMs = 20 +publishTimeoutMs = 20 client.configureMQTTOperationTimeout(publishTimeoutMs) client.publish("my/topic", "hello", 1) From 02d6779445c252587b6fe2ad882f0e45698c48e7 Mon Sep 17 00:00:00 2001 From: Alfred Gedeon Date: Fri, 23 Feb 2024 17:49:07 -0800 Subject: [PATCH 11/12] Fix --- documents/MIGRATION_GUIDE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/documents/MIGRATION_GUIDE.md b/documents/MIGRATION_GUIDE.md index 048a5a6e..54d51677 100644 --- a/documents/MIGRATION_GUIDE.md +++ b/documents/MIGRATION_GUIDE.md @@ -557,7 +557,7 @@ In the v1 SDK, all operations (*publish*, *subscribe*, *unsubscribe*) will take In the v2 SDK, operations timeout is set for the MQTT5 client with the [ClientOptions](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.ClientOptions) class member `ack_timeout_sec`. -The default value is no timeout. As in the v1 SDK, failing to set a timeout can cause an operation to stuck forever, +The default value is no timeout. Failing to set a timeout can cause an operation to stuck forever, but it won't block the client. The [get\_stats](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.Client.get_stats) method returns From 92f9e146b7c772f4cbca2d3f5c2e3cb838889a75 Mon Sep 17 00:00:00 2001 From: Alfred Gedeon Date: Mon, 26 Feb 2024 14:26:33 -0800 Subject: [PATCH 12/12] Fix comments --- documents/MIGRATION_GUIDE.md | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/documents/MIGRATION_GUIDE.md b/documents/MIGRATION_GUIDE.md index 54d51677..a877c6fd 100644 --- a/documents/MIGRATION_GUIDE.md +++ b/documents/MIGRATION_GUIDE.md @@ -254,9 +254,9 @@ The returned `PublishCompletionData` will contain different data depending on th > connection > closed but instead receive a PUBACK with a reason code. -* For QoS 0 (AT\_MOST\_ONCE): Calling `get_result` will return with no data +* For QoS 0 (AT\_MOST\_ONCE): Calling `result` will return with no data and the promise will be complete as soon as the packet has been written to the socket. -* For QoS 1 (AT\_LEAST\_ONCE): Calling `get_result` will return a +* For QoS 1 (AT\_LEAST\_ONCE): Calling `result` will return a [awscrt.mqtt5.PubAckPacket](https://awslabs.github.io/aws-crt-python/api/mqtt5.html#awscrt.mqtt5.PubackPacket) and the promise will be complete as soon as the PUBACK is received from the broker. @@ -336,13 +336,6 @@ With this callback, you can process messages made to subscribed topics through i #### Example of subscribing in the v1 SDK ```python -def on_publish_received(publish_received_data): - return - -client_options = mqtt5.ClientOptions( ... ) -client_options.on_publish_received = on_publish_received - -client = mqtt5.Client(client_options) client.configureMQTTOperationTimeout(30) # 30 Seconds def ackCallback(mid, data): @@ -369,6 +362,14 @@ client.subscribeAsync( #### Example of subscribing in the v2 SDK ```python + +def on_publish_received(publish_received_data): + return + +client_options = mqtt5.ClientOptions( ... ) +client_options.on_publish_received = on_publish_received +client = mqtt5.Client(client_options) + subscribe_future = client.subscribe( subscribe_packet=mqtt5.SubscribePacket( subscriptions=[mqtt5.Subscription( @@ -503,9 +504,9 @@ mqtt5_client.start() ### Offline Operations Queue -In the v1 SDK, if you're having too many in-flight QoS 1 messages, you can encounter the `too many publishes in Progress` error -on publishing messages. This is caused by the so-called in-flight publish limit. By default, ther v1 SDK supports -a maximum of 20 in-flight operations. +In the v1 SDK, if you're having too many in-flight QoS 1 messages, all extra messages will be queued for them to +be sent at a later time, when the number of in-flight messages goes below the so-called in-flight publish limit. +By default, the v1 SDK supports a maximum of 20 in-flight operations. The v2 SDK does not limit the number of in-flight messages. Additionally, the v2 SDK provides a way to configure which kind of packets will be placed into the offline queue @@ -591,7 +592,7 @@ mqtt5_client = mqtt5_client_builder.mtls_from_path( The v1 SDK uses `AWSIoTPythonSDK.core` custom logger for logging. -The v2 SDK uses a standard [logging facility](https://docs.python.org/3/howto/logging.html). +The v2 SDK uses the logging facility provided by the [crt-io](https://awslabs.github.io/aws-crt-python/api/io.html) #### Example of using logging in the v1 SDK