Files

120 lines
3.5 KiB
JavaScript

import Gio from 'gi://Gio';
import GLib from 'gi://GLib';
export default class WattdUtil {
constructor(intervalSeconds = 5) {
this._powerDir = '/run/power';
this._readings = [];
this._updated = false;
this._available = GLib.file_test(this._powerDir, GLib.FileTest.IS_DIR);
this._intervalUsec = 0;
this._lastUpdateUsec = 0;
this.interval = intervalSeconds;
}
get available() {
return this._available;
}
get updated() {
return this._updated;
}
set updated(updated) {
this._updated = updated;
}
execute(callback) {
const nowUsec = GLib.get_monotonic_time();
const remaining = this._intervalUsec - (nowUsec - this._lastUpdateUsec);
if (this._intervalUsec > 0 && this._lastUpdateUsec !== 0 && remaining > 0) {
if (callback)
callback();
return;
}
this._updated = false;
this._readings = [];
try {
this._available = GLib.file_test(this._powerDir, GLib.FileTest.IS_DIR);
if (!this._available) {
return;
}
const directory = Gio.File.new_for_path(this._powerDir);
let enumerator = null;
try {
enumerator = directory.enumerate_children('standard::name,standard::type', Gio.FileQueryInfoFlags.NONE, null);
let info;
while ((info = enumerator.next_file(null)) !== null) {
if (info.get_file_type() !== Gio.FileType.REGULAR)
continue;
const name = info.get_name();
const file = directory.get_child(name);
try {
const [ok, contents] = file.load_contents(null);
if (!ok)
continue;
const value = parseFloat(new TextDecoder('utf-8').decode(contents).trim());
if (isNaN(value))
continue;
const feature = {
label: this._formatLabel(name),
power: Math.abs(value),
};
this._readings.push(feature);
} catch (e) {
logError(e, `[FREON] Failed to read wattd metric ${name}`);
}
}
} finally {
if (enumerator !== null)
enumerator.close(null);
}
this._readings.sort((a, b) => a.label.localeCompare(b.label, undefined, {numeric: true}));
} catch (e) {
logError(e, '[FREON] Failed to enumerate wattd metrics');
this._available = false;
this._readings = [];
} finally {
this._lastUpdateUsec = nowUsec;
this._updated = true;
if (callback)
callback();
}
}
get power() {
return this._readings;
}
destroy() {
this._readings = [];
this._lastUpdateUsec = 0;
}
set interval(seconds) {
const clamped = Math.max(1, seconds | 0);
this._intervalUsec = clamped * 1000000;
this._lastUpdateUsec = 0;
}
_formatLabel(name) {
const parts = name.split(/[-_]/).filter(part => part.length > 0);
if (parts.length === 0)
return name;
return parts.map(part => part[0].toUpperCase() + part.slice(1)).join(' ');
}
}