Compare commits
7 Commits
c812353f45
...
5a9c93d329
Author | SHA1 | Date |
---|---|---|
Villivateur Von | 5a9c93d329 | |
Villivateur Von | 0863c5c6d4 | |
Villivateur Von | 283364ea70 | |
Villivateur Von | 80a0ce5852 | |
Villivateur Von | a3dc135d70 | |
Villivateur Von | 793cc69a9e | |
Villivateur Von | 32c0376820 |
|
@ -1,5 +1,2 @@
|
|||
.pio
|
||||
.vscode/.browse.c_cpp.db*
|
||||
.vscode/c_cpp_properties.json
|
||||
.vscode/launch.json
|
||||
.vscode/ipch
|
||||
.vscode
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
{
|
||||
// See http://go.microsoft.com/fwlink/?LinkId=827846
|
||||
// for the documentation about the extensions.json format
|
||||
"recommendations": [
|
||||
"platformio.platformio-ide"
|
||||
]
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
{
|
||||
"files.associations": {
|
||||
"*.tcc": "cpp",
|
||||
"array": "cpp",
|
||||
"string": "cpp",
|
||||
"string_view": "cpp",
|
||||
"ranges": "cpp",
|
||||
"deque": "cpp",
|
||||
"list": "cpp",
|
||||
"unordered_map": "cpp",
|
||||
"vector": "cpp",
|
||||
"initializer_list": "cpp",
|
||||
"cmath": "cpp",
|
||||
"cstdint": "cpp",
|
||||
"functional": "cpp"
|
||||
}
|
||||
}
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
Topuino 是一个桌面小摆件,可以实现通用服务器或计算机的数据监控,包括 CPU 占用、RAM 占用、两个硬盘的可用空间、硬盘读写速度、网络 IO 速率。
|
||||
|
||||
![](https://img.vvzero.com/blog/Topuino-the-wonderful-Knickknack-for-server-monitoring/1.png)
|
||||
![](https://img.vvzero.com/ih/5d606a6c-926f-4690-8924-8931ec0f5f97.jpg)
|
||||
|
||||
## 为什么叫 Topuino
|
||||
|
||||
|
@ -18,6 +18,6 @@ Topuino 是一个桌面小摆件,可以实现通用服务器或计算机的数
|
|||
|
||||
## Topuino 的工作原理
|
||||
|
||||
- 服务器部分:主站使用了 Flask,维护一个数据库,保存着从站(被监控服务器)UUID 与运行参数的映射关系(实际上现在是用 python 的字典简单实现的)。主站接收从站的运行数据,并向 Topuino 回传数据;
|
||||
- 服务器从站采用 python 的 psutil 库,获取所有的运行数据;
|
||||
- Topuino 硬件部分使用了 ESP-12F 作为 MCU,显示采用 LED 整列和数码管,显示驱动是 TM1638 芯片。
|
||||
- 服务端使用了 Flask,维护一个内存数据库(实际上是 Python 的字典),保存着从站(被监控服务器)UUID 与运行参数的映射关系。主站接收从站的运行数据,并向 Topuino 回传数据;
|
||||
- 客户端采用 python 的 psutil 库,获取所有的运行数据;
|
||||
- 硬件端使用了 ESP-12F 作为 MCU,显示采用 LED 阵列和数码管,显示驱动是 TM1638 芯片。
|
||||
|
|
|
@ -2,4 +2,4 @@
|
|||
|
||||
Topunio is a wonderful knickknack for server monitoring. CPU usage, RAM usage, disk usage, disk I/O and network I/O can be displayed on Topuino.
|
||||
|
||||
![](https://img.vvzero.com/blog/Topuino-the-wonderful-Knickknack-for-server-monitoring/1.png)
|
||||
![](https://img.vvzero.com/ih/5d606a6c-926f-4690-8924-8931ec0f5f97.jpg)
|
||||
|
|
|
@ -1,36 +1,34 @@
|
|||
# Topuino 用户操作手册 V0.3
|
||||
# Topuino 用户操作手册
|
||||
|
||||
## 使用前准备
|
||||
|
||||
1. Topuino 依赖 2.4G Wi-Fi 连接互联网,并且不支持 5G Wi-Fi,所以你需要有一个可以连接互联网的 2.4G Wi-Fi 接入点,并且 SSID 不可以包含特殊字符(包括中文字符),且必须有密码;
|
||||
2. Topuino 通过 HTTP 协议与 iot.vvzero.com 通讯以获取实时监控数据,所以请确保网络链路中不存在拦截、缓存等异常行为;
|
||||
3. Topuino 使用 USB TypeC 接口供电,供电电压为 5V,市面上绝大多数手机充电器、电脑 USB 输出均可;
|
||||
4. 被监控机器上需要运行一个 python 脚本以向 iot.vvzero.com 上传监控数据,所以请安装 python3;
|
||||
5. 被监控机器与 Topuino 之间通过一个 UUID 绑定,所以请提前准备好一个 UUID,如果不知道怎么生成 UUID,可以看看 <https://www.uuidgenerator.net/>
|
||||
4. 客户端需要运行一个 python 脚本以向 iot.vvzero.com 上传监控数据,所以请安装 python3;
|
||||
5. 客户端、硬件端通过 Topuino 硬件背面贴着的 SN 号进行绑定,请留意。
|
||||
|
||||
## 待监控的服务器/电脑配置
|
||||
|
||||
1. 安装 python 依赖包 requests 和 psutil,注意 psutil 在某些机器上可能因为缺少某些库而 build 失败(比如 armbian),请用搜索引擎搜索对应的报错信息,一般很容易解决;
|
||||
2. 下载 [监控用的 python 脚本文件](https://git.vvzero.com/villivateur/TopuinoServer/raw/branch/master/slave/main.py);
|
||||
3. 修改 main.py,将准备好的 UUID 填入 main.py 的指定位置;同时请填入需要监控的两个磁盘挂载点;
|
||||
2. 下载 [客户端 python 脚本文件](https://git.vvzero.com/villivateur/Topuino_Client/raw/branch/master/main.py);
|
||||
3. 修改 main.py,将硬件背面的 SN 填入 main.py 的指定位置;同时请填入需要监控的两个磁盘挂载点;
|
||||
4. 直接使用 python3 运行 main.py,将会每隔 1s 向 iot.vvzero.com 报告当前监控数据;
|
||||
5. 如果需要配置自动启动和 daemon,建议参考 [这个 systemd 服务文件](https://git.vvzero.com/villivateur/TopuinoServer/raw/branch/master/slave/topuino_slave.service)
|
||||
5. 如果需要配置自动启动和 daemon,建议参考 [这个 systemd 服务文件](https://git.vvzero.com/villivateur/Topuino_Client/raw/branch/master/topuino_client.service)
|
||||
|
||||
## Topuino 配置
|
||||
|
||||
1. Topuino 初次上电后,右上角的红色状态灯应当以 0.5 Hz 闪烁(一亮一灭表示一个周期),表示正在等待配置;
|
||||
2. 以安卓手机配置为例,请先把准备好的 UUID 复制到剪切板中;
|
||||
3. 为避免某些手机的自动网络优化,请暂时关闭数据流量;
|
||||
4. 请暂时关闭手机上的任何代理软件;
|
||||
5. 打开 Wi-Fi,并连接 SSID 为 `Topuino` 的接入点,密码是 `vvzero.com`。 如果系统提示该网络无法访问互联网,请忽略并继续保持连接;
|
||||
6. 打开一个正常的浏览器,访问 192.168.1.1;
|
||||
7. 在网页中填入 Topuino 可连接的、可访问互联网的 2.4G Wi-Fi 接入点的 SSID 和密码,并粘贴你刚刚复制的 UUID;
|
||||
8. 点击提交后,页面会返回一个 OK;
|
||||
9. 此时 Topuino 的状态灯应当以 2Hz 闪烁,等待几秒至十几秒后,状态灯熄灭,面板开始正常显示。
|
||||
2. 以安卓手机配置为例,为避免某些手机的自动网络优化,请暂时关闭数据流量;
|
||||
3. 请暂时关闭手机上的任何代理软件;
|
||||
4. 打开 Wi-Fi,并连接 SSID 为 `Topuino` 的接入点,密码是 `vvzero.com`。 如果系统提示该网络无法访问互联网,请忽略并继续保持连接;
|
||||
5. 打开一个正常的浏览器,访问 192.168.1.1;
|
||||
6. 在网页中填入 Topuino 可连接的、可访问互联网的 2.4G Wi-Fi 接入点的 SSID 和密码;
|
||||
7. 点击提交后,页面会返回一个 OK(某些情况下可能会出现 Connection Reset,请忽略);
|
||||
8. 此时 Topuino 的状态灯应当以 2Hz 闪烁,等待几秒至十几秒后,状态灯熄灭,面板开始正常显示。
|
||||
|
||||
## 常见问题分析
|
||||
|
||||
- Q:我遇到问题了怎么办?A:请再认真读一遍该手册,如果无法解决,请继续往下看。
|
||||
- Q:上电后闪灯状态不对怎么办?A:请先短按 RESET 键并观察,如果不行,请长按 FUNC 键 6 秒以上,再次观察,如果还是不行,请联系开发者。
|
||||
- Q:我在配置 Topuino 时输错了 SSID、密码或 UUID 怎么办?A:请长按 FUNC 键 6 秒以上,重新配置。
|
||||
- Q:我想换一台服务器监控怎么办?A:一样的,长按 FUNC 键 6 秒以上,重新配置。
|
||||
- Q:我在配置 Topuino 时输错了 SSID、密码怎么办?A:请长按 FUNC 键 6 秒以上,重新配置。
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
factory_info.h
|
|
@ -14,6 +14,4 @@ public:
|
|||
void SetWifiSsid(String ssid);
|
||||
String GetWifiPasswd();
|
||||
void SetWifiPasswd(String password);
|
||||
String GetDeviceUuid();
|
||||
void SetDeviceUuid(String uuid);
|
||||
};
|
||||
|
|
|
@ -1,31 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>Topuino</title>
|
||||
<meta name='viewport' content='width=device-width, initial-scale=1, user-scalable=no' />
|
||||
<link rel='shortcut icon' href='data:,'>
|
||||
</head>
|
||||
<body>
|
||||
<h1 style='text-align: center; font-size: 40px'>Topuino Config Page</h1>
|
||||
<form action='/setup' method='POST'>
|
||||
<div style='text-align: center'>
|
||||
<div style='font-size: 20px; margin-bottom: 15px'>
|
||||
<label for='ssid'><b>Wi-Fi SSID</b></label>
|
||||
<input type='text' name='ssid' required>
|
||||
</div>
|
||||
<div style='font-size: 20px; margin-bottom: 15px'>
|
||||
<label for='psw'><b>Wi-Fi Password</b></label>
|
||||
<input type='password' name='psw' required>
|
||||
</div>
|
||||
<div style='font-size: 20px; margin-bottom: 15px'>
|
||||
<label for='uuid'><b>Device ID</b></label>
|
||||
<input type='text' name='uuid' required>
|
||||
</div>
|
||||
<div style='font-size: 20px'>
|
||||
<button type='submit'>Commit</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
|
@ -2,6 +2,7 @@
|
|||
#include "status_blink.h"
|
||||
#include "user_data.h"
|
||||
#include "func_button.h"
|
||||
#include "factory_info.h"
|
||||
|
||||
extern StatusBlink* statusLed;
|
||||
extern UserData* userdataManager;
|
||||
|
@ -18,8 +19,8 @@ ClientNetwork::ClientNetwork()
|
|||
funcButton->Scan();
|
||||
}
|
||||
statusLed->SetBlinkRate(StatusBlink::BlinkRate::RateAlwaysOff);
|
||||
url = "http://iot.vvzero.com/topuino/getdata?UUID=";
|
||||
url += userdataManager->GetDeviceUuid();
|
||||
url = "http://iot.vvzero.com/topuino/getdata?SN=";
|
||||
url += DEVICE_SN;
|
||||
status = FAIL;
|
||||
}
|
||||
|
||||
|
|
|
@ -29,10 +29,6 @@ static String configPage("\
|
|||
<label for='psw'><b>Wi-Fi Password</b></label>\
|
||||
<input type='password' name='psw' required>\
|
||||
</div>\
|
||||
<div style='font-size: 20px; margin-bottom: 15px'>\
|
||||
<label for='uuid'><b>Device ID</b></label>\
|
||||
<input type='text' name='uuid' required>\
|
||||
</div>\
|
||||
<div style='font-size: 20px'>\
|
||||
<button type='submit'>Commit</button>\
|
||||
</div>\
|
||||
|
@ -50,10 +46,9 @@ static void handleOnConnect()
|
|||
|
||||
static void handleOnCommit()
|
||||
{
|
||||
if (configManager->httpServer.hasArg("ssid") && configManager->httpServer.hasArg("psw") && configManager->httpServer.hasArg("uuid")) {
|
||||
if (configManager->httpServer.hasArg("ssid") && configManager->httpServer.hasArg("psw")) {
|
||||
userdataManager->SetWifiSsid(configManager->httpServer.arg("ssid"));
|
||||
userdataManager->SetWifiPasswd(configManager->httpServer.arg("psw"));
|
||||
userdataManager->SetDeviceUuid(configManager->httpServer.arg("uuid"));
|
||||
userdataManager->ConfirmData();
|
||||
configManager->httpServer.send(200, "text/html", "OK");
|
||||
delay(200);
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#define CLOCK_TM 4 // clock = GPIO connected to clock line of module
|
||||
#define DIO_TM 5 // data = GPIO connected to data line of module
|
||||
#define HIGH_FREQ false //default false, If using a high freq CPU > ~100 MHZ set to true.
|
||||
#define LED_BRIGHTNESS 1
|
||||
|
||||
DisplayPanel::DisplayPanel()
|
||||
{
|
||||
|
@ -16,6 +17,9 @@ DisplayPanel::DisplayPanel()
|
|||
percentLed->displayBegin();
|
||||
diskIoLed->displayBegin();
|
||||
netIoLed->displayBegin();
|
||||
percentLed->brightness(LED_BRIGHTNESS);
|
||||
diskIoLed->brightness(LED_BRIGHTNESS);
|
||||
netIoLed->brightness(LED_BRIGHTNESS);
|
||||
}
|
||||
|
||||
uint16_t DisplayPanel::PercentToBitmap(uint8_t percent)
|
||||
|
|
|
@ -21,6 +21,7 @@ void FuncButton::Scan()
|
|||
}
|
||||
if (pressedTime > 5) {
|
||||
userdataManager->EraseData();
|
||||
delay(1000);
|
||||
ESP.restart();
|
||||
}
|
||||
}
|
22
src/main.cpp
22
src/main.cpp
|
@ -34,13 +34,19 @@ void loop()
|
|||
delay(1000);
|
||||
funcButton->Scan();
|
||||
|
||||
if (netClient->FetchNewData() != OK) {
|
||||
return;
|
||||
if (netClient->FetchNewData() == OK) {
|
||||
displayPanel->DisplayCpuPercent(netClient->GetPercent(CPU_PERCENT));
|
||||
displayPanel->DisplayMemPercent(netClient->GetPercent(MEM_PERCENT));
|
||||
displayPanel->DisplayDisk0Percent(netClient->GetPercent(DISK0_PERCENT));
|
||||
displayPanel->DisplayDisk1Percent(netClient->GetPercent(DISK1_PERCENT));
|
||||
displayPanel->DisplayDiskRate(netClient->GetRate(DISK_READ_RATE), netClient->GetRate(DISK_WRITE_RATE));
|
||||
displayPanel->DisplayNetRate(netClient->GetRate(NET_SENT_RATE), netClient->GetRate(NET_RECV_RATE));
|
||||
} else {
|
||||
displayPanel->DisplayCpuPercent(0);
|
||||
displayPanel->DisplayMemPercent(0);
|
||||
displayPanel->DisplayDisk0Percent(0);
|
||||
displayPanel->DisplayDisk1Percent(0);
|
||||
displayPanel->DisplayDiskRate(0, 0);
|
||||
displayPanel->DisplayNetRate(0, 0);
|
||||
}
|
||||
displayPanel->DisplayCpuPercent(netClient->GetPercent(CPU_PERCENT));
|
||||
displayPanel->DisplayMemPercent(netClient->GetPercent(MEM_PERCENT));
|
||||
displayPanel->DisplayDisk0Percent(netClient->GetPercent(DISK0_PERCENT));
|
||||
displayPanel->DisplayDisk1Percent(netClient->GetPercent(DISK1_PERCENT));
|
||||
displayPanel->DisplayDiskRate(netClient->GetRate(DISK_READ_RATE), netClient->GetRate(DISK_WRITE_RATE));
|
||||
displayPanel->DisplayNetRate(netClient->GetRate(NET_SENT_RATE), netClient->GetRate(NET_RECV_RATE));
|
||||
}
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
#define VALIDATION_OFFSET 0x00
|
||||
#define SSID_OFFSET 0x20
|
||||
#define PASSWORD_OFFSET 0x40
|
||||
#define UUID_OFFSET 0x60
|
||||
|
||||
UserData::UserData()
|
||||
{
|
||||
|
@ -73,13 +72,3 @@ void UserData::SetWifiPasswd(String password)
|
|||
{
|
||||
return WriteEepromString(password, PASSWORD_OFFSET);
|
||||
}
|
||||
|
||||
String UserData::GetDeviceUuid()
|
||||
{
|
||||
return ReadEepromString(UUID_OFFSET);
|
||||
}
|
||||
|
||||
void UserData::SetDeviceUuid(String uuid)
|
||||
{
|
||||
return WriteEepromString(uuid, UUID_OFFSET);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue