Major changes: logic add to panel, local variables, panel histor, users management...

This commit is contained in:
Martino Ferrari
2026-06-18 17:37:04 +02:00
parent 71430bc3b0
commit aba394b84d
54 changed files with 6104 additions and 1166 deletions
+82
View File
@@ -0,0 +1,82 @@
// Panel-local state variables (ds === 'local').
//
// Definitions live in the interface XML and travel with the panel, but the live
// value is instantiated per browser/panel instance starting from the variable's
// initial value — nothing is persisted server-side and no WebSocket traffic is
// involved. The panel logic (a future feature) and write-capable widgets can
// update these values locally.
//
// This module deliberately depends only on the store primitives and types so it
// can be imported by both stores.ts and ws.ts without creating an import cycle.
import { writable, type Readable, type Writable } from './store';
import type { SignalValue, SignalMeta, StateVar } from './types';
const valueStores = new Map<string, Writable<SignalValue>>();
const metaStores = new Map<string, Writable<SignalMeta | null>>();
const DEFAULT_VALUE: SignalValue = { value: null, quality: 'unknown', ts: null };
function valueW(name: string): Writable<SignalValue> {
let s = valueStores.get(name);
if (!s) {
s = writable<SignalValue>(DEFAULT_VALUE);
valueStores.set(name, s);
}
return s;
}
function metaW(name: string): Writable<SignalMeta | null> {
let s = metaStores.get(name);
if (!s) {
s = writable<SignalMeta | null>(null);
metaStores.set(name, s);
}
return s;
}
// coerce parses a state variable's stored string into a live value.
function coerce(v: StateVar): any {
switch (v.type) {
case 'bool':
return v.initial === 'true' || v.initial === '1';
case 'string':
return v.initial;
default: {
const n = parseFloat(v.initial);
return isNaN(n) ? 0 : n;
}
}
}
// initLocalState (re)instantiates every state variable to its initial value and
// publishes metadata. Call this whenever a panel is loaded.
export function initLocalState(vars: StateVar[] | undefined): void {
for (const v of vars ?? []) {
valueW(v.name).set({
value: coerce(v),
quality: 'good',
ts: new Date().toISOString(),
});
metaW(v.name).set({
type: v.type ?? 'number',
unit: v.unit,
displayLow: v.low ?? 0,
displayHigh: v.high ?? 100,
writable: true,
});
}
}
export function getLocalValueStore(name: string): Readable<SignalValue> {
return valueW(name);
}
export function getLocalMetaStore(name: string): Readable<SignalMeta | null> {
return metaW(name);
}
// writeLocalState updates a local variable's live value in place.
export function writeLocalState(name: string, value: any): void {
valueW(name).set({ value, quality: 'good', ts: new Date().toISOString() });
}