Compare commits

...

4 commits

Author SHA1 Message Date
Rahix e4fa961ef0 succd: Only show voltage on hover
All checks were successful
/ test (push) Successful in 10s
/ test (pull_request) Successful in 10s
Another HP HMI thing: "Only show information that is immediately
relevant".  Let's hide the pirani voltage as it is mostly no longer
interesting to the user.  For situations where it is, it can be revealed
by hovering over the pirani pressure value.
2024-10-05 02:53:16 +02:00
Rahix 314dd72aa6 succd: Optimize color usage for HP HMI
In the process automation world, there is a trend to move away from
colorful user-interfaces, towards more "boring" colorschemes.  The
argument is about situational awareness - by only using colors to
highlight abnormal situations, they become instantly recognizable to the
operators.

This design philosophy is outlined by the ISA-101 [1] under the name
"High Performance HMI".  While it covers much more than just colors, I
think this is the most important part and the one that is most
applicable for our usecase.

So let's do a bit of HP HMI - reduce colors usage such that only
important information is highlighted.

[1]: https://www.isa.org/standards-and-publications/isa-standards/isa-standards-committees/isa101
2024-10-05 02:52:51 +02:00
Rahix 276551064f succd: Fix mobile layout
Use smaller font sizes for mobile devices so the full interface fits on
a single screen (mostly).
2024-10-05 02:52:48 +02:00
Rahix 4f74e92c45 succd: Fix layout on large screens
Make sure the grid cannot grow too large on big screens.  Also slightly
adjust the breakpoint to avoid some weird artifacts.
2024-10-05 02:40:20 +02:00

View file

@ -52,15 +52,42 @@ td > span {
height: 10em; height: 10em;
} }
.graph-container {
background-color: #e8e8e8;
text-align: center;
}
.main-grid { .main-grid {
margin: 2em; margin-top: 2em;
margin-left: auto;
margin-right: auto;
max-width: 160em;
clear: both; clear: both;
display: grid; display: grid;
grid-template-columns: repeat(auto-fit, minmax(50em, 1fr)); grid-template-columns: repeat(auto-fit, minmax(54em, 1fr));
column-gap: 2em; column-gap: 2em;
row-gap: 2em; row-gap: 2em;
} }
.has-hidden .hidden-text {
display: none;
}
.has-hidden:hover .hidden-text {
display: block;
@media only screen and (max-width: 700px) {
body {
font-size: 6px;
}
table {
font-size: 20px;
}
th {
font-size: 15px;
}
}
</style> </style>
<div class="logo"><img src="/favicon.png" /></div> <div class="logo"><img src="/favicon.png" /></div>
@ -95,13 +122,13 @@ td > span {
<table> <table>
<tr> <tr>
<th rowspan="2">Pirani Gauge</th> <th>Pirani Pressure</th>
<th>Voltage</th> <td class="has-hidden">
<td id="volts">{{ .Pirani.Volts }}</td> <div id="mbar">{{ .Pirani.Mbar }}</div>
</tr> <div class="hidden-text" style="color: #606060;">
<tr> <span>Voltage: </span><span id="volts">{{ .Pirani.Volts }}</span>
<th>Pressure</th> </div>
<td id="mbar">{{ .Pirani.Mbar }}</td> </td>
</tr> </tr>
</table> </table>
@ -136,9 +163,9 @@ td > span {
</tr> </tr>
</table> </table>
<p> <div class="graph-container">
<canvas id="graph" width="1024" height="512" style="max-width: 100%;"></canvas> <canvas id="graph" width="1024" height="512" style="max-width: 100%;"></canvas>
</p> </div>
</div> </div>
<p style="font-style: italic; font-size: 12px; margin-top: 5em;"> <p style="font-style: italic; font-size: 12px; margin-top: 5em;">
@ -170,7 +197,7 @@ let historicalDraw = (w, h) => {
// coordinate calculation. // coordinate calculation.
canvas.clearRect(0, 0, w, h); canvas.clearRect(0, 0, w, h);
canvas.fillStyle = "#f0f0f0"; canvas.fillStyle = "#e8e8e8";
canvas.fillRect(0, 0, w, h); canvas.fillRect(0, 0, w, h);
// Margins of the main graph window. // Margins of the main graph window.
@ -297,6 +324,14 @@ window.addEventListener("load", (_) => {
let rpoff = document.querySelector("#rpoff"); let rpoff = document.querySelector("#rpoff");
canvas = document.querySelector("#graph").getContext("2d"); canvas = document.querySelector("#graph").getContext("2d");
let colors = {
default: "background-color: #e8e8e8",
highlightNeutral: "background-color: #8282ff",
highlightCaution: "background-color: #ff941a",
highlightFault: "background-color: #f06060",
highlightGood: "background-color: #60f060",
};
// TODO(q3k): unhardcode this. // TODO(q3k): unhardcode this.
historicalDraw(1024, 512); historicalDraw(1024, 512);
@ -318,7 +353,7 @@ window.addEventListener("load", (_) => {
connected = true; connected = true;
console.log("Socket connected!"); console.log("Socket connected!");
status.innerHTML = "Online"; status.innerHTML = "Online";
status.style = "background-color: #60f060;"; status.style = colors.default;
}); });
socket.addEventListener("message", (event) => { socket.addEventListener("message", (event) => {
const data = JSON.parse(event.data); const data = JSON.parse(event.data);
@ -326,47 +361,47 @@ window.addEventListener("load", (_) => {
mbar.innerHTML = data.Pirani.Mbar; mbar.innerHTML = data.Pirani.Mbar;
if (data.Safety.Failsafe) { if (data.Safety.Failsafe) {
failsafe.innerHTML = "ON"; failsafe.innerHTML = "ON";
failsafe.style = "background-color: #f06060"; failsafe.style = colors.highlightFault;
} else { } else {
failsafe.innerHTML = "OFF"; failsafe.innerHTML = "OFF";
failsafe.style = "background-color: #60f060"; failsafe.style = colors.default;
} }
if (data.Safety.HighPressure) { if (data.Safety.HighPressure) {
highpressure.innerHTML = "ON"; highpressure.innerHTML = "ON";
highpressure.style = "background-color: #f06060"; highpressure.style = colors.default;
} else { } else {
highpressure.innerHTML = "OFF"; highpressure.innerHTML = "OFF";
highpressure.style = "background-color: #60f060"; highpressure.style = colors.default;
} }
if (data.Pumps.RPOn) { if (data.Pumps.RPOn) {
rp.innerHTML = "ON"; rp.innerHTML = "ON";
rp.style = "background-color: #60f060"; rp.style = colors.default;
} else { } else {
rp.innerHTML = "OFF"; rp.innerHTML = "OFF";
rp.style = "background-color: #f06060"; rp.style = colors.highlightNeutral;
} }
if (data.Pumps.DPOn) { if (data.Pumps.DPOn) {
dp.innerHTML = "ON"; dp.innerHTML = "ON";
dp.style = "background-color: #60f060"; dp.style = colors.highlightCaution;
} else { } else {
dp.innerHTML = "OFF"; dp.innerHTML = "OFF";
dp.style = "background-color: #f06060"; dp.style = colors.default;
} }
let t = []; let t = [];
if (data.Feedback.RoughReached) { if (data.Feedback.RoughReached) {
trough.innerHTML = "OK"; trough.innerHTML = "OK";
trough.style = "background-color: #60f060"; trough.style = colors.highlightGood;
} else { } else {
trough.innerHTML = "NOK"; trough.innerHTML = "NOK";
trough.style = "background-color: #f06060"; trough.style = colors.default;
} }
if (data.Feedback.HighReached) { if (data.Feedback.HighReached) {
thigh.innerHTML = "OK"; thigh.innerHTML = "OK";
thigh.style = "background-color: #60f060"; thigh.style = colors.highlightGood;
} else { } else {
thigh.innerHTML = "NOK"; thigh.innerHTML = "NOK";
thigh.style = "background-color: #f06060"; thigh.style = colors.default;
} }
load.innerHTML = data.LoopLoad.toString() + "%"; load.innerHTML = data.LoopLoad.toString() + "%";
historicalPush(data.Pirani.MbarFloat); historicalPush(data.Pirani.MbarFloat);
@ -374,7 +409,7 @@ window.addEventListener("load", (_) => {
}); });
socket.addEventListener("close", (event) => { socket.addEventListener("close", (event) => {
status.innerHTML = "Offline"; status.innerHTML = "Offline";
status.style = "background-color: #f06060;"; status.style = colors.highlightFault;
if (connected) { if (connected) {
console.log("Socket dead, reconnecting..."); console.log("Socket dead, reconnecting...");
} }