make more generic
This commit is contained in:
@ -80,7 +80,6 @@
|
||||
border-radius: 12px;
|
||||
}
|
||||
|
||||
|
||||
.content-container {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
@ -90,68 +89,127 @@
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="content-container">
|
||||
<object id="pump-svg" type="image/svg+xml" data="/static/UI5.svg"></object>
|
||||
|
||||
<div class="control-panel">
|
||||
<h1> DIL5 Control </h1>
|
||||
<p> States </p>
|
||||
<div class="button-container">
|
||||
<button id = "test-btn" class="control-button" onclick="handleStateClick('TEST')">Test</button>
|
||||
<button id = "condense-btn" class="control-button" onclick="handleStateClick('CONDENSE')">Condense</button>
|
||||
<button id = "circulate-btn" class="control-button" onclick="handleStateClick('CIRCULATE')">Circulate</button>
|
||||
<button id = "remove-btn" class="control-button" onclick="handleStateClick('REMOVE')">Remove</button>
|
||||
<button id = "manual-btn" class="control-button" onclick="handleStateClick('MANUAL')">Manual</button>
|
||||
</div>
|
||||
<p> Status messages </p>
|
||||
<textarea name="outputtext" id="outputtext" rows="10" cols="30" readonly></textarea>
|
||||
</div>
|
||||
<div class="content-container">
|
||||
<! object id="pump-svg" type="image/svg+xml" data="/static/UI5.svg"><! /object>
|
||||
{% include svg_ui %}
|
||||
<div class="control-panel">
|
||||
<h1> DIL5 Control </h1>
|
||||
<p> States </p>
|
||||
<div class="button-container">
|
||||
<button id = "test-btn" class="control-button" onclick="handleStateClick('TEST')">Test</button>
|
||||
<button id = "condense-btn" class="control-button" onclick="handleStateClick('CONDENSE')">Condense</button>
|
||||
<button id = "circulate-btn" class="control-button" onclick="handleStateClick('CIRCULATE')">Circulate</button>
|
||||
<button id = "remove-btn" class="control-button" onclick="handleStateClick('REMOVE')">Remove</button>
|
||||
<button id = "manual-btn" class="control-button" onclick="handleStateClick('MANUAL')">Manual</button>
|
||||
</div>
|
||||
<p> Status messages </p>
|
||||
<textarea name="outputtext" id="outputtext" rows="10" cols="30" readonly></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
<script>
|
||||
|
||||
//var ctr_ids = ["MV9", "turbopump", "MV10", "MV11", "MV12", "MV13", "MV8", "MVB", "MV2", "MV1", "MV3a", "MV3b", "GV1", "GV2", "MV14", "V1", "V2", "V9", "V5", "V4", "pump", "compressor"];
|
||||
//var ctr_mod = ["MV9", "turbopump", "MV10", "MV11", "MV12", "MV13", "MV8", "MVB", "MV2", "MV1", "MV3a", "MV3b", "GV1", "GV2", "MV14", "V1", "V2", "V9", "V5", "V4", "pump", "compressor"];
|
||||
function v(mod, value) {
|
||||
}
|
||||
|
||||
function boolstate(mod, value) {
|
||||
}
|
||||
|
||||
function label(mod, value) {
|
||||
}
|
||||
|
||||
var modules = {
|
||||
V1: v, V2: v, V4: v, V5: v, V9: v,
|
||||
MV1: 0, MV2: 0, MV3a: 0, MV3b: 0, MV9: 0, MV10: 0, MV11: 0, MV12: 0, MV13: 0,
|
||||
GV1: 0, GV2: 0,
|
||||
turbopump: 0, pump: 0, compressor: 0,
|
||||
Druckluft: 1,
|
||||
}
|
||||
// var ctr_state = new Array(ctr_mod.length).fill("init");
|
||||
|
||||
const svgElements = {};
|
||||
let updateQueue = [];
|
||||
|
||||
var state_ids = ["Airpressure"];
|
||||
var state_mod = ["Druckluft"];
|
||||
var colors = {true: "#66ffba", false: "#ff3067", error: "#ffff00", clicked: "#ffffff", ok: "#ffffff"};
|
||||
|
||||
var param_ids = ["P1txt", "P2txt", "P3txt", "P4txt", "P5txt", "speedtxt", "currenttxt"];
|
||||
var param_unit = [" mbar", " mbar", " mbar", " mbar", " mbar", " Hz", " %"];
|
||||
var param_mod = ["p1", "p2", "p3", "p4", "p5", "turbopumpspeed", "turbopumpcurrent"];
|
||||
|
||||
var colors = {true: "#66ffba", false: "#ff3067", error: "#ff8000", clicked: "#ffffff"};
|
||||
|
||||
var controlpanelObject = document.getElementById("pump-svg");
|
||||
var svgDoc;
|
||||
let active_state = "MANUAL";
|
||||
|
||||
let pollTimer;
|
||||
const POLL_INTERVAL = 500;
|
||||
var description;
|
||||
var changeFuncs = {};
|
||||
var updateValues = {};
|
||||
|
||||
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;
|
||||
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) {
|
||||
elem.textContent = pat.replace('*', value);
|
||||
elem.style.fill = "#d5d5d5";
|
||||
}
|
||||
}
|
||||
if (func.includes("command")) {
|
||||
console.log(func, mod, param);
|
||||
addClickListener(elem, mod + ":" + param, sendCommand);
|
||||
}
|
||||
})
|
||||
if (stateElement && clickElement) {
|
||||
clickElement.stateElement = stateElement;
|
||||
}
|
||||
}
|
||||
console.log('ACTIVATE', changeFuncs);
|
||||
doSend("activate");
|
||||
}
|
||||
|
||||
function handle_update(action, modpar, data) {
|
||||
if (modpar.startsWith('compressor')) 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)) {
|
||||
if (modpar.startsWith('compressor')) console.log('process', modpar, value);
|
||||
changeFuncs[modpar](value);
|
||||
}
|
||||
requestAnimationFrame(processUpdates);
|
||||
}
|
||||
|
||||
|
||||
function handleStateClick(state) {
|
||||
changeState("stateMachine", 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;
|
||||
@ -164,34 +222,13 @@
|
||||
active_state = state;
|
||||
}
|
||||
|
||||
function changeControlledValve(mod, state) {
|
||||
if (mod in ctr_state) {
|
||||
ctr_state[mod] = state;
|
||||
if (state in colors) {
|
||||
svgElements[mod].style.fill = colors[state];
|
||||
} else {
|
||||
svgElements[mod].style.fill = "#eaeaea" ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function fillstateID(mod, state) {
|
||||
const index = state_mod.indexOf(mod);
|
||||
const element = svgDoc.querySelector("#" + state_ids[index]);
|
||||
if (index !== -1 && element) {
|
||||
element.style.fill = state === true ? "#66ffbaff" :
|
||||
state === false ? "#ff3067ff" : "#eaeaea";
|
||||
}
|
||||
}
|
||||
|
||||
function editText(mod, text) {
|
||||
const index = param_mod.indexOf(mod);
|
||||
if (index !== -1) {
|
||||
const textElement = svgDoc.querySelector("#" + param_ids[index]);
|
||||
if (textElement) {
|
||||
textElement.textContent = text + param_unit[index];
|
||||
textElement.style.fill = "#d5d5d5";
|
||||
}
|
||||
function changeFill(element, state) {
|
||||
stateElement = element.stateElement || element;
|
||||
stateElement.state = state;
|
||||
if (state in colors) {
|
||||
stateElement.style.fill = colors[state];
|
||||
} else {
|
||||
stateElement.style.fill = "#eaeaea" ;
|
||||
}
|
||||
}
|
||||
|
||||
@ -205,22 +242,19 @@
|
||||
websocket = new WebSocket("ws://linse-dil5:8010/");
|
||||
websocket.onopen = evt => onOpen(evt);
|
||||
websocket.onclose = evt => onClose(evt);
|
||||
websocket.onmessage = evt => updateQueue.push(evt.data);
|
||||
websocket.onmessage = evt => handleMSG(evt.data);
|
||||
websocket.onerror = evt => onError(evt);
|
||||
}
|
||||
|
||||
function onOpen(evt) {
|
||||
writeToScreen("Connected to DIL5\n");
|
||||
//doSend("activate");
|
||||
doSend("describe");
|
||||
/*
|
||||
for (var mod in ctr_state) {
|
||||
readValue(mod);
|
||||
}
|
||||
startPolling();
|
||||
}
|
||||
|
||||
function changeTarget(mod, value) {
|
||||
doSend(`change ${mod}:target ${value}`);
|
||||
|
||||
*/
|
||||
}
|
||||
|
||||
function changeState(mod, value) {
|
||||
@ -228,10 +262,6 @@
|
||||
//writeToScreen(`change ${mod}:target "${value}"\n`);
|
||||
}
|
||||
|
||||
function readValue(mod) {
|
||||
doSend("read " + mod + ":value");
|
||||
}
|
||||
|
||||
function onClose(evt) {
|
||||
writeToScreen("disconnected\n");
|
||||
stopPolling();
|
||||
@ -249,153 +279,32 @@
|
||||
}
|
||||
|
||||
function doSend(message) {
|
||||
console.log('>', message);
|
||||
websocket.send(message);
|
||||
}
|
||||
|
||||
function handleUpdate(action, modpar, data) {
|
||||
const [mod, param] = modpar.split(':')
|
||||
const value = data[0]
|
||||
|
||||
if (param === "status") {
|
||||
console.log('S', mod, value)
|
||||
}
|
||||
if (param === "status" && value[0] >= 400) {
|
||||
value = 'error';
|
||||
param = 'value';
|
||||
}
|
||||
if (param === "value") {
|
||||
value = value.toString();
|
||||
if (mod in ctr_state) {
|
||||
changeControlledValve(mod, value);
|
||||
} else if (param_mod.includes(mod)) {
|
||||
editText(mod, value);
|
||||
} else if (state_mod.includes(mod)) {
|
||||
fillstateID(mod, value);
|
||||
} else if (mod == "stateMachine"){
|
||||
if (value == "5"){
|
||||
if (active_state != "TEST"){
|
||||
updateState("TEST")
|
||||
}
|
||||
} else if (value == "4"){
|
||||
if (active_state != "MANUAL"){
|
||||
updateState("MANUAL")
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
} else if (param === "_speed") {
|
||||
editText("turbopumpspeed", value);
|
||||
} else if (param === "_current") {
|
||||
editText("turbopumpcurrent", value);
|
||||
} else if (param === "stateMachine") {
|
||||
console.log(msg)
|
||||
updateState(value)
|
||||
}
|
||||
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 handleMSG(msg) {
|
||||
const [action, modpar, ...tail] = msg.split(" ");
|
||||
let data = tail.join(' ');
|
||||
if (data) {
|
||||
data = JSON.parse(data)
|
||||
}
|
||||
if (action in ["changed", "update", "reply"]) {
|
||||
handleUpdate(action, modpar, data);
|
||||
} else {
|
||||
console.log(msg);
|
||||
}
|
||||
function sendCommand(element, modcmd) {
|
||||
console.log('command', modcmd);
|
||||
doSend(`do ${modcmd}`);
|
||||
}
|
||||
|
||||
function processUpdateQueue() {
|
||||
if (updateQueue.length > 0) {
|
||||
const queueCopy = updateQueue.slice();
|
||||
updateQueue = [];
|
||||
queueCopy.forEach(msg => handleMSG(msg));
|
||||
}
|
||||
requestAnimationFrame(processUpdateQueue);
|
||||
}
|
||||
|
||||
function addClickListener(element, id) {
|
||||
if (! element) {
|
||||
console.log(id, 'does not exist');
|
||||
return;
|
||||
}
|
||||
element.addEventListener('click', () => {
|
||||
console.log("click");
|
||||
const state = ctr_state[id];
|
||||
let newState = state === "false";
|
||||
console.log(id, state, newState);
|
||||
changeControlledValve(id, "clicked");
|
||||
changeTarget(id, newState);
|
||||
});
|
||||
function addClickListener(element, arg, func) {
|
||||
element.addEventListener('click', () => { func(element, arg); });
|
||||
element.classList.add('clickable');
|
||||
}
|
||||
|
||||
function startPolling() {
|
||||
pollTimer = setInterval(() => {
|
||||
pollAllStates();
|
||||
}, POLL_INTERVAL);
|
||||
}
|
||||
|
||||
|
||||
function stopPolling() {
|
||||
clearInterval(pollTimer);
|
||||
}
|
||||
|
||||
function sleep(ms) {
|
||||
return new Promise(resolve => setTimeout(resolve, ms));
|
||||
}
|
||||
|
||||
async function pollAllStates() {
|
||||
for (const mod in ctr_state) {
|
||||
doSend(`read ${mod}:value`);
|
||||
doSend(`read ${mod}:status`);
|
||||
await sleep(50);
|
||||
}
|
||||
await sleep(50);
|
||||
doSend('read turbopump:_speed');
|
||||
await sleep(50);
|
||||
doSend('read turbopump:_current');
|
||||
await sleep(50);
|
||||
doSend('read stateMachine:value');
|
||||
|
||||
for (const mod of state_mod) {
|
||||
doSend(`read ${mod}:value`);
|
||||
await sleep(50);
|
||||
}
|
||||
|
||||
for (const mod of param_mod) {
|
||||
doSend(`read ${mod}:value`);
|
||||
await sleep(50);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function pollSingle(mod) {
|
||||
doSend(`read ${mod}:value`);
|
||||
}
|
||||
|
||||
var winLoaded = false;
|
||||
var svgLoaded = false;
|
||||
|
||||
function afterLoad() {
|
||||
window.onload = function () {
|
||||
doConnect();
|
||||
svgDoc = controlpanelObject.contentDocument;
|
||||
for (var id in ctr_state) {
|
||||
element = svgDoc.querySelector("#" + id);
|
||||
svgElements[id] = element;
|
||||
addClickListener(element, id);
|
||||
element = svgDoc.querySelector("#" + id + "fill");
|
||||
if (element) {
|
||||
svgElements[id] = element;
|
||||
// addClickListener(element, id);
|
||||
}
|
||||
};
|
||||
requestAnimationFrame(processUpdateQueue);
|
||||
requestAnimationFrame(processUpdates);
|
||||
}
|
||||
|
||||
window.onload = function () { winLoaded = true; if (svgLoaded) afterLoad(); }
|
||||
controlpanelObject.onload = function () { svgLoaded = true; if (winLoaded) afterLoad(); }
|
||||
</script>
|
||||
|
||||
|
||||
|
1353
templates/dil5.svg
Normal file
1353
templates/dil5.svg
Normal file
File diff suppressed because it is too large
Load Diff
After Width: | Height: | Size: 190 KiB |
Reference in New Issue
Block a user