Switched from influx to victoria metrics (more light weight for pi)
This commit is contained in:
@@ -1,11 +1,11 @@
|
|||||||
import {cfg} from './config.mjs';
|
import {cfg} from './config.mjs';
|
||||||
|
|
||||||
const MEASUREMENTS = ['accumulation', 'environment', 'light', 'lightning', 'rain', 'seismic', 'wind'];
|
async function query(c, q, start, end) {
|
||||||
|
|
||||||
async function query(c, q) {
|
|
||||||
const url = new URL('/api/v1/query_range', c.INFLUX_URL);
|
const url = new URL('/api/v1/query_range', c.INFLUX_URL);
|
||||||
url.searchParams.set('query', q);
|
url.searchParams.set('query', q);
|
||||||
url.searchParams.set('step', '60s');
|
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 res = await fetch(url);
|
||||||
const json = await res.json();
|
const json = await res.json();
|
||||||
return json.data?.result || [];
|
return json.data?.result || [];
|
||||||
@@ -29,69 +29,67 @@ function metricToFields(results) {
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// vm.mjs
|
||||||
export async function queryCurrent() {
|
export async function queryCurrent() {
|
||||||
const c = cfg();
|
const c = cfg();
|
||||||
const now = Math.floor(Date.now() / 1000);
|
|
||||||
const out = {time: new Date()};
|
const out = {time: new Date()};
|
||||||
|
|
||||||
for (const m of MEASUREMENTS) {
|
// Query all metrics at once, no measurement filter needed
|
||||||
const results = await queryInstant(c, `{measurement="${m}"}`);
|
const results = await queryInstant(c, `{__name__!=""}`);
|
||||||
Object.assign(out, metricToFields(results));
|
Object.assign(out, metricToFields(results));
|
||||||
}
|
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function queryHourly(start, end) {
|
export async function queryHourly(start, end) {
|
||||||
const c = cfg();
|
const c = cfg();
|
||||||
const s = Math.floor(start.getTime() / 1000);
|
const s = Math.floor(start.getTime() / 1000);
|
||||||
const e = Math.floor(end.getTime() / 1000);
|
const e = Math.floor(end.getTime() / 1000);
|
||||||
const byTime = {};
|
const byTime = {};
|
||||||
|
|
||||||
for (const m of MEASUREMENTS) {
|
const results = await query(c, `avg_over_time({__name__!=""}[1h])`, s, e);
|
||||||
const results = await query(c, `avg_over_time({measurement="${m}"}[1h])`);
|
results.forEach(r => {
|
||||||
results.forEach(r => {
|
const field = r.metric.__name__;
|
||||||
const field = r.metric.__name__;
|
r.values.forEach(([ts, val]) => {
|
||||||
r.values.forEach(([ts, val]) => {
|
const time = new Date(ts * 1000).toISOString().slice(0, 13) + ':00';
|
||||||
const time = new Date(ts * 1000).toISOString().slice(0, 13) + ':00';
|
if (!byTime[time]) byTime[time] = {time};
|
||||||
if (!byTime[time]) byTime[time] = {time};
|
byTime[time][field] = parseFloat(val);
|
||||||
byTime[time][field] = parseFloat(val);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
});
|
||||||
return Object.values(byTime).sort((a, b) => a.time.localeCompare(b.time));
|
return Object.values(byTime).sort((a, b) => a.time.localeCompare(b.time));
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function queryDaily(start, end) {
|
export async function queryDaily(start, end) {
|
||||||
const c = cfg();
|
const c = cfg();
|
||||||
|
const s = Math.floor(start.getTime() / 1000);
|
||||||
|
const e = Math.floor(end.getTime() / 1000);
|
||||||
const byTime = {};
|
const byTime = {};
|
||||||
|
|
||||||
for (const m of ['accumulation', 'environment', 'light', 'lightning', 'seismic']) {
|
const [means, mins, maxs] = await Promise.all([
|
||||||
const [means, mins, maxs] = await Promise.all([
|
query(c, `avg_over_time({__name__!=""}[1d])`, s, e),
|
||||||
query(c, `avg_over_time({measurement="${m}"}[1d])`),
|
query(c, `min_over_time({__name__!=""}[1d])`, s, e),
|
||||||
query(c, `min_over_time({measurement="${m}"}[1d])`),
|
query(c, `max_over_time({__name__!=""}[1d])`, s, e),
|
||||||
query(c, `max_over_time({measurement="${m}"}[1d])`),
|
]);
|
||||||
]);
|
|
||||||
|
|
||||||
means.forEach(r => {
|
means.forEach(r => {
|
||||||
r.values.forEach(([ts, val]) => {
|
r.values.forEach(([ts, val]) => {
|
||||||
const time = new Date(ts * 1000).toISOString().slice(0, 10);
|
const time = new Date(ts * 1000).toISOString().slice(0, 10);
|
||||||
if (!byTime[time]) byTime[time] = {time};
|
if (!byTime[time]) byTime[time] = {time};
|
||||||
byTime[time][r.metric.__name__] = parseFloat(val);
|
byTime[time][r.metric.__name__] = parseFloat(val);
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
const applyMinMax = (results, suffix) => results.forEach(r => {
|
const applyMinMax = (results, suffix) => results.forEach(r => {
|
||||||
if (r.metric.__name__ !== 'temperature') return;
|
if (r.metric.__name__ !== 'temperature') return;
|
||||||
r.values.forEach(([ts, val]) => {
|
r.values.forEach(([ts, val]) => {
|
||||||
const time = new Date(ts * 1000).toISOString().slice(0, 10);
|
const time = new Date(ts * 1000).toISOString().slice(0, 10);
|
||||||
if (!byTime[time]) byTime[time] = {time};
|
if (!byTime[time]) byTime[time] = {time};
|
||||||
byTime[time][suffix] = parseFloat(val);
|
byTime[time][suffix] = parseFloat(val);
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
applyMinMax(mins, 'env_temp_min_c');
|
||||||
|
applyMinMax(maxs, 'env_temp_max_c');
|
||||||
|
|
||||||
applyMinMax(mins, 'env_temp_min_c');
|
|
||||||
applyMinMax(maxs, 'env_temp_max_c');
|
|
||||||
}
|
|
||||||
return Object.values(byTime).sort((a, b) => a.time.localeCompare(b.time));
|
return Object.values(byTime).sort((a, b) => a.time.localeCompare(b.time));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
8
setup.sh
8
setup.sh
@@ -3,7 +3,6 @@ set -e
|
|||||||
|
|
||||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
USER_NAME="$(whoami)"
|
USER_NAME="$(whoami)"
|
||||||
VM_VERSION="1.99.0"
|
|
||||||
VM_DIR="/opt/victoriametrics"
|
VM_DIR="/opt/victoriametrics"
|
||||||
|
|
||||||
echo "🔧 Setting up Weather Station..."
|
echo "🔧 Setting up Weather Station..."
|
||||||
@@ -13,10 +12,9 @@ echo "🔧 Setting up Weather Station..."
|
|||||||
if ! systemctl is-enabled --quiet victoriametrics 2>/dev/null; then
|
if ! systemctl is-enabled --quiet victoriametrics 2>/dev/null; then
|
||||||
echo "📦 Installing VictoriaMetrics..."
|
echo "📦 Installing VictoriaMetrics..."
|
||||||
sudo mkdir -p $VM_DIR/data
|
sudo mkdir -p $VM_DIR/data
|
||||||
|
cd $VM_DIR
|
||||||
wget -qO /tmp/vm.tar.gz \
|
wget -qO vm.tar.gz "https://github.com/VictoriaMetrics/VictoriaMetrics/releases/download/v1.146.0/victoria-metrics-linux-arm64-v1.146.0.tar.gz"
|
||||||
"https://github.com/VictoriaMetrics/VictoriaMetrics/releases/download/v${VM_VERSION}/victoria-metrics-arm-v7-v${VM_VERSION}.tar.gz"
|
sudo tar -xzf vm.tar.gz
|
||||||
sudo tar xf /tmp/vm.tar.gz -C $VM_DIR
|
|
||||||
sudo chmod +x $VM_DIR/victoria-metrics-prod
|
sudo chmod +x $VM_DIR/victoria-metrics-prod
|
||||||
rm /tmp/vm.tar.gz
|
rm /tmp/vm.tar.gz
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user