ESP8266使用Micropython urllib访问HTTPS报OSError:-40如何解决
问题原因
- OSError -40在Micropython网络栈中对应MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE,即SSL/TLS握手失败。可正常运行的URL为HTTP协议,报错的为HTTPS协议,核心原因是ESP8266的Micropython固件对TLS版本、加密套件的支持能力有限,目标HTTPS站点使用了ESP8266默认不支持的高版本TLS协议或加密套件。
- ESP8266可用RAM仅几十KB,urequest默认处理HTTPS请求时,如果服务器返回的证书过大、握手阶段交互数据量超过内存上限,也会触发该报错。
- 部分HTTPS站点要求SNI(Server Name Indication)扩展,旧版本的ESP8266 Micropython的urequest默认未开启SNI支持,会导致握手被服务器主动拒绝。
解决方案
- 方案1:升级到最新版的ESP8266 Micropython固件,新版固件已默认开启SNI支持,同时优化了TLS握手的内存占用,适配更多常用加密套件。
- 方案2:改用手动调用
socket+ssl模块的方式发起请求,显式配置TLS参数适配站点要求,非敏感场景下可关闭证书校验降低资源占用,示例代码如下:
import socket import ssl import json # 解析域名与请求路径 host = "dashboard.elering.ee" path = "/api/nps/price?start=2021-12-01T21%3A00%3A00.000Z&end=2021-12-02T20%3A00%3A00.000Z" addr = socket.getaddrinfo(host, 443)[0][-1] # 建立基础socket连接 s = socket.socket() s.connect(addr) # 包装SSL层,指定SNI、关闭证书校验 s = ssl.wrap_socket(s, server_hostname=host, cert_reqs=ssl.CERT_NONE) # 发送GET请求 s.write(f"GET {path} HTTP/1.1\r\nHost: {host}\r\nConnection: close\r\n\r\n") # 分段读取响应避免内存溢出 resp = b"" while True: chunk = s.read(1024) if not chunk: break resp += chunk s.close() # 提取响应体中的JSON数据 json_content = resp[resp.find(b"\r\n\r\n")+4:] data = json.loads(json_content) print(data)
- 方案3:可搭建本地HTTP中转服务,由中转服务请求目标HTTPS接口返回数据,ESP8266直接请求该HTTP中转地址,完全避开TLS握手的兼容性和内存问题。
内容的提问来源于stack exchange,提问作者Taimo
相关产品推荐
相关产品推荐

