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 {