diff --git a/public/index.html b/public/index.html
index 265f225..f820118 100644
--- a/public/index.html
+++ b/public/index.html
@@ -92,7 +92,7 @@
this.mac = "";
this.antName = "";
this.adc = 0;
- this.lastSeen = 0;
+ this.online = false;
this.bands = [];
}
}
@@ -242,6 +242,24 @@
ctx.clearRect(0, 0, sz, sz);
ctx.drawImage(this.bgCanvas, 0, 0);
+ const isOffline = !this.state.online;
+
+ if (isOffline) {
+ // Grey overlay
+ ctx.beginPath();
+ ctx.arc(cx, cy, sz / 2 * 0.9, 0, 2 * Math.PI);
+ ctx.fillStyle = 'rgba(0, 0, 0, 0.6)';
+ ctx.fill();
+
+ // OFFLINE label
+ ctx.font = 'bold 50px Arial';
+ ctx.textAlign = 'center';
+ ctx.textBaseline = 'middle';
+ ctx.fillStyle = '#666';
+ ctx.fillText('OFFLINE', cx, cy);
+ return;
+ }
+
// Setpoint line (only while turning)
if (targetAngle != null && status !== 4) {
ctx.beginPath();
@@ -412,10 +430,9 @@
this.els.az.innerText = this.state.azimuth;
- const isOffline = (Date.now() - this.state.lastSeen) > 1500;
- this.els.online.innerHTML = isOffline
- ? " | • Offline"
- : " | • Connected";
+ this.els.online.innerHTML = this.state.online
+ ? " | • Connected"
+ : " | • Offline";
}
updateTurnedBy(sourceIp, targetAz) {
@@ -457,6 +474,7 @@
document.title = Object.values(this.rotators)
.map(r => r.state.antName || "Rotator")
.join(" / ");
+
}
async startWs() {
@@ -483,13 +501,15 @@
if (!rot) continue;
if (rotData.dynamic) {
- const { azimuth, status, adc } = rotData.dynamic;
- let needsRender = rot.state.azimuth !== azimuth || rot.state.status !== status;
+ const { azimuth, status, adc, online } = rotData.dynamic;
+ let needsRender = rot.state.azimuth !== azimuth
+ || rot.state.status !== status
+ || rot.state.online !== online;
rot.state.adc = adc;
rot.state.azimuth = azimuth;
rot.state.status = status;
- rot.state.lastSeen = Date.now();
+ rot.state.online = online;
if (needsRender) rot.ui.renderer.render();
rot.ui.updateDynamic();
diff --git a/src/RotClient.ts b/src/RotClient.ts
index 7120925..c399f9b 100644
--- a/src/RotClient.ts
+++ b/src/RotClient.ts
@@ -65,7 +65,13 @@ export default class RotClient {
{ key: 'status', url: 'readStat', numType: NumType.Int },
];
- const data = await this.readEndpoints(endpoints) as unknown as DynamicData;
+ const raw = await this.readEndpoints(endpoints);
+ const data: DynamicData = {
+ adc: raw.adc as number | null,
+ azimuth: raw.azimuth as number | null,
+ status: raw.status as number | null,
+ online: raw.azimuth !== null,
+ };
if (this.dynamicData !== null) {
const oldData = this.dynamicData;
diff --git a/src/types.ts b/src/types.ts
index df377ae..895d23b 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -19,6 +19,7 @@ export interface DynamicData {
adc: number | null;
azimuth: number | null;
status: number | null;
+ online: boolean;
}
export interface InitData {