在不到 30 分钟内构建一个树莓派监控仪表盘
使用 Python 制作一个 API 来监控你的树莓派硬件，并使用 Appsmith 建立一个仪表盘。如果你想知道你的树莓派的性能如何，那么你可能需要一个树莓派的仪表盘。在本文中，我将演示如何快速构建一个按需监控仪表盘，以实时查看你的树莓派的 CPU 性能、内存和磁盘使用情况，并根据需要随时添加更多视图和操作。如果你已经使用 Appsmith，你还可以直接导入 示例应用程序 并开始使用。AppsmithAppsmith 是一个开源的 低代码 应用构建工具，帮助开发人员轻松快速地构建内部应用，如仪表盘和管理面板。它是一个用于仪表盘的很好选择，并减少了传统编码方法所需的时间和复杂性。在此示例的仪表盘中，我显示以下统计信息：CPU占用百分比频率或时钟速度计数温度内存占用百分比可用内存百分比总内存空闲内存磁盘磁盘使用百分比绝对磁盘空间使用量可用磁盘空间总磁盘空间创建一个端点你需要一种从树莓派获取这些数据并传递给 Appsmith 的方法。psutil 是一个用于监控和分析的 Python 库，而 Flask-RESTful 是一个创建 REST API 的 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 虚拟环境：$ 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 方法 来定义 API 对象。在 Flask-RESTful 中将 PiData 定义为具体的 Resource 类 ，以公开每个支持的 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 的文章 《打开端口并通过你的防火墙路由流量》。或者，你可以使用 localtunnel 来使用动态端口转发服务。一旦你的流量到达树莓派，你就可以查询你的 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 上构建仪表盘要制作一个像这样的仪表盘，你需要将公开的 API 端点连接到 Appsmith，使用 Appsmith 的小部件库构建用户界面，并将 API 的响应绑定到小部件上。如果你已经使用 Appsmith，你可以直接导入 示例应用程序 并开始使用。如果你还没有，请 注册 一个免费的 Appsmith 帐户。或者，你可以选择 自托管 Appsmith。将 API 作为 Appsmith 数据源连接登录到你的 Appsmith 帐户。在左侧导航栏中找到并点击 “ 查询或 JS QUERIES/JS ” 旁边的 “+” 按钮。点击 “ 创建一个空白 API Create a blank API ”。在页面顶部，将你的项目命名为 “PiData”。获取你的 API 的 URL。如果你使用的是 localtunnel，则是一个 localtunnel.me 地址，总是在末尾添加 /get-stats 以获取统计数据。将其粘贴到页面的第一个空白字段中，然后点击 “RUN” 按钮。确保在 “ 响应 Response ” 面板中看到成功的响应。构建用户界面Appsmith 的界面非常直观，但如果你感到迷失，我建议你查看 在 Appsmith 上构建你的第一个应用程序 教程。对于标题，将 “ 文本 Text ”、“ 图像 Image ” 和 “ 分隔线 Divider ” 小部件拖放到画布上。将它们排列如下：“ 文本 Text ” 小部件包含你页面的实际标题。键入比“Raspberry Pi Stats”更酷的内容。“ 图像 Image ” 小部件用于展示仪表盘的独特标志。你可以使用你喜欢的任何标志。使用 “ 开关 Switch ” 小部件来切换实时数据模式。在 “ 属性 Property ” 面板中进行配置，以从你构建的 API 获取数据。对于主体部分，使用来自左侧的小部件库的以下小部件创建一个 CPU 统计信息区域，使用以下小部件： 进度条 Progress Bar 统计框 Stat Box 图表 Chart 对于内存和磁盘统计信息部分，重复相同的步骤。磁盘统计信息部分不需要图表，但如果你能找到用途，那也可以使用它。你的最终小部件布局应该类似于以下：最后一步是将 API 的数据绑定到你的小部件上。将数据绑定到小部件上返回到画布，并在三个类别的部分中找到你的小部件。首先设置 CPU 统计信息。要将数据绑定到 “ 进度条 Progress Bar ” 小部件：单击 “ 进度条 Progress Bar ” 小部件，以打开右侧的 “ 属性 Property ” 面板。查找 “ 进度 Progress ” 属性。单击 “JS” 按钮以激活 JavaScript。在 “ 进度 Progress ” 字段中粘贴 {{PiData.data.cpu_percent ?? 0}}。此代码引用了你的 API 的数据流，名为 PiData。Appsmith 将响应数据缓存在 PiData 的 .data 运算符内。键 cpu_percent 包含了 Appsmith 用来显示 CPU 利用率百分比的数据。在 “ 进度条 Progress Bar ” 小部件下方添加一个 “ 文本 Text ” 小部件作为标签。在 CPU 部分有三个 “ 统计框 Stat Box ” 小部件。将数据绑定到每个小部件的步骤与绑定 “ 进度条 Progress Bar ” 小部件的步骤完全相同，只是你需要从 .data 运算符中绑定不同的数据属性。按照相同的步骤进行操作，但有以下例外：使用 {{${PiData.data.cpu_freq[0]} ?? 0 }} 来显示时钟速度。使用 {{${PiData.data.cpu_count} ?? 0 }} 来显示 CPU 计数。使用 {{${(PiData.data.sensor_temperatures).toPrecision(3)} ?? 0 }} 来显示 CPU 温度数据。如果一切顺利，你将得到一个漂亮的仪表盘，如下所示：CPU 利用率趋势图你可以使用 “ 图表 Chart ” 小部件将 CPU 利用率显示为趋势线，并使其随时间自动更新。首先，单击小部件，在右侧找到 “ 图表类型 Chart Type ” 属性，并将其更改为 “ 折线图 LINE CHART ”。为了显示趋势线，需要将 cpu_percent 存储在数据点数组中。你的 API 目前将其作为单个时间数据点返回，因此可以使用 Appsmith 的 storeValue 函数（Appsmith 内置的 setItem 方法的一个原生实现）来获取一个数组。在 “ 查询或 JS QUERIES/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 对象中创建了一个 JavaScript 函数，并将 storeValue 函数放在其中。你使用 storeValue("cpu_util_data", []); 将 cpu_util_data 中的值存储到 storeValue 函数中。此函数在页面加载时运行。到目前为止，每次刷新页面时，代码都会将 cpu_util_data 中的一个数据点存储到 Store 中。为了存储一个数组，你使用了 x 和 y 的下标变量，两者都存储了来自 cpu_percent 数据属性的值。你还希望通过设定存储值之间的固定时间间隔来自动存储这些数据。当执行 setInterval 函数时：获取存储在 cpu_util_data 中的值。调用 API PiData。使用返回的最新 cpu_percent 数据将 cpu_util_data 更新为 x 和 y 变量。将 cpu_util_data 的值存储在键 utilData 中。仅当设置为自动执行函数时，才重复执行步骤 1 到 4。你使用 Switch 小部件将其设置为自动执行，这就解释了为什么有一个 getLiveData 父函数。在 “ 设置 Settings ” 选项卡中，找到对象中的所有父函数，并在 “ 页面加载时运行 RUN ON PAGE LOAD ” 选项中将 initialOnPageLoad 设置为 “Yes（是）”。现在刷新页面进行确认。返回到画布。单击 “ 图表 Chart ” 小部件，并找到 “ 图表数据 Chart Data ” 属性。将绑定 {{ appsmith.store.disk_util_data }} 粘贴到其中。这样，如果你自己多次运行对象 utils，就可以获得图表数据。要自动运行此操作：查找并单击仪表盘标题中的 “ 实时数据开关 Live Data Switch ” 小部件。查找 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 对象在打开和关闭真实数据开关时触发的数据流可视化如下所示：在打开实时数据开关时，图表会变成这样：整体上，它既漂亮，又简约，而且非常有用。祝你使用愉快！当你对 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 选题：lkxed 译者：ChatGPT 校对：wxy本文由 LCTT 原创编译，Linux中国 荣誉推出