Switched from influx to victoria metrics (more light weight for pi)
This commit is contained in:
104
server/src/sensors.mjs
Normal file
104
server/src/sensors.mjs
Normal file
@@ -0,0 +1,104 @@
|
||||
import {cfg} from './config.mjs';
|
||||
|
||||
async function query(c, q, start, end) {
|
||||
const url = new URL('/api/v1/query_range', c.VM_URL);
|
||||
url.searchParams.set('query', q);
|
||||
url.searchParams.set('step', '60s');
|
||||
if (start) url.searchParams.set('start', start);
|
||||
if (end) url.searchParams.set('end', end);
|
||||
const res = await fetch(url);
|
||||
const json = await res.json();
|
||||
return json.data?.result || [];
|
||||
}
|
||||
|
||||
async function queryInstant(c, q) {
|
||||
const url = new URL('/api/v1/query', c.VM_URL);
|
||||
url.searchParams.set('query', q);
|
||||
const res = await fetch(url);
|
||||
const json = await res.json();
|
||||
return json.data?.result || [];
|
||||
}
|
||||
|
||||
function metricToFields(results) {
|
||||
const out = {};
|
||||
for (const r of results) {
|
||||
const val = r.value?.[1] ?? r.values?.at(-1)?.[1];
|
||||
if (val !== undefined) out[r.metric.__name__] = parseFloat(val);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
export async function queryCurrent() {
|
||||
const c = cfg();
|
||||
const results = await queryInstant(c, `{__name__!=""}`);
|
||||
return {time: new Date(), ...metricToFields(results)};
|
||||
}
|
||||
|
||||
export async function queryHourly(start, end) {
|
||||
const c = cfg();
|
||||
const s = Math.floor(start.getTime() / 1000);
|
||||
const e = Math.floor(end.getTime() / 1000);
|
||||
const byTime = {};
|
||||
|
||||
const results = await query(c, `avg_over_time({__name__!=""}[1h])`, s, e);
|
||||
results.forEach(r => {
|
||||
r.values.forEach(([ts, val]) => {
|
||||
const time = new Date(ts * 1000).toISOString().slice(0, 13) + ':00';
|
||||
if (!byTime[time]) byTime[time] = {time};
|
||||
byTime[time][r.metric.__name__] = parseFloat(val);
|
||||
});
|
||||
});
|
||||
return Object.values(byTime).sort((a, b) => a.time.localeCompare(b.time));
|
||||
}
|
||||
|
||||
export async function queryDaily(start, end) {
|
||||
const c = cfg();
|
||||
const s = Math.floor(start.getTime() / 1000);
|
||||
const e = Math.floor(end.getTime() / 1000);
|
||||
const byTime = {};
|
||||
|
||||
const [means, mins, maxs] = await Promise.all([
|
||||
query(c, `avg_over_time({__name__!=""}[1d])`, s, e),
|
||||
query(c, `min_over_time({__name__!=""}[1d])`, s, e),
|
||||
query(c, `max_over_time({__name__!=""}[1d])`, s, e),
|
||||
]);
|
||||
|
||||
means.forEach(r => {
|
||||
r.values.forEach(([ts, val]) => {
|
||||
const time = new Date(ts * 1000).toISOString().slice(0, 10);
|
||||
if (!byTime[time]) byTime[time] = {time};
|
||||
byTime[time][r.metric.__name__] = parseFloat(val);
|
||||
});
|
||||
});
|
||||
|
||||
mins.forEach(r => {
|
||||
if (r.metric.__name__ !== 'temperature') return;
|
||||
r.values.forEach(([ts, val]) => {
|
||||
const time = new Date(ts * 1000).toISOString().slice(0, 10);
|
||||
if (!byTime[time]) byTime[time] = {time};
|
||||
byTime[time].env_temp_min_c = parseFloat(val);
|
||||
});
|
||||
});
|
||||
|
||||
maxs.forEach(r => {
|
||||
if (r.metric.__name__ !== 'temperature') return;
|
||||
r.values.forEach(([ts, val]) => {
|
||||
const time = new Date(ts * 1000).toISOString().slice(0, 10);
|
||||
if (!byTime[time]) byTime[time] = {time};
|
||||
byTime[time].env_temp_max_c = parseFloat(val);
|
||||
});
|
||||
});
|
||||
|
||||
return Object.values(byTime).sort((a, b) => a.time.localeCompare(b.time));
|
||||
}
|
||||
|
||||
export async function getCoords() {
|
||||
const c = cfg();
|
||||
const results = await queryInstant(c, `{__name__=~"latitude|longitude|altitude"}`);
|
||||
const fields = metricToFields(results);
|
||||
|
||||
if (fields.latitude && fields.longitude) {
|
||||
return {latitude: fields.latitude, longitude: fields.longitude, altitude: fields.altitude || c.ALTITUDE};
|
||||
}
|
||||
return {latitude: c.LATITUDE, longitude: c.LONGITUDE, altitude: c.ALTITUDE};
|
||||
}
|
||||
Reference in New Issue
Block a user