如何用Python更新Azure IoT Hub设备孪生?SSL错误及参数问题排查
我尝试使用Python更新Azure IoT Hub中NodeMCU设备的设备孪生属性,但因SSL错误无法完成操作。同时尝试设置connection_verify=False绕过验证时,该参数报错,求解决方法。
我的代码
from azure.iot.hub import IoTHubRegistryManager import certifi import ssl # Connect to IoT Hub and send message to device CONNECTION_STRING = "HostName=iothub-jein02-np-eas-ua-eztr01.azure-devices.net;SharedAccessKeyName=service;SharedAccessKey=Mmjc..." DEVICE_ID = "NodeMCU" '''first used this method''' #ca_cert_path = "D:/new/cacert.pem" '''later used this method''' # Set the CA certificates globally ssl_context = ssl.create_default_context(cafile=certifi.where()) try: # Create IoTHubRegistryManager registry_manager = IoTHubRegistryManager.from_connection_string(CONNECTION_STRING, connection_verify = False) # Update the desired properties twin = registry_manager.update_twin(DEVICE_ID, { "properties": { "desired": { "temp": "100" } } }) except Exception as ex: print(f"Error sending message to device: {str(ex)}") raise
报错信息
msrest.exceptions.ClientRequestError: Error occurred in request., SSLError: HTTPSConnectionPool(host='iothub-jein02-np-eas-ua-eztr01.azure-devices.net', port=443): Max retries exceeded with url: /twins/NodeMCU?api-version=2021-04-12 (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:997)')))
解决方法
1. 修正connection_verify参数的错误
IoTHubRegistryManager.from_connection_string方法不支持connection_verify参数,要控制证书验证,需要通过自定义HTTP客户端或全局SSL上下文实现。
2. 解决SSL证书验证失败问题
方法1:配置正确的CA证书(推荐生产环境使用)
Azure IoT Hub使用Baltimore CyberTrust Root证书,你可以直接使用certifi提供的证书集合,修改代码如下:
from azure.iot.hub import IoTHubRegistryManager from azure.core.pipeline.transport import RequestsTransport import certifi CONNECTION_STRING = "你的连接字符串" DEVICE_ID = "NodeMCU" # 配置使用certifi的CA证书 transport = RequestsTransport(verify=certifi.where()) try: registry_manager = IoTHubRegistryManager.from_connection_string(CONNECTION_STRING, transport=transport) # 更新设备孪生属性 twin = registry_manager.update_twin(DEVICE_ID, { "properties": { "desired": { "temp": "100" } } }) print("设备孪生更新成功") except Exception as ex: print(f"错误: {str(ex)}") raise
方法2:临时禁用证书验证(仅测试环境)
如果是测试环境,可通过修改全局SSL上下文跳过验证,注意这会带来安全风险:
from azure.iot.hub import IoTHubRegistryManager import ssl CONNECTION_STRING = "你的连接字符串" DEVICE_ID = "NodeMCU" # 全局禁用SSL证书验证 ssl._create_default_https_context = ssl._create_unverified_context try: registry_manager = IoTHubRegistryManager.from_connection_string(CONNECTION_STRING) twin = registry_manager.update_twin(DEVICE_ID, { "properties": { "desired": { "temp": "100" } } }) print("设备孪生更新成功") except Exception as ex: print(f"错误: {str(ex)}") raise
内容的提问来源于stack exchange,提问作者sai

