端午放假,本想註冊個美團眾包騎自行車送外賣體驗一下生活,奈何這幾天北京熱的要死,只能作罷,還是苟在屋裡空調續命吧。
無事幹的時候,想著給我花盆監控升個級,換個電容的土壤檢測(之前的腐蝕了gg了
)但是電容的是3v的,esp8266只能檢測1v的,所以買了一個新的esp32-cam,正好帶個攝像頭,間隔5分鐘拍個照片,一天下來還能拼接一個延時攝影的效果,奈何這個板子有點毛病,跑不起來,如下圖(商家也無法解決)
無奈退貨(有大哥知道這個怎麼解決麻煩指導一下小弟
),想著下雨天打孩子,閒著也是閒著,這條路走不通了,換個其他的玩玩了。
我的樹莓派有個風扇,成天在轉,給他加一個控制,超出設定的溫度再啟動,最好在給個頁面去控制一下,開搞
還有就是這個樹莓派我買的時候400,我靠這玩意還漲價了,無語了,當時400我都覺得貴,還不如買個微控制器30塊就能玩
- 裝置控制-遠端控制啟停
- 後臺定時任務-定時記錄溫度,根據設定的溫度控制風扇啟停
- 服務處理請求-展示溫度曲線
- 當前的實現是用python來寫的,我不想每次重啟裝置後都要ssh上去再使用命令列啟動,問了公司大神給了個解決方案:systemctl,可以實現開機自啟,使用方式如下,想了解更多可以看:https://ruanyifeng.com/blog/2016/03/systemd-tutorial-commands.html
當人為了防止程式掛掉,或者我退出以後停了,使用了nohup讓python指令碼一直在後太執行- 如何控制風扇啟停呢?樹莓派上帶了不少Gpio的介面,但是輸出的電流只能點亮個led帶不動風扇,所以我們需要一個三極體,我買的是
s8050
NPN的有兩種別買錯了
,pnp是接在地線上的,用流程圖畫一個接線圖吧
,意思一下得了markdown
不知道怎麼畫電路圖
/etc/systemd/system 增加對應的檔案
fanServer.service
[Unit]
Description=test deamon
After=rc-local.service
[Service]
Type=simple
User=root
Group=root
WorkingDirectory=檔案的路徑
ExecStart=nohup python3 -u processRequest.py > service.log 2>&1 &
Restart=always
[Install]
WantedBy=multi-user.target
fan.service
[Unit]
Description=test deamon
After=rc-local.service
[Service]
Type=simple
User=root
Group=root
WorkingDirectory=檔案所在的路徑
ExecStart=nohup python3 -u index.py > fan.log 2>&1 &
Restart=always
[Install]
WantedBy=multi-user.target
啟動
sudo systemctl start fan.service
sudo systemctl start fanServer.service
新增到開機自啟
sudo systemctl enable fan.service
sudo systemctl enable fanServer.service
意思一下得了哈,效果看圖片
全部程式碼地址:https://github.com/dadademo/piFan
裝置控制主要就是:1. 展示資料 2. 傳送裝置控制指令
寫個vue的頁面,用腦子設計一下:開關按鈕得有,溫度設定得有,還得有個圖表,還得加個篩選時間,根據時間來篩選資料。就醬式的吧
https://github.com/dadademo/piFan/blob/main/fanUi/src/components/home.vue
後臺定時任務:1. 定時讀取任務,根據設定的溫度決定是否開/關風扇 2. 定時記錄資訊,將資訊存在資料裡面
這些服務本來想用node寫,奈何node操作gpio的庫一直不能下載,只能用python來搞了
注意
這個程式碼我是直接複製的,依賴一些我寫的其他的python指令碼,如果想跑起來的話還直接拉全部程式碼去看吧
這裡就是用python啟動一個服務,接收網頁傳送的請求,例如設定溫度,還有啟停的製冷
這裡就是每隔5分鐘讀取一次溫度,超過了就啟動風扇,沒超過就停止
# 使用內建的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啟動一個服務,接收網頁傳送的請求,例如設定溫度,還有啟停的風扇指令,寫這個程式碼還了解了一下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()
主要邏輯就這麼多,全部的程式碼看git的地址吧,readme裡面也有對應的操作,想網存取的話可以看我上一篇文章,有對應的連結,就不再這裡嗶嗶了