timmy ревизий этого фрагмента 10 months ago. К ревизии
2 files changed, 0 insertions, 0 deletions
gistfile1.txt переименован в environment_db_setup.sql
Файл переименован без изменений
gistfile2.txt переименован в sensor_monitor_supervisor.conf
Файл переименован без изменений
timmy ревизий этого фрагмента 10 months ago. К ревизии
Без изменений
timmy ревизий этого фрагмента 1 year ago. К ревизии
3 files changed, 106 insertions
gistfile1.txt(файл создан)
| @@ -0,0 +1,10 @@ | |||
| 1 | + | CREATE DATABASE environment; | |
| 2 | + | ||
| 3 | + | USE environment; | |
| 4 | + | ||
| 5 | + | CREATE TABLE environment_data ( | |
| 6 | + | id INT AUTO_INCREMENT PRIMARY KEY, | |
| 7 | + | humidity FLOAT NOT NULL, | |
| 8 | + | temperature FLOAT NOT NULL, | |
| 9 | + | recorded_at DATETIME DEFAULT CURRENT_TIMESTAMP | |
| 10 | + | ); | |
gistfile2.txt(файл создан)
| @@ -0,0 +1,7 @@ | |||
| 1 | + | [program:sensor_monitor] | |
| 2 | + | command=/usr/bin/python3 /path/to/sensor_monitor.py | |
| 3 | + | directory=/path/to/ | |
| 4 | + | autostart=true | |
| 5 | + | autorestart=true | |
| 6 | + | redirect_stderr=true | |
| 7 | + | stdout_logfile=/path/to/sensor_monitor.log | |
sensor_monitor.py(файл создан)
| @@ -0,0 +1,89 @@ | |||
| 1 | + | import Adafruit_DHT | |
| 2 | + | import schedule | |
| 3 | + | import time | |
| 4 | + | from gpiozero import LED | |
| 5 | + | import pymysql.cursors | |
| 6 | + | from datetime import datetime | |
| 7 | + | import os | |
| 8 | + | import logging | |
| 9 | + | ||
| 10 | + | # 日誌設定 | |
| 11 | + | logging.basicConfig(level=logging.INFO, filename='sensor.log', | |
| 12 | + | format='%(asctime)s - %(levelname)s - %(message)s') | |
| 13 | + | ||
| 14 | + | # 資料庫設定 | |
| 15 | + | DB_HOST = os.getenv('DB_HOST', '127.0.0.1') # 預設為本地端 | |
| 16 | + | DB_USER = os.getenv('DB_USER', 'db_user') # 資料庫使用者名稱 | |
| 17 | + | DB_PASSWORD = os.getenv('DB_PASSWORD', 'db_password') # 資料庫密碼 | |
| 18 | + | DB_NAME = os.getenv('DB_NAME', 'environment') # 資料庫名稱 | |
| 19 | + | ||
| 20 | + | # LED 腳位設定 | |
| 21 | + | green_led = LED(17) # 綠燈 | |
| 22 | + | yellow_led = LED(27) # 黃燈 | |
| 23 | + | red_led = LED(22) # 紅燈 | |
| 24 | + | ||
| 25 | + | # DHT11 感測器設定 | |
| 26 | + | sensor = Adafruit_DHT.DHT11 # 感測器型號 | |
| 27 | + | pin = 4 # 感測器連接的 GPIO 腳位 | |
| 28 | + | ||
| 29 | + | ||
| 30 | + | # LED 控制函數 | |
| 31 | + | def control_leds(temp): | |
| 32 | + | green_led.on() if temp < 25.0 else green_led.off() | |
| 33 | + | yellow_led.on() if 25.0 <= temp < 30.0 else yellow_led.off() | |
| 34 | + | red_led.on() if temp >= 30.0 else red_led.off() | |
| 35 | + | ||
| 36 | + | ||
| 37 | + | # 定時執行的核心任務 | |
| 38 | + | def job(): | |
| 39 | + | try: | |
| 40 | + | # 讀取感測器數據 | |
| 41 | + | humidity, temperature = Adafruit_DHT.read_retry(sensor, pin) | |
| 42 | + | now = datetime.now().strftime("%Y-%m-%d %H:%M:%S") | |
| 43 | + | ||
| 44 | + | if humidity is not None and temperature is not None: | |
| 45 | + | logging.info(f"{now} - Temp: {temperature:.1f}°C, Humidity: {humidity:.1f}%") | |
| 46 | + | ||
| 47 | + | # 儲存數據到資料庫 | |
| 48 | + | try: | |
| 49 | + | connection = pymysql.connect( | |
| 50 | + | host=DB_HOST, | |
| 51 | + | user=DB_USER, | |
| 52 | + | password=DB_PASSWORD, | |
| 53 | + | db=DB_NAME, | |
| 54 | + | charset='utf8mb4', | |
| 55 | + | cursorclass=pymysql.cursors.DictCursor | |
| 56 | + | ) | |
| 57 | + | ||
| 58 | + | with connection.cursor() as cursor: | |
| 59 | + | sql = "INSERT INTO environment_data (humidity, temperature) VALUES (%s, %s)" | |
| 60 | + | cursor.execute(sql, (humidity, temperature)) | |
| 61 | + | connection.commit() | |
| 62 | + | ||
| 63 | + | except Exception as db_err: | |
| 64 | + | logging.error(f"資料庫連線錯誤: {db_err}") | |
| 65 | + | finally: | |
| 66 | + | if 'connection' in locals(): | |
| 67 | + | connection.close() | |
| 68 | + | ||
| 69 | + | # 控制 LED | |
| 70 | + | control_leds(temperature) | |
| 71 | + | else: | |
| 72 | + | logging.warning("感測器讀取失敗,無法取得數據") | |
| 73 | + | ||
| 74 | + | except Exception as e: | |
| 75 | + | logging.error(f"執行任務時發生錯誤: {e}") | |
| 76 | + | ||
| 77 | + | ||
| 78 | + | # 排程設定,每 5 分鐘執行一次 | |
| 79 | + | schedule.every(300).seconds.do(job) | |
| 80 | + | ||
| 81 | + | try: | |
| 82 | + | while True: | |
| 83 | + | schedule.run_pending() | |
| 84 | + | time.sleep(1) | |
| 85 | + | except KeyboardInterrupt: | |
| 86 | + | logging.info("程式已被使用者中斷") | |
| 87 | + | green_led.off() | |
| 88 | + | yellow_led.off() | |
| 89 | + | red_led.off() | |