NEWS
Mitsubishi Heavy Industries Split Klimaanlage
-
Ich habe eine telegraf config für influxdb erstellt und visualisiere dann mit Grafana.
Es scheint aber auch einen ping Adapter zu geben, das zusammen mit dem History Feature von iobroker sollte ein ähnliches Ergebnis liefern.
-
@saeft_2003 Es wird im angegebenen Interval abgefragt. Bei einer erfolgreichen Abfrage wird der Datenpunkt "online" auf true gesetzt. Bei jedem Intervall werden am Ende alle online Datenpunkte evaluiert und sofern alle true sind, wird der Gesamstatus auch aktualisiert. So sollte sich der Zustand auch ohne Neustart wieder fangen. Du könntest das nächste mal schauen, ob alle online Datenpunkte der aktiven Geräte true sind und der Adapterzustand dennoch gelb.
-
@hacki11 sagte in Mitsubishi Heavy Industries Split Klimaanlage:
Ich habe eine telegraf config für influxdb erstellt und visualisiere dann mit Grafana.
Es scheint aber auch einen ping Adapter zu geben, das zusammen mit dem History Feature von iobroker sollte ein ähnliches Ergebnis liefern.
Den ping andapter hab ich laufen, aber woher kommt die Zeit wie lang der ping gebraucht hat? Beim Adapter bekomme ich doch nur true oder false? -
@hacki11 sagte in Mitsubishi Heavy Industries Split Klimaanlage:
@saeft_2003 Es wird im angegebenen Interval abgefragt. Bei einer erfolgreichen Abfrage wird der Datenpunkt "online" auf true gesetzt. Bei jedem Intervall werden am Ende alle online Datenpunkte evaluiert und sofern alle true sind, wird der Gesamstatus auch aktualisiert. So sollte sich der Zustand auch ohne Neustart wieder fangen. Du könntest das nächste mal schauen, ob alle online Datenpunkte der aktiven Geräte true sind und der Adapterzustand dennoch gelb.
Alles klar falls das wieder vorkommt mache ich das.
-
Denke ich habs. Intervall ping alle 60 sek?
-
@saeft_2003 Jede Sekunde
-
Das lässt der ping adapter nicht zu. kürzester intervall sind alle 5 sek.
-
@saeft_2003 passt auch noch
-
Alles klar ich lass das mal bis morgen so laufen und schau ob ich in grafana was sehe und melde mich.
-
-
Das sieht mir nach einer schlechten WLAN-Verbindung aus.
-
@saeft_2003 Nimm mal den alive mit in die history auf. Aber man sieht schon schön ne Lücke in dem Graphen. Vermutlich gab’s keine Werte und es wird linear mit dem ersten Ping der wiederkommt verbunden? Zumindest würde das den Graphen erklären.
-
Ich hab die Klima jetzt wieder auf den AP gelockt der theoretisch am besten ist. Normalerweise muss die Verbindung hier top sein. Luftlinie ist der nur 2m weg und nur dünne Wände dazwischen. Andere Geräte zum Teil weiter weg haben null Probleme.
-
@saeft_2003 Mein IG nimmt auch immer den weiter entfernten AP statt dem der 4m entfernt steht. Roaming ist in dem WLAN deaktiviert, da viele IOT Geräte damit nicht klar kommen. Das IG vermutlich gleich dreimal nicht.
-
@hacki11 Ich habe das WLAN so konfiguriert, dass die Geräte in einem separaten WLAN in 2.4Ghz am jeweils nächstliegenden AP eingesperrt sind. Habe kurz ein Shellscript für Linux mit Chat GPT entwickelt, was ne csv mitloggt (im Subfolder "Log" im Scriptordner. Inhalt der CSV:
Name;Zeitstempel;Erreichbar;Zeit(ms) Klima-Spitzboden;2025-05-15 13:39:18;True;30.4 Klima-K1;2025-05-15 13:39:18;True;85.3 Klima-K2;2025-05-15 13:39:18;True;95.8
Ist auch ein Billigfrontend drauf:
Hier das Script (IPs und Aliase anpassen!):
#!/bin/bash # Intervall in Sekunden INTERVAL=5 # IP-Adressen und Aliasnamen IPS=("192.168.120.135" "192.168.120.138" "192.168.120.137" "192.168.120.136" "192.168.120.166") ALIASES=("Klima-Spitzboden" "Klima-K1" "Klima-K2" "Klima-Esszimmer" "Klima-Buero") # Logging-Verzeichnis und -Datei SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" LOG_DIR="$SCRIPT_DIR/log" CSV_FILE="$LOG_DIR/ping_log.csv" mkdir -p "$LOG_DIR" # CSV-Datei initialisieren, falls noch nicht vorhanden if [ ! -f "$CSV_FILE" ]; then echo "Name;Zeitstempel;Erreichbar;Zeit(ms)" >> "$CSV_FILE" fi # Statusspeicher declare -A LAST_RESPONSE declare -A LAST_SEEN_DOWN # Spaltenbreiten WIDTH_ALIAS=20 WIDTH_REACH=12 WIDTH_TIME=10 WIDTH_LASTDOWN=25 # Initialisieren for alias in "${ALIASES[@]}"; do LAST_RESPONSE["$alias"]="-" LAST_SEEN_DOWN["$alias"]="-" done # Letzte bekannte False-Zeiten aus CSV rekonstruieren if [ -f "$CSV_FILE" ]; then for alias in "${ALIASES[@]}"; do last_false=$(grep "^$alias;" "$CSV_FILE" | grep ";False;" | tail -n 1 | cut -d';' -f2) if [ -n "$last_false" ]; then epoch=$(date -d "$last_false" +%s 2>/dev/null) if [ -n "$epoch" ]; then LAST_SEEN_DOWN["$alias"]=$epoch fi fi done fi # Funktion für menschenlesbare Zeitangabe time_diff_human() { local last_time=$1 [[ "$last_time" == "-" ]] && echo "-" && return local now=$(date +%s) local diff=$((now - last_time)) (( diff < 60 )) && echo "vor $diff Sek." && return (( diff < 3600 )) && echo "vor $((diff / 60)) Min." && return echo "vor $((diff / 3600)) Std." } # Hauptschleife while true; do clear printf "%-${WIDTH_ALIAS}s | %-${WIDTH_REACH}s | %-${WIDTH_TIME}s | %-${WIDTH_LASTDOWN}s\n" "Alias" "Erreichbar" "Zeit(ms)" "Nicht erreichbar vor" printf "%-${WIDTH_ALIAS}s-+-%-${WIDTH_REACH}s-+-%-${WIDTH_TIME}s-+-%-${WIDTH_LASTDOWN}s\n" \ "$(printf '─%.0s' $(seq 1 $WIDTH_ALIAS))" \ "$(printf '─%.0s' $(seq 1 $WIDTH_REACH))" \ "$(printf '─%.0s' $(seq 1 $WIDTH_TIME))" \ "$(printf '─%.0s' $(seq 1 $WIDTH_LASTDOWN))" for i in "${!IPS[@]}"; do IP=${IPS[$i]} NAME=${ALIASES[$i]} TIMESTAMP_HUMAN=$(date '+%Y-%m-%d %H:%M:%S') TIMESTAMP_EPOCH=$(date +%s) PING_OUTPUT=$(ping -c 1 -W 1 "$IP" 2>/dev/null) if echo "$PING_OUTPUT" | grep -q "1 received"; then TIME_MS=$(echo "$PING_OUTPUT" | grep "time=" | sed -E 's/.*time=([0-9.]+) ms/\1/') LAST_RESPONSE["$NAME"]=$TIME_MS REACH="Ja" DOWNTIME=$(time_diff_human "${LAST_SEEN_DOWN[$NAME]}") echo "$NAME;$TIMESTAMP_HUMAN;True;$TIME_MS" >> "$CSV_FILE" else REACH="Nein" TIME_MS="-" if [[ "${LAST_SEEN_DOWN[$NAME]}" == "-" ]]; then LAST_SEEN_DOWN["$NAME"]=$TIMESTAMP_EPOCH fi DOWNTIME=$(time_diff_human "${LAST_SEEN_DOWN[$NAME]}") echo "$NAME;$TIMESTAMP_HUMAN;False;" >> "$CSV_FILE" fi printf "%-${WIDTH_ALIAS}s | %-${WIDTH_REACH}s | %-${WIDTH_TIME}s | %-${WIDTH_LASTDOWN}s\n" \ "$NAME" "$REACH" "${LAST_RESPONSE[$NAME]}" "$DOWNTIME" done sleep "$INTERVAL" done
Falls Ihr irgendwo Linux habt, könnt Ihr das da laufen lassen.
Und hier das Script, um die CSV als Bild darzustellen:
#!/usr/bin/env python3 import pandas as pd import matplotlib.pyplot as plt from datetime import timedelta import matplotlib.dates as mdates import os # 🕒 Benutzerabfrage zum Stundenbereich try: user_input = input("Wie viele Stunden zurück anzeigen? [Default: 24]: ").strip() MAX_HOURS = int(user_input) if user_input else 24 except Exception: MAX_HOURS = 24 # 📥 CSV einlesen CSV_PATH = "./log/ping_log.csv" df = pd.read_csv(CSV_PATH, sep=';') df['Zeitstempel'] = pd.to_datetime(df['Zeitstempel'], format="%Y-%m-%d %H:%M:%S") df['Farbe'] = df['Erreichbar'].apply(lambda x: 'green' if str(x).strip().lower() == 'true' else 'red') df['Erreichbar_bool'] = df['Erreichbar'].apply(lambda x: str(x).strip().lower() == 'true') # 🧭 Zeitbereich setzen latest_time = df['Zeitstempel'].max() earliest_time = df['Zeitstempel'].min() start_time = max(earliest_time, latest_time - timedelta(hours=MAX_HOURS)) df = df[df['Zeitstempel'] >= start_time].copy() # 📋 Aliasnamen extrahieren aliases = df['Name'].unique() aliases_sorted = list(aliases) # 📁 Diagrammverzeichnis erstellen output_dir = "./diagramm_pix" os.makedirs(output_dir, exist_ok=True) # 📊 Plot vorbereiten fig, ax = plt.subplots(figsize=(14, len(aliases_sorted) * 1.2)) def plot_status_blocks(data, y_pos): current_color = None block_start = None for _, row in data.iterrows(): color = row['Farbe'] timestamp = row['Zeitstempel'] if color != current_color: if current_color is not None: duration = (timestamp - block_start).total_seconds() ax.barh( y=y_pos, width=duration / 3600, left=block_start, height=0.6, color=current_color, edgecolor='none' ) block_start = timestamp current_color = color if block_start is not None and current_color is not None: duration = (latest_time - block_start).total_seconds() ax.barh( y=y_pos, width=duration / 3600, left=block_start, height=0.6, color=current_color, edgecolor='none' ) for i, alias in enumerate(aliases_sorted): data = df[df['Name'] == alias].sort_values(by='Zeitstempel') plot_status_blocks(data, i) # 📐 Achsen und Format ax.set_yticks(range(len(aliases_sorted))) ax.set_yticklabels(aliases_sorted) ax.set_xlim(start_time, latest_time) ax.invert_yaxis() ax.xaxis.set_major_formatter(mdates.DateFormatter('%H:%M')) ax.set_xlabel("Uhrzeit") ax.set_title("Erreichbarkeit der IPs – zusammenhängende Zustandsbereiche") plt.grid(axis='x', linestyle='--', alpha=0.5) plt.tight_layout() # 💾 Bild speichern image_filename = f"{output_dir}/ping_status_{latest_time.strftime('%Y%m%d_%H%M%S')}.png" plt.savefig(image_filename) plt.show() # 📋 Zusammenfassung pro Alias print("\nZusammenfassung:") total_minutes = MAX_HOURS * 60 for alias in aliases_sorted: alias_data = df[df['Name'] == alias].sort_values(by='Zeitstempel') alias_data['diff'] = alias_data['Zeitstempel'].diff().dt.total_seconds().fillna(0) # Statuswechsel ermitteln alias_data['is_new_block'] = (alias_data['Erreichbar_bool'] != alias_data['Erreichbar_bool'].shift()) alias_data['block_id'] = alias_data['is_new_block'].cumsum() # Offline-Blöcke false_blocks = alias_data[alias_data['Erreichbar_bool'] == False] grouped = false_blocks.groupby('block_id') total_offline_secs = grouped['diff'].sum().sum() total_offline_minutes = round(total_offline_secs / 60, 2) total_outages = grouped.ngroups outages_per_hour = round(total_outages / MAX_HOURS, 2) avg_offline_per_hour = round(total_offline_minutes / MAX_HOURS, 2) # Antwortzeiten nur bei True true_responses = alias_data[alias_data['Erreichbar_bool'] == True].copy() true_responses['Zeit(ms)'] = pd.to_numeric(true_responses['Zeit(ms)'], errors='coerce') min_time = round(true_responses['Zeit(ms)'].min(), 2) avg_time = round(true_responses['Zeit(ms)'].mean(), 2) max_time = round(true_responses['Zeit(ms)'].max(), 2) print(f"{alias}:") print(f" Gesamtofflinezeit: {total_offline_minutes:.2f} Min") print(f" Ø Offlinezeit/Stunde: {avg_offline_per_hour:.2f} Min") print(f" Gesamtzahl Ausfälle: {total_outages}") print(f" Ø Ausfälle/Stunde: {outages_per_hour}") print(f" Antwortzeit (Min/Ø/Max): {min_time:.2f} / {avg_time:.2f} / {max_time:.2f} ms\n")
-
@mrlarodos Habe mir noch ein Script gebaut, das die CSV als Diagramm visualisiert:
Und hier die Zusammenfassung der bisherigen Messung:
Klima-Spitzboden:
Gesamtofflinezeit: 3.50 Min
Ø Offlinezeit/Stunde: 0.15 Min
Gesamtzahl Ausfälle: 19
Ø Ausfälle/Stunde: 0.79
Antwortzeit (Min/Ø/Max): 4.30 / 82.30 / 878.00 msKlima-K1:
Gesamtofflinezeit: 6.25 Min
Ø Offlinezeit/Stunde: 0.26 Min
Gesamtzahl Ausfälle: 21
Ø Ausfälle/Stunde: 0.88
Antwortzeit (Min/Ø/Max): 4.09 / 77.67 / 452.00 msKlima-K2:
Gesamtofflinezeit: 6.42 Min
Ø Offlinezeit/Stunde: 0.27 Min
Gesamtzahl Ausfälle: 28
Ø Ausfälle/Stunde: 1.17
Antwortzeit (Min/Ø/Max): 3.88 / 85.14 / 680.00 msKlima-Esszimmer:
Gesamtofflinezeit: 3.35 Min
Ø Offlinezeit/Stunde: 0.14 Min
Gesamtzahl Ausfälle: 8
Ø Ausfälle/Stunde: 0.33
Antwortzeit (Min/Ø/Max): 3.74 / 78.01 / 979.00 msKlima-Buero:
Gesamtofflinezeit: 0.18 Min
Ø Offlinezeit/Stunde: 0.01 Min
Gesamtzahl Ausfälle: 2
Ø Ausfälle/Stunde: 0.08
Antwortzeit (Min/Ø/Max): 4.20 / 73.71 / 993.00 msHm. Hilft uns das sehr?
-
@mrlarodos Zur Sicherheit mal den Adapter stoppen und prüfen ob die Offlinezeit dadurch beeinflusst wird. Falls nicht ist zumindest der Adapter raus 🫠
-
@hacki11 Gute Idee
Ich hoffe, dann ist alles grün
<sleep canceled> ist dann angesagt
-
@mrlarodos So, der Adapter ist aus. Nun wird es spannend
-