detect_dht11.py 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. #!/usr/bin/env python3
  2. """
  3. DHT11 GPIO 自动探测脚本
  4. 在目标板子上运行,自动尝试多个候选 GPIO line,找到能成功读取 DHT11 的 pin。
  5. 探测成功后输出 JSON,供部署脚本读取并写入环境变量配置。
  6. """
  7. import os
  8. import sys
  9. import json
  10. import time
  11. # 把 backend 目录加入路径,以便复用 dht11_sensor 模块
  12. SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
  13. BACKEND_DIR = os.path.dirname(SCRIPT_DIR)
  14. sys.path.insert(0, BACKEND_DIR)
  15. from modules.dht11_sensor import DHT11Sensor
  16. # 候选 GPIO line 编号:RK3562 GPIO0_C3_d 对应 gpiochip0 line 19。
  17. # 如需扫描更多,可通过环境变量 DHT11_GPIO_PIN 指定一个或多个(逗号分隔)。
  18. DEFAULT_CANDIDATES = [19]
  19. def detect(gpio_pin=None, gpio_chip='gpiochip0', max_attempts=3, simulate=False):
  20. """
  21. 探测 DHT11 传感器。
  22. 如果 gpio_pin 给出,只尝试该 pin;否则扫描 DEFAULT_CANDIDATES。
  23. 返回 (pin, temperature, humidity) 或 None。
  24. simulate=True 用于无硬件环境测试脚本流程。
  25. """
  26. if simulate:
  27. sensor = DHT11Sensor(gpio_pin=gpio_pin or 0, gpio_chip=gpio_chip, simulate=True)
  28. temp, hum = sensor._read_simulated()
  29. return {
  30. 'gpio_pin': int(gpio_pin) if gpio_pin else 0,
  31. 'gpio_chip': gpio_chip,
  32. 'temperature': temp,
  33. 'humidity': hum,
  34. 'success': True
  35. }
  36. if gpio_pin:
  37. # 支持逗号分隔的多个候选,例如 "2,64,72"
  38. candidates = [int(p.strip()) for p in str(gpio_pin).split(',')]
  39. else:
  40. candidates = DEFAULT_CANDIDATES
  41. for pin in candidates:
  42. sensor = DHT11Sensor(gpio_pin=pin, gpio_chip=gpio_chip, simulate=False)
  43. for attempt in range(max_attempts):
  44. try:
  45. temp, hum = sensor._read_real()
  46. if temp is not None and hum is not None:
  47. return {
  48. 'gpio_pin': pin,
  49. 'gpio_chip': gpio_chip,
  50. 'temperature': temp,
  51. 'humidity': hum,
  52. 'success': True
  53. }
  54. except Exception as e:
  55. print(f" 探测 GPIO {pin} 失败: {e}", file=sys.stderr)
  56. time.sleep(2.5) # DHT11 两次读取间隔需 >2s
  57. return None
  58. def main():
  59. pin_env = os.getenv('DHT11_GPIO_PIN')
  60. chip_env = os.getenv('DHT11_GPIO_CHIP', 'gpiochip0')
  61. simulate = os.getenv('DHT11_SIMULATE', 'false').lower() in ('1', 'true', 'yes')
  62. print(f"开始探测 DHT11 (chip={chip_env}, simulate={simulate})...", file=sys.stderr)
  63. if pin_env:
  64. print(f"用户指定优先探测 GPIO: {pin_env}", file=sys.stderr)
  65. result = detect(gpio_pin=pin_env, gpio_chip=chip_env, simulate=simulate)
  66. if result:
  67. # 同时输出机器可读行和 JSON,方便部署脚本解析
  68. print(
  69. f"DHT11_OK pin={result['gpio_pin']} chip={result['gpio_chip']} "
  70. f"temp={result['temperature']} hum={result['humidity']}"
  71. )
  72. print(json.dumps(result, ensure_ascii=False))
  73. print(
  74. f"探测成功: GPIO pin={result['gpio_pin']}, "
  75. f"温度={result['temperature']}°C, 湿度={result['humidity']}%",
  76. file=sys.stderr
  77. )
  78. sys.exit(0)
  79. else:
  80. print("DHT11_FAIL")
  81. error = {
  82. 'success': False,
  83. 'error': '未能在任何候选 GPIO 上读取到 DHT11,请检查接线或手动指定 DHT11_GPIO_PIN',
  84. 'candidates': DEFAULT_CANDIDATES if not pin_env else [int(pin_env)]
  85. }
  86. print(json.dumps(error, ensure_ascii=False))
  87. sys.exit(1)
  88. if __name__ == '__main__':
  89. main()