Use el SDK para Python 2.7 para conectar un cliente AMQP a Alibaba Cloud IoT Platform y recibir mensajes mediante la suscripción del lado del servidor.
Requisitos previos
Debe haber obtenido un ID de grupo de consumidores y haberse suscrito a los mensajes de topic necesarios.
Manage AMQP consumer groups: Use el grupo de consumidores predeterminado (DEFAULT_GROUP) en IoT Platform o cree un nuevo grupo de consumidores.
Configure an AMQP server-side subscription: Suscríbase a los mensajes de topic requeridos mediante un grupo de consumidores.
Entorno de desarrollo
Este ejemplo usa Python 2.7.
Descarga del SDK
Se recomienda la biblioteca Apache Qpid Proton 0.29.0, que encapsula la API de Python. Para descargar la biblioteca y consultar las instrucciones, visite Qpid Proton 0.29.0.
Instale Qpid Proton. Para obtener más información, consulte Installing Qpid Proton.
Después de instalar Qpid Proton, ejecute el siguiente comando de Python para comprobar que la biblioteca SSL está disponible:
import proton;print('%s' % 'SSL present' if proton.SSL.present() else 'SSL NOT AVAILABLE')
Código de ejemplo
# encoding=utf-8
import sys
import logging
import time
from proton.handlers import MessagingHandler
from proton.reactor import Container
import hashlib
import hmac
import base64
import os
reload(sys)
sys.setdefaultencoding('utf-8')
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
console_handler = logging.StreamHandler(sys.stdout)
def current_time_millis():
return str(int(round(time.time() * 1000)))
def do_sign(secret, sign_content):
m = hmac.new(secret, sign_content, digestmod=hashlib.sha1)
return base64.b64encode(m.digest())
class AmqpClient(MessagingHandler):
def __init__(self):
super(AmqpClient, self).__init__()
def on_start(self, event):
# The endpoint used to connect to IoT Platform. For details, see the AMQP connection guide.
url = "amqps://${YourHost}:5671"
# Hard-coding an AccessKey pair in your project code poses a security risk. If the code is leaked, your AccessKey pair will be exposed, compromising all resources in your account. The following code retrieves the AccessKey pair from environment variables as a best practice. This is for reference only.
accessKey = os.environ['ALIBABA_CLOUD_ACCESS_KEY_ID']
accessSecret = os.environ['ALIBABA_CLOUD_ACCESS_KEY_SECRET']
consumerGroupId = "${YourConsumerGroupId}"
clientId = "${YourClientId}"
# iotInstanceId: The ID of the IoT Platform instance.
iotInstanceId = "${YourIotInstanceId}"
# The signature algorithm. Valid values: hmacmd5, hmacsha1, and hmacsha256.
signMethod = "hmacsha1"
timestamp = current_time_millis()
# For instructions on how to construct the userName parameter, see the AMQP connection guide.
userName = clientId + "|authMode=aksign" + ",signMethod=" + signMethod \
+ ",timestamp=" + timestamp + ",authId=" + accessKey \
+ ",iotInstanceId=" + iotInstanceId + ",consumerGroupId=" + consumerGroupId + "|"
signContent = "authId=" + accessKey + "×tamp=" + timestamp
# Calculate the signature. For instructions on how to construct the password, see the AMQP connection guide.
passWord = do_sign(accessSecret.encode("utf-8"), signContent.encode("utf-8"))
conn = event.container.connect(url, user=userName, password=passWord, heartbeat=60)
self.receiver = event.container.create_receiver(conn)
# Called when the connection is successfully established.
def on_connection_opened(self, event):
logger.info("Connection established, remoteUrl: %s", event.connection.hostname)
# Called when the connection is closed.
def on_connection_closed(self, event):
logger.info("Connection closed: %s", self)
# Called when the remote peer closes the connection due to an error.
def on_connection_error(self, event):
logger.info("Connection error")
# Called when an AMQP connection error occurs, such as an authentication or socket error.
def on_transport_error(self, event):
if event.transport.condition:
if event.transport.condition.info:
logger.error("%s: %s: %s" % (
event.transport.condition.name, event.transport.condition.description,
event.transport.condition.info))
else:
logger.error("%s: %s" % (event.transport.condition.name, event.transport.condition.description))
else:
logging.error("Unspecified transport error")
# Called when a message is received.
def on_message(self, event):
message = event.message
content = message.body.decode('utf-8')
topic = message.properties.get("topic")
message_id = message.properties.get("messageId")
print("receive message: message_id=%s, topic=%s, content=%s" % (message_id, topic, content))
event.receiver.flow(1)
Container(AmqpClient()).run()
Configure los parámetros del código anterior como se describe en la siguiente tabla. Para obtener más información, consulte Connect an AMQP client to IoT Platform.
Especifique valores de parámetro válidos. De lo contrario, el cliente AMQP no podrá conectarse a IoT Platform.
|
Parámetro |
Descripción |
|
url |
El endpoint que usa el cliente AMQP para conectarse a IoT Platform. Formato: Para obtener más información sobre el endpoint que puede especificar en la variable |
|
accessKey |
Inicie sesión en la consola de IoT Platform, pase el cursor sobre la imagen de perfil en la esquina superior derecha y haga clic en AccessKey Management para obtener el AccessKey ID y el AccessKey secret. Nota
Si usa un usuario de Resource Access Management (RAM), debe adjuntar la directiva AliyunIOTFullAccess al usuario de RAM para otorgarle permisos de gestión de recursos de IoT Platform. De lo contrario, la conexión fallará. Para obtener más información, consulte Access IoT Platform as a RAM user. |
|
accessSecret |
|
|
consumerGroupId |
El ID del grupo de consumidores en la instancia de IoT Platform. Inicie sesión en la consola de IoT Platform. En la instancia correspondiente, vaya a para consultar su ID de grupo de consumidores. |
|
iotInstanceId |
El ID de la instancia de IoT Platform. Puede consultar el ID de la instancia en la pestaña Overview de la consola de IoT Platform.
|
|
clientId |
El ID del cliente. Debe definir este ID, el cual puede tener una longitud máxima de 64 caracteres. Se recomienda usar un identificador único, como el UUID, la dirección MAC o la dirección IP del servidor donde se encuentra su cliente AMQP. Una vez que el cliente AMQP esté conectado e iniciado, inicie sesión en la consola de IoT Platform. En la página de la instancia, dentro de la pestaña Consumer Groups, haga clic en View junto al grupo de consumidores. La página Consumer Group Details muestra este parámetro, lo que facilita la identificación de los distintos clientes. |
Resultados de ejemplo
-
Éxito: El siguiente mensaje de registro indica que el cliente AMQP se conectó correctamente a IoT Platform y está recibiendo mensajes.
202x-xx-xx xx:xx:xx,490 - __main__ - INFO - Connection established, remoteUrl: xxx.amqp.iothub.aliyuncs.com receive message: message_id=13xxx, topic=/xxx/thing/event/property/post, content={"deviceType":"CustomCategory","iotId":"xxx","requestId":"1xxx"} receive message: message_id=13xxx, topic=/xxx/thing/event/property/post, content={"deviceType":"CustomCategory","iotId":"xxx","requestId":"1xxx"}Parámetro
Ejemplo
Descripción
message_id
2****7
El ID del mensaje.
topic
//*/thing/event/property/post
El topic usado para enviar las propiedades del dispositivo.
content
{"deviceType":"CustomCategory","iotId":"qPi","requestId":"161","checkFailedData":{},"productKey":"g4","gmtCreate":1613635594038,"deviceName":"de","items":{"Temperature":{"value":24,"time":1613635594036},"Humidity":{"value":26,"time":1613635594036}}}
El contenido del mensaje.
-
Si se muestra información similar a la siguiente salida, significa que el cliente AMQP no pudo conectarse a IoT Platform.
Revise su código y la configuración de red mediante el registro de errores. Resuelva el problema y vuelva a ejecutar el código.
2021-02-18 16:19:40,993 - proton - ERROR - Couldn't connect: 10053 2021-02-18 16:19:40,996 - __main__ - ERROR - proton.pythonio: Connection error: 10053 2021-02-18 16:19:40,996 - proton - INFO - Disconnected, reconnecting... Traceback (most recent call last): File "xxx", line 87, in <module> Container(AmqpClient()).run() File "xxx", line 181, in run while self.process(): pass File "xxx", line 240, in process event.dispatch(self._global_handler) File "xxx", line 135, in dispatch _dispatch(handler, type.method, self) File "xxx", line 117, in _dispatch handler.on_unhandled(method, *args) File "xxx", line 665, in on_unhandled event.dispatch(self.base) File "xxx", line 135, in dispatch _dispatch(handler, type.method, self) File "xxx", line 115, in _dispatch m(*args) File "xxx", line 892, in on_connection_bound addrs = socket.getaddrinfo(host, port, socket.AF_UNSPEC, socket.SOCK_STREAM) socket.gaierror: [Errno 11001] getaddrinfo failed
Referencias
Para obtener más información sobre los códigos de error en los mensajes de suscripción del lado del servidor, consulte Message-related error codes.