Files
mars3142_collection/plugin/actions/PetrolAction.js
T
mars3142 fbf40f75b2 first plugins for Ulanzi D200H
- petrol watch
- copilot usage

Signed-off-by: Peter Siegmund <developer@mars3142.org>
2026-04-09 20:42:31 +02:00

152 lines
4.3 KiB
JavaScript

class PetrolAction {
constructor($UD, context) {
this.$UD = $UD;
this.context = context;
this.config = {
url: '',
stationUuid: '',
fuelType: '',
refreshRate: '1',
};
this.refreshTimer = null;
this.debounceTimer = 0;
this.previousPrice = null;
this.lastDelta = null;
this.$UD.onDidReceiveSettings(jsn => {
if (jsn.context !== this.context) return;
const s = jsn.settings || {};
this.config = Object.assign(this.config, s);
if (s.previousPrice != null) this.previousPrice = s.previousPrice;
if (s.lastDelta != null) this.lastDelta = s.lastDelta;
});
}
setActive() {}
onClear() {
if (this.refreshTimer) {
clearInterval(this.refreshTimer);
this.refreshTimer = null;
}
if (this.debounceTimer) {
clearTimeout(this.debounceTimer);
this.debounceTimer = 0;
}
}
setParams(jsn) {
const params = (jsn && jsn.param) || {};
this.config = Object.assign(this.config, params);
this.$UD.getSettings(this.context);
this.start();
}
onRun() {
this.fetchPrice();
}
start() {
this.onClear();
this.fetchPrice();
const duration = this.getRefreshDuration();
if (duration > 0) {
this.refreshTimer = setInterval(() => this.fetchPrice(), duration * 60 * 1000);
}
}
async fetchPrice() {
if (this.debounceTimer) clearTimeout(this.debounceTimer);
this.debounceTimer = setTimeout(async () => {
if (!this.config.url || !this.config.stationUuid || !this.config.fuelType) {
this.renderButton('?', null);
return;
}
try {
const response = await fetch(this.config.url);
const text = await response.text();
const raw = this.parsePrometheus(text);
if (raw) {
const current = parseFloat(raw);
if (this.previousPrice !== null) {
const delta = current - this.previousPrice;
if (delta !== 0) this.lastDelta = delta;
}
this.previousPrice = current;
this.renderButton(`${raw}`, this.lastDelta);
this.$UD.setSettings({ ...this.config, previousPrice: this.previousPrice, lastDelta: this.lastDelta }, this.context);
} else {
this.renderButton('N/A', null);
}
} catch (e) {
this.renderButton('ERR', null);
}
}, 300);
}
parsePrometheus(text) {
for (const line of text.split('\n')) {
const trimmed = line.trim();
if (!trimmed || trimmed.startsWith('#')) continue;
if (trimmed.startsWith('petrol_price_euro') && trimmed.includes(this.config.stationUuid) && trimmed.includes(this.config.fuelType)) {
const closingBrace = trimmed.indexOf('}');
if (closingBrace !== -1) return trimmed.slice(closingBrace + 1).trim();
}
}
return null;
}
renderButton(priceText, delta) {
const canvas = document.createElement('canvas');
canvas.width = 196;
canvas.height = 196;
const ctx = canvas.getContext('2d');
ctx.fillStyle = '#000000';
ctx.fillRect(0, 0, 196, 196);
ctx.strokeStyle = '#000';
ctx.lineWidth = 3;
ctx.textBaseline = 'middle';
ctx.textAlign = 'center';
// Fuel type — top, light blue
ctx.fillStyle = '#7ec8e3';
ctx.font = 'bold 28px "Source Han Sans SC"';
ctx.strokeText(this.config.fuelType, 98, 45);
ctx.fillText(this.config.fuelType, 98, 45);
// Price — middle, yellow
const fSize = priceText.length > 6 ? 34 - priceText.length : 40;
ctx.fillStyle = '#f0c040';
ctx.font = `bold ${fSize}px "Source Han Sans SC"`;
ctx.strokeText(priceText, 98, 105);
ctx.fillText(priceText, 98, 105);
// Delta — bottom
if (delta !== null) {
const arrow = delta > 0 ? '▲' : '▼';
const color = delta > 0 ? '#ff6b6b' : '#6bff6b';
const deltaText = `${arrow} ${Math.abs(delta).toFixed(3)}`;
ctx.fillStyle = color;
ctx.font = '18px "Source Han Sans SC"';
ctx.strokeText(deltaText, 98, 142);
ctx.fillText(deltaText, 98, 142);
}
this.$UD.setBaseDataIcon(this.context, canvas.toDataURL('image/png'));
}
getRefreshDuration() {
switch (this.config.refreshRate) {
case '1': return 1;
case '2': return 2;
case '3': return 5;
case '4': return 10;
case '5': return 30;
case '6': return 60;
default: return 0;
}
}
}