在不到 30 分鐘內(nèi)構(gòu)建一個樹莓派監(jiān)控儀表盤
如果你想知道你的樹莓派的性能如何,那么你可能需要一個樹莓派的儀表盤。在本文中,我將演示如何快速構(gòu)建一個按需監(jiān)控儀表盤,以實時查看你的樹莓派的 CPU 性能、內(nèi)存和磁盤使用情況,并根據(jù)需要隨時添加更多視圖和操作。
如果你已經(jīng)使用 Appsmith,你還可以直接導入 示例應(yīng)用程序 并開始使用。
Appsmith
Appsmith 是一個開源的 低代碼 應(yīng)用構(gòu)建工具,幫助開發(fā)人員輕松快速地構(gòu)建內(nèi)部應(yīng)用,如儀表盤和管理面板。它是一個用于儀表盤的很好選擇,并減少了傳統(tǒng)編碼方法所需的時間和復雜性。
在此示例的儀表盤中,我顯示以下統(tǒng)計信息:
- CPU
- 占用百分比
- 頻率或時鐘速度
- 計數(shù)
- 溫度
- 內(nèi)存
- 占用百分比
- 可用內(nèi)存百分比
- 總內(nèi)存
- 空閑內(nèi)存
- 磁盤
- 磁盤使用百分比
- 絕對磁盤空間使用量
- 可用磁盤空間
- 總磁盤空間
創(chuàng)建一個端點
你需要一種從樹莓派獲取這些數(shù)據(jù)并傳遞給 Appsmith 的方法。psutil 是一個用于監(jiān)控和分析的 Python 庫,而 Flask-RESTful 是一個創(chuàng)建 REST API 的 Flask 擴展。
Appsmith 每隔幾秒鐘調(diào)用 REST API 以自動刷新數(shù)據(jù),并以 JSON 對象作為響應(yīng),其中包含所有所需的統(tǒng)計信息,如下所示:
{ "cpu_count": 4,
"cpu_freq": [
600.0,
600.0,
1200.0 ],
"cpu_mem_avail": 463953920,
"cpu_mem_free": 115789824,
"cpu_mem_total": 971063296,
"cpu_mem_used": 436252672,
"cpu_percent": 1.8,
"disk_usage_free": 24678121472,
"disk_usage_percent": 17.7,
"disk_usage_total": 31307206656,
"disk_usage_used": 5292728320,
"sensor_temperatures": 52.616 }
1、設(shè)置 REST API
如果你的樹莓派尚未安裝 Python,請在樹莓派上打開終端并運行此安裝命令:
$ sudo apt install python3
現(xiàn)在為你的開發(fā)設(shè)置一個 Python 虛擬環(huán)境:
$ python -m venv PiData
接下來,激活該環(huán)境。你必須在重新啟動樹莓派后執(zhí)行此操作。
$ source PiData/bin/activate
$ cd PiData
為了安裝 Flask、Flask-RESTful 和以后需要的依賴項,請在你的 Python 虛擬環(huán)境中創(chuàng)建一個名為 requirements.txt
的文件,并將以下內(nèi)容添加到其中:
flask
flask-restful
gunicorn
保存文件,然后使用 pip
一次性安裝它們。你必須在重新啟動樹莓派后執(zhí)行此操作。
(PyData)$ python -m pip install -r requirements.txt
接下來,創(chuàng)建一個名為 pi_stats.py
的文件來存放使用 psutil
檢索樹莓派系統(tǒng)統(tǒng)計信息的邏輯。將以下代碼粘貼到 pi_stats.py
文件中:
from flask import Flask
from flask_restful import Resource, Api
import psutil
app = Flask(__name__)
api = Api(app)
class PiData(Resource):
def get(self):
return "RPI Stat dashboard"
api.add_resource(PiData, '/get-stats')
if __name__ == '__main__':
app.run(debug=True)
這段代碼的作用如下:
- 使用
app = Flask(name)
來定義嵌套 API 對象的應(yīng)用程序。 - 使用 Flask-RESTful 的 API 方法 來定義 API 對象。
- 在 Flask-RESTful 中將
PiData
定義為具體的 Resource 類 ,以公開每個支持的 HTTP 方法。 - 使用
api.add_resource(PiData, '/get-stats')
將資源PiData
附加到 API 對象api
。 - 每當你訪問 URL
/get-stats
時,將返回PiData
作為響應(yīng)。
2、使用 psutil 讀取統(tǒng)計信息
要從你的樹莓派獲取統(tǒng)計信息,你可以使用 psutil
提供的這些內(nèi)置函數(shù):
cpu_percentage
、cpu_count
、cpu_freq
和sensors_temperatures
函數(shù)分別用于獲取 CPU 的占用百分比、計數(shù)、時鐘速度和溫度。sensors_temperatures
報告了與樹莓派連接的所有設(shè)備的溫度。要僅獲取 CPU 的溫度,請使用鍵cpu-thermal
。virtual_memory
函數(shù)可返回總內(nèi)存、可用內(nèi)存、已使用內(nèi)存和空閑內(nèi)存的統(tǒng)計信息(以字節(jié)為單位)。disk_usage
函數(shù)可返回總磁盤空間、已使用空間和可用空間的統(tǒng)計信息(以字節(jié)為單位)。
將所有函數(shù)組合到一個 Python 字典中的示例如下:
system_info_data = {
'cpu_percent': psutil.cpu_percent(1),
'cpu_count': psutil.cpu_count(),
'cpu_freq': psutil.cpu_freq(),
'cpu_mem_total': memory.total,
'cpu_mem_avail': memory.available,
'cpu_mem_used': memory.used,
'cpu_mem_free': memory.free,
'disk_usage_total': disk.total,
'disk_usage_used': disk.used,
'disk_usage_free': disk.free,
'disk_usage_percent': disk.percent,
'sensor_temperatures': psutil.sensors_temperatures()['cpu-thermal'][0].current,
}
下一節(jié)將使用該字典。
3、從 Flask-RESTful API 獲取數(shù)據(jù)
為了在 API 響應(yīng)中看到來自樹莓派的數(shù)據(jù),請更新 pi_stats.py
文件,將字典 system_info_data
包含在 PiData
類中:
from flask import Flask
from flask_restful import Resource, Api
import psutil
app = Flask(__name__)
api = Api(app)
class PiData(Resource):
def get(self):
memory = psutil.virtual_memory()
disk = psutil.disk_usage('/')
system_info_data = {
'cpu_percent': psutil.cpu_percent(1),
'cpu_count': psutil.cpu_count(),
'cpu_freq': psutil.cpu_freq(),
'cpu_mem_total': memory.total,
'cpu_mem_avail': memory.available,
'cpu_mem_used': memory.used,
'cpu_mem_free': memory.free,
'disk_usage_total': disk.total,
'disk_usage_used': disk.used,
'disk_usage_free': disk.free,
'disk_usage_percent': disk.percent,
'sensor_temperatures': psutil.sensors_temperatures()['cpu-thermal'][0].current, }
return system_info_data
api.add_resource(PiData, '/get-stats')
if __name__ == '__main__':
app.run(debug=True)
你的腳本已經(jīng)就緒,下面運行 PiData.py
:
$ python PyData.py
* Serving Flask app "PiData" (lazy loading)
* Environment: production
WARNING: This is a development server. Do not run this in a production environment.
* Debug mode: on
* Running on http://127.0.0.1:5000 (Press CTRL+C to quit)
* Restarting with stat
* Debugger is active!
你有了一個可以工作的 API。
4、將 API 提供給互聯(lián)網(wǎng)
你可以在本地網(wǎng)絡(luò)中與 API 進行交互。然而,要在互聯(lián)網(wǎng)上訪問它,你必須在防火墻中打開一個端口,并將傳入的流量轉(zhuǎn)發(fā)到由 Flask
提供的端口。然而,正如你的測試輸出建議的那樣,在 Flask 中運行 Flask 應(yīng)用程序僅適用于開發(fā),而不適用于生產(chǎn)。為了安全地將 API
提供給互聯(lián)網(wǎng),你可以使用安裝過程中安裝的 gunicorn
生產(chǎn)服務(wù)器。
現(xiàn)在,你可以啟動 Flask API。每次重新啟動樹莓派時都需要執(zhí)行此操作。
$ gunicorn -w 4 'PyData:app'
Serving on http://0.0.0.0:8000
要從外部世界訪問你的樹莓派,請在網(wǎng)絡(luò)防火墻中打開一個端口,并將流量定向到你樹莓派的 IP 地址,端口為 8000。
首先,獲取樹莓派的內(nèi)部 IP 地址:
$ ip addr show | grep inet
內(nèi)部 IP 地址通常以 10 或 192 或 172 開頭。
接下來,你必須配置防火墻。通常,你從互聯(lián)網(wǎng)服務(wù)提供商(ISP)獲取的路由器中嵌入了防火墻。通常,你可以通過網(wǎng)絡(luò)瀏覽器訪問家用路由器。路由器的地址有時會打印在路由器的底部,它以 192.168 或 10 開頭。不過,每個設(shè)備都不同,因此我無法告訴你需要點擊哪些選項來調(diào)整設(shè)置。關(guān)于如何配置防火墻的完整描述,請閱讀 Seth Kenlon 的文章 《打開端口并通過你的防火墻路由流量》。
或者,你可以使用 localtunnel 來使用動態(tài)端口轉(zhuǎn)發(fā)服務(wù)。
一旦你的流量到達樹莓派,你就可以查詢你的 API:
$ curl https://example.com/get-stats
{
"cpu_count": 4,
"cpu_freq": [
600.0,
600.0,
1200.0 ],
"cpu_mem_avail": 386273280,
...
如果你已經(jīng)執(zhí)行到這一步,那么最困難的部分已經(jīng)過去了。
5、重復步驟
如果你重新啟動了樹莓派,你必須按照以下步驟進行操作:
- 使用
source
重新激活 Python 環(huán)境 - 使用
pip
刷新應(yīng)用程序的依賴項 - 使用
gunicorn
啟動 Flask 應(yīng)用程序
你的防火墻設(shè)置是持久的,但如果你使用了 localtunnel,則必須在重新啟動后啟動新的隧道。
如果你愿意,可以自動化這些任務(wù),但那是另一個教程的內(nèi)容。本教程的最后一部分是在 Appsmith 上構(gòu)建一個用戶界面,使用拖放式小部件和一些 JavaScript,將你的樹莓派數(shù)據(jù)綁定到用戶界面。相信我,從現(xiàn)在開始很容易!
在 Appsmith 上構(gòu)建儀表盤
硬件監(jiān)控儀表盤
要制作一個像這樣的儀表盤,你需要將公開的 API 端點連接到 Appsmith,使用 Appsmith 的小部件庫構(gòu)建用戶界面,并將 API 的響應(yīng)綁定到小部件上。如果你已經(jīng)使用 Appsmith,你可以直接導入 示例應(yīng)用程序 并開始使用。
如果你還沒有,請 注冊 一個免費的 Appsmith 帳戶?;蛘?,你可以選擇 自托管 Appsmith。
將 API 作為 Appsmith 數(shù)據(jù)源連接
登錄到你的 Appsmith 帳戶。
- 在左側(cè)導航欄中找到并點擊 “查詢或 JSQUERIES/JS” 旁邊的 “+” 按鈕。
- 點擊 “創(chuàng)建一個空白 APICreate a blank API”。
- 在頁面頂部,將你的項目命名為 “PiData”。
- 獲取你的 API 的 URL。如果你使用的是 localtunnel,則是一個
localtunnel.me
地址,總是在末尾添加/get-stats
以獲取統(tǒng)計數(shù)據(jù)。將其粘貼到頁面的第一個空白字段中,然后點擊 “RUN” 按鈕。
確保在 “響應(yīng)Response” 面板中看到成功的響應(yīng)。
Appsmith 界面
構(gòu)建用戶界面
Appsmith 的界面非常直觀,但如果你感到迷失,我建議你查看 在 Appsmith 上構(gòu)建你的第一個應(yīng)用程序 教程。
對于標題,將 “文本Text”、“圖像Image” 和 “分隔線Divider” 小部件拖放到畫布上。將它們排列如下:
設(shè)置項目標題
“文本Text” 小部件包含你頁面的實際標題。鍵入比“Raspberry Pi Stats”更酷的內(nèi)容。
“圖像Image” 小部件用于展示儀表盤的獨特標志。你可以使用你喜歡的任何標志。
使用 “開關(guān)Switch” 小部件來切換實時數(shù)據(jù)模式。在 “屬性Property” 面板中進行配置,以從你構(gòu)建的 API 獲取數(shù)據(jù)。
對于主體部分,使用來自左側(cè)的小部件庫的以下小部件創(chuàng)建一個 CPU 統(tǒng)計信息區(qū)域,使用以下小部件:
- 進度條Progress Bar
- 統(tǒng)計框Stat Box
- 圖表Chart
對于內(nèi)存和磁盤統(tǒng)計信息部分,重復相同的步驟。磁盤統(tǒng)計信息部分不需要圖表,但如果你能找到用途,那也可以使用它。
你的最終小部件布局應(yīng)該類似于以下:
Appsmith 中的屬性設(shè)置
最后一步是將 API 的數(shù)據(jù)綁定到你的小部件上。
將數(shù)據(jù)綁定到小部件上
返回到畫布,并在三個類別的部分中找到你的小部件。首先設(shè)置 CPU 統(tǒng)計信息。
要將數(shù)據(jù)綁定到 “進度條Progress Bar” 小部件:
- 單擊 “進度條Progress Bar” 小部件,以打開右側(cè)的 “屬性Property” 面板。
- 查找 “進度Progress” 屬性。
- 單擊 “JS” 按鈕以激活 JavaScript。
- 在 “進度Progress” 字段中粘貼
{{PiData.data.cpu_percent ?? 0}}
。此代碼引用了你的 API 的數(shù)據(jù)流,名為PiData
。Appsmith 將響應(yīng)數(shù)據(jù)緩存在PiData
的.data
運算符內(nèi)。鍵cpu_percent
包含了 Appsmith 用來顯示 CPU 利用率百分比的數(shù)據(jù)。 - 在 “進度條Progress Bar” 小部件下方添加一個 “文本Text” 小部件作為標簽。
在配置屏幕中綁定數(shù)據(jù)
在 CPU 部分有三個 “統(tǒng)計框Stat Box” 小部件。將數(shù)據(jù)綁定到每個小部件的步驟與綁定 “進度條Progress Bar” 小部件的步驟完全相同,只是你需要從 .data
運算符中綁定不同的數(shù)據(jù)屬性。按照相同的步驟進行操作,但有以下例外:
- 使用
{{${PiData.data.cpu_freq[0]} ?? 0 }}
來顯示時鐘速度。 - 使用
{{${PiData.data.cpu_count} ?? 0 }}
來顯示 CPU 計數(shù)。 - 使用
{{${(PiData.data.sensor_temperatures).toPrecision(3)} ?? 0 }}
來顯示 CPU 溫度數(shù)據(jù)。
如果一切順利,你將得到一個漂亮的儀表盤,如下所示:
樹莓派的儀表盤
CPU 利用率趨勢圖
你可以使用 “圖表Chart” 小部件將 CPU 利用率顯示為趨勢線,并使其隨時間自動更新。
首先,單擊小部件,在右側(cè)找到 “圖表類型Chart Type” 屬性,并將其更改為 “折線圖LINE CHART”。為了顯示趨勢線,需要將 cpu_percent
存儲在數(shù)據(jù)點數(shù)組中。你的 API 目前將其作為單個時間數(shù)據(jù)點返回,因此可以使用 Appsmith 的 storeValue
函數(shù)(Appsmith 內(nèi)置的 setItem
方法的一個原生實現(xiàn))來獲取一個數(shù)組。
在 “查詢或 JSQUERIES/JS” 旁邊單擊 “+” 按鈕,并將其命名為 “utils”。
將以下 JavaScript 代碼粘貼到 “代碼Code” 字段中:
export default {
getLiveData: () => {
//When switch is on:
if (Switch1.isSwitchedOn) {
setInterval(() => {
let utilData = appsmith.store.cpu_util_data;
PiData.run()
storeValue("cpu_util_data", [...utilData, {
x: PiData.data.cpu_percent,
y: PiData.data.cpu_percent
}]);
}, 1500, 'timerId')
} else {
clearInterval('timerId');
}
},
initialOnPageLoad: () => {
storeValue("cpu_util_data", []);
}
}
為了初始化 Store
,你在 initialOnPageLoad
對象中創(chuàng)建了一個 JavaScript 函數(shù),并將 storeValue
函數(shù)放在其中。
你使用 storeValue("cpu_util_data", []);
將 cpu_util_data
中的值存儲到 storeValue
函數(shù)中。此函數(shù)在頁面加載時運行。
到目前為止,每次刷新頁面時,代碼都會將 cpu_util_data
中的一個數(shù)據(jù)點存儲到 Store
中。為了存儲一個數(shù)組,你使用了 x
和 y
的下標變量,兩者都存儲了來自 cpu_percent
數(shù)據(jù)屬性的值。
你還希望通過設(shè)定存儲值之間的固定時間間隔來自動存儲這些數(shù)據(jù)。當執(zhí)行 setInterval 函數(shù)時:
- 獲取存儲在
cpu_util_data
中的值。 - 調(diào)用 API
PiData
。 - 使用返回的最新
cpu_percent
數(shù)據(jù)將cpu_util_data
更新為x
和y
變量。 - 將
cpu_util_data
的值存儲在鍵utilData
中。 - 僅當設(shè)置為自動執(zhí)行函數(shù)時,才重復執(zhí)行步驟 1 到 4。你使用 Switch 小部件將其設(shè)置為自動執(zhí)行,這就解釋了為什么有一個
getLiveData
父函數(shù)。
在 “設(shè)置Settings” 選項卡中,找到對象中的所有父函數(shù),并在 “頁面加載時運行RUN ON PAGE LOAD” 選項中將 initialOnPageLoad
設(shè)置為 “Yes(是)”。
設(shè)置頁面加載時要執(zhí)行的函數(shù)
現(xiàn)在刷新頁面進行確認。
返回到畫布。單擊 “圖表Chart” 小部件,并找到 “圖表數(shù)據(jù)Chart Data” 屬性。將綁定 {{ appsmith.store.disk_util_data }}
粘貼到其中。這樣,如果你自己多次運行對象 utils
,就可以獲得圖表數(shù)據(jù)。要自動運行此操作:
- 查找并單擊儀表盤標題中的 “實時數(shù)據(jù)開關(guān)Live Data Switch” 小部件。
- 查找
onChange
事件。 - 將其綁定到
{{ utils.getLiveData() }}
。JavaScript 對象是utils
,而getLiveData
是在你切換開關(guān)時激活的函數(shù),它會從你的樹莓派獲取實時數(shù)據(jù)。但是還有其他實時數(shù)據(jù),因此同一開關(guān)也適用于它們。繼續(xù)閱讀以了解詳情。
將數(shù)據(jù)綁定到內(nèi)存和磁盤部分的小部件與你在 CPU 統(tǒng)計信息部分所做的方式類似。
對于內(nèi)存部分,綁定如下所示:
- 進度條中的綁定為:
{{( PiData.data.cpu_mem_avail/1000000000).toPrecision(2) \* 100 ?? 0 }}
。 - 三個統(tǒng)計框小部件的綁定分別為:
{{ \${(PiData.data.cpu_mem_used/1000000000).toPrecision(2)} ?? 0 }} GB
、{{ \${(PiData.data.cpu_mem_free/1000000000).toPrecision(2)} ?? 0}} GB
和{{ \${(PiData.data.cpu_mem_total/1000000000).toPrecision(2)} ?? 0 }} GB
。
對于磁盤部分,進度條和統(tǒng)計框小部件的綁定分別變?yōu)椋?/p>
- 進度條的綁定為:
{{ PiData.data.disk_usage_percent ?? 0 }}
。 - 三個統(tǒng)計框小部件的綁定分別為:
{{ \${(PiData.data.disk_usage_used/1000000000).toPrecision(2)} ?? 0 }} GB
、{{ \${(PiData.data.disk_usage_free/1000000000).toPrecision(2)} ?? 0 }} GB
和{{ \${(PiData.data.disk_usage_total/1000000000).toPrecision(2)} ?? 0 }} GB
。
這里的圖表需要更新你為 CPU 統(tǒng)計信息創(chuàng)建的 utils
對象,使用 storeValue
鍵名為 disk_util_data
,嵌套在 getLiveData
下面,其邏輯與 cpu_util_data
類似。對于磁盤利用率圖表,我們存儲的 disk_util_data
的邏輯與 CPU 利用率趨勢圖的邏輯相同。
export default {
getLiveData: () => {
//When switch is on:
if (Switch1.isSwitchedOn) {
setInterval(() => {
const cpuUtilData = appsmith.store.cpu_util_data;
const diskUtilData = appsmith.store.disk_util_data;
PiData.run();
storeValue("cpu_util_data", [...cpuUtilData, { x: PiData.data.cpu_percent,y: PiData.data.cpu_percent }]);
storeValue("disk_util_data", [...diskUtilData, { x: PiData.data.disk_usage_percent,y: PiData.data.disk_usage_percent }]);
}, 1500, 'timerId')
} else {
clearInterval('timerId');
}
},
initialOnPageLoad: () => {
storeValue("cpu_util_data", []);
storeValue("disk_util_data", []);
}
}
通過使用 utils
JavaScript 對象在打開和關(guān)閉真實數(shù)據(jù)開關(guān)時觸發(fā)的數(shù)據(jù)流可視化如下所示:
切換
在打開實時數(shù)據(jù)開關(guān)時,圖表會變成這樣:
顯示實時數(shù)據(jù)
整體上,它既漂亮,又簡約,而且非常有用。
祝你使用愉快!
當你對 psutils
、JavaScript 和 Appsmith 更加熟悉時,我相信你會發(fā)現(xiàn)可以輕松無限地調(diào)整你的儀表板,實現(xiàn)非常酷的功能,例如:
- 查看先前一周、一個月、一個季度、一年或根據(jù)你的樹莓派數(shù)據(jù)允許的任何自定義范圍的趨勢
- 為任何統(tǒng)計數(shù)據(jù)的閾值違規(guī)構(gòu)建報警機制
- 監(jiān)控連接到你的樹莓派的其他設(shè)備
- 將
psutils
擴展到另一臺安裝有 Python 的計算機上 - 使用其他庫監(jiān)控你家庭或辦公室的網(wǎng)絡(luò)
- 監(jiān)控你的花園
- 跟蹤你自己的生活習慣
在下一個令人興奮的項目中,祝你玩得愉快!