{{ _('OCPP Broker Monitor') }}

{{ _('Live-Überblick über den OCPP-Broker. Alle Aufrufe nutzen kurze Timeouts (%(seconds)s s) und markieren nicht erreichbare Ziele als offline.', seconds=timeout_seconds) }}

{{ _('API-Basis') }}
{{ api_base or _('Offline') }}
{% if api_error %}
{{ api_error }}
{% endif %}
{{ _('Timeout: %(seconds)s s', seconds=timeout_seconds) }} {{ _('Direktaufruf der Broker-API') }}
{% if warnings %} {% endif %}
{{ _('WebSocket & FD-Status') }}
{{ _('Aktuelle Verbindungsauslastung') }}
{% set ws_error = endpoint_results['websocket_counts']['error'] %} {% if ws_error %}{{ _('Offline') }}{% else %}{{ _('Online') }}{% endif %}
{% if ws_error %}

{{ ws_error }}

{% else %}
{{ _('Wallbox → Broker') }} {{ websocket_counts.get('wallbox_to_broker', 0) }}
{{ _('Broker → Backend') }} {{ websocket_counts.get('broker_to_backend', 0) }}
{{ _('Geschätzte FDs') }} {{ websocket_counts.get('estimated_fd_usage') if websocket_counts.get('estimated_fd_usage') is not none else '–' }}
{{ _('Freie FDs (geschätzt)') }} {{ websocket_counts.get('estimated_free') if websocket_counts.get('estimated_free') is not none else '–' }}
{% if system_limits.get('estimation_note') %}

{{ system_limits.get('estimation_note') }}

{% endif %} {% endif %}
{{ _('DB-Pool') }}
{{ _('Konfiguration vs. Live-Status') }}
{% set db_error = endpoint_results['mysql_pool_status']['error'] or endpoint_results['db_pool_metrics']['error'] %} {% if db_error %}{{ _('Offline') }}{% else %}{{ _('Online') }}{% endif %}
{% if db_error %}

{{ db_error }}

{% else %}
{{ _('Konfiguriert') }} {{ mysql_pool_status.get('configured', {}).get('minsize') or '–' }} / {{ mysql_pool_status.get('configured', {}).get('maxsize') or '–' }} ({{ _('min/max') }})
{{ _('Live') }} {{ mysql_pool_status.get('pool', {}).get('freesize') if mysql_pool_status.get('pool', {}).get('freesize') is not none else '–' }} {{ _('frei von') }} {{ mysql_pool_status.get('pool', {}).get('size') if mysql_pool_status.get('pool', {}).get('size') is not none else '–' }}
{{ _('Belegt') }} {% if mysql_pool_status.get('pool', {}).get('used') is not none %} {{ mysql_pool_status.get('pool', {}).get('used') }} {% if derived.pool_usage_ratio is not none %} ({{ (derived.pool_usage_ratio * 100) | round(1) }}%){% endif %} {% else %} – {% endif %}
{{ _('Queue') }} {{ db_metrics.get('waiting', 0) }} {{ _('wartend') }}
{{ _('Latenz') }} {{ _('Ø %(avg)s ms / P95 %(p95)s ms', avg=(db_metrics.get('latency_avg_ms', 0) | round(2) if db_metrics.get('latency_avg_ms') is not none else '–'), p95=(db_metrics.get('latency_p95_ms', 0) | round(2) if db_metrics.get('latency_p95_ms') is not none else '–')) }}
{% endif %}
{{ _('Pings & Uptime') }}
{{ _('connectionStats') }}
{% set conn_error = endpoint_results['connection_stats']['error'] %} {% if conn_error %}{{ _('Offline') }}{% else %}{{ _('Online') }}{% endif %}
{% if conn_error %}

{{ conn_error }}

{% else %}
{{ _('Pings gesendet') }} {{ connection_totals.get('pings_sent', 0) }}
{{ _('Fehlgeschlagen') }} {{ connection_totals.get('pings_failed', 0) }}
{{ _('Erfolgsquote') }} {% if connection_totals.get('success_rate') is not none %} {{ (connection_totals.get('success_rate') * 100) | round(2) }}% {% else %}–{% endif %}
{{ _('RTT avg / p95') }} {{ connection_totals.get('avg_rtt_ms') | round(2) if connection_totals.get('avg_rtt_ms') is not none else '–' }} ms / {{ connection_totals.get('p95_rtt_ms') | round(2) if connection_totals.get('p95_rtt_ms') is not none else '–' }} ms
{{ _('Uptime') }} {% if connection_totals.get('uptime_ratio') is not none %} {{ (connection_totals.get('uptime_ratio') * 100) | round(2) }}% {% else %}–{% endif %}
{% endif %}
{{ _('Reconnects & Handshakes') }}
{{ _('Fenster: %(seconds)s s', seconds=reconnect_stats.get('window_seconds', '–')) }}
{% set rec_error = endpoint_results['reconnect_stats']['error'] %} {% if rec_error %}{{ _('Offline') }}{% else %}{{ _('Online') }}{% endif %}
{% if rec_error %}

{{ rec_error }}

{% else %}
{{ _('Reconnects (Fenster): %(count)s', count=reconnect_totals.get('reconnects', 0)) }} {{ _('Rate/Tag: %(rate)s (Warnung ≥ %(threshold)s)', rate=(reconnect_totals.get('reconnect_rate_per_day') | round(2) if reconnect_totals.get('reconnect_rate_per_day') is not none else '–'), threshold=reconnect_thresholds.get('reconnect_rate_per_day') or '–') }} {{ _('Handshake OK: %(count)s', count=reconnect_totals.get('handshake_success', 0)) }} {{ _('Handshake NOK: %(count)s (Warnung ≥ %(threshold)s)', count=reconnect_totals.get('handshake_failure', 0), threshold=reconnect_thresholds.get('handshake_failures') or '–') }}
{{ _('Handshake-Fehler nach Grund (letzte %(seconds)s s)', seconds=recent_handshakes.get('window_seconds', '–')) }}
{% set by_reason = recent_handshakes.get('by_reason', {}) %} {% if by_reason %} {% for reason, count in by_reason.items() %} {% endfor %} {% else %} {% endif %}
{{ _('Grund') }} {{ _('Anzahl') }}
{{ reason }} {{ count }}
{{ _('Keine Fehler im Fenster.') }}
{% endif %}
{{ _('Systemlimits') }}
{{ _('ulimit & FD Snapshot') }}
{% set sys_error = endpoint_results['system_limits']['error'] %} {% if sys_error %}{{ _('Offline') }}{% else %}{{ _('Online') }}{% endif %}
{% if sys_error %}

{{ sys_error }}

{% else %}
{{ _('ulimit (soft/hard)') }} {{ system_limits.get('ulimit_no_file_soft', '–') }} / {{ system_limits.get('ulimit_no_file_hard', '–') }}
{{ _('FD Nutzung') }} {{ system_limits.get('estimated_fd_usage', '–') }}
{{ _('FD frei (geschätzt)') }} {{ system_limits.get('estimated_free', '–') }}
{{ _('Wallbox / Backend') }} {{ system_limits.get('wallbox_to_broker', '–') }} / {{ system_limits.get('broker_to_backend', '–') }}
{% endif %}
{{ _('API-Endpunkte') }}
{{ _('Alle Abfragen werden unabhängig geprüft; Fehler bleiben isoliert.') }}
{% set endpoint_labels = { 'broker_status': _('Broker Status'), 'db_pool_metrics': _('DB-Pool Metrics'), 'connection_stats': _('Connection Stats'), 'reconnect_stats': _('Reconnect Stats'), 'websocket_counts': _('WebSocket Counts'), 'mysql_pool_status': _('MySQL Pool Status'), 'system_limits': _('System Limits') } %} {% for key, label in endpoint_labels.items() %} {% set result = endpoint_results.get(key, {}) %} {% endfor %}
{{ _('Endpoint') }} {{ _('Status') }} {{ _('Details') }}
{{ label }} {% if result.error %} {{ _('Offline') }} {% else %} {{ _('OK') }} {% endif %} {% if result.error %} {{ result.error }} {% else %} {{ result.url }} {% endif %}