![](/img/trans.png)
[英]Azure IoT Hub Device x509 Self-Signed Certificate (Python MQTT)
[英]Issues with Azure IoT Hub Python SDK using self-signed x509 Certs where protocol != MQTT_WS
有一些很奇怪的问题,与我的Python脚本,但我可以用包括在他们的Python SDK微软的示例脚本复制它在这里 。
基本上,当我使用MQTT_WS以外的任何方式运行此代码时,它将失败并显示各种错误。 这是代码:(注意,我删除了实际的证书/密钥,因此这对您不起作用)。
# Copyright (c) Microsoft. All rights reserved.
# Licensed under the MIT license. See LICENSE file in the project root for
# full license information.
import random
import time
import sys
import iothub_client
from iothub_client import IoTHubClient, IoTHubClientError, IoTHubTransportProvider, IoTHubClientResult
from iothub_client import IoTHubMessage, IoTHubMessageDispositionResult, IoTHubError
from iothub_client_args import get_iothub_opt, OptionError
# HTTP options
# Because it can poll "after 9 seconds" polls will happen effectively
# at ~10 seconds.
# Note that for scalabilty, the default value of minimumPollingTime
# is 25 minutes. For more information, see:
# https://azure.microsoft.com/documentation/articles/iot-hub-devguide/#messaging
TIMEOUT = 241000
MINIMUM_POLLING_TIME = 9
# messageTimeout - the maximum time in milliseconds until a message times out.
# The timeout period starts at IoTHubClient.send_event_async.
# By default, messages do not expire.
MESSAGE_TIMEOUT = 10000
RECEIVE_CONTEXT = 0
AVG_WIND_SPEED = 10.0
MIN_TEMPERATURE = 20.0
MIN_HUMIDITY = 60.0
MESSAGE_COUNT = 5
RECEIVED_COUNT = 0
# global counters
RECEIVE_CALLBACKS = 0
SEND_CALLBACKS = 0
PROTOCOL = IoTHubTransportProvider.MQTT_WS
# String containing Hostname, Device Id in the format:
# "HostName=<host_name>;DeviceId=<device_id>;x509=true"
CONNECTION_STRING = "HostName=hub.azure-devices.net;DeviceId=device;x509=true"
MSG_TXT = "{\"deviceId\": \"device\",\"windSpeed\": %.2f,\"temperature\": %.2f,\"humidity\": %.2f}"
X509_CERTIFICATE = (
'''-----BEGIN CERTIFICATE-----
MIIFtTCCA52gAwIBAgIBAzANBgkqhkiG9w0BAQsFADA0MTIwMAYDVQQDDClBenVy
...
T4kySzeQghCYqpkF06hER0KXTP8shMZedg==
-----END CERTIFICATE-----'''
)
X509_PRIVATEKEY = (
'''-----BEGIN RSA PRIVATE KEY-----
MIIJKAIBAAKCAgEAnEOzMmctBZke/1kD+5g/soUTucJ28odMTW2RIlfj4kAhT1gW
...
UOBMkQUpHEBNWtBbQIyJbgrb26P1oec7dk5f2xvg7tHjSZLDOZprdEp8gxU=
-----END RSA PRIVATE KEY-----'''
)
# some embedded platforms need certificate information
def receive_message_callback(message, counter):
global RECEIVE_CALLBACKS
message_buffer = message.get_bytearray()
size = len(message_buffer)
print("Received Message [%d]:" % counter)
print(" Data: <<<%s>>> & Size=%d" % (message_buffer[:size].decode('utf-8'), size))
map_properties = message.properties()
key_value_pair = map_properties.get_internals()
print(" Properties: %s" % key_value_pair)
counter += 1
RECEIVE_CALLBACKS += 1
print(" Total calls received: %d" % RECEIVE_CALLBACKS)
return IoTHubMessageDispositionResult.ACCEPTED
def send_confirmation_callback(message, result, user_context):
global SEND_CALLBACKS
print("Confirmation[%d] received for message with result = %s" % (user_context, result))
map_properties = message.properties()
print(" message_id: %s" % message.message_id)
print(" correlation_id: %s" % message.correlation_id)
key_value_pair = map_properties.get_internals()
print(" Properties: %s" % key_value_pair)
SEND_CALLBACKS += 1
print(" Total calls confirmed: %d" % SEND_CALLBACKS)
def iothub_client_init():
# prepare iothub client
client = IoTHubClient(CONNECTION_STRING, PROTOCOL)
# HTTP specific settings
if client.protocol == IoTHubTransportProvider.HTTP:
client.set_option("timeout", TIMEOUT)
client.set_option("MinimumPollingTime", MINIMUM_POLLING_TIME)
# set the time until a message times out
client.set_option("messageTimeout", MESSAGE_TIMEOUT)
# this brings in x509 privateKey and certificate
client.set_option("x509certificate", X509_CERTIFICATE)
client.set_option("x509privatekey", X509_PRIVATEKEY)
# to enable MQTT logging set to 1
if client.protocol == IoTHubTransportProvider.MQTT:
client.set_option("logtrace", 0)
client.set_message_callback(
receive_message_callback, RECEIVE_CONTEXT)
return client
def print_last_message_time(client):
try:
last_message = client.get_last_message_receive_time()
print("Last Message: %s" % time.asctime(time.localtime(last_message)))
print("Actual time : %s" % time.asctime())
except IoTHubClientError as iothub_client_error:
if iothub_client_error.args[0].result == IoTHubClientResult.INDEFINITE_TIME:
print("No message received")
else:
print(iothub_client_error)
def iothub_client_sample_x509_run():
try:
client = iothub_client_init()
while True:
# send a few messages every minute
print("IoTHubClient sending %d messages" % MESSAGE_COUNT)
for message_counter in range(0, MESSAGE_COUNT):
temperature = MIN_TEMPERATURE + (random.random() * 10)
humidity = MIN_HUMIDITY + (random.random() * 20)
msg_txt_formatted = MSG_TXT % (
AVG_WIND_SPEED + (random.random() * 4 + 2),
temperature,
humidity)
# messages can be encoded as string or bytearray
if (message_counter & 1) == 1:
message = IoTHubMessage(bytearray(msg_txt_formatted, 'utf8'))
else:
message = IoTHubMessage(msg_txt_formatted)
# optional: assign ids
message.message_id = "message_%d" % message_counter
message.correlation_id = "correlation_%d" % message_counter
# optional: assign properties
prop_map = message.properties()
prop_map.add("temperatureAlert", 'true' if temperature > 28 else 'false')
client.send_event_async(message, send_confirmation_callback, message_counter)
print(
"IoTHubClient.send_event_async accepted message [%d] for transmission to IoT Hub." % message_counter)
# Wait for Commands or exit
print("IoTHubClient waiting for commands, press Ctrl-C to exit")
status_counter = 0
while status_counter <= MESSAGE_COUNT:
status = client.get_send_status()
print("Send status: %s" % status)
time.sleep(10)
status_counter += 1
except IoTHubError as iothub_error:
print("Unexpected error %s from IoTHub" % iothub_error)
return
except KeyboardInterrupt:
print("IoTHubClient sample stopped")
print_last_message_time(client)
def usage():
print("Usage: iothub_client_sample.py -p <protocol> -c <connectionstring>")
print(" protocol : <amqp, http, mqtt>")
print(" connectionstring: <HostName=<host_name>;DeviceId=<device_id>;SharedAccessKey=<device_key>>")
if __name__ == '__main__':
print("\nPython %s" % sys.version)
# print ( "IoT Hub for Python SDK Version: %s" % iothub_client.__version__ )
try:
(CONNECTION_STRING, PROTOCOL) = get_iothub_opt(sys.argv[1:], CONNECTION_STRING, PROTOCOL)
except OptionError as option_error:
print(option_error)
usage()
sys.exit(1)
print("Starting the IoT Hub Python sample...")
print(" Protocol %s" % PROTOCOL)
print(" Connection string=%s" % CONNECTION_STRING)
iothub_client_sample_x509_run()
成功运行: MQTT_WS(端口443)
IoTHubClient.send_event_async accepted message [0] for transmission to IoT Hub.
Confirmation[0] received for message with result = OK
message_id: message_0
correlation_id: correlation_0
Properties: {'temperatureAlert': 'false'}
Total calls confirmed: 1
运行不成功: MQTT(端口8883)-检索期间消息超时
IoTHubClient.send_event_async accepted message [0] for transmission to IoT Hub.
Confirmation[0] received for message with result = MESSAGE_TIMEOUT
message_id: message_0
correlation_id: correlation_0
Properties: {'temperatureAlert': 'false'}
Total calls confirmed: 1
运行不成功: AMQP(端口5671)-尝试连接时出错,然后出现消息超时
IoTHubClient.send_event_async accepted message [0] for transmission to IoT Hub.
Error: Time:Tue Aug 21 17:14:37 2018 File:C:\Release\iot-sdks-internals\release\python\automation\aziotsdk_pytools\src\c\iothub_client\src\iothubtransport_amqp_common.c Func:on_amqp_connection_state_changed Line:772 amqp_connection was closed unexpectedly; connection retry will be triggered.
Info: Preparing transport for re-connection
Error: Time:Tue Aug 21 17:14:37 2018 File:C:\Release\iot-sdks-internals\release\python\automation\aziotsdk_pytools\src\c\iothub_client\src\iothubtransportamqp_methods.c Func:iothubtransportamqp_methods_unsubscribe Line:891 unsubscribe called while not subscribed
Error: Time:Tue Aug 21 17:14:37 2018 File:C:\Release\iot-sdks-internals\release\python\automation\aziotsdk_pytools\src\c\c-utility\adapters\tlsio_schannel.c Func:send_chunk Line:430 invalid tls_io_instance->tlsio_state: TLSIO_STATE_NOT_OPEN
Error: Time:Tue Aug 21 17:14:37 2018 File:C:\Release\iot-sdks-internals\release\python\automation\aziotsdk_pytools\src\c\c-utility\adapters\tlsio_schannel.c Func:internal_send Line:525 send_chunk failed
Error: Time:Tue Aug 21 17:14:37 2018 File:C:\Release\iot-sdks-internals\release\python\automation\aziotsdk_pytools\src\c\c-utility\adapters\tlsio_schannel.c Func:tlsio_schannel_send Line:1263 send failed
Error: Time:Tue Aug 21 17:14:37 2018 File:C:\Release\iot-sdks-internals\release\python\automation\aziotsdk_pytools\src\c\uamqp\src\connection.c Func:on_bytes_encoded Line:268 Cannot send encoded bytes
Error: Time:Tue Aug 21 17:14:37 2018 File:C:\Release\iot-sdks-internals\release\python\automation\aziotsdk_pytools\src\c\c-utility\adapters\tlsio_schannel.c Func:tlsio_schannel_close Line:1195 invalid tls_io_instance->tlsio_state = TLSIO_STATE_NOT_OPEN
Error: Time:Tue Aug 21 17:14:37 2018 File:C:\Release\iot-sdks-internals\release\python\automation\aziotsdk_pytools\src\c\uamqp\src\connection.c Func:on_bytes_encoded Line:272 xio_close failed
Error: Time:Tue Aug 21 17:14:37 2018 File:C:\Release\iot-sdks-internals\release\python\automation\aziotsdk_pytools\src\c\c-utility\adapters\tlsio_schannel.c Func:tlsio_schannel_close Line:1195 invalid tls_io_instance->tlsio_state = TLSIO_STATE_NOT_OPEN
Error: Time:Tue Aug 21 17:14:37 2018 File:C:\Release\iot-sdks-internals\release\python\automation\aziotsdk_pytools\src\c\uamqp\src\connection.c Func:connection_close Line:1437 xio_close failed
Error: Time:Tue Aug 21 17:14:37 2018 File:C:\Release\iot-sdks-internals\release\python\automation\aziotsdk_pytools\src\c\iothub_client\src\iothubtransport_amqp_common.c Func:on_amqp_connection_state_changed Line:772 amqp_connection was closed unexpectedly; connection retry will be triggered.
Info: Preparing transport for re-connection
Confirmation[0] received for message with result = MESSAGE_TIMEOUT
message_id: message_0
correlation_id: correlation_0
Properties: {'temperatureAlert': 'false'}
Total calls confirmed: 1
运行不成功: AMQP_WS(端口443)-尝试连接时出错,然后出现消息超时
Same as regular AMQP
运行不成功: HTTP(端口443)-尝试连接时出错
IoTHubClient.send_event_async accepted message [0] for transmission to IoT Hub.
Error: Time:Tue Aug 21 17:20:18 2018 File:C:\Release\iot-sdks-internals\release\python\automation\aziotsdk_pytools\src\c\iothub_client\src\iothubtransporthttp.c Func:DoEvent Line:1700 unexpected HTTP status code (401)
Error: Time:Tue Aug 21 17:20:18 2018 File:C:\Release\iot-sdks-internals\release\python\automation\aziotsdk_pytools\src\c\iothub_client\src\iothubtransporthttp.c Func:DoMessages Line:2102 expected status code was 200, but actually was received 401... moving on
IoTHubClient.send_event_async accepted message [4] for transmission to IoT Hub.
Error: Time:Tue Aug 21 17:20:18 2018 File:C:\Release\iot-sdks-internals\release\python\automation\aziotsdk_pytools\src\c\iothub_client\src\iothubtransporthttp.c Func:DoEvent Line:1700 unexpected HTTP status code (401)
我在Windows 10计算机上安装了Python版本3.6.6。
老实说,我不确定是什么导致了此问题。 我不认为这是证书,因为当我将它们与MQTT_WS结合使用时,它们就可以工作。 在测试期间,我尝试短暂禁用Windows上的防火墙,但这也无济于事。
此外,这以前工作。 我构建了一个单独的脚本,该脚本将连接到用户传入的协议,并且我的测试脚本将循环遍历以确保所有功能正常。 我休息了一段时间,努力使这些脚本适用于Mac / Linux。 我遇到了那些平台上的障碍,当我切换回Windows时,意识到它也遇到了同样的问题。 我没有更改Azure Hub上的任何内容以阻止某种类型的连接,因此不确定是什么原因导致了此问题。
我尝试生成新证书并创建新的x509自签名设备,但是它也遇到了相同的问题:(
希望有人可以提供帮助!
编辑:我能够通过为IoTHub创建新证书来解决我的问题。 看来我那里的脚本是用测试脚本生成的,所以只用了30天就可以了。 尽管我不了解MQTT_WS协议如何仍然能够解决并通过它,但这完全是一个单独的问题。
感谢那些试图提供帮助的人!
我正在尝试重现此问题,但是失败了。 使用最新版本的Python SDK,您提到的所有协议HTTP,MQTT,MQTT_WS,AMQP,AMQP_WS对我来说都很好。
为了缩小此问题的范围,建议您创建一个新的Azure IoT中心以查看问题是否与Azure IoT中心的特定实例有关。 您可以为测试目的创建一个免费的。
如果该问题与特定的Azure IoT中心无关,则该问题也可能与网络问题有关。 请检查端口是否未阻塞,如果您在组织环境中工作,可能需要与IT部门确认。 或者,您可以在另一个网络环境中进行测试以确认此问题。
以下是测试步骤,可能也对您有所帮助:
通过PowerShell创建X.509自签名证书
New-SelfSignedCertificate -DnsName“ www.fabrikam.com”,“ www.contoso.com” -CertStoreLocation“ cert:\\ LocalMachine \\ My”
使用下面的命令导出证书和密钥
openssl pkcs12 -in yourpfxfile.pfx -nokeys -out publiccert.pem -nodes
openssl pkcs12 -in x.pfx -nocerts -nodes -pass pass:123456 | openssl rsa -out privkey.pem
在Azure门户上添加X.509自签名证书设备
安装最新的Azure IoT设备SDK
python -m pip安装azure-iothub-device-client
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.