Azure IoT Hub - "订阅"代码无效:"连接被拒绝"

时间:2018-05-18 19:08:22

标签: azure iot publish-subscribe azure-iot-hub subscribe

我正在尝试接收"通知"当一些数据发布到MQTT主题devices/device_id/messages/events/时,来自IoT Hub。要接收数据,我使用以下主题:devices/device_id/messages/devicebound/。我的订阅代码如下(Python):

import paho.mqtt.client as mqtt
import ssl, random
from time import sleep

root_ca = "./certs/digicertbaltimoreroot.pem"
public_crt = './certs/rsa_cert.pem'
private_key = './certs/rsa_private.pem'

iothub_name = "myhub"
device_id = "mydevice"
mqtt_url = "{}.azure-devices.net".format(iothub_name)
mqtt_port = 8883
topic = "devices/{}/messages/devicebound/#".format(device_id)

def error_str(rc):
    return "Some error occurred. {}: {}".format(rc, mqtt.error_string(rc))

def on_disconnect(unused_client, unused_userdata, rc):
    print("on_disconnect", error_str(rc))

def on_connect(client, userdata, flags, response_code):
    print("Connected with status: {0}".format(response_code))
    client.subscribe(topic, 1)

def on_subscribe(client, userdata, mid, granted_qos):
    print("Subscribed: "+str(mid)+" "+str(granted_qos))

def on_message(client, userdata, msg):
    print("Topic: {0} -- Payload: {1}".format(msg.topic, str(msg.payload)))

if __name__ == "__main__":    
    client = mqtt.Client(device_id, protocol=mqtt.MQTTv311)

    client.tls_set(root_ca,
                   certfile = public_crt,
                   keyfile = private_key,
                   cert_reqs = ssl.CERT_REQUIRED,
                   tls_version = ssl.PROTOCOL_TLSv1_2,
                   ciphers = None)

    client.on_connect = on_connect
    client.on_message = on_message
    client.on_disconnect = on_disconnect

    print("Connecting to Azure IoT Hub...")
    client.connect(mqtt_url, mqtt_port, keepalive=60)
    client.loop_forever()

当我跑步时,我得到以下输出:

  

连接到Azure IoT Hub ...
  连接状态:3
  (' on_disconnect','发生了一些错误.5:连接被拒绝。')
  连接状态:3
  (' on_disconnect','发生了一些错误.5:连接遭到拒绝。')

任何人都可以建议我缺少什么吗?

2 个答案:

答案 0 :(得分:1)

根据文档"Using the MQTT protocol directly",您需要

  

下载并参考DigiCert Baltimore Root Certificate。此证书是Azure用于保护连接的证书。

正如您在发布过程中所做的那样:

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.username_pw_set(username=iot_hub_name+".azure-devices.net/" + device_id, password=sas_token)

最后,您可以订阅,如下所示:

client.subscribe(topic=topic, qos=0)

安全密钥验证设备的示例代码:

import paho.mqtt.client as mqtt
import ssl, random
from time import sleep

path_to_root_cert = "./certs/digicertbaltimoreroot.cer"

iothub_name = "your hub name"
device_id = "device1"
sas_token = "SharedAccessSignature sr=[your hub name].azure-devices.net%2Fdevices%2Fdevice1&sig=[sig]&se=1526955728"
mqtt_url = "{}.azure-devices.net".format(iothub_name)
mqtt_port = 8883
topic = "devices/{}/messages/devicebound/#".format(device_id)

def error_str(rc):
    return "Some error occurred. {}: {}".format(rc, mqtt.error_string(rc))

def on_disconnect(unused_client, unused_userdata, rc):
    print("on_disconnect", error_str(rc))

def on_connect(client, userdata, flags, response_code):
    print("Connected with status: {0}".format(response_code))
    client.subscribe(topic, 1)

def on_subscribe(client, userdata, mid, granted_qos):
    print("Subscribed: "+str(mid)+" "+str(granted_qos))

def on_message(client, userdata, msg):
    print("Topic: {0} -- Payload: {1}".format(msg.topic, str(msg.payload)))

if __name__ == "__main__":    
    client = mqtt.Client(device_id, protocol=mqtt.MQTTv311)

    client.username_pw_set(username=iothub_name+".azure-devices.net/" + device_id, password=sas_token)

    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.on_connect = on_connect
    client.on_message = on_message
    client.on_disconnect = on_disconnect


    print("Connecting to Azure IoT Hub...")
    client.connect(mqtt_url, mqtt_port, keepalive=60)
    client.subscribe(topic=topic, qos=0)
    client.loop_forever()

x509经过身份验证的设备的示例代码: (需要提供设备证书和私钥文件。不需要SAS令牌作为密码;只需将其留空。但仍需要设置用户名。)

import paho.mqtt.client as mqtt
import ssl, random
from time import sleep

root_ca = "./certs/digicertbaltimoreroot.cer"
public_crt = './certs/mydevice-public.pem'
private_key = './certs/mydevice-private.pem'

iothub_name = "your hub name"
device_id = "mydevice"
mqtt_url = "{}.azure-devices.net".format(iothub_name)
mqtt_port = 8883
topic = "devices/{}/messages/devicebound/#".format(device_id)

def error_str(rc):
    return "Some error occurred. {}: {}".format(rc, mqtt.error_string(rc))

def on_disconnect(unused_client, unused_userdata, rc):
    print("on_disconnect", error_str(rc))

def on_connect(client, userdata, flags, response_code):
    print("Connected with status: {0}".format(response_code))
    client.subscribe(topic, 1)

def on_subscribe(client, userdata, mid, granted_qos):
    print("Subscribed: "+str(mid)+" "+str(granted_qos))

def on_message(client, userdata, msg):
    print("Topic: {0} -- Payload: {1}".format(msg.topic, str(msg.payload)))

if __name__ == "__main__":    
    client = mqtt.Client(device_id, protocol=mqtt.MQTTv311)

    client.on_connect = on_connect
    client.on_message = on_message
    client.on_disconnect = on_disconnect

    client.username_pw_set(username=iothub_name+".azure-devices.net/" + device_id, password="")

    client.tls_set(root_ca,
                   certfile = public_crt,
                   keyfile = private_key,
                   cert_reqs = ssl.CERT_REQUIRED,
                   tls_version = ssl.PROTOCOL_TLSv1_2,
                   ciphers = None)
    client.tls_insecure_set(False)


    print("Connecting to Azure IoT Hub...")
    client.connect(mqtt_url, mqtt_port, keepalive=60)
    client.subscribe(topic=topic, qos=0)
    client.loop_forever()

注意:主题为" devices / {device-id} / messages / devicebound / "。

如何创建设备证书文件,您可以参考here

更新:这些示例代码用于接收您可以发送的D2C messages,以便进行简单测试:

来自device explorer

enter image description here

来自azure portal:

enter image description here

Upate:接收D2C消息:

正如我在评论中指出的,Azure IoT Hub不是通用的MQTT brober,因此您无法直接订阅从设备发送的消息。 要解决此问题,您可以使用IoT Hub公开的与事件中心兼容的端点,例如" Read the telemetry from your hub "部分呢。但不幸的是,Python并不支持这种方式。您可以使用iothub-explorer CLI实用程序或创建基于Node.js.NETJava事件集线器的控制台应用程序来读取来自IoT Hub的设备到云消息。

答案 1 :(得分:0)

由于丽塔已经提到当前在设备端不支持D2C消息。

Azure IoT中心是物联网解决方案中的云门方式,如下图所示: enter image description here

Azure IoT中心根据endpoints为支持的解决方案和设备端提供服务。目前,它提供device to cloud feature D2C消息 Device Twin的报告属性文件上传。从云端,我们可以使用cloud to device feature直接方法, Twin的所需属性云端设备消息

  

当我将一些数据发布到MQTT主题设备/ device_id / messages / events /

时,我试图从IoT Hub接收“通知”

这取决于您希望接收消息的那一方。目前,Azure IoT中心支持两种方案。

  1. 在设备端发送Device-to-Cloud消息,并在云后端解决方案上接收消息(D2C消息仅支持AMQP协议)

  2. 在云后端解决方案上发送可以设备的消息,并在设备端接收消息。

    如果您对Azure IoT Hub有任何想法或反馈,可以通过Azure IoT Hub - user voice提交。