494 lines
15 KiB
JavaScript
494 lines
15 KiB
JavaScript
/**
|
|
* Live-Drucker-Monitor für MYP Platform
|
|
* Verwaltet Live-Status-Updates mit Session-Caching und automatischer Aktualisierung
|
|
*/
|
|
|
|
class PrinterMonitor {
|
|
constructor() {
|
|
this.refreshInterval = 30000; // 30 Sekunden Standard-Intervall
|
|
this.fastRefreshInterval = 5000; // 5 Sekunden für schnelle Updates
|
|
this.currentInterval = null;
|
|
this.printers = new Map();
|
|
this.callbacks = new Set();
|
|
this.isActive = false;
|
|
this.useCache = true;
|
|
this.lastUpdate = null;
|
|
this.errorCount = 0;
|
|
this.maxErrors = 3;
|
|
|
|
// Status-Kategorien für bessere Übersicht
|
|
this.statusCategories = {
|
|
'online': { label: 'Online', color: 'success', icon: '🟢' },
|
|
'offline': { label: 'Offline', color: 'danger', icon: '🔴' },
|
|
'standby': { label: 'Standby', color: 'warning', icon: '🟡' },
|
|
'unreachable': { label: 'Nicht erreichbar', color: 'secondary', icon: '⚫' },
|
|
'unconfigured': { label: 'Nicht konfiguriert', color: 'info', icon: '🔵' }
|
|
};
|
|
|
|
console.log('🖨️ PrinterMonitor initialisiert');
|
|
}
|
|
|
|
/**
|
|
* Startet das Live-Monitoring
|
|
*/
|
|
start() {
|
|
if (this.isActive) {
|
|
console.log('⚠️ PrinterMonitor läuft bereits');
|
|
return;
|
|
}
|
|
|
|
this.isActive = true;
|
|
this.errorCount = 0;
|
|
|
|
console.log('🚀 Starte PrinterMonitor');
|
|
|
|
// Sofortige erste Aktualisierung
|
|
this.updatePrinterStatus();
|
|
|
|
// Reguläres Intervall starten
|
|
this.startInterval();
|
|
|
|
// Event-Listener für Sichtbarkeitsänderungen
|
|
document.addEventListener('visibilitychange', this.handleVisibilityChange.bind(this));
|
|
}
|
|
|
|
/**
|
|
* Stoppt das Live-Monitoring
|
|
*/
|
|
stop() {
|
|
if (!this.isActive) {
|
|
return;
|
|
}
|
|
|
|
this.isActive = false;
|
|
|
|
if (this.currentInterval) {
|
|
clearInterval(this.currentInterval);
|
|
this.currentInterval = null;
|
|
}
|
|
|
|
document.removeEventListener('visibilitychange', this.handleVisibilityChange.bind(this));
|
|
|
|
console.log('⏹️ PrinterMonitor gestoppt');
|
|
}
|
|
|
|
/**
|
|
* Startet das Update-Intervall
|
|
*/
|
|
startInterval() {
|
|
if (this.currentInterval) {
|
|
clearInterval(this.currentInterval);
|
|
}
|
|
|
|
this.currentInterval = setInterval(() => {
|
|
this.updatePrinterStatus();
|
|
}, this.refreshInterval);
|
|
}
|
|
|
|
/**
|
|
* Behandelt Sichtbarkeitsänderungen der Seite
|
|
*/
|
|
handleVisibilityChange() {
|
|
if (document.hidden) {
|
|
// Seite nicht sichtbar - langsamere Updates
|
|
this.refreshInterval = 60000; // 1 Minute
|
|
} else {
|
|
// Seite sichtbar - normale Updates
|
|
this.refreshInterval = 30000; // 30 Sekunden
|
|
// Sofortige Aktualisierung wenn Seite wieder sichtbar
|
|
this.updatePrinterStatus();
|
|
}
|
|
|
|
if (this.isActive) {
|
|
this.startInterval();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Holt aktuelle Drucker-Status-Daten
|
|
*/
|
|
async updatePrinterStatus() {
|
|
if (!this.isActive) {
|
|
return;
|
|
}
|
|
|
|
try {
|
|
const response = await fetch(`/api/printers/monitor/live-status?use_cache=${this.useCache}`, {
|
|
method: 'GET',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'X-Requested-With': 'XMLHttpRequest'
|
|
}
|
|
});
|
|
|
|
if (!response.ok) {
|
|
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
}
|
|
|
|
const data = await response.json();
|
|
|
|
if (data.success) {
|
|
this.processPrinterData(data);
|
|
this.errorCount = 0; // Reset error count on success
|
|
} else {
|
|
throw new Error(data.error || 'Unbekannter Fehler');
|
|
}
|
|
|
|
} catch (error) {
|
|
this.errorCount++;
|
|
console.error('❌ Fehler beim Abrufen des Drucker-Status:', error);
|
|
|
|
// Bei wiederholten Fehlern weniger frequent versuchen
|
|
if (this.errorCount >= this.maxErrors) {
|
|
this.refreshInterval = Math.min(this.refreshInterval * 2, 300000); // Max 5 Minuten
|
|
this.startInterval();
|
|
|
|
this.notifyCallbacks({
|
|
type: 'error',
|
|
message: `Drucker-Status nicht verfügbar (${this.errorCount} Fehler)`,
|
|
timestamp: new Date().toISOString()
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Verarbeitet empfangene Drucker-Daten
|
|
*/
|
|
processPrinterData(data) {
|
|
const previousPrinters = new Map(this.printers);
|
|
|
|
// Drucker-Daten aktualisieren
|
|
this.printers.clear();
|
|
|
|
// Flexible Datenextraktion für verschiedene API-Response-Strukturen
|
|
let printersData = null;
|
|
|
|
if (data && data.printers && typeof data.printers === 'object') {
|
|
// Alte Struktur: data.printers
|
|
printersData = data.printers;
|
|
} else if (data && data.status && typeof data.status === 'object') {
|
|
// Neue Struktur: data.status
|
|
printersData = data.status;
|
|
} else if (data && typeof data === 'object' && !data.success && !data.error) {
|
|
// Direkte Drucker-Daten ohne Wrapper
|
|
printersData = data;
|
|
}
|
|
|
|
if (printersData && typeof printersData === 'object') {
|
|
// Drucker-Daten verarbeiten
|
|
Object.values(printersData).forEach(printer => {
|
|
// Sichere Validierung der Drucker-Objekte
|
|
if (printer && typeof printer === 'object' && printer.id) {
|
|
this.printers.set(printer.id, {
|
|
...printer,
|
|
statusInfo: this.statusCategories[printer.status] || this.statusCategories['offline']
|
|
});
|
|
} else {
|
|
console.warn('⚠️ Ungültiges Drucker-Objekt übersprungen:', printer);
|
|
}
|
|
});
|
|
|
|
console.log(`✅ ${this.printers.size} Drucker erfolgreich verarbeitet`);
|
|
} else {
|
|
console.warn('⚠️ Keine gültigen Drucker-Daten in Response-Struktur gefunden');
|
|
console.debug('Response-Struktur:', data);
|
|
|
|
// Benachrichtige Callbacks über fehlende Daten (aber nicht als Fehler)
|
|
this.notifyCallbacks({
|
|
type: 'warning',
|
|
message: 'Keine Drucker-Daten verfügbar',
|
|
data: data
|
|
});
|
|
return;
|
|
}
|
|
|
|
this.lastUpdate = new Date(data.timestamp || Date.now());
|
|
|
|
// Änderungen erkennen und benachrichtigen
|
|
const changes = this.detectChanges(previousPrinters, this.printers);
|
|
|
|
// Callbacks benachrichtigen
|
|
this.notifyCallbacks({
|
|
type: 'update',
|
|
printers: this.printers,
|
|
summary: data.summary,
|
|
changes: changes,
|
|
timestamp: this.lastUpdate,
|
|
cacheUsed: data.cache_used
|
|
});
|
|
|
|
console.log(`🔄 Drucker-Status aktualisiert: ${this.printers.size} Drucker`);
|
|
}
|
|
|
|
/**
|
|
* Erkennt Änderungen zwischen zwei Drucker-Status-Maps
|
|
*/
|
|
detectChanges(oldPrinters, newPrinters) {
|
|
const changes = [];
|
|
|
|
newPrinters.forEach((newPrinter, id) => {
|
|
const oldPrinter = oldPrinters.get(id);
|
|
|
|
if (!oldPrinter) {
|
|
changes.push({
|
|
type: 'added',
|
|
printer: newPrinter
|
|
});
|
|
} else if (oldPrinter.status !== newPrinter.status) {
|
|
changes.push({
|
|
type: 'status_change',
|
|
printer: newPrinter,
|
|
oldStatus: oldPrinter.status,
|
|
newStatus: newPrinter.status
|
|
});
|
|
}
|
|
});
|
|
|
|
oldPrinters.forEach((oldPrinter, id) => {
|
|
if (!newPrinters.has(id)) {
|
|
changes.push({
|
|
type: 'removed',
|
|
printer: oldPrinter
|
|
});
|
|
}
|
|
});
|
|
|
|
return changes;
|
|
}
|
|
|
|
/**
|
|
* Benachrichtigt alle registrierten Callbacks
|
|
*/
|
|
notifyCallbacks(data) {
|
|
this.callbacks.forEach(callback => {
|
|
try {
|
|
callback(data);
|
|
} catch (error) {
|
|
console.error('❌ Fehler in PrinterMonitor Callback:', error);
|
|
}
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Registriert einen Callback für Status-Updates
|
|
*/
|
|
onUpdate(callback) {
|
|
if (typeof callback === 'function') {
|
|
this.callbacks.add(callback);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Entfernt einen Callback
|
|
*/
|
|
offUpdate(callback) {
|
|
this.callbacks.delete(callback);
|
|
}
|
|
|
|
/**
|
|
* Erzwingt eine sofortige Aktualisierung ohne Cache
|
|
*/
|
|
async forceUpdate() {
|
|
const oldUseCache = this.useCache;
|
|
this.useCache = false;
|
|
|
|
try {
|
|
await this.updatePrinterStatus();
|
|
} finally {
|
|
this.useCache = oldUseCache;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Löscht den Cache und erzwingt eine Aktualisierung
|
|
*/
|
|
async clearCache() {
|
|
try {
|
|
const response = await fetch('/api/printers/monitor/clear-cache', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'X-Requested-With': 'XMLHttpRequest'
|
|
}
|
|
});
|
|
|
|
if (response.ok) {
|
|
console.log('🧹 Drucker-Cache geleert');
|
|
await this.forceUpdate();
|
|
} else {
|
|
throw new Error(`HTTP ${response.status}`);
|
|
}
|
|
|
|
} catch (error) {
|
|
console.error('❌ Fehler beim Leeren des Caches:', error);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Holt eine schnelle Status-Zusammenfassung
|
|
*/
|
|
async getSummary() {
|
|
try {
|
|
const response = await fetch('/api/printers/monitor/summary', {
|
|
method: 'GET',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'X-Requested-With': 'XMLHttpRequest'
|
|
}
|
|
});
|
|
|
|
if (response.ok) {
|
|
const data = await response.json();
|
|
return data.success ? data.summary : null;
|
|
}
|
|
|
|
} catch (error) {
|
|
console.error('❌ Fehler beim Abrufen der Zusammenfassung:', error);
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Gibt den aktuellen Status eines Druckers zurück
|
|
*/
|
|
getPrinter(id) {
|
|
return this.printers.get(id);
|
|
}
|
|
|
|
/**
|
|
* Gibt alle Drucker zurück
|
|
*/
|
|
getAllPrinters() {
|
|
return Array.from(this.printers.values());
|
|
}
|
|
|
|
/**
|
|
* Gibt Drucker nach Status gefiltert zurück
|
|
*/
|
|
getPrintersByStatus(status) {
|
|
return this.getAllPrinters().filter(printer => printer.status === status);
|
|
}
|
|
|
|
/**
|
|
* Gibt eine Status-Zusammenfassung zurück
|
|
*/
|
|
getStatusSummary() {
|
|
const summary = {
|
|
total: this.printers.size,
|
|
online: 0,
|
|
offline: 0,
|
|
printing: 0, // Neuer Status: Drucker druckt gerade
|
|
standby: 0,
|
|
unreachable: 0,
|
|
unconfigured: 0,
|
|
error: 0 // Status für unbekannte Fehler
|
|
};
|
|
|
|
this.printers.forEach(printer => {
|
|
const status = printer.status;
|
|
if (summary.hasOwnProperty(status)) {
|
|
summary[status]++;
|
|
} else {
|
|
// Fallback für unbekannte Status
|
|
summary.offline++;
|
|
}
|
|
});
|
|
|
|
return summary;
|
|
}
|
|
|
|
/**
|
|
* Aktiviert schnelle Updates (für kritische Operationen)
|
|
*/
|
|
enableFastUpdates() {
|
|
this.refreshInterval = this.fastRefreshInterval;
|
|
if (this.isActive) {
|
|
this.startInterval();
|
|
}
|
|
console.log('⚡ Schnelle Updates aktiviert');
|
|
}
|
|
|
|
/**
|
|
* Deaktiviert schnelle Updates
|
|
*/
|
|
disableFastUpdates() {
|
|
this.refreshInterval = 30000; // Zurück zu normal
|
|
if (this.isActive) {
|
|
this.startInterval();
|
|
}
|
|
console.log('🐌 Normale Updates aktiviert');
|
|
}
|
|
|
|
/**
|
|
* Initialisiert alle Steckdosen (nur für Admins)
|
|
*/
|
|
async initializeAllOutlets() {
|
|
try {
|
|
const response = await fetch('/api/printers/monitor/initialize-outlets', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'X-Requested-With': 'XMLHttpRequest'
|
|
}
|
|
});
|
|
|
|
if (response.ok) {
|
|
const data = await response.json();
|
|
|
|
if (data.success) {
|
|
console.log('🔌 Steckdosen-Initialisierung erfolgreich:', data.statistics);
|
|
|
|
// Benachrichtige über Initialisierung
|
|
this.notifyCallbacks({
|
|
type: 'initialization',
|
|
results: data.results,
|
|
statistics: data.statistics,
|
|
message: data.message
|
|
});
|
|
|
|
// Erzwinge Update nach Initialisierung
|
|
await this.forceUpdate();
|
|
|
|
return data;
|
|
} else {
|
|
throw new Error(data.error || 'Initialisierung fehlgeschlagen');
|
|
}
|
|
} else {
|
|
throw new Error(`HTTP ${response.status}`);
|
|
}
|
|
|
|
} catch (error) {
|
|
console.error('❌ Fehler bei Steckdosen-Initialisierung:', error);
|
|
throw error;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Globale Instanz
|
|
window.printerMonitor = new PrinterMonitor();
|
|
|
|
// Auto-Start wenn DOM bereit ist
|
|
document.addEventListener('DOMContentLoaded', () => {
|
|
// Nur starten wenn wir auf einer relevanten Seite sind
|
|
const relevantPages = ['/printers', '/dashboard', '/admin', '/admin-dashboard'];
|
|
const currentPath = window.location.pathname;
|
|
|
|
if (relevantPages.some(page => currentPath.includes(page))) {
|
|
console.log('🖨️ Auto-Start PrinterMonitor für Seite:', currentPath);
|
|
window.printerMonitor.start();
|
|
}
|
|
});
|
|
|
|
// Automatisches Cleanup bei Seitenverlassen
|
|
window.addEventListener('beforeunload', () => {
|
|
if (window.printerMonitor) {
|
|
window.printerMonitor.stop();
|
|
}
|
|
});
|
|
|
|
// Export für Module
|
|
if (typeof module !== 'undefined' && module.exports) {
|
|
module.exports = PrinterMonitor;
|
|
}
|