Compare commits

...

7 Commits

Author SHA1 Message Date
Villivateur Von 5a9c93d329 update 2022-04-06 20:54:02 +08:00
Villivateur Von 0863c5c6d4 fix possible flash write problem 2022-03-29 22:27:51 +08:00
Villivateur Von 283364ea70 update User manual 2022-03-28 20:12:27 +08:00
Villivateur Von 80a0ce5852 update to SN mode 2022-03-27 12:40:12 +08:00
Villivateur Von a3dc135d70 adjust brightness 2022-03-23 22:03:10 +08:00
Villivateur Von 793cc69a9e fix readme 2022-03-17 20:21:36 +08:00
Villivateur Von 32c0376820 delete vscode 2022-03-17 20:20:21 +08:00
15 changed files with 44 additions and 109 deletions

5
.gitignore vendored
View File

@ -1,5 +1,2 @@
.pio
.vscode/.browse.c_cpp.db*
.vscode/c_cpp_properties.json
.vscode/launch.json
.vscode/ipch
.vscode

View File

@ -1,7 +0,0 @@
{
// See http://go.microsoft.com/fwlink/?LinkId=827846
// for the documentation about the extensions.json format
"recommendations": [
"platformio.platformio-ide"
]
}

17
.vscode/settings.json vendored
View File

@ -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"
}
}

View File

@ -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 芯片。

View File

@ -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)

View File

@ -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 秒以上,重新配置。

1
include/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
factory_info.h

View File

@ -14,6 +14,4 @@ public:
void SetWifiSsid(String ssid);
String GetWifiPasswd();
void SetWifiPasswd(String password);
String GetDeviceUuid();
void SetDeviceUuid(String uuid);
};

View File

@ -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>

View File

@ -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;
}

View File

@ -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);

View File

@ -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)

View File

@ -21,6 +21,7 @@ void FuncButton::Scan()
}
if (pressedTime > 5) {
userdataManager->EraseData();
delay(1000);
ESP.restart();
}
}

View File

@ -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));
}

View File

@ -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);
}