added temperature monitor
This commit is contained in:
@@ -13,6 +13,7 @@
|
|||||||
- **Авто-монтирование**: Автоматически монтирует `/dev/mmcblk1p1` в `/media`
|
- **Авто-монтирование**: Автоматически монтирует `/dev/mmcblk1p1` в `/media`
|
||||||
- **Поддержка больших файлов**: Загрузка файлов до 200 MB
|
- **Поддержка больших файлов**: Загрузка файлов до 200 MB
|
||||||
- **Перезагрузка системы**: Кнопка безопасной перезагрузки с корректным отмонтированием
|
- **Перезагрузка системы**: Кнопка безопасной перезагрузки с корректным отмонтированием
|
||||||
|
- **Мониторинг температуры**: Отображение температуры CPU с цветовой индикацией
|
||||||
|
|
||||||
## Структура проекта
|
## Структура проекта
|
||||||
|
|
||||||
@@ -86,6 +87,7 @@ sudo ./up
|
|||||||
| `/api/extlinux` | POST | Запись extlinux.conf |
|
| `/api/extlinux` | POST | Запись extlinux.conf |
|
||||||
| `/api/progress` | GET | Статус загрузки |
|
| `/api/progress` | GET | Статус загрузки |
|
||||||
| `/api/mount` | GET | Статус монтирования |
|
| `/api/mount` | GET | Статус монтирования |
|
||||||
|
| `/api/temperature` | GET | Температура CPU |
|
||||||
| `/api/reboot` | POST | Перезагрузка системы |
|
| `/api/reboot` | POST | Перезагрузка системы |
|
||||||
|
|
||||||
## Параметры загрузки
|
## Параметры загрузки
|
||||||
|
|||||||
+114
@@ -282,6 +282,118 @@ static void handle_mount_status(struct mg_connection *c) {
|
|||||||
cJSON_Delete(root);
|
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
|
// Handle system reboot
|
||||||
static void handle_reboot(struct mg_connection *c) {
|
static void handle_reboot(struct mg_connection *c) {
|
||||||
cJSON *root = cJSON_CreateObject();
|
cJSON *root = cJSON_CreateObject();
|
||||||
@@ -417,6 +529,8 @@ static void fn(struct mg_connection *c, int ev, void *ev_data) {
|
|||||||
handle_progress(c);
|
handle_progress(c);
|
||||||
} else if (mg_match_uri(hm->uri, "/api/mount")) {
|
} else if (mg_match_uri(hm->uri, "/api/mount")) {
|
||||||
handle_mount_status(c);
|
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")) {
|
} else if (mg_match_uri(hm->uri, "/api/reboot")) {
|
||||||
handle_reboot(c);
|
handle_reboot(c);
|
||||||
} else if (mg_match_uri(hm->uri, "/")) {
|
} else if (mg_match_uri(hm->uri, "/")) {
|
||||||
|
|||||||
+35
@@ -21,7 +21,9 @@ document.addEventListener("DOMContentLoaded", function () {
|
|||||||
|
|
||||||
// Initialize
|
// Initialize
|
||||||
checkMountStatus();
|
checkMountStatus();
|
||||||
|
checkTemperature();
|
||||||
setInterval(checkMountStatus, 10000); // Check every 10 seconds
|
setInterval(checkMountStatus, 10000); // Check every 10 seconds
|
||||||
|
setInterval(checkTemperature, 5000); // Check temperature every 5 seconds
|
||||||
|
|
||||||
// Tab switching
|
// Tab switching
|
||||||
tabBtns.forEach((btn) => {
|
tabBtns.forEach((btn) => {
|
||||||
@@ -306,4 +308,37 @@ document.addEventListener("DOMContentLoaded", function () {
|
|||||||
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
||||||
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + " " + sizes[i];
|
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
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -33,6 +33,14 @@
|
|||||||
<span class="status-text">Checking...</span>
|
<span class="status-text">Checking...</span>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</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>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
|||||||
@@ -98,6 +98,21 @@ h2 {
|
|||||||
box-shadow: 0 0 10px #ff4757;
|
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 Section */
|
||||||
.upload-tabs {
|
.upload-tabs {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
Reference in New Issue
Block a user