{
  "schemaVersion": 2,
  "assetModel": "SB-195-440-3-IE3-TYP1",
  "assetType": "vacuum-blower",
  "displayName": "Schmalz SB-195",
  "_v2": "Schema v2 (2026-07-10): + features (On-Edge-Analytik: RPM/Vibration/Unwucht/Huellkurve/umgebungsbereinigt), bearing, anomalies (Fehlerbilder als maschinenlesbare Regeln), ml (Baseline+Anomaly-Score). Groesser als 4 KB -> Laden ueber FINDER/HTTP oder Config-Upload (nicht der 4-KB-MQTT-Frame, ADR-082).",
  "identity": {
    "manufacturer": "J. Schmalz GmbH",
    "series": "SB (Seitenkanalverdichter)",
    "articleNumber": "10.04.01.00091",
    "ratedPowerKw": 3.0,
    "ratedPowerKw60Hz": 3.6,
    "ratedVacuumMbar": 440,
    "ratedFlowM3h": 195,
    "ratedCurrentA": 5.8,
    "startingCurrentA": 16.0,
    "ratedRpm": 2940,
    "ratedRpm60Hz": 3530,
    "poles": 2,
    "mainsHz": 50,
    "protection": "IP55",
    "insulationClass": "ISO F",
    "thermalProtection": "bimetal",
    "motor": "IE3",
    "medium": "Luft"
  },
  "electrical": {
    "_doc": "Motor-Elektrik + Sensorik-Stufe 1 (Stromzange, geplant). ratedCurrentA wiring-/spannungsabhaengig -> vor Ort am Motor-Typenschild verifizieren.",
    "ratedCurrentA": 5.8,
    "startingCurrentA": 16.0,
    "lineHz": 50,
    "currentModel": {
      "method": "load-from-current",
      "runThresholdFrac": 0.15,
      "publishAs": { "current": "motorCurrentA", "load": "motorLoadPct" },
      "_doc": "loadPct = 100 * I_gemessen / ratedCurrentA; runElectric = I > runThresholdFrac*ratedCurrentA (exakter als Vakuum-Lauf-Indikator)"
    },
    "mcsa": { "lineHz": 50, "_doc": "Seitenbaender bei lineHz +- 2*s*lineHz (Schlupf s) -> Rotorstab/Exzentrizitaet. Feature v2, sobald Stromkanal existiert." },
    "sensor": { "_annahme": "SCT-013-030 Stromzange -> ADS1115 A2 (I2C). Nennstrom am Typenschild verifizieren (Art 00091: DS 02989 Y350/D200 = 7.3/12.6 A)." }
  },
  "signals": {
    "run":          { "from": "s1", "runAboveMbar": 50, "_doc": "S1 (Geblaese-Saugseite) bleibt >0 solange der Motor laeuft -> Lauf-Indikator" },
    "suctionCycle": { "from": "s2", "highMbar": 200, "lowMbar": 100, "minPhaseMs": 300, "_doc": "S2 (ventilnah) schwingt mit dem Greif-Takt; steigende Flanke = 1 Saugzyklus" }
  },
  "temperatures": {
    "ambient": { "minC": -10, "maxC": 40, "maxAltitudeM": 800, "maxIntakeHumidityPct": 90, "_doc": "zulaessige Umgebung -10..40 C, max. 800 m ue. NN, max. 90% rF Ansaugluft (BAL 6.1)" },
    "bearing": { "from": "t1", "activeC": 48, "warnC": 90,  "critC": 120, "_doc": "Lager; BAL-Oberflaechentabelle; SB-195 laeuft kuehler (3 kW)" },
    "exhaust": { "from": "t2", "activeC": 60, "warnC": 115, "critC": 135, "maxC": 135, "maxAtRefC": 115, "sensorSaturatesC": 125, "_doc": "Abluft max. 115 C (BAL 6.2, Ref 1000 mbar/20 C); +20 K bei 40 C Umgebung -> bis ~135 C. DS18B20 saettigt bei 125 C -> PT100/MAX31865-Upgrade (KW29)" },
    "medium":  { "from": "t3", "activeC": 25, "minC": 0, "maxC": 40, "warnC": 40, "critC": 50, "_doc": "zulaessige Betriebsmedium-Temp 0-40 C (BAL)" }
  },
  "performance": {
    "_doc": "Saugvermoegen-Kennlinie (Volumenstrom vs. Unterdruck) aus Datenblatt SB-Serie (dc3ffd218e01, S.8) — Werte 'bezogen auf den Atmosphaerendruck' (Saugluftmenge referiert auf Referenzatmosphaere, ~ Masse). Betriebspunkt = S1-Vakuum -> Kennlinie interpolieren.",
    "curveReference": { "gas": "Luft", "atmosphereMbar": 1000, "atmosphereTempC": 20, "tolerancePct": 10, "basis": "atmosphereReferenced", "source": "DS 30.30.01.02989 (SB-195): Bezugsdaten (Atmosphaere) 1000 mbar, 20 C, Toleranz +-10%; max. Ablufttemp +20 K bei 40 C Ansaug/Umgebung" },
    "flowVsVacuum50Hz": {
      "vacuumMbar": [0, 100, 150, 200, 250, 300, 350, 400],
      "flowM3h":    [195, 148, 125, 105, 87, 72, 55, 47],
      "_doc": "linear interpolieren; nicht ueber 400 mbar extrapolieren (Endvakuum 440)"
    },
    "flowVsVacuum60Hz": {
      "vacuumMbar": [0, 100, 150, 200, 250, 300, 350, 400],
      "flowM3h":    [235, 180, 160, 145, 126, 104, 85, 73],
      "_doc": "gleiche Maschine bei 60 Hz (Kennlinie SB-235-400)"
    },
    "flowModel": {
      "method": "interp-atmosphere-referenced",
      "constants": { "rhoRefKgM3": 1.188, "rhoNormKgM3": 1.293, "rAirJkgK": 287.05, "refTempK": 293.15, "refMbar": 1000 },
      "steps": [
        "Q_atm_m3h = lin_interp(flowVsVacuum[mainsHz], vacuum_mbar_S1)   // bezogen auf 1000 mbar / 20 C (proportional zur Masse)",
        "massFlow_kg_h = Q_atm_m3h * 1.188                              // rho(1000 mbar, 20 C)",
        "flow_Nm3h     = massFlow_kg_h / 1.293                          // Norm 0 C / 1013 mbar",
        "p_inlet_mbar  = bme680.pressure_mbar - vacuum_mbar_S1          // realer Absolutdruck am Eingang (BME680-Ortsdruck)",
        "Q_inlet_m3h   = Q_atm_m3h * (1000.0/p_inlet_mbar) * ((bme680.temperature_C+273.15)/293.15)  // tatsaechl. Volumenstrom am gedrosselten Eingang"
      ],
      "publishAs": { "atmosphereReferenced": "flowAtmM3h", "mass": "massFlowKgH", "normalized": "flowNm3h", "intakeVolumetric": "flowInletM3h" },
      "_doc": "Kennlinie ist bereits auf Atmosphaere bezogen (~Masse). BME680-Temp+Druck korrigieren auf den realen Standort (z.B. 953 statt 1000 mbar) und liefern den tatsaechlichen Volumenstrom am Eingang -> 'Volumenstrom bei bestimmter Temperatur'."
    },
    "exhaustTempVsVacuum50Hz": { "vacuumMbar": [0, 100, 200, 300, 400], "tempC":   [30, 45, 62, 85, 115], "_doc": "abgelesen DS-Diagramm S.2 (30.30.01.02989), +-10%; Endpunkt = BAL-Max 115 C" },
    "exhaustTempVsVacuum60Hz": { "vacuumMbar": [0, 100, 200, 300, 400], "tempC":   [30, 43, 60, 82, 102], "_doc": "60 Hz = SB-235-400; Endpunkt BAL-Max 102 C" },
    "shaftPowerVsVacuum50Hz":  { "vacuumMbar": [0, 100, 200, 300, 400], "powerKw": [0.9, 1.4, 1.9, 2.4, 3.0], "_doc": "abgelesen DS-Diagramm S.2, +-10%; Endpunkt = Nennleistung 3.0 kW" },
    "shaftPowerVsVacuum60Hz":  { "vacuumMbar": [0, 100, 200, 300, 400], "powerKw": [1.1, 1.7, 2.3, 2.9, 3.6], "_doc": "60 Hz; Endpunkt = Nennleistung 3.6 kW" },
    "derivedModel": {
      "_doc": "Aus S1-Vakuum interpolieren (Kurve je mainsHz), Ref 1000 mbar/20 C, +-10%. Diagramme DS S.2.",
      "expectedExhaustC":     "lin_interp(exhaustTempVsVacuum[mainsHz], vacuum_mbar_S1)",
      "expectedShaftPowerKw": "lin_interp(shaftPowerVsVacuum[mainsHz], vacuum_mbar_S1)",
      "exhaustDeltaK":        "t2_measured_C - expectedExhaustC   // >0 = ueber der bauartbedingten Erwartung -> echter Fehler (Filter/Kuehlung/Ueberlast), vakuum-bereinigt",
      "energyKwh":            "akkumuliere expectedShaftPowerKw * dt_h   // Energie-/Lastschaetzung ohne Strommessung",
      "publishAs": { "expectedExhaustC": "exhaustExpC", "exhaustDeltaK": "exhaustDeltaK", "shaftPowerKw": "shaftPowerKw", "energy": "energyKwh" }
    }
  },
  "features": {
    "_doc": "On-Edge aus dem 1-kHz-Ring gerechnet (FFT/Statistik), parametrisiert durch dieses Modell. Publish nach metrics/analytics.",
    "sampleRateHz": 1000,
    "windowS": 10,
    "rpm":      { "from": "vibration", "method": "fft-peak", "bandHz": [25, 120], "expectedRpm": 2940, "toleranceRpm": 60, "publishAs": "driveSpeedRpm", "_doc": "FFT-Peak der Accel-Magnitude x60" },
    "vibration":{ "from": "accel", "metrics": ["rmsMg", "crest", "kurtosis"], "kurtosisWarn": 4.0, "crestWarn": 5.0, "_doc": "Kurtosis/Crest > Schwelle = impulsiv -> Lagerschaden-Frueherkennung" },
    "unbalance":{ "from": "vibration", "atOrderX": 1, "baselineMg": 44, "warnMg": 80, "critMg": 150, "_doc": "1x-Amplitude (Drehfrequenz). Live-Baseline SB-195 ~44 mg (hoehere Unwucht als SB-260)" },
    "envelope": { "from": "accel", "bandHz": [150, 450], "method": "hilbert-fft", "peakBandHz": [3, 200], "_doc": "HF-demoduliert -> nicht-synchroner Peak = Lager-Defektfrequenz (BPFO/BPFI, s. bearing)" },
    "ambientNormalized": { "reference": "bme680.temperature", "bearingBaselineDeltaK": 36.5, "bearingWarnDeltaK": 45, "mediumBaselineDeltaK": -19.5, "_doc": "Delta ueber Gehaeuse-Umgebung = umgebungsbereinigter Fingerabdruck (Tagesgang r=1.00 zur BME680 rausgerechnet). SB-195-Baseline Lager +36.5 K" }
  },
  "bearing": {
    "sparePartArticle": null,
    "geometry": { "balls": null, "ballDiaMm": null, "pitchDiaMm": null, "contactAngleDeg": 0, "_annahme": true, "_doc": "Waelzlager-Geometrie unbekannt -> BPFO/BPFI erst nach Lagertyp aus Datenblatt berechenbar" },
    "defectFrequenciesOrders": { "bpfo": null, "bpfi": null, "bsf": null, "ftf": null, "_doc": "als Vielfache der Drehfrequenz (x Order); nach Geometrie fuellen" }
  },
  "kpis": {
    "operatingHours": { "source": "run",          "persist": true, "seedable": true, "_doc": "kumulierte Laufzeit (S1 ueber Schwelle)" },
    "startCycles":    { "source": "run.edge",      "persist": true, "seedable": true, "_doc": "Geblaese-Starts (an/aus)" },
    "suctionCycles":  { "source": "suctionCycle",  "persist": true, "seedable": true, "_doc": "S2-Saugtakte" },
    "heatEvents":     { "source": "temperatures.exhaust", "aboveC": 100, "_doc": "Anzahl+Dauer Abluft ueber Warnschwelle" }
  },
  "anomalies": {
    "_doc": "Fehlerbilder (SB-Datenblatt + CM-Engineering). Edge wertet indicators gegen Features/Temps aus; Aggregat -> condition + recommendation.",
    "F2_bearing": {
      "name": "Lagerschaden / erhoehte Lagerlast", "severity": "warning",
      "indicators": [
        { "feature": "ambientNormalized.bearingDeltaK", "op": ">", "value": 45, "weight": 0.4 },
        { "feature": "vibration.kurtosis",              "op": ">", "value": 4.0, "weight": 0.4 },
        { "feature": "unbalance.mg",                    "op": ">", "value": 80,  "weight": 0.2 }
      ],
      "recommendation": "Wuchtung/Ausrichtung/Schmierung pruefen; erst bei steigender Kurtosis/Crest Lager tauschen.",
      "sparePartArticle": null
    },
    "F3_motorOverload": {
      "name": "Motor-Ueberlast / Abluft-Ueberhitzung", "severity": "critical",
      "indicators": [
        { "signal": "temperatures.exhaust", "op": ">=", "value": 125, "weight": 0.6, "_note": "DS18B20-Anschlag; PT100 liefert echten Wert" },
        { "signal": "temperatures.bearing", "op": ">",  "value": 90,  "weight": 0.4 }
      ],
      "recommendation": "Luftweg/Filter/Endvakuum-Dauerlast pruefen; Kuehlung/Aufstellung sicherstellen."
    },
    "unbalance": {
      "name": "Unwucht", "severity": "info",
      "indicators": [ { "feature": "unbalance.mg", "op": ">", "value": 80, "weight": 1.0 } ],
      "recommendation": "Laufrad wuchten; Befestigung/Fundament pruefen."
    }
  },
  "ml": {
    "baseline": { "learnHours": 24, "features": ["rpm", "ambientNormalized.bearingDeltaK", "unbalance.mg", "vibration.kurtosis"], "_doc": "Normalzustand ueber 24 h lernen -> je Feature Mittel+Streuung" },
    "anomalyScore": { "method": "zscore-baseline", "warnZ": 3, "critZ": 5, "publishAs": "health/anomalyScore", "_doc": "Abweichung jedes Features von seiner Baseline (z-Score) -> Aggregat 0..1" },
    "edgeImpulse": { "enabled": false, "modelRef": null, "_doc": "optional: trainiertes EI-Modell auf Vibrations-/Akustik-Features" }
  },
  "maintenance": {
    "serviceIntervalHours": 20000,
    "serviceIntervalNote": "Inspektion durch Schmalz-Service: 20.000 h, min. 1x/3 Jahre (BAL 30.30.01.01410 Kap. 11.3, bestaetigt)",
    "filterCleanIntervalHours": 200,
    "tasks": [
      { "task": "Gehaeuse/Oberflaeche reinigen (absaugen/Druckluft)",              "intervalHoursMin": 40, "intervalHoursMax": 200, "_doc": "Intervall nach Staubanfall (BAL 11.3/11.8)" },
      { "task": "Ansaugfilter reinigen (Druckluft, ggf. tauschen)",                "intervalHoursMax": 200, "_doc": "min. alle 200 h (BAL 11.9); nur Geraete mit Ansaugfilter" },
      { "task": "Vakuum-Sicherheitsventil bewegen (Festsetzen vermeiden)",         "intervalHoursMin": 40, "intervalHoursMax": 200, "_doc": "BAL 11.10" },
      { "task": "Sicherheits-/Schutzeinrichtungen pruefen (vollstaendig+intakt)",  "intervalHoursMin": 40, "intervalHoursMax": 200, "_doc": "BAL 11.3" },
      { "task": "Inspektion durch Schmalz-Service",                               "intervalHours": 20000, "intervalYearsMax": 3, "_doc": "20.000 h, min. 1x/3 Jahre (BAL 11.3)" }
    ],
    "operatingLimits": { "startStopCyclesPerHourMax": 10, "_doc": "max. 10 Start/Stopp-Zyklen pro Stunde (BAL 8.5)" },
    "remainingLife": { "method": "hours-vs-interval", "_doc": "Restlaufzeit = (Intervall - Betriebsstunden); mit h/Tag -> Wartungsdatum/KW. Kurzintervalle (Filter/Ventil 40-200 h) separat trenden." },
    "spareParts": [
      { "articleNumber": null, "name": "Lagersatz SB-195", "forAnomaly": "F2_bearing", "_annahme": "Artikel-Nr. aus Ersatzteilkatalog nachtragen" },
      { "name": "Filterreinigung", "intervalHours": 200 }
    ],
    "healthScore": { "enabled": true, "_doc": "0-100, eine Zahl (WHOOP-Prinzip); speist condition + Report" }
  },
  "publish": { "topic": "metrics/maintenance", "analyticsTopic": "metrics/analytics", "retained": true, "everySec": 60 },
  "_provenance": "Datenblatt DS 30.30.01.02989 (SB-195-440-3.0): 3.0/3.6 kW, 195 m3/h, 440 mbar, 2940/3530 min-1, IP55, ISO F, bimetal. Artikel 10.04.01.00091. + Live-Daten 2026-07-04/10 (D7F0, SN A4087845): Drehzahl 2946-2952 (Nenn 2940), Lager +36.5 K ueber Umgebung (umgebungsbereinigt), 1x-Unwucht ~44 mg, Kurtosis 2.07 (kein Lagerdefekt). Temp warn/crit + anomaly-Schwellen = Engineering-Wahl (Datenblatt nennt keine CM-Schwellen). Lager-Ersatzteil-Nr. + Lagergeometrie (BPFO/BPFI) [Annahme/offen]."
}
