Agregar temperatura Top-Rack
This commit is contained in:
@@ -165,12 +165,22 @@ function mockMetrics(device) {
|
||||
speedMbps: device.model === "RPi 3" ? null : 1000,
|
||||
rxBytesPerSecond: Math.round(seededNumber(`${device.id}:rx`, 1200, 95000)),
|
||||
txBytesPerSecond: Math.round(seededNumber(`${device.id}:tx`, 700, 55000))
|
||||
}
|
||||
},
|
||||
rackTemperature: device.rackTemperatureFile
|
||||
? {
|
||||
temperatureC: Number(seededNumber(`${device.id}:rack-temp`, 25, 37).toFixed(1)),
|
||||
sensor: "rack-top",
|
||||
updatedAt: new Date().toISOString(),
|
||||
ageSeconds: 0,
|
||||
sourceFile: device.rackTemperatureFile
|
||||
}
|
||||
: null
|
||||
};
|
||||
}
|
||||
|
||||
const REMOTE_METRICS_SCRIPT = `
|
||||
set +e
|
||||
rack_temperature_file="$RACK_TEMPERATURE_FILE"
|
||||
temp_raw="$(cat /sys/class/thermal/thermal_zone0/temp 2>/dev/null)"
|
||||
if [ -n "$temp_raw" ]; then
|
||||
temp_c="$(awk "BEGIN { printf \\"%.1f\\", $temp_raw / 1000 }")"
|
||||
@@ -259,6 +269,27 @@ if [ "$ha_status" = "n/a" ] && [ "$docker_installed" = "1" ]; then
|
||||
fi
|
||||
fi
|
||||
|
||||
rack_temperature_c=""
|
||||
rack_temperature_sensor=""
|
||||
rack_temperature_updated_at=""
|
||||
rack_temperature_age_seconds=""
|
||||
if [ -n "$rack_temperature_file" ] && [ -r "$rack_temperature_file" ]; then
|
||||
rack_payload="$(cat "$rack_temperature_file" 2>/dev/null)"
|
||||
rack_temperature_c="$(printf '%s' "$rack_payload" | awk -F '[:,}]' '/temperatureC/ { gsub(/[^0-9.\\-]/, "", $2); print $2; exit }')"
|
||||
if [ -z "$rack_temperature_c" ]; then
|
||||
rack_temperature_c="$(printf '%s' "$rack_payload" | awk 'NR==1 { gsub(/[^0-9.\\-]/, "", $1); print $1; exit }')"
|
||||
fi
|
||||
rack_temperature_sensor="$(printf '%s' "$rack_payload" | sed -n 's/.*"sensor"[[:space:]]*:[[:space:]]*"\\([^"]*\\)".*/\\1/p' | head -n 1)"
|
||||
rack_temperature_updated_at="$(printf '%s' "$rack_payload" | sed -n 's/.*"updatedAt"[[:space:]]*:[[:space:]]*"\\([^"]*\\)".*/\\1/p' | head -n 1)"
|
||||
if [ -n "$rack_temperature_updated_at" ]; then
|
||||
rack_updated_epoch="$(date -d "$rack_temperature_updated_at" +%s 2>/dev/null)"
|
||||
now_epoch="$(date +%s 2>/dev/null)"
|
||||
if [ -n "$rack_updated_epoch" ] && [ -n "$now_epoch" ] && [ "$now_epoch" -ge "$rack_updated_epoch" ]; then
|
||||
rack_temperature_age_seconds="$((now_epoch - rack_updated_epoch))"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
printf 'cpuTempC=%s\\n' "$temp_c"
|
||||
printf 'cpuCores=%s\\n' "$cpu_cores"
|
||||
printf 'cpuUsagePercent=%s\\n' "$cpu_usage"
|
||||
@@ -283,6 +314,10 @@ printf 'dockerRunning=%s\\n' "$docker_running"
|
||||
printf 'dockerStopped=%s\\n' "$docker_stopped"
|
||||
printf 'dockerUnhealthy=%s\\n' "$docker_unhealthy"
|
||||
printf 'homeAssistantStatus=%s\\n' "$ha_status"
|
||||
printf 'rackTemperatureC=%s\\n' "$rack_temperature_c"
|
||||
printf 'rackTemperatureSensor=%s\\n' "$rack_temperature_sensor"
|
||||
printf 'rackTemperatureUpdatedAt=%s\\n' "$rack_temperature_updated_at"
|
||||
printf 'rackTemperatureAgeSeconds=%s\\n' "$rack_temperature_age_seconds"
|
||||
`;
|
||||
|
||||
function parseKeyValueOutput(output) {
|
||||
@@ -301,6 +336,10 @@ function toNumber(value, fallback = 0) {
|
||||
return Number.isFinite(parsed) ? parsed : fallback;
|
||||
}
|
||||
|
||||
function shellQuote(value) {
|
||||
return `'${String(value || "").replace(/'/g, `'\\''`)}'`;
|
||||
}
|
||||
|
||||
function networkRates(device, values) {
|
||||
const sampleKey = device.id || `${device.host}:${device.port || 22}`;
|
||||
const now = Date.now();
|
||||
@@ -333,9 +372,12 @@ function networkRates(device, values) {
|
||||
};
|
||||
}
|
||||
|
||||
function runCommandWithInput(command, args, input, timeoutMs) {
|
||||
function runCommandWithInput(command, args, input, timeoutMs, env = {}) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const child = spawn(command, args, { stdio: ["pipe", "pipe", "pipe"] });
|
||||
const child = spawn(command, args, {
|
||||
stdio: ["pipe", "pipe", "pipe"],
|
||||
env: { ...process.env, ...env }
|
||||
});
|
||||
let stdout = "";
|
||||
let stderr = "";
|
||||
let settled = false;
|
||||
@@ -428,9 +470,11 @@ async function sshMetrics(device) {
|
||||
];
|
||||
}
|
||||
|
||||
const { stdout } = await runCommandWithInput(command, args, REMOTE_METRICS_SCRIPT, timeoutMs);
|
||||
const remoteScript = `RACK_TEMPERATURE_FILE=${shellQuote(device.rackTemperatureFile || "")}\n${REMOTE_METRICS_SCRIPT}`;
|
||||
const { stdout } = await runCommandWithInput(command, args, remoteScript, timeoutMs);
|
||||
const values = parseKeyValueOutput(stdout);
|
||||
const temp = toNumber(values.cpuTempC, 0);
|
||||
const rackTemperatureC = toNumber(values.rackTemperatureC, null);
|
||||
const loadAverage = String(values.loadAverage || "")
|
||||
.split(/\s+/)
|
||||
.filter(Boolean)
|
||||
@@ -460,7 +504,16 @@ async function sshMetrics(device) {
|
||||
detected: values.homeAssistantStatus && values.homeAssistantStatus !== "n/a",
|
||||
status: values.homeAssistantStatus || "n/a"
|
||||
},
|
||||
network: networkRates(device, values)
|
||||
network: networkRates(device, values),
|
||||
rackTemperature: Number.isFinite(rackTemperatureC)
|
||||
? {
|
||||
temperatureC: Number(rackTemperatureC.toFixed(1)),
|
||||
sensor: values.rackTemperatureSensor || "",
|
||||
updatedAt: values.rackTemperatureUpdatedAt || "",
|
||||
ageSeconds: toNumber(values.rackTemperatureAgeSeconds, null),
|
||||
sourceFile: device.rackTemperatureFile || ""
|
||||
}
|
||||
: null
|
||||
};
|
||||
}
|
||||
|
||||
@@ -520,6 +573,15 @@ function buildSummary(devices) {
|
||||
.filter((device) => device.metrics && Number.isFinite(device.metrics.cpuTempC))
|
||||
.map((device) => ({ name: device.name, value: device.metrics.cpuTempC }));
|
||||
const hottest = temps.sort((a, b) => b.value - a.value)[0] || null;
|
||||
const rackTemperature = online
|
||||
.map((device) => {
|
||||
const rack = device.metrics?.rackTemperature;
|
||||
return rack && Number.isFinite(rack.temperatureC)
|
||||
? { ...rack, deviceName: device.name }
|
||||
: null;
|
||||
})
|
||||
.filter(Boolean)
|
||||
.sort((a, b) => (a.ageSeconds ?? Number.MAX_SAFE_INTEGER) - (b.ageSeconds ?? Number.MAX_SAFE_INTEGER))[0] || null;
|
||||
const alerts = [];
|
||||
|
||||
for (const device of devices) {
|
||||
@@ -537,6 +599,7 @@ function buildSummary(devices) {
|
||||
online: online.length,
|
||||
offline: active.length - online.length,
|
||||
hottest,
|
||||
rackTemperature,
|
||||
alerts
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user