added temperature monitor

This commit is contained in:
wt
2026-03-14 05:59:41 +07:00
parent 3e8990f25a
commit febecf4dd9
5 changed files with 174 additions and 0 deletions
+2
View File
@@ -13,6 +13,7 @@
- **Авто-монтирование**: Автоматически монтирует `/dev/mmcblk1p1` в `/media`
- **Поддержка больших файлов**: Загрузка файлов до 200 MB
- **Перезагрузка системы**: Кнопка безопасной перезагрузки с корректным отмонтированием
- **Мониторинг температуры**: Отображение температуры CPU с цветовой индикацией
## Структура проекта
@@ -86,6 +87,7 @@ sudo ./up
| `/api/extlinux` | POST | Запись extlinux.conf |
| `/api/progress` | GET | Статус загрузки |
| `/api/mount` | GET | Статус монтирования |
| `/api/temperature` | GET | Температура CPU |
| `/api/reboot` | POST | Перезагрузка системы |
## Параметры загрузки
+114
View File
@@ -282,6 +282,118 @@ static void handle_mount_status(struct mg_connection *c) {
cJSON_Delete(root);
}
// Handle temperature read
static void handle_temperature(struct mg_connection *c) {
float temperature = 0.0f;
int success = 0;
char path[256];
// Try all thermal zones (0-3)
for (int i = 0; i < 4 && !success; i++) {
snprintf(path, sizeof(path), "/sys/class/thermal/thermal_zone%d/temp", i);
FILE *f = fopen(path, "r");
if (f) {
// Check zone type if available
char type_path[256];
snprintf(type_path, sizeof(type_path), "/sys/class/thermal/thermal_zone%d/type", i);
FILE *type_f = fopen(type_path, "r");
if (type_f) {
char type[32] = {0};
if (fscanf(type_f, "%31s", type) == 1) {
// Prefer CPU or soc zones
int is_cpu = (strstr(type, "cpu") != NULL ||
strstr(type, "soc") != NULL ||
strstr(type, "CPU") != NULL);
int temp_raw;
if (fscanf(f, "%d", &temp_raw) == 1) {
temperature = temp_raw / 1000.0f;
success = 1;
// If this is a CPU zone, use it immediately
if (is_cpu) {
fclose(f);
fclose(type_f);
break;
}
}
}
fclose(type_f);
}
fclose(f);
}
}
// If thermal zones failed, try hwmon (0-3)
if (!success) {
for (int i = 0; i < 4 && !success; i++) {
snprintf(path, sizeof(path), "/sys/class/hwmon/hwmon%d/temp1_input", i);
FILE *f = fopen(path, "r");
if (f) {
// Check sensor name
char name_path[256];
snprintf(name_path, sizeof(name_path), "/sys/class/hwmon/hwmon%d/name", i);
FILE *name_f = fopen(name_path, "r");
if (name_f) {
char name[32] = {0};
if (fscanf(name_f, "%31s", name) == 1) {
// Prefer CPU or sunxi sensors
int is_cpu = (strstr(name, "cpu") != NULL ||
strstr(name, "sunxi") != NULL ||
strstr(name, "CPU") != NULL ||
strstr(name, "acpitz") != NULL);
int temp_raw;
if (fscanf(f, "%d", &temp_raw) == 1) {
temperature = temp_raw / 1000.0f;
success = 1;
if (is_cpu) {
fclose(f);
fclose(name_f);
break;
}
}
}
fclose(name_f);
}
fclose(f);
}
}
}
// Last resort: try any temp1_input
if (!success) {
const char *fallback_paths[] = {
"/sys/class/hwmon/hwmon0/temp1_input",
"/sys/class/hwmon/hwmon1/temp1_input",
"/sys/class/hwmon/hwmon2/temp1_input",
"/sys/class/hwmon/hwmon3/temp1_input",
NULL
};
for (int i = 0; fallback_paths[i] != NULL && !success; i++) {
FILE *f = fopen(fallback_paths[i], "r");
if (f) {
int temp_raw;
if (fscanf(f, "%d", &temp_raw) == 1) {
temperature = temp_raw / 1000.0f;
success = 1;
}
fclose(f);
}
}
}
cJSON *root = cJSON_CreateObject();
cJSON_AddBoolToObject(root, "success", success);
cJSON_AddNumberToObject(root, "temperature", temperature);
cJSON_AddStringToObject(root, "unit", "Celsius");
char *json = cJSON_PrintUnformatted(root);
mg_http_reply(c, 200, "Content-Type: application/json\r\n", "%s\n", json);
free(json);
cJSON_Delete(root);
}
// Handle system reboot
static void handle_reboot(struct mg_connection *c) {
cJSON *root = cJSON_CreateObject();
@@ -417,6 +529,8 @@ static void fn(struct mg_connection *c, int ev, void *ev_data) {
handle_progress(c);
} else if (mg_match_uri(hm->uri, "/api/mount")) {
handle_mount_status(c);
} else if (mg_match_uri(hm->uri, "/api/temperature")) {
handle_temperature(c);
} else if (mg_match_uri(hm->uri, "/api/reboot")) {
handle_reboot(c);
} else if (mg_match_uri(hm->uri, "/")) {
+35
View File
@@ -21,7 +21,9 @@ document.addEventListener("DOMContentLoaded", function () {
// Initialize
checkMountStatus();
checkTemperature();
setInterval(checkMountStatus, 10000); // Check every 10 seconds
setInterval(checkTemperature, 5000); // Check temperature every 5 seconds
// Tab switching
tabBtns.forEach((btn) => {
@@ -306,4 +308,37 @@ document.addEventListener("DOMContentLoaded", function () {
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + " " + sizes[i];
}
// Temperature functions
const temperatureStatus = document.getElementById("temperature-status");
const tempValue = temperatureStatus
? temperatureStatus.querySelector(".temp-value")
: null;
async function checkTemperature() {
if (!tempValue) return;
try {
const response = await fetch("/api/temperature");
const data = await response.json();
if (data.success) {
tempValue.textContent = data.temperature.toFixed(1);
tempValue.style.color = getTempColor(data.temperature);
} else {
tempValue.textContent = "N/A";
tempValue.style.color = "#888";
}
} catch (error) {
tempValue.textContent = "Error";
tempValue.style.color = "#ff4757";
}
}
function getTempColor(temp) {
if (temp < 50) return "#00ff88"; // Green - cool
if (temp < 70) return "#00d9ff"; // Blue - normal
if (temp < 80) return "#ffa500"; // Orange - warm
return "#ff4757"; // Red - hot
}
});
+8
View File
@@ -33,6 +33,14 @@
<span class="status-text">Checking...</span>
</span>
</div>
<div class="status-item">
<span class="label">CPU Temperature:</span>
<span class="value" id="temperature-status">
<span class="temp-icon">🌡️</span>
<span class="temp-value">--</span>
<span class="temp-unit">°C</span>
</span>
</div>
</div>
</section>
+15
View File
@@ -98,6 +98,21 @@ h2 {
box-shadow: 0 0 10px #ff4757;
}
/* Temperature Display */
.temp-icon {
margin-right: 8px;
}
.temp-value {
color: #00d9ff;
font-size: 1.3rem;
}
.temp-unit {
color: #888;
font-size: 0.9rem;
}
/* Upload Section */
.upload-tabs {
display: flex;