Storage Energy not shown in UI (Local & Backend)

Hallo zusammen,

ich habe ein eigenes Modul für eine alte Samsung Batterie geschrieben.

Nun ist mir nach längerer Laufzeit aufgefallen, dass in der Historie keine Werte der Batterie angezeigt werden…

image

Below is the Code:

package io.openems.edge.ess.samsung.ess;


import org.osgi.service.component.ComponentContext;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.ConfigurationPolicy;
import org.osgi.service.component.annotations.Deactivate;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality;
import org.osgi.service.component.annotations.ReferencePolicy;
import org.osgi.service.component.annotations.ReferencePolicyOption;
import org.osgi.service.event.Event;
import org.osgi.service.event.EventHandler;
import org.osgi.service.event.propertytypes.EventTopics;
import org.osgi.service.metatype.annotations.Designate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.gson.JsonObject;

import io.openems.common.exceptions.OpenemsError.OpenemsNamedException;
import io.openems.edge.common.component.AbstractOpenemsComponent;
import io.openems.edge.common.component.OpenemsComponent;
import io.openems.edge.common.event.EdgeEventConstants;
import io.openems.edge.common.sum.GridMode;
import io.openems.edge.io.ess.samsung.common.SamsungApi;
import io.openems.edge.timedata.api.Timedata;
import io.openems.edge.timedata.api.TimedataProvider;
import io.openems.edge.timedata.api.utils.CalculateEnergyFromPower;
import io.openems.edge.ess.api.SymmetricEss;
import io.openems.edge.ess.dccharger.api.EssDcCharger;
import io.openems.edge.ess.api.HybridEss;


@Designate(ocd = Config.class, factory = true)
@Component(//
		name = "Ess.Samsung", immediate = true, //
		configurationPolicy = ConfigurationPolicy.REQUIRE//
)

@EventTopics({ //
	EdgeEventConstants.TOPIC_CYCLE_BEFORE_PROCESS_IMAGE, //
	EdgeEventConstants.TOPIC_CYCLE_AFTER_PROCESS_IMAGE //
})
public class SamsungEssImpl extends AbstractOpenemsComponent
		implements SamsungEss, SymmetricEss, OpenemsComponent, EventHandler, TimedataProvider, HybridEss{
			
	private final CalculateEnergyFromPower calculateAcChargeEnergy = new CalculateEnergyFromPower(this,
			SymmetricEss.ChannelId.ACTIVE_CHARGE_ENERGY);
	private final CalculateEnergyFromPower calculateAcDischargeEnergy = new CalculateEnergyFromPower(this,
			SymmetricEss.ChannelId.ACTIVE_DISCHARGE_ENERGY);
	

	@Reference(policy = ReferencePolicy.DYNAMIC, policyOption = ReferencePolicyOption.GREEDY, cardinality = ReferenceCardinality.OPTIONAL)
	private volatile Timedata timedata = null;
	
	
	private final Logger log = LoggerFactory.getLogger(SamsungEssImpl.class);
	private SamsungApi samsungApi = null;


	public SamsungEssImpl() {
		super(//
				OpenemsComponent.ChannelId.values(), //
				SymmetricEss.ChannelId.values(), //
				SamsungEss.ChannelId.values(),
				EssDcCharger.ChannelId.values(),
				HybridEss.ChannelId.values()
				//
		);
	}

	
	@Activate
	private void activate(ComponentContext context, Config config) {
	    super.activate(context, config.id(), config.alias(), config.enabled());
	    this.samsungApi = new SamsungApi(config.ip());
	    this._setCapacity(config.capacity());
		this._setGridMode(GridMode.ON_GRID);

	}

	@Override
	@Deactivate
	protected void deactivate() {
		super.deactivate();
	}

	@Override
	public void handleEvent(Event event) {
	    if (!this.isEnabled()) {
	        return;
	    }

	    switch (event.getTopic()) {
		case EdgeEventConstants.TOPIC_CYCLE_AFTER_PROCESS_IMAGE:
			this.calculateEnergy();
			break;
	    case EdgeEventConstants.TOPIC_CYCLE_BEFORE_PROCESS_IMAGE:
	        this.fetchAndUpdateEssRealtimeStatus();
	        break;
	    }
	}

	private void fetchAndUpdateEssRealtimeStatus() {
	    try {
	        // Fetch the necessary data from the API
	        JsonObject necessaryData = samsungApi.getEssRealtimeStatus();

	        // Populate the appropriate channels with the fetched data
	        double PvPw = necessaryData.get("PvPw").getAsDouble()*1000;
	        double PcsPw = necessaryData.get("PcsPw").getAsDouble();
	        int btSoc = necessaryData.get("BtSoc").getAsInt();
	        int BtStusCd = necessaryData.get("BtStusCd").getAsInt();


	        // Update the channels
	        this.channel(SymmetricEss.ChannelId.SOC).setNextValue(btSoc);
	        
	        switch (BtStusCd) {
	            case 0:
	                // Battery is in Discharge mode
	                if (PcsPw > 0) {
	                	this._setDcDischargePower((int) PcsPw);
	                    this.calculateAcChargeEnergy.update(0);
	                    this.calculateAcDischargeEnergy.update((int) PcsPw);

	                } else {
	                	this._setDcDischargePower((int) -PcsPw);
	                    this.calculateAcChargeEnergy.update((int) -PcsPw);
	                    this.calculateAcDischargeEnergy.update(0);

	                }
	                break;
	            case 1:
	                // Battery is in Charge mode
	                if (PcsPw > 0) {
	        	        this._setDcDischargePower((int) -PcsPw);
	                    this.calculateAcChargeEnergy.update((int) PcsPw);
	                    this.calculateAcDischargeEnergy.update(0);

	                } else {
	        	        this._setDcDischargePower((int) -PcsPw);
	                    this.calculateAcChargeEnergy.update(0);
	                    this.calculateAcDischargeEnergy.update((int) -PcsPw);

	                }
	                break;
	            case 2:
	                // Battery is in Idle mode
        	        this._setDcDischargePower(0);
	                this.calculateAcChargeEnergy.update(0);
	                this.calculateAcDischargeEnergy.update(0);
	                break;
	            default:
	                // Handle unknown status codes
	                this.logWarn(log, "Unknown Battery Status Code: " + BtStusCd);
	                break;
	        }
	       // this._setDcDischargePower(dcDischargePower);
	        this._setActivePower((int) (PcsPw - PvPw));
	        this._setSlaveCommunicationFailed(false);

	    } catch (OpenemsNamedException e) {
	        this._setSlaveCommunicationFailed(true);
	        this._setActivePower(0);
	        this.log.warn("Failed to fetch ESS Real-time Status", e);
	    }
	}

	
	
	@Override
	public String debugLog() {
		return "SoC:" + this.getSoc().asString() //
				+ "|L:" + this.getActivePower().asString() //
				+ "|" + this.getGridModeChannel().value().asOptionString(); //
	}
	

	@Override
	public Timedata getTimedata() {
		return this.timedata;
	}


	@Override
	public Integer getSurplusPower() {
	    try {
	        // Fetch the necessary data from the API
	        JsonObject necessaryData = samsungApi.getEssRealtimeStatus();
	        
	        // Extract relevant power values and status codes from the JSON object
	        double gridPw = necessaryData.get("GridPw").getAsDouble();
	        double pvPw = necessaryData.get("PvPw").getAsDouble();
	        double pcsPw = necessaryData.get("PcsPw").getAsDouble();
	        double consPw = necessaryData.get("ConsPw").getAsDouble();
	        int gridStatus = necessaryData.get("GridStusCd").getAsInt();
	        int batteryStatus = necessaryData.get("BtStusCd").getAsInt();
	        
	        // Adjust the sign of gridPw and pcsPw based on the status codes
	        if (gridStatus == 1) {
	            gridPw = -gridPw;
	        }
	        if (batteryStatus == 0) {
	            pcsPw = -pcsPw;
	        }
	        
	        // Calculate surplus power
	        double surplusPower = (gridPw + pvPw) - (pcsPw + consPw);
	        // Return the surplus power or 'null' if there is no surplus power
	        return surplusPower > 0 ? (int) surplusPower : null;
	    } catch (OpenemsNamedException e) {
	        log.warn("Failed to fetch ESS Real-time Status for Surplus Power Calculation", e);
	        return null;
	    }
	}
	
	
	private void calculateEnergy() {
		/*
		 * Calculate AC Energy
		 */
		var acActivePower = this.getActivePowerChannel().getNextValue().get();
		if (acActivePower == null) {
			// Not available
			this.calculateAcChargeEnergy.update(null);
			this.calculateAcDischargeEnergy.update(null);
		} else if (acActivePower > 0) {
			// Discharge
			this.calculateAcChargeEnergy.update(0);
			this.calculateAcDischargeEnergy.update(acActivePower);
		} else {
			// Charge
			this.calculateAcChargeEnergy.update(acActivePower * -1);
			this.calculateAcDischargeEnergy.update(0);
		}
	}

	


}

Hmm, die Verwendung von CalculateEnergyFromPower scheint korrekt zu sein. Du rufst allerdings die update()-Methode an zwei Stellen auf, einmal in handleEvent() und einmal in fetchAndUpdateEssRealtimeStatus(). Das ist aber wahrscheinlich nicht so schlimm (obwohl du es dir trotzdem sparen könntest).
Meine erste Vermutung wäre, dass du keine Timedata (also z.B. Timedata RRD4J) auf der Edge aktiviert hast. Hast du das geprüft?

Beste Grüße,
Thomas

Ja, die ist aktiv :slight_smile:

@stefan.feilmeier hast du noch eine Idee?

Mir ist auch aufgefallen, dass die Werte vom GoodWe DC Charger fehlen

Hast du denn Werte in den Channels ACTIVE_CHARGE_ENERGY und ACTIVE_DISCHARGE_ENERGY? (z. B. via Detailed-Debuglog)

1 Like

Hallo Stefan,

ja die habe ich, siehe Screenshot.

@stefan.feilmeier An was könnte es denn noch liegen?

Es fehlen ein paar Hintergrundinfos: Welche Datenbank verwendest du? Läuft die Datenbank Verbindung via Edge oder via Backend? Welches Datenbank Bundle wird genutzt?

Möglicherweise sind die Daten nicht in der Datenbank angekommen. Schon mal geprüft ob dort Werte hinterlegt sind?
Name des Feldes: <component ID>/ActiveChargeEnergy

Könnte mit der PersistencePriority deiner Backend Verbindung zu tun haben. Hast du evtl. eine AggregatedInfluxDB verwendet?

Guten Morgen,

ja, ich nutze eine Aggregated :slight_smile:

Anbei 2 Screenshots:

Timedata RRD4J:

Backend:

timedata0:

Der avg Wert in der aggregated0 ist allerdings komplett leer. Und genau da vermute ich mein Problem…

Also greifst du über die UI des Backends zu. Hast du im “Core-Timedata Manager” die Komponenten ID der “Timedata AggregatedInfluxDB” hinterlegt? Verwenden “Timedata Influx DB” und “Timedata AggregatedInfluxDB” zwei unterschiedliche Komponenten IDs. Das Backend meckert nicht, falls zwei identische Komponenten IDs verwendet werden. Dies könnte auch noch ein möglicher Grund für die fehlenden Daten sein.


Die “Timedata AggregatedInfluxDB” wird erst ab einer 4 stelligen Zahl an Edges relevant, davor ist die Standard Implementierung “Timedata Influx DB” vollkommen ausreichend.
Abhängig von der Anzahl Edges, welche an deinem Backend hängen, würde ich dir daher empfehlen, die “Timedata AggregatedInfluxDB” vollständig zu entfernen und nur die “Timedata Influx DB” zu nutzen. Dann bitte auch im “Core Timedata Manager” prüfen, dass dort nur die Komponenten ID der “Timedata Influx DB” verwendet wird. Das macht die Fehlersuche ein gutes Stück einfacher, denn die Abläufe bei Verwendung beider Datenbanken im Zusammenspiel zwischen Edge/Backend/UI sind nicht offensichtlich.

ja, wurde hinterlegt wie in der GettingStarted angeschrieben :slight_smile:

korrekt. timedata0 und timedata1

Ich würde die Konfiguration ungern ändern :frowning:

@stefan.feilmeier und @c.lehne habt ihr noch eine Idee um das zu debuggen?

Moin @Sn0w3y,

Hab es nicht mehr ganz vor Augen… ich hatte für InfluxDB vor ein paar Wochen erst die fehlende Methode implementiert damit CalculateEnergyFromPower überhaupt mit Influx funktioniert, bzw. einen System-Neustart überlebt. Für AggregatedInfluxDBhatte ich das nicht gemacht - ich setze kein Backend ein.

Wie @c.lehne schon schrieb: Hast Du Werte in der DB für die Energie-Channels?

Gruß,
klinki

Moin klinki,

genau da liegt wahrscheinlich auch “der Hund begraben”

wenn ich aktuell Timedata und oder den Backend Controller im Edge restarte, hängt sich das Edge komplett auf und ich muss openems restarten - demetsprechend ist das ein Bug, den wir eventuell im Repo auch fixen sollten :slight_smile:

Kann es daran liegen?

Ich hab gestern kurz mal mit Chronograf drauf geschaut (GUI für InfluxDB), hast du eventuell einen CLI SQL Query für mich, um zu überprüfen wo der Wert sein müsste?

Herzlichen Dank !!!

Ich hatte das Thema zusammen mit @michaelgrill bearbeitet. Dabei haben wir versucht die Änderungen möglichst allgemein zu formulieren.

Hier ein Link auf den PullRequest. Der ist ja inzwischen merged
Gaaanz komplizierte Sache :wink:: es sucht den letzten Wert des Energiechannels innerhalb der letzten 100 Tage und nimmt die Duration seit diesem Zeitpunkt.
Du musst nur die Variablen ersetzen.

Ich nutze nur das Standard-GUI auf Port 8086 von InfluxDB. Ein vernünftiges Tool habe ich leider immer noch nicht gefunden(wäre für jeden Tipp dankbar)

@Sn0w3y ich glaube du meinst folgende Fehlermeldung

java.lang.IllegalArgumentException: null
	at org.apache.felix.framework.BundleContextImpl$ServiceObjectsImpl.ungetService(BundleContextImpl.java:564) ~[?:?]
....

die ist mir vor kurzem auch aufgefallen bei der BridgeHttp gab es den selben Fehler.

Kurz zur Erklärung was diesen Fehler verursacht ist die Kombination von ServiceScope.PROTOTYPE und ReferenceScope.PROTOTYPE_REQUIRED ein Beispiel hierfür wäre folgendes:

@Designate(ocd = TestParent.Config.class, factory = true)
@Component(configurationPolicy = ConfigurationPolicy.REQUIRE)
public class TestParent {

	@ObjectClassDefinition(name = "Test parent")
	public static @interface Config {

	}

	@Component(scope = ServiceScope.PROTOTYPE, service = TestChild.class)
	public static class TestChild {

	}

	@Reference(scope = ReferenceScope.PROTOTYPE_REQUIRED)
	private TestChild child;

}

immer wenn die TestParent Klasse deaktiviert wird kommt der Fehler. Ich selbst würde behaupten, das das ein Fehler vom Apache Felix ist und eigentlich nicht das gewünschte verhalten hat.

Das kann man aber einfach mit einer Factory Klasse “umgehen” und man hat wieder das gewünschte verhalten, mit ein paar mehr Code-Zeilen.

Aber grundsätzlich wenn du das Edge neustartets sollte das keinen Einfluss auf das Senden der Daten haben. Außerdem brauchst du eigentlich zum senden der Daten ansich keine lokale Datenbank nur zum Daten nachsenden.

Wichtig wäre theoretisch noch die Einstellung am BackendController und dort der wert für die aggregationPriority dieser sollte aber passen wenn du ihn auf default gelassen hast.
Wie auch die anderen bereits meinte wäre es hilfreich ob überhaupt Daten am Backend ankommen und in der DB gespeichert werden mit z. B.

select count(*) from rp_max.max
select count(*) from rp_avg.avg

bzw. ob die retention policies richtig angelegt wurden

show retention policies
select count(*) from rp_max.max:
> select count(*) from rp_max.max
name: max
time count__sum/ConsumptionActiveEnergy count__sum/EssActiveChargeEnergy count__sum/EssActiveDischargeEnergy count__sum/EssDcChargeEnergy count__sum/EssDcDischargeEnergy count__sum/GridBuyActiveEnergy count__sum/GridSellActiveEnergy count__sum/ProductionAcActiveEnergy count__sum/ProductionActiveEnergy count__sum/ProductionDcActiveEnergy count_charger0/ActiveProductionEnergy count_charger0/ActualEnergy count_charger1/ActualEnergy count_ctrlChannelThreshold0/CumulatedActiveTime count_ctrlEssTimeOfUseTariff0/ChargedTime count_ctrlEssTimeOfUseTariff0/DelayedTime count_ctrlFixActivePower0/CumulatedActiveTime count_ctrlGridOptimizedCharge0/AvoidLowChargingTime count_ctrlGridOptimizedCharge0/DelayChargeTime count_ctrlGridOptimizedCharge0/NoLimitationTime count_ctrlGridOptimizedCharge0/SellToGridLimitTime count_ctrlIoHeatPump0/ForceOnStateTime count_ctrlIoHeatPump0/LockStateTime count_ctrlIoHeatPump0/RecommendationStateTime count_ctrlIoHeatPump0/RegularStateTime count_ctrlIoHeatingElement0/Level1CumulatedTime count_ctrlIoHeatingElement0/Level2CumulatedTime count_ctrlIoHeatingElement0/Level3CumulatedTime count_io0/ActiveProductionEnergy count_io1/ActiveProductionEnergy count_io2/ActiveProductionEnergy count_io3/ActiveProductionEnergy count_meter0/ActiveConsumptionEnergy count_meter0/ActiveProductionEnergy count_meter1/ActiveConsumptionEnergy count_meter1/ActiveProductionEnergy count_meter2/ActiveConsumptionEnergy count_meter2/ActiveProductionEnergy count_meter3/ActiveConsumptionEnergy count_meter3/ActiveProductionEnergy count_pvInverter0/ActiveProductionEnergy
---- ---------------------------------- -------------------------------- ----------------------------------- ---------------------------- ------------------------------- ------------------------------ ------------------------------- ----------------------------------- --------------------------------- ----------------------------------- ------------------------------------- --------------------------- --------------------------- ----------------------------------------------- ----------------------------------------- ----------------------------------------- --------------------------------------------- --------------------------------------------------- ---------------------------------------------- ----------------------------------------------- -------------------------------------------------- -------------------------------------- ----------------------------------- --------------------------------------------- -------------------------------------- ----------------------------------------------- ----------------------------------------------- ----------------------------------------------- -------------------------------- -------------------------------- -------------------------------- -------------------------------- ------------------------------------ ----------------------------------- ------------------------------------ ----------------------------------- ------------------------------------ ----------------------------------- ------------------------------------ ----------------------------------- ----------------------------------------
0    177                                127                              127                                 127                          127                             168                            168                             144                                 168                               127                                                                       27                          27                          8                                               5                                         5                                         19                                            1                                                   1                                              1                                               1                                                  12                                     12                                  12                                            12                                     40                                              40                                              40                                              4                                15                               15                               5                                88                                   88                                  42                                   42                                  63                                   63                                  21                                   21
> ^C
select count(*) from rp_avg.avg:
> select count(*) from rp_avg.avg
name: avg
time count__sum/ConsumptionActivePower count__sum/ConsumptionActivePowerL1 count__sum/ConsumptionActivePowerL2 count__sum/ConsumptionActivePowerL3 count__sum/EssActivePower count__sum/EssActivePowerL1 count__sum/EssActivePowerL2 count__sum/EssActivePowerL3 count__sum/EssDischargePower count__sum/EssSoc count__sum/GridActivePower count__sum/GridActivePowerL1 count__sum/GridActivePowerL2 count__sum/GridActivePowerL3 count__sum/ProductionAcActivePower count__sum/ProductionAcActivePowerL1 count__sum/ProductionAcActivePowerL2 count__sum/ProductionAcActivePowerL3 count__sum/ProductionActivePower count__sum/ProductionDcActualPower count__sum/UnmanagedConsumptionActivePower count_charger0/ActualPower count_charger1/ActualPower count_ctrlEmergencyCapacityReserve0/ActualReserveSoc count_ctrlEssTimeOfUseTariff0/QuarterlyPrices count_ctrlEssTimeOfUseTariff0/StateMachine count_ctrlGridOptimizedCharge0/DelayChargeMaximumChargeLimit count_ctrlGridOptimizedCharge0/SellToGridLimitMinimumChargeLimit count_ctrlGridOptimizedCharge0/_PropertyMaximumSellToGridPower count_ctrlIoHeatPump0/Status count_ctrlIoHeatingElement0/Level count_ess0/ActivePower count_ess0/Soc count_evcs0/ChargePower count_evcs1/ChargePower count_evcs2/ChargePower count_evcs3/ChargePower count_evcs4/ChargePower count_evcs5/ChargePower count_evcs6/ChargePower count_evcs7/ChargePower count_evcs8/ChargePower count_io0/Relay1 count_io0/Relay2 count_io0/Relay3 count_io0/Relay4 count_io0/Relay5 count_io0/Relay6 count_io0/Relay7 count_io0/Relay8 count_io1/Relay1 count_io1/Relay2 count_io1/Relay3 count_io1/Relay4 count_io1/Relay5 count_io1/Relay6 count_io1/Relay7 count_io1/Relay8 count_meter0/ActivePower count_meter0/ActivePowerL1 count_meter0/ActivePowerL2 count_meter0/ActivePowerL3 count_meter1/ActivePower count_meter1/ActivePowerL1 count_meter1/ActivePowerL2 count_meter1/ActivePowerL3 count_meter2/ActivePower count_meter2/ActivePowerL1 count_meter2/ActivePowerL2 count_meter2/ActivePowerL3 count_meter3/ActivePower count_meter3/ActivePowerL1 count_meter3/ActivePowerL2 count_meter3/ActivePowerL3 count_pvInverter0/ActivePower
---- --------------------------------- ----------------------------------- ----------------------------------- ----------------------------------- ------------------------- --------------------------- --------------------------- --------------------------- ---------------------------- ----------------- -------------------------- ---------------------------- ---------------------------- ---------------------------- ---------------------------------- ------------------------------------ ------------------------------------ ------------------------------------ -------------------------------- ---------------------------------- ------------------------------------------ -------------------------- -------------------------- ---------------------------------------------------- --------------------------------------------- ------------------------------------------ ------------------------------------------------------------ ---------------------------------------------------------------- -------------------------------------------------------------- ---------------------------- --------------------------------- ---------------------- -------------- ----------------------- ----------------------- ----------------------- ----------------------- ----------------------- ----------------------- ----------------------- ----------------------- ----------------------- ---------------- ---------------- ---------------- ---------------- ---------------- ---------------- ---------------- ---------------- ---------------- ---------------- ---------------- ---------------- ---------------- ---------------- ---------------- ---------------- ------------------------ -------------------------- -------------------------- -------------------------- ------------------------ -------------------------- -------------------------- -------------------------- ------------------------ -------------------------- -------------------------- -------------------------- ------------------------ -------------------------- -------------------------- -------------------------- -----------------------------
0    50588                             50611                               50608                               50601                               27947                     27947                       27947                       27947                       20859                        27921             50205                      43784                        43784                        43777                        34873                              20247                                19822                                14679                                42483                            14408                              48656                                      9154                       9153                       2069                                                 1653                                          42                                         162                                                          408                                                              997                                                            4636                         8798                              27945                  27919          7265                    7265                    7265                    7265                    7265                    7265                    7265                    7265                    7265                    12147            12147            12147            12148            11912            11912            11912            11912            1663             1663             1663             1663             1663             1663             1663             1663             28609                    22156                      22156                      22156                      13345                    6273                       6273                       6273                       20427                    20427                      20427                      20427                      6668                     6668                       6668                       6668                       244
>

> show retention policies
name    duration  shardGroupDuration replicaN default
----    --------  ------------------ -------- -------
autogen 0s        168h0m0s           1        true
rp_max  2160h0m0s 24h0m0s            1        false
rp_avg  2160h0m0s 24h0m0s            1        false
>

Ok da stehen schonmal grundsätzlich Werte drin. Im UI-Widget werden glaube ich “_sum/EssDcChargeEnergy” und “_sum/EssDcDischargeEnergy” angezeigt. Sind die bei dir richtig?

z. B.

select "_sum/EssDcChargeEnergy" from rp_max.max where edge = '%edgeNr%'

btw. precision rfc3339 für lesbareren output

Danke für diesen Command !! den habe ich schon kange gesucht haha

Ich schau heute abend mal :slight_smile: