TranslateProject/published/202307/20230306.1 ⭐️⭐️ Build a Raspberry Pi monitoring dashboard in under 30 minutes.md

498 lines
22 KiB
Markdown
Raw Normal View History

[#]: subject: "Build a Raspberry Pi monitoring dashboard in under 30 minutes"
[#]: via: "https://opensource.com/article/23/3/build-raspberry-pi-dashboard-appsmith"
[#]: author: "Keyur Paralkar https://opensource.com/users/keyur-paralkar"
[#]: collector: "lkxed"
[#]: translator: "ChatGPT"
[#]: reviewer: "wxy"
[#]: publisher: "wxy"
[#]: url: "https://linux.cn/article-15984-1.html"
在不到 30 分钟内构建一个树莓派监控仪表盘
======
![][0]
> 使用 Python 制作一个 API 来监控你的树莓派硬件,并使用 Appsmith 建立一个仪表盘。
如果你想知道你的树莓派的性能如何,那么你可能需要一个树莓派的仪表盘。在本文中,我将演示如何快速构建一个按需监控仪表盘,以实时查看你的树莓派的 CPU 性能、内存和磁盘使用情况,并根据需要随时添加更多视图和操作。
如果你已经使用 Appsmith你还可以直接导入 [示例应用程序][1] 并开始使用。
### Appsmith
Appsmith 是一个开源的 [低代码][2] 应用构建工具,帮助开发人员轻松快速地构建内部应用,如仪表盘和管理面板。它是一个用于仪表盘的很好选择,并减少了传统编码方法所需的时间和复杂性。
在此示例的仪表盘中,我显示以下统计信息:
- CPU
- 占用百分比
- 频率或时钟速度
- 计数
- 温度
- 内存
- 占用百分比
- 可用内存百分比
- 总内存
- 空闲内存
- 磁盘
- 磁盘使用百分比
- 绝对磁盘空间使用量
- 可用磁盘空间
- 总磁盘空间
### 创建一个端点
你需要一种从树莓派获取这些数据并传递给 Appsmith 的方法。[psutil][3] 是一个用于监控和分析的 Python 库,而 [Flask-RESTful][4] 是一个创建 [REST API][5] 的 Flask 扩展。
Appsmith 每隔几秒钟调用 REST API 以自动刷新数据,并以 JSON 对象作为响应,其中包含所有所需的统计信息,如下所示:
```
{ "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、设置 REST API
如果你的树莓派尚未安装 Python请在树莓派上打开终端并运行此安装命令
```
$ sudo apt install python3
```
现在为你的开发设置一个 [Python 虚拟环境][6]
```
$ python -m venv PiData
```
接下来,激活该环境。你必须在重新启动树莓派后执行此操作。
```
$ source PiData/bin/activate
$ cd PiData
```
为了安装 Flask、Flask-RESTful 和以后需要的依赖项,请在你的 Python 虚拟环境中创建一个名为 `requirements.txt` 的文件,并将以下内容添加到其中:
```
flask
flask-restful
gunicorn
```
保存文件,然后使用 `pip` 一次性安装它们。你必须在重新启动树莓派后执行此操作。
```
(PyData)$ python -m pip install -r requirements.txt
```
接下来,创建一个名为 `pi_stats.py` 的文件来存放使用 `psutil` 检索树莓派系统统计信息的逻辑。将以下代码粘贴到 `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 对象的应用程序。
- 使用 Flask-RESTful 的 [API 方法][7] 来定义 API 对象。
- 在 Flask-RESTful 中将 `PiData` 定义为具体的 [Resource 类][8] ,以公开每个支持的 HTTP 方法。
- 使用 `api.add_resource(PiData, '/get-stats')` 将资源 `PiData` 附加到 API 对象 `api`
- 每当你访问 URL `/get-stats` 时,将返回 `PiData` 作为响应。
#### 2、使用 psutil 读取统计信息
要从你的树莓派获取统计信息,你可以使用 `psutil` 提供的这些内置函数:
- `cpu_percentage`、`cpu_count`、`cpu_freq` 和 `sensors_temperatures` 函数分别用于获取 CPU 的占用百分比、计数、时钟速度和温度。`sensors_temperatures` 报告了与树莓派连接的所有设备的温度。要仅获取 CPU 的温度,请使用键 `cpu-thermal`
- `virtual_memory` 函数可返回总内存、可用内存、已使用内存和空闲内存的统计信息(以字节为单位)。
- `disk_usage` 函数可返回总磁盘空间、已使用空间和可用空间的统计信息(以字节为单位)。
将所有函数组合到一个 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,
}
```
下一节将使用该字典。
#### 3、从 Flask-RESTful API 获取数据
为了在 API 响应中看到来自树莓派的数据,请更新 `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)
```
你的脚本已经就绪,下面运行 `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 提供给互联网
你可以在本地网络中与 API 进行交互。然而,要在互联网上访问它,你必须在防火墙中打开一个端口,并将传入的流量转发到由 Flask 提供的端口。然而,正如你的测试输出建议的那样,在 Flask 中运行 Flask 应用程序仅适用于开发,而不适用于生产。为了安全地将 API 提供给互联网,你可以使用安装过程中安装的 `gunicorn` 生产服务器。
现在,你可以启动 Flask API。每次重新启动树莓派时都需要执行此操作。
```
$ gunicorn -w 4 'PyData:app'
Serving on http://0.0.0.0:8000
```
要从外部世界访问你的树莓派,请在网络防火墙中打开一个端口,并将流量定向到你树莓派的 IP 地址,端口为 8000。
首先,获取树莓派的内部 IP 地址:
```
$ ip addr show | grep inet
```
内部 IP 地址通常以 10 或 192 或 172 开头。
接下来你必须配置防火墙。通常你从互联网服务提供商ISP获取的路由器中嵌入了防火墙。通常你可以通过网络浏览器访问家用路由器。路由器的地址有时会打印在路由器的底部它以 192.168 或 10 开头。不过,每个设备都不同,因此我无法告诉你需要点击哪些选项来调整设置。关于如何配置防火墙的完整描述,请阅读 Seth Kenlon 的文章 《[打开端口并通过你的防火墙路由流量][9]》。
或者,你可以使用 [localtunnel][10] 来使用动态端口转发服务。
一旦你的流量到达树莓派,你就可以查询你的 API
```
$ curl https://example.com/get-stats
{
"cpu_count": 4,
"cpu_freq": [
600.0,
600.0,
1200.0 ],
"cpu_mem_avail": 386273280,
...
```
如果你已经执行到这一步,那么最困难的部分已经过去了。
#### 5、重复步骤
如果你重新启动了树莓派,你必须按照以下步骤进行操作:
- 使用 `source` 重新激活 Python 环境
- 使用 `pip` 刷新应用程序的依赖项
- 使用 `gunicorn` 启动 Flask 应用程序
你的防火墙设置是持久的,但如果你使用了 localtunnel则必须在重新启动后启动新的隧道。
如果你愿意,可以自动化这些任务,但那是另一个教程的内容。本教程的最后一部分是在 Appsmith 上构建一个用户界面,使用拖放式小部件和一些 JavaScript将你的树莓派数据绑定到用户界面。相信我从现在开始很容易
### 在 Appsmith 上构建仪表盘
![硬件监控仪表盘][11]
要制作一个像这样的仪表盘,你需要将公开的 API 端点连接到 Appsmith使用 Appsmith 的小部件库构建用户界面,并将 API 的响应绑定到小部件上。如果你已经使用 Appsmith你可以直接导入 [示例应用程序][1] 并开始使用。
如果你还没有,请 [注册][12] 一个免费的 Appsmith 帐户。或者,你可以选择 [自托管 Appsmith][13]。
### 将 API 作为 Appsmith 数据源连接
登录到你的 Appsmith 帐户。
- 在左侧导航栏中找到并点击 “<ruby>查询或 JS<rt>QUERIES/JS</rt></ruby>” 旁边的 “+” 按钮。
- 点击 “<ruby>创建一个空白 API<rt>Create a blank API</rt></ruby>”。
- 在页面顶部,将你的项目命名为 “PiData”。
- 获取你的 API 的 URL。如果你使用的是 localtunnel则是一个 `localtunnel.me` 地址,总是在末尾添加 `/get-stats` 以获取统计数据。将其粘贴到页面的第一个空白字段中,然后点击 “RUN” 按钮。
确保在 “<ruby>响应<rt>Response</rt></ruby>” 面板中看到成功的响应。
![Appsmith 界面][14]
### 构建用户界面
Appsmith 的界面非常直观,但如果你感到迷失,我建议你查看 [在 Appsmith 上构建你的第一个应用程序][15] 教程。
对于标题,将 “<ruby>文本<rt>Text</rt></ruby>”、“<ruby>图像<rt>Image</rt></ruby>” 和 “<ruby>分隔线<rt>Divider</rt></ruby>” 小部件拖放到画布上。将它们排列如下:
![设置项目标题][16]
<ruby>文本<rt>Text</rt></ruby>” 小部件包含你页面的实际标题。键入比“Raspberry Pi Stats”更酷的内容。
<ruby>图像<rt>Image</rt></ruby>” 小部件用于展示仪表盘的独特标志。你可以使用你喜欢的任何标志。
使用 “<ruby>开关<rt>Switch</rt></ruby>” 小部件来切换实时数据模式。在 “<ruby>属性<rt>Property</rt></ruby>” 面板中进行配置,以从你构建的 API 获取数据。
对于主体部分,使用来自左侧的小部件库的以下小部件创建一个 CPU 统计信息区域,使用以下小部件:
- <ruby>进度条<rt>Progress Bar</rt></ruby>
- <ruby>统计框<rt>Stat Box</rt></ruby>
- <ruby>图表<rt>Chart</rt></ruby>
对于内存和磁盘统计信息部分,重复相同的步骤。磁盘统计信息部分不需要图表,但如果你能找到用途,那也可以使用它。
你的最终小部件布局应该类似于以下:
![Appsmith 中的属性设置][17]
最后一步是将 API 的数据绑定到你的小部件上。
### 将数据绑定到小部件上
返回到画布,并在三个类别的部分中找到你的小部件。首先设置 CPU 统计信息。
要将数据绑定到 “<ruby>进度条<rt>Progress Bar</rt></ruby>” 小部件:
- 单击 “<ruby>进度条<rt>Progress Bar</rt></ruby>” 小部件,以打开右侧的 “<ruby>属性<rt>Property</rt></ruby>” 面板。
- 查找 “<ruby>进度<rt>Progress</rt></ruby>” 属性。
- 单击 “JS” 按钮以激活 JavaScript。
- 在 “<ruby>进度<rt>Progress</rt></ruby>” 字段中粘贴 `{{PiData.data.cpu_percent ?? 0}}`。此代码引用了你的 API 的数据流,名为 `PiData`。Appsmith 将响应数据缓存在 `PiData``.data` 运算符内。键 `cpu_percent` 包含了 Appsmith 用来显示 CPU 利用率百分比的数据。
- 在 “<ruby>进度条<rt>Progress Bar</rt></ruby>” 小部件下方添加一个 “<ruby>文本<rt>Text</rt></ruby>” 小部件作为标签。
![在配置屏幕中绑定数据][18]
在 CPU 部分有三个 “<ruby>统计框<rt>Stat Box</rt></ruby>” 小部件。将数据绑定到每个小部件的步骤与绑定 “<ruby>进度条<rt>Progress Bar</rt></ruby>” 小部件的步骤完全相同,只是你需要从 `.data` 运算符中绑定不同的数据属性。按照相同的步骤进行操作,但有以下例外:
- 使用 `{{${PiData.data.cpu_freq[0]} ?? 0 }}` 来显示时钟速度。
- 使用 `{{${PiData.data.cpu_count} ?? 0 }}` 来显示 CPU 计数。
- 使用 `{{${(PiData.data.sensor_temperatures).toPrecision(3)} ?? 0 }}` 来显示 CPU 温度数据。
如果一切顺利,你将得到一个漂亮的仪表盘,如下所示:
![树莓派的仪表盘][19]
### CPU 利用率趋势图
你可以使用 “<ruby>图表<rt>Chart</rt></ruby>” 小部件将 CPU 利用率显示为趋势线,并使其随时间自动更新。
首先,单击小部件,在右侧找到 “<ruby>图表类型<rt>Chart Type</rt></ruby>” 属性,并将其更改为 “<ruby>折线图<rt>LINE CHART</rt></ruby>”。为了显示趋势线,需要将 `cpu_percent` 存储在数据点数组中。你的 API 目前将其作为单个时间数据点返回,因此可以使用 Appsmith 的 `storeValue` 函数Appsmith 内置的 `setItem` 方法的一个原生实现)来获取一个数组。
在 “<ruby>查询或 JS<rt>QUERIES/JS</rt></ruby>” 旁边单击 “+” 按钮,并将其命名为 “utils”。
将以下 JavaScript 代码粘贴到 “<ruby>代码<rt>Code</rt></ruby>” 字段中:
```
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` 对象中创建了一个 JavaScript 函数,并将 `storeValue` 函数放在其中。
你使用 `storeValue("cpu_util_data", []);``cpu_util_data` 中的值存储到 `storeValue` 函数中。此函数在页面加载时运行。
到目前为止,每次刷新页面时,代码都会将 `cpu_util_data` 中的一个数据点存储到 `Store` 中。为了存储一个数组,你使用了 `x``y` 的下标变量,两者都存储了来自 `cpu_percent` 数据属性的值。
你还希望通过设定存储值之间的固定时间间隔来自动存储这些数据。当执行 [setInterval][20] 函数时:
- 获取存储在 `cpu_util_data` 中的值。
- 调用 API `PiData`
- 使用返回的最新 `cpu_percent` 数据将 `cpu_util_data` 更新为 `x``y` 变量。
-`cpu_util_data` 的值存储在键 `utilData` 中。
- 仅当设置为自动执行函数时,才重复执行步骤 1 到 4。你使用 Switch 小部件将其设置为自动执行,这就解释了为什么有一个 `getLiveData` 父函数。
在 “<ruby>设置<rt>Settings</rt></ruby>” 选项卡中,找到对象中的所有父函数,并在 “<ruby>页面加载时运行<rt>RUN ON PAGE LOAD</rt></ruby>” 选项中将 `initialOnPageLoad` 设置为 “Yes”。
![设置页面加载时要执行的函数][21]
现在刷新页面进行确认。
返回到画布。单击 “<ruby>图表<rt>Chart</rt></ruby>” 小部件,并找到 “<ruby>图表数据<rt>Chart Data</rt></ruby>” 属性。将绑定 `{{ appsmith.store.disk_util_data }}` 粘贴到其中。这样,如果你自己多次运行对象 `utils`,就可以获得图表数据。要自动运行此操作:
- 查找并单击仪表盘标题中的 “<ruby>实时数据开关<rt>Live Data Switch</rt></ruby>” 小部件。
- 查找 `onChange` 事件。
- 将其绑定到 `{{ utils.getLiveData() }}`。JavaScript 对象是 `utils`,而 `getLiveData` 是在你切换开关时激活的函数,它会从你的树莓派获取实时数据。但是还有其他实时数据,因此同一开关也适用于它们。继续阅读以了解详情。
将数据绑定到内存和磁盘部分的小部件与你在 CPU 统计信息部分所做的方式类似。
对于内存部分,绑定如下所示:
- 进度条中的绑定为:`{{( PiData.data.cpu_mem_avail/1000000000).toPrecision(2) \* 100 ?? 0 }}`。
- 三个统计框小部件的绑定分别为:`{{ \${(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`
对于磁盘部分,进度条和统计框小部件的绑定分别变为:
- 进度条的绑定为:`{{ PiData.data.disk_usage_percent ?? 0 }}`。
- 三个统计框小部件的绑定分别为:`{{ \${(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 统计信息创建的 `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 对象在打开和关闭真实数据开关时触发的数据流可视化如下所示:
![切换][22]
在打开实时数据开关时,图表会变成这样:
![显示实时数据][23]
整体上,它既漂亮,又简约,而且非常有用。
### 祝你使用愉快!
当你对 `psutils`、JavaScript 和 Appsmith 更加熟悉时,我相信你会发现可以轻松无限地调整你的仪表板,实现非常酷的功能,例如:
- 查看先前一周、一个月、一个季度、一年或根据你的树莓派数据允许的任何自定义范围的趋势
- 为任何统计数据的阈值违规构建报警机制
- 监控连接到你的树莓派的其他设备
-`psutils` 扩展到另一台安装有 Python 的计算机上
- 使用其他库监控你家庭或办公室的网络
- 监控你的花园
- 跟踪你自己的生活习惯
在下一个令人兴奋的项目中,祝你玩得愉快!
*题图MJ/9754eb1f-1722-4897-9c35-3f20c285c332*
--------------------------------------------------------------------------------
via: https://opensource.com/article/23/3/build-raspberry-pi-dashboard-appsmith
作者:[Keyur Paralkar][a]
选题:[lkxed][b]
译者ChatGPT
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://opensource.com/users/keyur-paralkar
[b]: https://github.com/lkxed/
[1]: https://github.com/appsmithorg/foundry/tree/main/resources/blogs/Raspberry%20Pi%20Dashboard
[2]: https://www.redhat.com/architect/low-code-platform?intcmp=7013a000002qLH8AAM
[3]: https://psutil.readthedocs.io/en/latest/
[4]: https://flask-restful.readthedocs.io/en/latest/
[5]: https://www.redhat.com/en/topics/api/what-is-a-rest-api?intcmp=7013a000002qLH8AAM
[6]: https://opensource.com/article/20/10/venv-python
[7]: https://flask-restful.readthedocs.io/en/latest/api.html#id1
[8]: https://flask-restful.readthedocs.io/en/latest/api.html#flask_restful.Resource
[9]: https://opensource.com/article/20/9/firewall
[10]: https://theboroer.github.io/localtunnel-www/
[11]: https://opensource.com/sites/default/files/2023-02/dashboard.png
[12]: https://appsmith.com/sign-up
[13]: https://docs.appsmith.com/getting-started/setup
[14]: https://opensource.com/sites/default/files/2023-02/success.webp
[15]: https://docs.appsmith.com/getting-started/start-building
[16]: https://opensource.com/sites/default/files/2023-02/TITLE.webp
[17]: https://opensource.com/sites/default/files/2023-02/property.webp
[18]: https://opensource.com/sites/default/files/2023-02/config.webp
[19]: https://opensource.com/sites/default/files/2023-02/final.webp
[20]: https://docs.appsmith.com/reference/appsmith-framework/widget-actions/intervals-time-events#setinterval
[21]: https://opensource.com/sites/default/files/2023-02/load-on-page.webp
[22]: https://opensource.com/sites/default/files/2023-02/toggle.gif
[23]: https://opensource.com/sites/default/files/2023-02/final.gif
[0]: https://img.linux.net.cn/data/attachment/album/202307/10/102705vfe3pb0wbqnf0see.jpg