class Dome { constructor(socketUrl) { // Verhindere mehrfache Instanzen if (window.activeDomeInstance) { console.warn('Dome instance already exists! Stopping old one...'); window.activeDomeInstance.stop(); } this.angle = 0; // Grad (Mitte des Spalts) this.slotWidth = 20; // Spaltbreite in Grad this.domeSpeed = 3.0; // Grad pro Frame (für smoothe animation) this.telescopeAngle = 0; // State Machine für diskrete Bewegung (wie Original) this.state = "IDLE"; // "IDLE" oder "MOVING" this.targetDomeAngle = this.angle; this.socket = io(socketUrl); // Registriere als aktive Instanz window.activeDomeInstance = this; this.setupSocketListeners(); this.startTracking(); } setupSocketListeners() { this.socket.on('connect', () => { console.log('Dome connected to server'); }); this.socket.on('telescope-position', (data) => { this.updateTelescopePosition(data.angle); }); } startTracking() { this.isTracking = true; // Tracking-Loop (30x pro Sekunde für smooth movement) this.trackingInterval = setInterval(() => { if (this.isTracking) { this.updateDomePosition(); } }, 1000 / 30); // 30 FPS für sehr smooth movement // Position broadcasting (10x pro Sekunde für responsive Visualisierung) this.broadcastInterval = setInterval(() => { this.broadcastPosition(); }, 100); // 10x pro Sekunde } updateTelescopePosition(telescopeAngle) { this.telescopeAngle = telescopeAngle; } updateDomePosition() { let diff = this.angleDiff(this.telescopeAngle, this.angle); let halfSlot = this.slotWidth / 2; let triggerPoint = halfSlot - 2.0; // Starte früher! (8° statt 10°) let moveDir = "STOP"; if (this.state === "IDLE") { // Prüfen, ob Teleskop aus Schlitz läuft - aber früher triggern! if (diff > triggerPoint) { // CW-Bewegung → Kuppel zentriert sich um das Teleskop this.targetDomeAngle = (this.telescopeAngle + 360) % 360; this.state = "MOVING"; console.log(`[Dome] START MOVING: Tel out of slot CW (${diff.toFixed(1)}° > ${triggerPoint.toFixed(1)}°), target: ${this.targetDomeAngle.toFixed(1)}° (centered on telescope)`); } else if (diff < -triggerPoint) { // CCW-Bewegung → Kuppel zentriert sich um das Teleskop this.targetDomeAngle = (this.telescopeAngle + 360) % 360; this.state = "MOVING"; console.log(`[Dome] START MOVING: Tel out of slot CCW (${diff.toFixed(1)}° < ${-triggerPoint.toFixed(1)}°), target: ${this.targetDomeAngle.toFixed(1)}° (centered on telescope)`); } } if (this.state === "MOVING") { let delta = this.angleDiff(this.targetDomeAngle, this.angle); if (Math.abs(delta) > this.domeSpeed) { this.angle = (this.angle + Math.sign(delta) * this.domeSpeed + 360) % 360; moveDir = Math.sign(delta) > 0 ? "CW" : "CCW"; } else { // Ziel erreicht this.angle = this.targetDomeAngle; this.state = "IDLE"; console.log(`[Dome] REACHED TARGET: ${this.angle.toFixed(1)}°, back to IDLE`); } } // Debug nur bei Aktivität if (moveDir !== "STOP") { console.log(`[Dome] ${this.state}: Tel=${this.telescopeAngle.toFixed(1)}°, Dome=${this.angle.toFixed(1)}° → ${this.targetDomeAngle.toFixed(1)}°, Dir=${moveDir}`); } } // Winkeldifferenz berechnen - kürzester Weg zwischen zwei Winkeln angleDiff(target, source) { // Standard-Formel für kürzesten Winkel let diff = target - source; // Normalisiere auf -180 bis +180 while (diff > 180) diff -= 360; while (diff < -180) diff += 360; return diff; } broadcastPosition() { const data = { angle: this.angle, slotWidth: this.slotWidth, telescopeAngle: this.telescopeAngle, diff: this.angleDiff(this.telescopeAngle, this.angle), timestamp: Date.now() }; this.socket.emit('dome-position', data); } stop() { this.isTracking = false; if (this.trackingInterval) clearInterval(this.trackingInterval); if (this.broadcastInterval) clearInterval(this.broadcastInterval); // Entferne Referenz als aktive Instanz if (window.activeDomeInstance === this) { window.activeDomeInstance = null; } } } // Wenn wir in einem Browser sind, NICHT automatisch initialisieren // Die Visualisierung wird die Kuppel kontrollieren if (typeof window !== 'undefined') { // Nur die Klasse verfügbar machen, aber noch nicht instanziieren window.Dome = Dome; } // Node.js Export für separate Prozesse if (typeof module !== 'undefined' && module.exports) { module.exports = Dome; }