[#]: 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 帐户。 - 在左侧导航栏中找到并点击 “查询或 JSQUERIES/JS” 旁边的 “+” 按钮。 - 点击 “创建一个空白 APICreate a blank API”。 - 在页面顶部,将你的项目命名为 “PiData”。 - 获取你的 API 的 URL。如果你使用的是 localtunnel,则是一个 `localtunnel.me` 地址,总是在末尾添加 `/get-stats` 以获取统计数据。将其粘贴到页面的第一个空白字段中,然后点击 “RUN” 按钮。 确保在 “响应Response” 面板中看到成功的响应。 ![Appsmith 界面][14] ### 构建用户界面 Appsmith 的界面非常直观,但如果你感到迷失,我建议你查看 [在 Appsmith 上构建你的第一个应用程序][15] 教程。 对于标题,将 “文本Text”、“图像Image” 和 “分隔线Divider” 小部件拖放到画布上。将它们排列如下: ![设置项目标题][16] “文本Text” 小部件包含你页面的实际标题。键入比“Raspberry Pi Stats”更酷的内容。 “图像Image” 小部件用于展示仪表盘的独特标志。你可以使用你喜欢的任何标志。 使用 “开关Switch” 小部件来切换实时数据模式。在 “属性Property” 面板中进行配置,以从你构建的 API 获取数据。 对于主体部分,使用来自左侧的小部件库的以下小部件创建一个 CPU 统计信息区域,使用以下小部件: - 进度条Progress Bar - 统计框Stat Box - 图表Chart 对于内存和磁盘统计信息部分,重复相同的步骤。磁盘统计信息部分不需要图表,但如果你能找到用途,那也可以使用它。 你的最终小部件布局应该类似于以下: ![Appsmith 中的属性设置][17] 最后一步是将 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” 小部件作为标签。 ![在配置屏幕中绑定数据][18] 在 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 温度数据。 如果一切顺利,你将得到一个漂亮的仪表盘,如下所示: ![树莓派的仪表盘][19] ### CPU 利用率趋势图 你可以使用 “图表Chart” 小部件将 CPU 利用率显示为趋势线,并使其随时间自动更新。 首先,单击小部件,在右侧找到 “图表类型Chart Type” 属性,并将其更改为 “折线图LINE CHART”。为了显示趋势线,需要将 `cpu_percent` 存储在数据点数组中。你的 API 目前将其作为单个时间数据点返回,因此可以使用 Appsmith 的 `storeValue` 函数(Appsmith 内置的 `setItem` 方法的一个原生实现)来获取一个数组。 在 “查询或 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` 对象中创建了一个 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` 父函数。 在 “设置Settings” 选项卡中,找到对象中的所有父函数,并在 “页面加载时运行RUN ON PAGE LOAD” 选项中将 `initialOnPageLoad` 设置为 “Yes(是)”。 ![设置页面加载时要执行的函数][21] 现在刷新页面进行确认。 返回到画布。单击 “图表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 对象在打开和关闭真实数据开关时触发的数据流可视化如下所示: ![切换][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