Navigation

    Logo
    • Register
    • Login
    • Search
    • Recent
    • Tags
    • Unread
    • Categories
    • Unreplied
    • Popular
    • GitHub
    • Docu
    • Hilfe
    1. Home
    2. Deutsch
    3. ioBroker Allgemein
    4. Shelly 3PM Pro Emulator

    NEWS

    • UPDATE 31.10.: Amazon Alexa - ioBroker Skill läuft aus ?

    • Monatsrückblick – September 2025

    • Neues Video "KI im Smart Home" - ioBroker plus n8n

    Shelly 3PM Pro Emulator

    This topic has been deleted. Only users with topic management privileges can see it.
    • G
      Gismoh @Gismoh last edited by Gismoh

      @gismoh

      3-MARSTEK-Monitor-Control:

      // ===================================================
      // MARSTEK-Monitor-Control v2.0 - ÜBERWACHUNG & STEUERUNG
      // ===================================================
      // 
      // 📊 ZWECK: ÜBERWACHUNG, DIAGNOSE & STEUERUNG
      // ✅ Steuerungsmodus-Erkennung (CT vs Manuell)
      // ✅ API-Integration + Smart-Timing
      // ✅ Diagnose-System + Datenpunkte-Verwaltung
      // ✅ Debug-Modi + Override-Funktionen
      // ✅ SOC-Daten für Intelligence-Script v2.0
      // ✅ v2.0: Kompatibel mit korrigierter Regelungslogik
      // 
      // ⚠️ DARF CRASHEN ohne Core/Intelligence zu stoppen!
      // 
      // ===================================================
      
      // KONFIGURATION
      const MONITOR_CONFIG = {
          // API-Zugangsdaten (werden aus Datenpunkten gelesen)
          API_ENABLED: true,
          API_INTERVAL: 300000,
          
          // Steuerungsmodus-Erkennung
          MODE_DETECTION_ENABLED: true,
          
          // Timing
          UPDATE_INTERVAL: 10000,  // Monitor läuft langsamer
          
          // Kommunikation - BITTE ANPASSEN!
          SHARED_PREFIX: '0_userdata.0.marstek_V-E.shared.',        // ← Dein Shared-Prefix hier eintragen
          INTEL_PREFIX: '0_userdata.0.marstek_V-E.intel.',          // ← Dein Intelligence-Prefix hier eintragen
          MONITOR_PREFIX: '0_userdata.0.marstek_V-E.monitor.',      // ← Dein Monitor-Prefix hier eintragen
          
          // Logging
          LOG_MONITOR: true,
          LOG_MODE_DETECTION: true,
          LOG_API: true
      };
      
      // MONITOR STATE
      let monitorState = {
          // Von Core/Intelligence empfangen
          coreActive: false,
          intelActive: false,
          tibberCurrent: 0,
          reportedPower: 0,          // v2.0: Neuer Name für gemeldeten Wert
          limitingActive: false,
          
          // API-Daten
          deviceSoc: 0,
          deviceCharge: 0,
          deviceDischarge: 0,
          lastReportTime: 0,
          
          // Steuerungsmodus-Erkennung
          controlMode: 'unbekannt',
          controlModeConfidence: 'niedrig',
          lastModeDetection: 0,
          modeDetectionHistory: [],
          apiModeData: {},
          behaviorModeData: {
              responseCount: 0,
              noResponseCount: 0,
              avgEfficiency: 0,
              lastBehaviorCheck: 0
          },
          
          // API-Timing
          apiState: {
              lastFetch: 0,
              lastActivity: Date.now(),
              nextFetchTime: 0
          },
          
          // Status & Diagnose
          monitorActive: true,
          lastUpdate: 0,
          systemStatus: 'starting',
          alarms: [],
          
          // Override-Modi
          overrideMode: '',
          manualModeOverride: ''
      };
      
      // ===================================================
      // MONITOR DATENPUNKTE
      // ===================================================
      
      function createMonitorDatapoints() {
          const prefix = MONITOR_CONFIG.MONITOR_PREFIX;
          
          const datapoints = [
              // API-Konfiguration - BITTE AUSFÜLLEN!
              { name: 'mailbox', value: '', desc: 'MARSTEK Mailbox (deine E-Mail)' },
              { name: 'token', value: '', desc: 'MARSTEK API Token (aus App)' },
              { name: 'deviceId', value: 'XXXX', desc: 'MARSTEK Device ID (z.B. 3456)' },      // ← ANPASSEN!
              { name: 'enable_second_storage', value: false, desc: '🔄 Zweiter Speicher (MSTYYYY)' },
              
              // Status
              { name: 'system_status', value: 'starting', desc: '🔧 System-Status (shared)', shared: true },
              { name: 'monitor_active', value: true, desc: '📊 Monitor läuft' },
              { name: 'api_connected', value: false, desc: '📡 API verbunden' },
              
              // Steuerungsmodus-Erkennung
              { name: 'control_mode_detected', value: 'unbekannt', desc: '🎮 Erkannter Steuerungsmodus' },
              { name: 'control_mode_confidence', value: 'niedrig', desc: '🎯 Erkennungs-Sicherheit' },
              { name: 'control_mode_method', value: 'keine', desc: '🔍 Erkennungsmethode' },
              { name: 'manual_mode_active', value: false, desc: '⚠️ Manueller Modus aktiv' },
              { name: 'regulation_possible', value: true, desc: '✅ Regelung möglich' },
              { name: 'check_mode_now', value: false, desc: '🔄 Sofort-Prüfung starten' },
              
              // API-Daten
              { name: 'device_charge', value: 0, desc: 'Speicher lädt [W]' },
              { name: 'device_discharge', value: 0, desc: 'Speicher entlädt [W]' },
              { name: 'device_soc', value: 0, desc: 'Speicher SOC [%]' },
              { name: 'api_delay', value: 0, desc: '📡 API Verzögerung [s]' },
              { name: 'last_api_fetch', value: 0, desc: '🕐 Letzte API-Abfrage' },
              { name: 'next_api_fetch', value: 0, desc: '⏰ Nächste API-Abfrage' },
              
              // Berechnete Werte
              { name: 'net_result', value: 0, desc: 'Resultat am Netz [W]' },
              { name: 'regulation_quality', value: 0, desc: '📈 Regelgüte [%]' },  // v2.0: Neu
              { name: 'current_efficiency', value: 0, desc: '📈 Aktuelle Effizienz [%]' },
              
              // Override & Debug
              { name: 'override_mode', value: '', desc: '🔧 Override-Modus (test/zero/normal)' },
              { name: 'manual_mode_override', value: '', desc: '🎮 Modus-Override (ct/manual/auto)' },
              { name: 'debug_mode', value: false, desc: '🔍 Debug-Modus aktiv' },
              
              // Diagnose
              { name: 'status', value: '', desc: 'Aktueller Status' },
              { name: 'timeline', value: '', desc: 'Timeline' },
              { name: 'alarms', value: '', desc: '🚨 Aktive Alarme' },
              
              // Statistiken (Überblick)
              { name: 'daily_summary', value: '', desc: '📊 Tages-Zusammenfassung' },
              { name: 'system_version', value: 'v2.0', desc: '🔧 System-Version' }  // v2.0: Neu
          ];
          
          datapoints.forEach(dp => {
              try {
                  const base = dp.shared ? MONITOR_CONFIG.SHARED_PREFIX : prefix;
                  createState(base + dp.name, dp.value, {
                      name: dp.desc,
                      type: typeof dp.value,
                      read: true,
                      write: true,
                      desc: `MARSTEK Monitor v2.0 - ${dp.desc}`
                  });
              } catch (error) {
                  // State existiert bereits
              }
          });
      }
      
      // ===================================================
      // KOMMUNIKATION MIT ANDEREN SCRIPTS
      // ===================================================
      
      function readFromOtherScripts() {
          try {
              const sharedPrefix = MONITOR_CONFIG.SHARED_PREFIX;
              const intelPrefix = MONITOR_CONFIG.INTEL_PREFIX;
              
              // Von Core
              monitorState.coreActive = getState(sharedPrefix + 'core_active').val || false;
              monitorState.tibberCurrent = getState(sharedPrefix + 'tibber_current').val || 0;
              
              // v2.0: Neuer Name für gemeldeten Wert
              monitorState.reportedPower = getState(sharedPrefix + 'target_power').val || 0;
              
              // Von Intelligence v2.0
              try {
                  monitorState.intelActive = getState(intelPrefix + 'intel_active').val || false;
                  monitorState.limitingActive = getState(intelPrefix + 'limiting_active').val || false;
              } catch (error) {
                  // Intelligence möglicherweise nicht gestartet
                  monitorState.intelActive = false;
              }
              
              return true;
          } catch (error) {
              console.error('❌ Monitor: Fehler beim Lesen von anderen Scripts:', error.message);
              return false;
          }
      }
      
      // ===================================================
      // ROBUSTER STATE-SETTER
      // ===================================================
      
      function safeSetState(id, value) {
          if (existsState(id)) {
              try {
                  setState(id, value);
              } catch (e) {
                  console.warn(`⚠️ Monitor safeSetState: Fehler beim Setzen von ${id}: ${e.message}`);
              }
          } else {
              console.warn(`⚠️ Monitor safeSetState: Datenpunkt ${id} existiert nicht.`);
          }
      }
      
      // ===================================================
      // KOMMUNIKATION MIT ANDEREN SCRIPTS (ROBUST)
      // ===================================================
      
      function sendToOtherScripts() {
          try {
              const sharedPrefix = MONITOR_CONFIG.SHARED_PREFIX;
              const monitorPrefix = MONITOR_CONFIG.MONITOR_PREFIX;
      
              // Override-Modus an alle
              safeSetState(sharedPrefix + 'override_mode', monitorState.overrideMode);
      
              // System-Status
              safeSetState(sharedPrefix + 'system_status', monitorState.systemStatus);
      
              // Steuerungsmodus-Info
              safeSetState(monitorPrefix + 'control_mode_detected', monitorState.controlMode);
              safeSetState(monitorPrefix + 'control_mode_confidence', monitorState.controlModeConfidence);
              safeSetState(monitorPrefix + 'manual_mode_active', monitorState.controlMode === 'manual');
              safeSetState(monitorPrefix + 'regulation_possible', monitorState.controlMode === 'ct');
      
              return true;
      
          } catch (error) {
              console.error('❌ Monitor: Fehler beim Senden an andere Scripts:', error.message);
              return false;
          }
      }
      
      // ===================================================
      // API-INTEGRATION (MARSTEK CLOUD)
      // ===================================================
      
      function fetchDeviceData() {
          if (!MONITOR_CONFIG.API_ENABLED) return;
          
          try {
              const prefix = MONITOR_CONFIG.MONITOR_PREFIX;
              const mailbox = getState(prefix + 'mailbox').val;
              const token = getState(prefix + 'token').val;
              const deviceId = getState(prefix + 'deviceId').val;
              
              if (!mailbox || !token || !deviceId) {
                  console.error("❌ Monitor: API-Zugangsdaten fehlen!");
                  return;
              }
              
              if (MONITOR_CONFIG.LOG_API) {
                  console.log("🔄 Monitor v2.0: API-Abfrage für Speicher " + deviceId);
              }
              
              const url = `https://eu.hamedata.com/ems/api/v1/getDeviceList?mailbox=${encodeURIComponent(mailbox)}&token=${token}`;
              
              httpGet(url, function(error, response) {
                  if (error) {
                      console.error("❌ Monitor: HTTP Fehler:", error);
                      return;
                  }
                  
                  try {
                      const result = JSON.parse(response.data);
                      
                      if (!result || result.code !== 1) {
                          console.log("❌ Monitor: API Error:", result?.msg || "Unknown");
                          return;
                      }
                      
                      const devices = result.data;
                      const targetDevice = devices.find(d => d.mac && d.mac.endsWith(deviceId));
                      
                      if (targetDevice) {
                          // Standard-Daten speichern
                          monitorState.deviceSoc = parseFloat(targetDevice.soc) || 0;
                          monitorState.deviceCharge = parseFloat(targetDevice.charge) || 0;
                          monitorState.deviceDischarge = parseFloat(targetDevice.discharge) || 0;
                          monitorState.lastReportTime = targetDevice.report_time;
                          
                          const prefix = MONITOR_CONFIG.MONITOR_PREFIX;
                          setState(prefix + 'device_charge', monitorState.deviceCharge);
                          setState(prefix + 'device_discharge', monitorState.deviceDischarge);
                          setState(prefix + 'device_soc', monitorState.deviceSoc);
                          setState(prefix + 'api_connected', true);
                          
                          // Steuerungsmodus-Erkennung
                          detectControlModeFromAPI(targetDevice);
                          
                          if (MONITOR_CONFIG.LOG_API) {
                              console.log(`✅ Monitor v2.0: API OK - SOC: ${monitorState.deviceSoc}%, Charge: ${monitorState.deviceCharge}W, Discharge: ${monitorState.deviceDischarge}W`);
                          }
                      }
                      
                  } catch (e) {
                      console.error("❌ Monitor: Parse Fehler:", e.message);
                  }
              });
              
          } catch (error) {
              console.error('❌ Monitor: API-Fetch Fehler:', error.message);
          }
      }
      
      function fetchDeviceDataSmart() {
          if (!MONITOR_CONFIG.API_ENABLED) return;
          
          const now = Date.now();
          
          if (now < monitorState.apiState.nextFetchTime) {
              return;
          }
          
          const currentPower = Math.abs(monitorState.tibberCurrent);
          const isActive = currentPower > 100;
          
          if (isActive) {
              monitorState.apiState.lastActivity = now;
          }
          
          // Modus-abhängige Intervalle
          let interval;
          if (monitorState.controlMode === 'manual' && monitorState.controlModeConfidence !== 'niedrig') {
              // MANUELLER MODUS: Häufiger prüfen (auf Umstellung warten)
              interval = 60000 + Math.random() * 30000; // 1-1.5 Minuten
          } else if (isActive) {
              // AKTIV: Normale Intervalle
              interval = 240000 + Math.random() * 120000; // 4-6 Minuten
          } else {
              // INAKTIV: Längere Intervalle
              interval = 600000 + Math.random() * 300000; // 10-15 Minuten
          }
          
          monitorState.apiState.nextFetchTime = now + interval;
          monitorState.apiState.lastFetch = now;
          
          // Timing-Info speichern
          const prefix = MONITOR_CONFIG.MONITOR_PREFIX;
          setState(prefix + 'last_api_fetch', monitorState.apiState.lastFetch);
          setState(prefix + 'next_api_fetch', monitorState.apiState.nextFetchTime);
          
          fetchDeviceData();
      }
      
      // ===================================================
      // STEUERUNGSMODUS-ERKENNUNG (UNVERÄNDERT)
      // ===================================================
      
      function detectControlModeFromAPI(deviceData) {
          if (!MONITOR_CONFIG.MODE_DETECTION_ENABLED || !deviceData) return 'unbekannt';
          
          let detectedMode = 'unbekannt';
          let confidence = 'niedrig';
          let reasons = [];
          
          // API-Feld-Analyse
          if (deviceData.status !== undefined) {
              if (deviceData.status === 0) {
                  detectedMode = 'ct';
                  confidence = 'mittel';
                  reasons.push('status=0 → CT-Modus vermutet');
              } else if (deviceData.status === 1) {
                  reasons.push('status=1 → Gerät online, Modus unklar');
              }
          }
          
          // Weitere Modus-Felder suchen
          const modeFields = ['mode', 'control_mode', 'work_mode', 'operation_mode', 'ct_mode', 'manual_mode'];
          for (const field of modeFields) {
              if (deviceData[field] !== undefined) {
                  const value = String(deviceData[field]).toLowerCase();
                  if (value.includes('manual')) {
                      detectedMode = 'manual';
                      confidence = 'hoch';
                      reasons.push(`${field}="${value}" → Manueller Modus`);
                      break;
                  } else if (value.includes('ct') || value.includes('auto') || value.includes('grid')) {
                      detectedMode = 'ct';
                      confidence = 'hoch';
                      reasons.push(`${field}="${value}" → CT-Modus`);
                      break;
                  }
              }
          }
          
          // API-Daten speichern
          monitorState.apiModeData = {
              access: deviceData.access,
              status: deviceData.status,
              detectedMode: detectedMode,
              confidence: confidence,
              reasons: reasons,
              lastUpdate: Date.now(),
              rawData: JSON.stringify(deviceData, null, 2)
          };
          
          return { mode: detectedMode, confidence: confidence, reasons: reasons };
      }
      
      function updateControlModeDetection() {
          if (!MONITOR_CONFIG.MODE_DETECTION_ENABLED) return;
          
          const now = Date.now();
          
          // API-basierte Erkennung
          let apiResult = { mode: 'unbekannt', confidence: 'niedrig', reasons: [] };
          if (monitorState.apiModeData && monitorState.apiModeData.lastUpdate && 
              (now - monitorState.apiModeData.lastUpdate) < 600000) {
              apiResult = {
                  mode: monitorState.apiModeData.detectedMode || 'unbekannt',
                  confidence: monitorState.apiModeData.confidence || 'niedrig',
                  reasons: monitorState.apiModeData.reasons || []
              };
          }
          
          // Intelligente Kombination
          let finalMode = 'unbekannt';
          let finalConfidence = 'niedrig';
          let detectionMethod = 'keine';
          
          if (apiResult.confidence === 'hoch') {
              finalMode = apiResult.mode;
              finalConfidence = 'hoch';
              detectionMethod = 'api';
          } else if (apiResult.confidence === 'mittel') {
              finalMode = apiResult.mode;
              finalConfidence = 'mittel';
              detectionMethod = 'api';
          } else {
              finalMode = 'unbekannt';
              finalConfidence = 'niedrig';
              detectionMethod = 'unclear';
          }
          
          // Update State
          const previousMode = monitorState.controlMode;
          monitorState.controlMode = finalMode;
          monitorState.controlModeConfidence = finalConfidence;
          monitorState.lastModeDetection = now;
          
          // History
          monitorState.modeDetectionHistory.push({
              time: now,
              mode: finalMode,
              confidence: finalConfidence,
              method: detectionMethod
          });
          if (monitorState.modeDetectionHistory.length > 20) {
              monitorState.modeDetectionHistory.shift();
          }
          
          // Logging bei Änderungen
          if (previousMode !== finalMode && MONITOR_CONFIG.LOG_MODE_DETECTION) {
              console.log(`🎮 Monitor v2.0: MODUS-ÄNDERUNG! ${previousMode.toUpperCase()} → ${finalMode.toUpperCase()}`);
              console.log(`   Sicherheit: ${finalConfidence}, Methode: ${detectionMethod}`);
              
              if (finalMode === 'manual' && finalConfidence !== 'niedrig') {
                  console.log(`⚠️ Monitor: KRITISCH - Wechsel zu MANUELLER STEUERUNG!`);
                  console.log(`   ❌ CT-Signale werden ignoriert`);
                  console.log(`   🔧 Scripts v2.0 können nicht mehr regeln`);
                  console.log(`   💡 LÖSUNG: In MARSTEK App auf CT-Modus umstellen`);
                  
                  // Alarm hinzufügen
                  monitorState.alarms.push({
                      time: now,
                      type: 'critical',
                      message: 'Manueller Modus erkannt - CT-Regelung deaktiviert'
                  });
                  
              } else if (finalMode === 'ct' && finalConfidence !== 'niedrig') {
                  console.log(`✅ Monitor: PERFEKT - Wechsel zu CT-STEUERUNG!`);
                  console.log(`   ✅ Scripts v2.0 können wieder regeln`);
                  console.log(`   🎯 Automatische 0W-Regelung aktiviert`);
                  
                  // Alarm entfernen wenn vorhanden
                  monitorState.alarms = monitorState.alarms.filter(a => a.type !== 'critical');
              }
          }
          
          // An andere Scripts senden
          sendToOtherScripts();
      }
      
      // ===================================================
      // v2.0: REGELGÜTE-BERECHNUNG
      // ===================================================
      
      function calculateRegulationQuality() {
          try {
              const netResult = Math.abs(monitorState.tibberCurrent);
              
              // Regelgüte in % (100% = perfekte 0W-Regelung)
              let quality = 100;
              
              if (netResult <= 20) {
                  quality = 100; // Exzellent
              } else if (netResult <= 50) {
                  quality = 95;  // Sehr gut
              } else if (netResult <= 100) {
                  quality = 85;  // Gut
              } else if (netResult <= 200) {
                  quality = 70;  // Befriedigend
              } else {
                  quality = Math.max(0, 50 - ((netResult - 200) / 20)); // Schlechter werdend
              }
              
              // Bei manueller Steuerung = 0%
              if (monitorState.controlMode === 'manual') {
                  quality = 0;
              }
              
              safeSetState(MONITOR_CONFIG.MONITOR_PREFIX + 'regulation_quality', Math.round(quality));
              
              return quality;
              
          } catch (error) {
              console.error('❌ Monitor: Regelgüte-Berechnung Fehler:', error.message);
              return 0;
          }
      }
      
      // ===================================================
      // DIAGNOSE & STATUS-UPDATES (v2.0)
      // ===================================================
      
      function updateDiagnoseAndStatus() {
          try {
              const prefix = MONITOR_CONFIG.MONITOR_PREFIX;
              
              // Netz-Resultat berechnen
              const netResult = monitorState.tibberCurrent - monitorState.deviceDischarge + monitorState.deviceCharge;
              setState(prefix + 'net_result', Math.round(netResult));
              
              // v2.0: Regelgüte berechnen
              const quality = calculateRegulationQuality();
              
              // Status-Text erstellen
              let status = "";
              const absNetResult = Math.abs(netResult);
              const modeInfo = monitorState.controlMode !== 'unbekannt' ? ` (${monitorState.controlMode.toUpperCase()}-Modus)` : '';
              
              if (monitorState.controlMode === 'manual' && monitorState.controlModeConfidence !== 'niedrig') {
                  status = `⚠️ MANUELLER MODUS AKTIV - CT-Regelung DEAKTIVIERT! In App auf CT-Modus umstellen.`;
              } else if (!monitorState.coreActive) {
                  status = `❌ CORE-ENGINE v2.0 NICHT AKTIV - CT-Simulation gestoppt!`;
              } else if (!monitorState.intelActive) {
                  status = `⚠️ Intelligence v2.0 nicht aktiv - nur Basis-CT`;
              } else if (monitorState.limitingActive) {
                  status = `🔒 Begrenzung aktiv${modeInfo} - System v2.0 funktioniert optimal`;
              } else if (absNetResult <= 20) {
                  status = `🏆 EXZELLENTE 0W-REGELUNG v2.0!${modeInfo} (${Math.round(quality)}% Güte)`;
              } else if (absNetResult <= 50) {
                  status = `✅ Gut geregelt v2.0${modeInfo} (${Math.round(quality)}% Güte)`;
              } else {
                  status = `🎯 Normale Regelung v2.0${modeInfo} - ${Math.round(netResult)}W Netz-Resultat (${Math.round(quality)}% Güte)`;
              }
              setState(prefix + 'status', status);
              
              // Timeline erstellen (v2.0)
              const now = new Date().toLocaleTimeString();
              const coreStatus = monitorState.coreActive ? '✅' : '❌';
              const intelStatus = monitorState.intelActive ? '✅' : '⚠️';
              const apiStatus = (Date.now() - monitorState.apiState.lastFetch) < 600000 ? '✅' : '⚠️';
              
              const timeline = [
                  `[${now}] 📊 MARSTEK MONITOR v2.0`,
                  `Core: ${coreStatus} | Intelligence: ${intelStatus} | API: ${apiStatus}`,
                  `Modus: ${monitorState.controlMode.toUpperCase()} (${monitorState.controlModeConfidence})`,
                  `SOC: ${monitorState.deviceSoc}% | Netz: ${Math.round(netResult)}W | Güte: ${Math.round(quality)}%`,
                  `Tibber: ${Math.round(monitorState.tibberCurrent)}W → Gemeldet: ${Math.round(monitorState.reportedPower)}W`,
                  `System: ${monitorState.systemStatus} v2.0`
              ].join(' | ');
              setState(prefix + 'timeline', timeline);
              
              // API-Timing
              if (monitorState.lastReportTime) {
                  const apiDelay = Math.round(Date.now()/1000 - monitorState.lastReportTime);
                  setState(prefix + 'api_delay', apiDelay);
              }
              
              // Alarme
              const alarmText = monitorState.alarms.map(a => `[${new Date(a.time).toLocaleTimeString()}] ${a.message}`).join(' | ');
              setState(prefix + 'alarms', alarmText);
              
              // v2.0: Erweiterte Tages-Zusammenfassung
              let dailySummary = `SOC: ${monitorState.deviceSoc}% | Netz: ${Math.round(netResult)}W | Modus: ${monitorState.controlMode} | Güte: ${Math.round(quality)}%`;
              if (monitorState.intelActive) {
                  // Daten von Intelligence v2.0 holen
                  try {
                      const dailyNetPurchase = getState(MONITOR_CONFIG.INTEL_PREFIX + 'daily_net_purchase_kwh').val || 0;
                      const zeroWattPercent = getState(MONITOR_CONFIG.INTEL_PREFIX + 'zero_watt_time_percent').val || 0;
                      dailySummary += ` | Bezug: ${dailyNetPurchase.toFixed(2)}kWh | 0W: ${zeroWattPercent.toFixed(1)}%`;
                  } catch (error) {
                      // Intelligence-Daten nicht verfügbar
                  }
              }
              setState(prefix + 'daily_summary', dailySummary);
              
          } catch (error) {
              console.error('❌ Monitor: Diagnose-Update Fehler:', error.message);
          }
      }
      
      // ===================================================
      // HAUPT-MONITOR-LOOP (v2.0)
      // ===================================================
      
      function runMonitorLoop() {
          try {
              // 1. Von anderen Scripts lesen
              readFromOtherScripts();
              
              // 2. Steuerungsmodus-Erkennung aktualisieren
              const shouldUpdateMode = !monitorState.lastModeDetection || 
                  (Date.now() - monitorState.lastModeDetection) > 60000 ||
                  (monitorState.controlMode === 'manual' && (Date.now() - monitorState.lastModeDetection) > 30000);
              
              if (shouldUpdateMode) {
                  updateControlModeDetection();
              }
              
              // 3. System-Status bewerten (v2.0)
              if (monitorState.coreActive && monitorState.intelActive) {
                  monitorState.systemStatus = 'optimal-v2.0';
              } else if (monitorState.coreActive) {
                  monitorState.systemStatus = 'basic-ct-v2.0';
              } else {
                  monitorState.systemStatus = 'critical';
              }
              
              // 4. Diagnose & Status aktualisieren
              updateDiagnoseAndStatus();
              
              // 5. An andere Scripts senden
              sendToOtherScripts();
              
              monitorState.lastUpdate = Date.now();
              
          } catch (error) {
              console.error('❌ Monitor: Loop-Fehler:', error.message);
              monitorState.systemStatus = 'error';
          }
      }
      
      // ===================================================
      // OVERRIDE & DEBUG FUNKTIONEN (UNVERÄNDERT)
      // ===================================================
      
      function handleOverrides() {
          try {
              const prefix = MONITOR_CONFIG.MONITOR_PREFIX;
              
              // Override-Modus prüfen
              const overrideMode = getState(prefix + 'override_mode').val || '';
              if (overrideMode !== monitorState.overrideMode) {
                  monitorState.overrideMode = overrideMode;
                  if (MONITOR_CONFIG.LOG_MONITOR) {
                      console.log(`🔧 Monitor v2.0: Override-Modus geändert: "${overrideMode}"`);
                  }
              }
              
              // Manueller Modus-Override
              const manualModeOverride = getState(prefix + 'manual_mode_override').val || '';
              if (manualModeOverride !== monitorState.manualModeOverride) {
                  monitorState.manualModeOverride = manualModeOverride;
                  if (manualModeOverride === 'ct') {
                      monitorState.controlMode = 'ct';
                      monitorState.controlModeConfidence = 'hoch';
                      console.log(`🔧 Monitor v2.0: Manueller Override - Modus auf CT gesetzt`);
                  } else if (manualModeOverride === 'manual') {
                      monitorState.controlMode = 'manual';
                      monitorState.controlModeConfidence = 'hoch';
                      console.log(`🔧 Monitor v2.0: Manueller Override - Modus auf MANUAL gesetzt`);
                  }
              }
              
              // Sofort-Prüfung
              const checkModeNow = getState(prefix + 'check_mode_now').val;
              if (checkModeNow === true) {
                  console.log('🔄 Monitor v2.0: Sofort-Prüfung gestartet...');
                  fetchDeviceData(); // Sofortige API-Abfrage
                  setState(prefix + 'check_mode_now', false); // Reset
              }
              
          } catch (error) {
              console.error('❌ Monitor: Override-Handling Fehler:', error.message);
          }
      }
      
      // ===================================================
      // MONITOR START (v2.0)
      // ===================================================
      
      function startMonitor() {
          console.log('📊 MARSTEK-Monitor-Control v2.0 - ÜBERWACHUNG & STEUERUNG\n');
          console.log('🎯 ZWECK: ÜBERWACHUNG, DIAGNOSE & STEUERUNG');
          console.log('✅ Steuerungsmodus-Erkennung (CT vs Manuell)');
          console.log('✅ API-Integration + Smart-Timing');
          console.log('✅ Diagnose-System + Datenpunkte-Verwaltung');
          console.log('✅ Debug-Modi + Override-Funktionen');
          console.log('✅ SOC-Intelligence (von API für Intelligence v2.0)');
          console.log('✅ v2.0: Regelgüte-Monitoring für korrekte Logik');
          console.log('');
          console.log('🔗 KOMMUNIKATION:');
          console.log('   📥 Überwacht: Core v2.0 + Intelligence v2.0 Status');
          console.log('   📡 API: MARSTEK Cloud-Integration');
          console.log('   🎮 Steuert: Override-Modi und Modus-Erkennung');
          console.log('   📈 Überwacht: Regelgüte der neuen 0W-Regelung');
          console.log('   ⚠️ Darf crashen ohne CT/Intelligence zu stoppen!');
          console.log('=====================================');
          
          // Datenpunkte erstellen
          createMonitorDatapoints();
              
          // Status setzen
          safeSetState(MONITOR_CONFIG.MONITOR_PREFIX + 'monitor_active', true);
          safeSetState(MONITOR_CONFIG.MONITOR_PREFIX + 'system_status', 'starting');
          safeSetState(MONITOR_CONFIG.SHARED_PREFIX + 'system_status', 'starting-v2.0');
          safeSetState(MONITOR_CONFIG.MONITOR_PREFIX + 'system_version', 'v2.0');
      
          
          // Loops starten
          setInterval(runMonitorLoop, MONITOR_CONFIG.UPDATE_INTERVAL);         // 10s Monitor-Loop
          setInterval(fetchDeviceDataSmart, 30000);                           // 30s API-Check
          setInterval(handleOverrides, 5000);                                 // 5s Override-Check
          
          // Sofort starten
          setTimeout(runMonitorLoop, 3000);
          setTimeout(fetchDeviceData, 5000);
          
          console.log('\n📊 MONITOR v2.0 AKTIV!');
          console.log('💡 Überwacht Core v2.0 + Intelligence v2.0');
          console.log('🎮 Modus-Erkennung: ' + (MONITOR_CONFIG.MODE_DETECTION_ENABLED ? 'Aktiv' : 'Deaktiviert'));
          console.log('📡 API-Integration: ' + (MONITOR_CONFIG.API_ENABLED ? 'Aktiv' : 'Deaktiviert'));
          console.log('🔋 SOC-Intelligence: Übertragen an Intelligence-Script v2.0');
          console.log('📈 Regelgüte-Monitoring: Aktiv');
          console.log('=====================================\n');
      }
      
      function stopMonitor() {
          try {
              safeSetState(MONITOR_CONFIG.MONITOR_PREFIX + 'monitor_active', false);
              safeSetState(MONITOR_CONFIG.MONITOR_PREFIX + 'system_status', 'stopped');
              console.log('🛑 MARSTEK-Monitor v2.0 beendet');
          } catch (error) {
              console.error('❌ Monitor Stop-Fehler:', error.message);
          }
      }
      
      // ===================================================
      // SCRIPT START
      // ===================================================
      
      startMonitor();
      
      // Event-Handler für Sofort-Prüfung
      on({id: MONITOR_CONFIG.MONITOR_PREFIX + 'check_mode_now', change: 'ne'}, function (obj) {
          if (obj.state.val === true) {
              fetchDeviceData();
              setTimeout(() => {
                  setState(MONITOR_CONFIG.MONITOR_PREFIX + 'check_mode_now', false);
              }, 1000);
          }
      });
      
      onStop(() => {
          stopMonitor();
      });
      
      // ===================================================
      // KONFIGURATIONSHINWEISE FÜR FORUM-NUTZER:
      // ===================================================
      /*
      WICHTIGE ANPASSUNGEN NÖTIG:
      
      1. PREFIXE ANPASSEN:
         Zeile 20: SHARED_PREFIX: '0_userdata.0.marstek_V-E.shared.'
         Zeile 21: INTEL_PREFIX: '0_userdata.0.marstek_V-E.intel.'
         Zeile 22: MONITOR_PREFIX: '0_userdata.0.marstek_V-E.monitor.'
         → Passe die Prefixe an deine ioBroker-Struktur an
      
      2. API-ZUGANGSDATEN AUSFÜLLEN:
         Nach dem Script-Start in ioBroker:
         - monitor.mailbox: Deine E-Mail-Adresse für MARSTEK-App
         - monitor.token: API-Token aus der MARSTEK-App
         - monitor.deviceId: Deine MARSTEK Speicher-ID (z.B. 3456, 4567, etc.)
         
      3. MARSTEK API-TOKEN ERHALTEN:
         - MARSTEK-App öffnen
         - Einstellungen → API oder Entwickler-Bereich
         - Token generieren und kopieren
         
      4. DEVICE-ID FINDEN:
         - In der MARSTEK-App: Geräteinfo
         - Oder MAC-Adresse → letzte 4 Stellen (z.B. ABCD3456 → 4567)
         
      5. ZWEITER SPEICHER (OPTIONAL):
         - enable_second_storage auf true setzen falls vorhanden
         - Zweite Device-ID entsprechend anpassen
      
      FEATURES DEAKTIVIEREN (OPTIONAL):
      - API_ENABLED: false → Deaktiviert Cloud-Integration
      - MODE_DETECTION_ENABLED: false → Deaktiviert Modus-Erkennung
      - Logging reduzieren: LOG_MONITOR/LOG_API: false setzen
      
      HINWEIS: 
      Das Monitor-Script ist optional! Core + Intelligence funktionieren auch ohne Monitor.
      Monitor bietet aber wertvolle Diagnose- und Überwachungsfunktionen.
      */
      

      Grundsätzlich läuft es mir, bin aber mit der Regelung noch nicht zufrieden.

      Edit:
      Ne, die Regelung ist noch nicht richtig, es Oszilliert zu viel hin und her bei der Entladung.

      C 1 Reply Last reply Reply Quote 0
      • C
        cwa @Gismoh last edited by

        @gismoh
        Vielen Dank!
        Werde ich nach dem Urlaub direkt ausprobieren.

        G 1 Reply Last reply Reply Quote 0
        • G
          Gismoh @cwa last edited by

          @cwa
          Gerne 😉

          Evtl. bin ich dann auch schon weiter mit dem Regelverhalten.

          S 1 Reply Last reply Reply Quote 0
          • S
            Steffen 5 @Gismoh last edited by

            Hallo @gismoh,
            ich habe auch einen neuen Marstek Speicher und freu mich über Deine Lösungsidee.
            Ich hab Deine Skripte gelesen und würde mit Dir gerne über die oszillierende Regelung diskutieren.
            🙂 Nur wenn Du willst natürlich.
            Meiner Meinung nach darfst Du keine "ANTI-OSZILLATIONS-GLÄTTUNG (des Tibber-Werts)" machen, denn das erzeugt schnell einen instabilen (=oszillierenden) Regelkreis.

            Wenn der B2500 auch ohne Glättung des Tibber-Werts noch viel oszilliert, kann es helfen, wenn der 'currentValue' mit einem konstanten Faktor x (0< x< 1) multipliziert wird, bevor er an den B2500 gemeldet wird.

            Kurze Erklärung:
            Im Haus wird der Strom verbraucht, den der Stromspeicher und der Netzanschluss liefert.
            Die Aufgabe des Stromspeichers ist soviel Strom zu liefern, dass der Netzanschluss 0kW liefert.

            (Vereinfachte) Funktion der Regelschleife mit Glättung:
            t0: Stromspeicher bekommt gemeldet, dass der Netzanschluss 100W liefert --> Leistungsabgabe des Stromspeichers steigt um 100W
            t1: Netzanschluss liefert 0W, wegen der Glättungsfunktion wird dem Stromspeicher nicht 0W, sondern 70W gemeldet. --> Leistungsabgabe des Stromzählers wird weiter erhöht. (Es entsteht eine Oszillation...)

            (Vereinfachte) Funktion der Regelschleife mit Dämpfung:
            Beispiel mit Dämpfungsfaktor x = 0.8
            t0: Netzanschluss liefert 100W --> Stromspeicher bekommt gemeldet, dass 80W an Leistung fehlen --> Leistungsabgabe des Stromspeichers steigt um 80W
            t1: Netzanschluss liefert 20W --> Stromspeicher bekommt gemeldet, dass 16W an Leistung fehlen --> Leistungsabgabe des Stromspeichers steigt um 16W
            t2: Netzanschluss liefert 4W --> Stromspeicher bekommt gemeldet, dass 3.2W an Leistung fehlen --> Leistungsabgabe des Stromspeichers steigt um 3,2W
            (Nach ein paar Zyklen stimmt die Leistungsabgabe des Stromspeichers perfekt)

            Viele Grüße,
            Steffen

            G 1 Reply Last reply Reply Quote 0
            • G
              Gismoh @Steffen 5 last edited by

              Moin @steffen-5
              , besten Dank und sehr gerne.
              Bin gerade leider etwas im Streß, und sehe mir später deinen Kommentar noch mal an.
              Aktuell sind meine Scripte eh bereits etwas anders - hatte noch einen "Blöden" Fehler bei mir gehabt.

              1 Reply Last reply Reply Quote 0
              • O
                ottelo last edited by ottelo

                Hi zusammen. Ich komme aus dem Tasmota Bereich und habe ein Blog bzgl. Stromzähler auslesen mit Wifi Lesekopf und Tasmota. Zusammen mit ein paar anderen Usern und einem Entwickler von Tasmota (Script) haben wir es geschafft, den Shelly 3EM mit Tasmota zu emulieren, damit man keine extra Hardware benötigt. Also gleicher Ansatz wie hier beschrieben, aber mit eine Standalone Lösung, die nur einen WiFi Tasmota Lesekopf für den Stromzähler und den Marstek Akku (Jupiter, Venus, B2500) benötigt.

                Bzgl. Oszillation hatten wir auch so unsere Probleme, die wir aber nun gemeinsam lösen konnten. Bei Interesse gerne mal hier vorbeischauen oder auf meinem Blog. Ein Austausch untereinander ist für die Community immer sinnvoll. Gruß 🙂

                G 1 Reply Last reply Reply Quote 1
                • G
                  Gismoh @ottelo last edited by Gismoh

                  @ottelo @steffen-5

                  danke für eure Rückmeldungen.

                  Ich bin da aktuell noch mitten in der Umsetzung.
                  Grundsätzlich funktioniert die reine Skriptlösung – man braucht also keinen zusätzlichen Docker oder andere externe Tools. JS-Skripte im ioBroker reichen völlig aus.

                  Derzeit arbeite ich eher an der Steuerung und Logik. Ziel ist u.a. eine SoC-Berücksichtigung, die Marstek selbst nicht vorsieht. Also z.B.: Akku nur bis XX % laden oder nur bis XX % entladen – frei im Skript einstellbar.

                  Außerdem möchte ich eine regelbare Lade-/Entladeleistung integrieren.
                  In der App kann man zwar Grenzen setzen (z.B. max. 800 W oder 2.500 W), aber:

                  Bei der Entladung halten sich die Speicher an die eingestellte Begrenzung (u.a. wegen Leitungs-/Brandschutz).

                  Beim Laden leider nicht – selbst wenn man 800 W vorgibt, ziehen die Speicher problemlos 2.500 W. Für die Leitungen macht es aber keinen Unterschied, ob der Strom „+“ oder „–“ ist (Laden/Entladen) – belastet werden sie gleich stark.

                  Da ich selbst nicht programmieren kann, nutze ich KI zur Unterstützung. Allerdings stoße ich dabei immer wieder (trotz bezahlter Tarife) auf Sperren und Timeouts, was das Ganze ziemlich ausbremst.

                  Als Nächstes möchte ich eine Mehr-Speicher-Lösung sauber umsetzen. Erste Ansätze habe ich bereits bei mir integriert. Auch der API-Abruf läuft momentan noch in einem separaten Skript – den würde ich dann einarbeiten, sobald die Basis stabil läuft.

                  S 1 Reply Last reply Reply Quote 0
                  • LukyLuke
                    LukyLuke last edited by

                    Hallo, ich möchte mich hier mit einklinken.

                    Seit einer Woche besitze ich einen Marstek venus E V3.0. Im Haus läuft ein SMA Home Manager 2 an der PV Anlage inkl. Speicher.
                    Nun würde ich gerne die Venus über iobroker steuern, also nur die PV-Überproduktion speichern und nach Bedarf bzw. nachts wieder abgeben.

                    Mein Problem: Wie installiere ich unimeter in Docker auf meiner Synology 7.2?
                    Könnt ihr mir da weiterhelfen? Den Container habe ich soweit am Laufen, aber die Venus findet nix. Vermutlich habe ich das ganze falsch konfiguriert. Kennt jemand ein how2 für unimeter unter Docker?

                    Vielen Dank vorab
                    Gruß Luky

                    1 Reply Last reply Reply Quote 0
                    • S
                      stephan61 @Gismoh last edited by

                      @gismoh
                      Hallo gismoh
                      habe die venus V3.0 und habe mir lan und API freischalten lassen
                      wie komme ich an den API Token?

                      Gruß Stephan

                      G 1 Reply Last reply Reply Quote 0
                      • G
                        Gismoh @stephan61 last edited by

                        @stephan61
                        Hallo stephan61,
                        hatte es via http Toolkit gemacht.

                        Beste Grüße!

                        1 Reply Last reply Reply Quote 0
                        • First post
                          Last post

                        Support us

                        ioBroker
                        Community Adapters
                        Donate
                        FAQ Cloud / IOT
                        HowTo: Node.js-Update
                        HowTo: Backup/Restore
                        Downloads
                        BLOG

                        905
                        Online

                        32.4k
                        Users

                        81.2k
                        Topics

                        1.3m
                        Posts

                        14
                        28
                        8786
                        Loading More Posts
                        • Oldest to Newest
                        • Newest to Oldest
                        • Most Votes
                        Reply
                        • Reply as topic
                        Log in to reply
                        Community
                        Impressum | Datenschutz-Bestimmungen | Nutzungsbedingungen
                        The ioBroker Community 2014-2023
                        logo