树莓派通过Socket发送DHT11温湿度数据报TypeError错误解决方案咨询
报错根因
client_socket.send()方法仅接收字节类型参数,传入的result是dht11库自定义的DHT11Result类对象,无法直接传输。
需要调整的内容
1. 数据格式化转字节
从result中提取温湿度、采集时间等有效字段,拼接为结构化字符串后调用encode()方法转成字节再发送,推荐使用sendall()替代send(),避免数据量较大时传输不完整:
# 将原代码中的 client_socket.send(result) 替换为以下内容 data_str = f"{datetime.datetime.now()},{result.temperature:.1f},{result.humidity:.1f}" client_socket.sendall(data_str.encode('utf-8'))
字符串使用逗号分隔字段的格式,也方便PC端接收后直接拆分解析。
2. 增加连接异常处理
原代码在PC端主动断开连接时会直接崩溃,需要捕获连接相关异常,断开后自动等待新的连接:
try: client_socket.sendall(data_str.encode('utf-8')) except (BrokenPipeError, ConnectionResetError): print("客户端断开连接,等待重连...") client_socket.close() client_socket, addr = server_socket.accept() print('新连接建立:', addr)
3. DHT11读取容错优化
DHT11本身读取成功率不高,原代码仅在读取成功时才会执行延迟,读取失败时会进入空循环占满CPU,需要将延迟逻辑移到读取判断的外部:
if result.is_valid(): # 原有打印、发送逻辑 time.sleep(6) # 不管读取是否成功都执行延迟
4. 资源释放逻辑完善
原代码仅在键盘中断时才会清理资源,如果运行过程中出现其他异常退出,GPIO、socket资源可能无法正常释放,需要用finally块兜底处理:
except KeyboardInterrupt: print("程序退出") finally: GPIO.cleanup() if 'client_socket' in locals(): client_socket.close() if 'server_socket' in locals(): server_socket.close()
完整修改后代码
import RPi.GPIO as GPIO import dht11 import time import datetime import socket GPIO.setwarnings(True) GPIO.setmode(GPIO.BCM) instance = dht11.DHT11(pin=18) HOST = '192.168.35.129' PORT = 9999 server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) server_socket.bind((HOST, PORT)) server_socket.listen() print("等待客户端连接...") client_socket, addr = server_socket.accept() print('已连接设备:', addr) try: while True: result = instance.read() if result.is_valid(): print("最后有效采集时间:" + str(datetime.datetime.now())) print("温度:%-3.1f C" % result.temperature) print("湿度:%-3.1f %%" % result.humidity) # 格式化数据并发送 data_str = f"{datetime.datetime.now()},{result.temperature:.1f},{result.humidity:.1f}" try: client_socket.sendall(data_str.encode('utf-8')) except (BrokenPipeError, ConnectionResetError): print("客户端断开,等待重连...") client_socket.close() client_socket, addr = server_socket.accept() print('新连接建立:', addr) time.sleep(6) except KeyboardInterrupt: print("程序退出,清理资源") finally: GPIO.cleanup() if 'client_socket' in locals(): client_socket.close() if 'server_socket' in locals(): server_socket.close()
内容的提问来源于stack exchange,提问作者user17135507
相关产品推荐
相关产品推荐

