Files
boxweb/templates/secop.js
T
zolliker 3ec80585b1 implement configuration of format for numbers display
- '*' for a default (5 signiciant digits)
- '*<dig>' for an other number of significant digits
- '*.<dig>' for fixed number of digits after decimal point
2026-04-10 12:47:17 +02:00

209 lines
6.0 KiB
JavaScript

const svgElements = {};
var colors = {true: "#66ffba", false: "#ff3067", error: "#ffff00", clicked: "#ffffff", ok: "#ffffff"};
let active_state = "MANUAL";
var description;
var changeFuncs = {};
var updateValues = {};
function formatValue(value, prec) {
return Number(value.toPrecision(prec)).toString();
}
function handle_describing(action, modpar, data) {
description = data;
for (const mod of Object.keys(data.modules)) {
const mdesc = data.modules[mod];
if (! mdesc) {
console.log('bad mod', mod)
continue;
}
const elems = document.querySelectorAll("[id^='" + mod + ":']");
let stateElement = null;
let clickElement = null;
elems.forEach(elem => {
let [parmod, ...func] = elem.id.split('-');
const [mod, param] = parmod.split(':');
// console.log(mod, param, func);
if (func.includes("click")) {
clickElement = elem;
if (writable) {
addClickListener(elem, mod, toggleTarget);
}
}
if (func.includes("fault")) {
changeFuncs[mod + ":status"] = function (value) {
changeFill(elem, value[0] < 400 ? "ok" : "error");
}
}
if (func.includes("state")) {
stateElement = elem;
changeFuncs[mod + ":" + (param || 'value')] = function (value) {
changeFill(elem, value);
}
}
if (func.includes("text")) {
const pat = elem.textContent;
changeFuncs[mod + ":" + (param || 'value')] = function (value) {
let [repl, dot, fix] = pat.match(/\*(\.)?(\d)?/);
if (dot) {
formatted = value.toFixed(fix || 0);
} else {
formatted = formatValue(value, fix || 5);
}
elem.textContent = pat.replace(repl, formatted);
// elem.style.color = "000000";
}
}
if (func.includes("command")) {
console.log(func, mod, param);
if (writable) {
addClickListener(elem, mod + ":" + param, sendCommand);
}
}
})
if (stateElement && clickElement) {
// the clickElement needs a reference to the state for toggleTarget()
clickElement.stateElement = stateElement;
}
}
console.log('ACTIVATE', changeFuncs);
doSend("activate");
}
function handle_update(action, modpar, data) {
// console.log(action, modpar, data);
if (modpar in changeFuncs) {
updateValues[modpar] = data[0];
}
}
handle_reply = handle_update;
handle_changed = handle_update;
function handle_error_update(action, modpar, data) {
}
function handleMSG(msg) {
const [action, modpar, ...tail] = msg.split(" ");
let data = tail.join(' ');
if (data) {
data = JSON.parse(data);
}
handler = window["handle_" + action];
if (handler) {
handler(action, modpar, data);
} else {
console.log(msg);
}
}
function processUpdates() {
let updates = updateValues;
updateValues = {};
for (const [modpar, value] of Object.entries(updates)) {
// console.log('process', modpar, value);
changeFuncs[modpar](value);
}
requestAnimationFrame(processUpdates);
}
function handleStateClick(state) {
changeState("dil", state);
document.getElementById(state.toLowerCase() + "-btn").style.backgroundColor = "white";
document.getElementById(active_state.toLowerCase() + "-btn").style.backgroundColor = "rgb(175, 176, 177)";
active_state = state;
}
function updateState(state) {
document.getElementById(state.toLowerCase() + "-btn").style.backgroundColor = "white";
document.getElementById(active_state.toLowerCase() + "-btn").style.backgroundColor = "rgb(175, 176, 177)";
active_state = state;
}
function changeFill(element, state) {
// stateElement = element.stateElement || element;
element.state = state;
if (state in colors) {
element.style.fill = colors[state];
} else {
element.style.fill = "#eaeaea" ;
}
}
function writeToScreen(message) {
const output = document.getElementById("outputtext");
output.value += message;
output.scrollTop = output.scrollHeight;
}
function doConnect() {
websocket = new WebSocket(wsaddr);
websocket.onopen = evt => onOpen(evt);
websocket.onclose = evt => onClose(evt);
websocket.onmessage = evt => handleMSG(evt.data);
websocket.onerror = evt => onError(evt);
}
function onOpen(evt) {
writeToScreen("Connected to "+ wsaddr + "\n");
doSend("describe");
/*
for (var mod in ctr_state) {
readValue(mod);
}
startPolling();
*/
}
function changeState(mod, value) {
doSend(`change ${mod}:target "${value}"`);
//writeToScreen(`change ${mod}:target "${value}"\n`);
}
function onClose(evt) {
writeToScreen("disconnected\n");
}
function onError(evt) {
if (evt.data === undefined) {
writeToScreen("Unable to connect to "+ wsaddr + "\n");
} else {
writeToScreen("error: " + evt.data + '\n');
websocket.close();
}
}
function doSend(message) {
console.log('>', message);
websocket.send(message);
}
function toggleTarget(element, mod) {
stateElement = element.stateElement || element
const newState = stateElement.state === false;
console.log('click', element, mod, stateElement.state, newState);
changeFill(element, "clicked");
doSend(`change ${mod}:target ${newState}`);
}
function sendCommand(element, modcmd) {
console.log('command', modcmd);
doSend(`do ${modcmd}`);
}
function addClickListener(element, arg, func) {
element.addEventListener('click', () => { func(element, arg); });
element.classList.add('clickable');
}
window.onload = function () {
doConnect();
requestAnimationFrame(processUpdates);
}