閒來無事-控制樹莓派風扇啟停

2023-06-24 18:00:45

扯淡時間

端午放假,本想註冊個美團眾包騎自行車送外賣體驗一下生活,奈何這幾天北京熱的要死,只能作罷,還是苟在屋裡空調續命吧。
無事幹的時候,想著給我花盆監控升個級,換個電容的土壤檢測(之前的腐蝕了gg了)但是電容的是3v的,esp8266只能檢測1v的,所以買了一個新的esp32-cam,正好帶個攝像頭,間隔5分鐘拍個照片,一天下來還能拼接一個延時攝影的效果,奈何這個板子有點毛病,跑不起來,如下圖(商家也無法解決)

無奈退貨,想著下雨天打孩子,閒著也是閒著,這條路走不通了,換個其他的玩玩了。
我的樹莓派有個風扇,成天在轉,給他加一個控制,超出設定的溫度再啟動,最好在給個頁面去控制一下,開搞
還有就是這個樹莓派我買的時候400,我靠這玩意還漲價了,無語了,當時400我都覺得貴,還不如買個微控制器30塊就能玩

思路

  1. 裝置控制-遠端控制啟停
  2. 後臺定時任務-定時記錄溫度,根據設定的溫度控制風扇啟停
  3. 服務處理請求-展示溫度曲線

思路有了就開幹

裝置控制

裝置控制主要就是:1. 展示資料 2. 傳送裝置控制指令

寫個vue的頁面,用腦子設計一下:開關按鈕得有,溫度設定得有,還得有個圖表,還得加個篩選時間,根據時間來篩選資料。就醬式的吧

程式碼如下(太多了給個連結吧)

https://github.com/dadademo/piFan/blob/main/fanUi/src/components/home.vue

後臺定時任務

後臺定時任務:1. 定時讀取任務,根據設定的溫度決定是否開/關風扇 2. 定時記錄資訊,將資訊存在資料裡面

這些服務本來想用node寫,奈何node操作gpio的庫一直不能下載,只能用python來搞了
注意這個程式碼我是直接複製的,依賴一些我寫的其他的python指令碼,如果想跑起來的話還直接拉全部程式碼去看吧

程式碼如下


# 使用內建的signal庫捕獲Ctrl+C
import signal
# 風扇模組
import controlFan
# 退出程式
import sys
# 參照db模組
import db
import time


# 開始時間
beginTimeHour = 7
# 結束時間
endTimeHour = 20

# 每隔5分鐘判斷一次溫度
timeOut = 60*5



# 程式停止
def stop():
    # 停止gpio操作
    controlFan.quit()
    # 退出程式
    sys.exit()

controlFan.init_gpio()

# 監聽Ctr+C
signal.signal(signal.SIGINT, stop)
while True:
    # 0/1 當前風扇狀態
    fanStatus = 0
    # 設定狀態,預設40度
    setTemp = 0
    # 獲取狀態
    lastData = db.getLastData()
    fanStatus =  lastData.get('fanStatus')
    setTemp = lastData.get('setTemp')

    # 獲取當前溫度
    currentTemp = controlFan.read_cpu_temperature()
    # 時間
    currentTime = time.localtime()
    dt = time.strftime('%Y:%m:%d %H:%M:%S', currentTime)
    print(dt)
    # 當前溫度大於設定溫度
    ctrlVal = currentTemp > setTemp
    # 判斷邏輯
    if ctrlVal:
        fanStatus = 1
    else:
        fanStatus = 0
    # 初始化後追加狀態
    db.addInfo(fanStatus, currentTemp, setTemp)
    if ctrlVal:
        # 夜間模式
        if currentTime.tm_hour < beginTimeHour and currentTime.tm_hour > endTimeHour:
            controlFan.set_fan(False)
        else:
            controlFan.set_fan(True)
    else:
        controlFan.set_fan(False)
    time.sleep(timeOut)

服務處理請求

這裡就是用python啟動一個服務,接收網頁傳送的請求,例如設定溫度,還有啟停的製冷

程式碼如下

# 匯入http.server模組
import http.server
import socketserver

# json物件
import json

# 引數解析
from urllib.parse import urlparse, parse_qs, parse_qsl

import db
import controlFan

# 定義埠號
HTTP_PORT = 3001

# 獲取query資訊並轉為obj


def getQureyData(url):
    retObj = {}
    currentQuery = parse_qs(urlparse(url).query)
    for key in currentQuery:
        if len(currentQuery[key]) == 1:
            retObj[key] = currentQuery[key][0]
        else:
            retObj[key] = currentQuery[key]
    return retObj


# 處理相應
class httpResponse(http.server.SimpleHTTPRequestHandler):
    # 處理get請求
    def do_GET(self):
        # 當前存取的連結決定
        currentUrl = urlparse(self.path).path
        print(currentUrl)
        if currentUrl == '/getFan':
            self.send_response(200)
            self.send_header('Content-type', 'application/json')
            self.end_headers()
            # 讀取資訊
            query = getQureyData(self.path)
            jsonInfo = db.getInfo(
                query.get('startTimestamp'), query.get('endTimestamp'), query.get('pageIndex'), query.get('pageSize'), query.get('all'))

            retStr = json.dumps(jsonInfo)
            self.wfile.write(bytes(retStr, "utf8"))

        if currentUrl == '/getLast':
            self.send_response(200)
            self.send_header('Content-type', 'application/json')
            self.end_headers()
            jsonInfo = db.getLastData()
            retStr = json.dumps(jsonInfo)
            self.wfile.write(bytes(retStr, "utf8"))
        return

    # 處理post請求
    def do_POST(self):
        # 獲取POST請求的資料
        currentUrl = urlparse(self.path).path
        if currentUrl == '/setFan':
            self.send_response(200)
            self.send_header('Content-type', 'application/json')
            self.end_headers()
            # 當前資訊
            query = getQureyData(self.path)
            # 獲取最後的資訊
            lastData = db.getLastData()
            fanStatus = int(query.get('fanStatus')
                            or lastData.get('fanStatus'))
            setTemp = int(query.get('setTemp') or lastData.get('setTemp'))
            print(fanStatus, fanStatus == 1)
            # 寫入狀態
            db.addInfo(fanStatus, controlFan.read_cpu_temperature(), setTemp)

            if fanStatus == 1:
                controlFan.set_fan(True)
            else:
                controlFan.set_fan(False)

            self.wfile.write(bytes("{status:200}", "utf8"))
        return


# 啟動http服務
def beginServer():
    with socketserver.TCPServer(("", HTTP_PORT), httpResponse) as httpd:
        print("serving at port", HTTP_PORT)
        httpd.serve_forever()

controlFan.init_gpio()
# 開啟服務
beginServer()

程式碼地址:https://github.com/dadademo/piFan

最後放一張效果圖