【问题标题】:Connecting with M2MQTT Paho Python client to Azure IoT Hub使用 M2MQTT Paho Python 客户端连接到 Azure IoT Hub
【发布时间】:2019-07-28 17:40:25
【问题描述】:

我正在使用以下代码尝试连接到 Azure IoT Hub。它使用 SAS,因此不需要安全证书。我在 C# 中使用相同的 M2MQTT 库成功连接到 Azure IoT Hub,但此代码失败: 连接失败。连接被拒绝,未授权。错误代码= 5

我尝试了任何可能的安全参数组合,但无济于事。 SAS 令牌由 DeviceExplorer 生成。

#! /usr/bin/python3.5
import serial
import time
import datetime
import os
import socket
import ssl
import logging
import paho.mqtt.client as mqtt
import sys
print(sys.executable)

def on_disconnect(client, userdata, rc):
    if rc==0:
        print("client disconnected OK")
        client.connected_flag=False

def on_connect(client, userdata, flags, rc):
    if rc==0:
        print("Connected OK")
        mqtt.Client.connected_flag=True
        mqtt.Client.bad_connection_params=False
    else:
        mqtt.Client.bad_connection_params=True

        if rc==1:
            print("Failed to connect. Connection refused, unacceptable 
protocol version. Error Code=", rc)
        elif rc==2:
            print("Failed to connect.Connection refused, identifier 
rejected. Error Code=", rc)
        elif rc==3:
            print("Failed to connect.Connection refused, server unavailable. Error Code=", rc)
        elif rc==4:
        print("Failed to connect.Connection refused, bad user name or password. Error Code=", rc)
        elif rc==5:
        print("Failed to connect.Connection refused, not authorized. Error Code=", rc)


def on_publish(client, userdata, mid):
    if rc==0:
        print("Data published OK: ", userdata)
    else:
        print("Failed to publish data. MessageID=", mid)
    pass

broker="myIoTHubName.azure-devices.net"
port=8883
DeviceID="MasterTag"
DeviceKey="myDeviceKey"
IoTHubName="myIoTHubName"
SasToken="SharedAccessSignature sr=myIoTHubName.azure-devices.net&sig=..."

# Create client object
# 4 stands for MQTTv311
rpiclient = mqtt.Client("PahoClient-on-RPi-Gateway2", clean_session=True, userdata=None, protocol=4, transport="tcp") 

usernameFormat="{}{}{}"
username=usernameFormat.format(IoTHubName, ".azure-devices.net/", DeviceID)
password=SasToken

rpiclient.username_pw_set(username, password)
rpiclient.tls_set(tls_version=ssl.PROTOCOL_TLSv1_2)
rpiclient.tls_insecure_set(True)

# connection flag indicates that connection was made or not
mqtt.Client.connected_flag = False

# connection parameters are incorrect: ip address, port, authentication, etc
mqtt.Client.bad_connection_params=False

#assign function to callback
rpiclient.on_connect = on_connect

#assign function to callback
rpiclient.on_publish = on_publish

# bind the disconnect callback   
rpiclient.on_disconnect = on_disconnect

rpiclient.loop_start()

rpiclient.will_set("dwm/position", "Client PahoClient-on-RPi2 had unexpectedly disconnected", 1, True)

try:
    print("Connecting to MQTT broker ",broker)
    # Connect to the MQTT Broker
    rpiclient.connect(broker, port)
    time.sleep(1)

    # Wait in a loop until we are connected
    print("mqtt.Client.connected_flag={}, 

mqtt.Client.bad_connection_params={}".format(mqtt.Client.connected_flag, mqtt.Client.bad_connection_params)) 而 mqtt.Client.connected_flag == False 和 mqtt.Client.bad_connection_params == False: print("等待连接..."); 时间.sleep(1) 如果 mqtt.Client.bad_connection_params == True: rpiclient.loop_stop() sys.exit()

except Exception as ex:
    print("Connection to MQTT Broker failed: ", ex)

rpiclient.loop_stop()

# Disconnect MQTT Client
rpiclient.disconnect()

感谢任何建议。

【问题讨论】:

    标签: python iot azure-iot-hub paho


    【解决方案1】:

    以下是使用 paho.Mqtt 客户端库连接到 Azure IoT 中心的模拟 device1 的工作示例:

    from paho.mqtt import client as mqtt
    import time
    import ssl
    
    def on_subscribe(client, userdata, mid, granted_qos):
    print('Subscribed for m' + str(mid))
    
    def on_connect(client, userdata, flags, rc):
        print("Connected with result code "+str(rc))
    
    def on_message(client, userdata, message):
        print("Received message '" + str(message.payload) + "' on topic '" + message.topic + "' with QoS " + str(message.qos))
    
    def on_log(client, userdata, level, buf):
        print("log: ",buf)
    
    device_id = "device1"
    iot_hub_name = "myIoTHub"
    sas_token = "SharedAccessSignature sr=myIoTHub.azure-devices.net%2Fdevices%2Fdevice1&sig=****&se=1586926815"
    client = mqtt.Client(client_id=device_id, protocol=mqtt.MQTTv311,  clean_session=False)
    client.on_log = on_log
    client.tls_set_context(context=None)
    
    # Set up client credentials
    username = "{}.azure-devices.net/{}/api-version=2018-06-30".format(iot_hub_name, device_id)
    client.username_pw_set(username=username, password=sas_token)
    
    # Connect to the Azure IoT Hub
    client.on_connect = on_connect
    client.connect(iot_hub_name+".azure-devices.net", port=8883)
    
    # Publish 
    client.publish("devices/{device_id}/messages/events/".format(device_id=device_id), payload="{}", qos=0, retain=False)
    
    # Subscribing on the topic , 
    client.on_message = on_message
    client.on_subscribe = on_subscribe 
    client.subscribe("devices/{device_id}/messages/devicebound/#".format(device_id=device_id))
    client.subscribe("$iothub/twin/PATCH/properties/desired/#")
    client.subscribe("$iothub/methods/POST/#")
    
    client.loop_forever()
    

    更新:

    可以使用Device Explorer工具生成特定设备的sas_token,参见下面的屏幕sn-p:

    并且输出日志应该看起来像下面的屏幕 sn-p:

    【讨论】:

    • 我刚刚运行了我的代码,并对我发现的差异进行了所有调整。我现在得到:“连接失败。连接被拒绝,服务器不可用。错误代码= 3”。如果您的代码真的有效,我看到的唯一区别是在 SAS 中。我使用 DeviceExplorer 生成了我的。你是如何产生你的?我的形式是:SharedAccessSignature sr=myIotHub-IoTHub.azure-devices.net&sig=****%2Fxxxxxxxxxxx%3D&se=1595980678 所以,我确实看到了格式上的差异,而不仅仅是内容......
    • 查看我的更新。您似乎没有为设备生成 sas_token。
    • 因此,您指出的 SAS 方法在我设法连接到 Azure 时有效。我在 DeviceExplorer 中生成的 SAS 在格式上仍然与您的不同(但我可以接受 ;-)
    • 我的下一个任务是连接到 AWS IoT 工作,这几天我一直在苦苦挣扎......
    • 查看此文档以生成 sas 令牌:docs.microsoft.com/en-us/azure/iot-hub/…,还有一个 Cloud Explorer 工具
    【解决方案2】:

    当您使用 MQTT 直接连接 Azure IoT Hub 时,您需要通过 TLS/SSL 进行连接。为了建立 TLS 连接,您可能需要下载并引用 DigiCert Baltimore 根证书,然后为 TLS/SSL 连接设置证书。请参阅文档Communicate with your IoT hub using the MQTT protocol

    client.tls_set(ca_certs=path_to_root_cert, certfile=None, keyfile=None,
                   cert_reqs=ssl.CERT_REQUIRED, tls_version=ssl.PROTOCOL_TLSv1, ciphers=None)
    client.tls_insecure_set(False)
    

    【讨论】:

    • 我很难处理你有争议的文件。您所指的同一文档(您论坛上的其他团队成员也这么说)说:“如果您使用 X.509 证书身份验证,则不需要 SAS 令牌密码。有关详细信息,请参阅设置 X。 Azure IoT Hub 中的 509 安全性”。顺便说一句,假设你是对的:我过去也尝试过这种方法 - 使用证书和密码 - 无济于事......如果你愿意,我可以发布整个源代码。
    • 好吧,我不是科学家,但我确实遵循系统的方法,所以我回到使用您建议的方法的脚本版本并在没有更改的情况下运行它:......并且奇迹般地 -有效!所以,我很抱歉咆哮,但你仍然需要清理你当时非常混乱的文档......
    • 我必须纠正自己 - 成功的代码是使用 SAS 方法的代码。在此代码中,我删除了对证书的所有引用。因此,我的第一点是正确的——在 SAS 方法中不需要证书。我不确定反之亦然是否正确 - 使用证书是否需要密码......这将是我的下一步......
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多