WinCC Unified Ineinander verschachtelte Bildfenster gleichzeitig ändern

Botimperator

Level-2
Beiträge
635
Reaktionspunkte
279
Zuviel Werbung?
-> Hier kostenlos registrieren
Moin zusammen,

ich hab hier ein Problem, bei dem ich irgendwie auf dem Schlauch stehe...
TIA V20
MTP1500, Runtime-Version V20.0.0

Ich hab meine Bilder bisher wie in der Template-Suite aufgebaut:
1740479235393.png

(1) liegt auf dem Hauptbild und enthällt die jeweilig angewählte Hauptstruktur, in meinem Fall welcher Anlagenverbund angewählt ist.
(2) Hier im SubNav habe ich die einzelnen Anlagen-Baugruppen untergebracht.
(3) der ThirdNav enthält Untermenüs zu der jeweiligen Anlagen-Baugruppe (Einstellwerte und so Zeug).

Im "normalen" Durchklicken der Fenster klappt das auch wunderbar.
Jetzt habe ich allerdings folgende Situation, die ich nicht gelöst bekomme:

Offen habe ich beispielsweise folgende Bildfenster:
Code:
| MainNav     | SubNav                          | ThirdNav                                   |
|-------------|---------------------------------|--------------------------------------------|
| Application | 12111_Application_SubNav_1_Home | 12121_Application_ThirdNav_Home_1_Overview |

Jetzt möchte ich über eine Schaltfläche direkt in ein Untermenü einer anderen Baugruppe springen.
Code:
| MainNav     | SubNav                           | ThirdNav                                   |
|-------------|----------------------------------|--------------------------------------------|
| Application | 12112_Application_SubNav_2_FOCOS | 12222_Application_ThirdNav_FOCOS_2_Records |

Dazu muss ich das Bildfenster "swSubNavContend" und gleichzeitig das INNERHALB von "swSubNavContend" liegende Bildfenster "swThirdNavContend" ändern.
"swSubNavContend" zu ändern ist kein Problem, aber an "swThirdNavContend" beiß ich mir grade die Zähne aus.

Mein erster Versuch hat erwartbarerweise nicht funktioniert.
Javascript:
HMIRuntime.UI.SysFct.ChangeScreen("12112_Application_SubNav_2_FOCOS", "~/swContent/swSubNavContent");
HMIRuntime.UI.SysFct.ChangeScreen("12222_Application_ThirdNav_FOCOS_2_Records", "~/swContent/swSubNavContent/swThirdNavContent");
Ich bekomme den Fehler, dass "swThirdNavContent" nicht existieren würde (was ja auch erst der Fall ist wenn "swSubNavContent" fertig geladen wurde).
Die beiden Befehle für sich funktionieren aber, also kein Problem mit dem Pfad oder sowas.

Das ganze mit asynchronem Script und "await" funktioniert ebenfalls nicht => ebenfalls "swThirdNavContent" existiert nicht.
Javascript:
await HMIRuntime.UI.SysFct.ChangeScreenAsync("12112_Application_SubNav_2_FOCOS", "~/swContent/swSubNavContent");
await HMIRuntime.UI.SysFct.ChangeScreenAsync("12222_Application_ThirdNav_FOCOS_2_Records", "~/swContent/swSubNavContent/swThirdNavContent");

Jetzt hatte ich noch die Idee das Ganze per Promise zu machen.
Javascript:
HMIRuntime.UI.SysFct.ChangeScreenAsync("12112_Application_SubNav_2_FOCOS", "~/swContent/swSubNavContent")
.then(HMIRuntime.Trace("Aktueller SubNavContent: " + UI.FindItem("~/swContent/swSubNavContent").Screen, HMIRuntime.Trace.Enums.hmiSeverity.Info))
.then(HMIRuntime.UI.SysFct.ChangeScreenAsync("12222_Application_ThirdNav_FOCOS_2_Records", "~/swContent/swSubNavContent/swThirdNavContent")
  .then(HMIRuntime.Trace("Aktueller ThirdNavContent: " + UI.FindItem("~/swContent/swSubNavContent/swThirdNavContent").Screen, HMIRuntime.Trace.Enums.hmiSeverity.Info))
);
Für den ersten Trace bekomme ich
Javascript:
Trace(): Aktueller SubNavContent: HMI_RT_2::12112_Application_SubNav_2_FOCOS
Also wurde der Inhalt des Bildfensters "swSubNavContent" korrekt geändert.

Für den zweiten Bildwechsel/Trace bekomme ich aber wieder einen "swThirdNavContent existiert nicht"-Fehler.
Also wird der fulfilled-Status doch nicht nach vollständigem Laden des Bildfensters gesetzt...

Und jetzt stehe ich so langsam auf dem Schlauch :(
Wie bekomme ich es hin die beiden Bildfenster mit einem Befehl nacheinander zu ändern?
Irgendjemand ne Idee?

edit:
Tippfehler korrigiert.
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Hi,
meine Idee dazu:
Jetzt möchte ich über eine Schaltfläche direkt in ein Untermenü einer anderen Baugruppe springen.
Beim drücken dieser Schaltfläche den Bildwechsel vollziehen und eine Interne Variable auf 1 setzen.
Das nun aufgeschaltene Bild mit Eriegnis "Aufgebaut" die Variable abfragen, wenn diese == 1, dann öffne in swThirdNavContent das nächste Bild. Und setze Variable wieder auf 0.

Gruß ;)
 
Beim drücken dieser Schaltfläche den Bildwechsel vollziehen und eine Interne Variable auf 1 setzen.
Das nun aufgeschaltene Bild mit Eriegnis "Aufgebaut" die Variable abfragen, wenn diese == 1, dann öffne in swThirdNavContent das nächste Bild. Und setze Variable wieder auf 0.
War auch einer meiner Gedankengänge.
Nur ist die Überwachung der Variable das Problem.
Die musst du ja zyklisch lesen um sie auf Wertänderung zu prüfen.
Hatte das mit einer do..while Schleife in einem asynchronen Script probiert, habe aber keine zufriedenstellende Lösung gestrickt bekommen.

Zudem müsste ich bei jedem Bild, dass möglicherweise in der Verschachtelung aufgerufen werden könnte, dieses "setze Variable wenn aufgebaut" projektieren, was ich gerne vermeiden würde.
 
Nur ist die Überwachung der Variable das Problem.
Die musst du ja zyklisch lesen um sie auf Wertänderung zu prüfen.
Der Zustand ist doch nur einmal beim Aufbau des Bildes interessant, um zu prüfen, ob ein weiteres Bild in swThirdNavContent aufgeschalten werden muss oder eben nicht.

Zudem müsste ich bei jedem Bild, dass möglicherweise in der Verschachtelung aufgerufen werden könnte, dieses "setze Variable wenn aufgebaut" projektieren, was ich gerne vermeiden würde.
Da gebe ich dir Recht, bei vielen Bildern könnte das nerven.
Lösung dafür: schreibe 1 globales Skript und rufe das einfach nur bei jedem dieser Bilder auf.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Der Zustand ist doch nur einmal beim Aufbau des Bildes interessant, um zu prüfen, ob ein weiteres Bild in swThirdNavContent aufgeschalten werden muss oder eben nicht.
Ich bin nicht sicher ob wir das Gleiche denken...

Ich habe folgende, maximale Verschachtelungstiefe:
(es ist inzwischen noch eine 4. Bildfenster dazu gekommen, ändert aber am Konzept erstmal nichts)
"~/swContent/swSubNavContent/swThirdNavContent/swInScreenTabContent"

Ich möchte diese Bildfenster jeweils mit neuem Inhalt laden.
Da das jeweils im Bild enthaltene Bildfenster erst existiert wenn das Bild komplett geladen wurde, kann ich die komplette Verschachtelung nicht in einem Rutsch mit neuem Inhalt versorgen.
Ich muss also warten bis swContent geladen ist um swSubNavContent mit neuem Inhalt versorgen zu können, und so weiter.
Also muss ich irgendwie an das Ereignis "Bild ist fertig geladen" ran kommen.
Wenn ich also eine Variable an den Bildaufbau kopple, muss ich diese in meinem Script auf Wertänderung abfragen um zu wissen, dass der Bildaufbau erfolgt ist.

Oder meinst du ich soll die Liste mit dem neuen Inhalt beim Triggern des Sprungs in den globalen Definitionsbereich des Scripts laden und
dann am "Bild Aufgebaut" Ereignis jeder Ebene ein weiteres Script aufrufen, dass dann jeweils den Inhalt der Ebene darunter in das betreffende Bildfenster läd?
 
Oder meinst du ich soll die Liste mit dem neuen Inhalt beim Triggern des Sprungs in den globalen Definitionsbereich des Scripts laden und
dann am "Bild Aufgebaut" Ereignis jeder Ebene ein weiteres Script aufrufen, dass dann jeweils den Inhalt der Ebene darunter in das betreffende Bildfenster läd?
Ja ich denke genau das meine ich, und genau das sollte dein Problem lösen.

Beim drücken dieser Schaltfläche den Bildwechsel vollziehen und eine Interne Variable auf 1 setzen.
Wenn ich also eine Variable an den Bildaufbau kopple, muss ich diese in meinem Script auf Wertänderung abfragen um zu wissen, dass der Bildaufbau erfolgt ist.
Und genau diese Variable soll vorher auf 1 gesetzt werden.

(Ich hoffe wir bringen uns so langsam nicht selber durcheinander 😂)
 
Ich habs eben mal ausprobiert über das "Aufgebaut"-Ereignis ein weiteres Script aufzurufen & das nächste Bildfenster zu ändern.
=> funktioniert prinzipiell, sofern die komplette Verschachtelung neu geladen wird.

Diese Lösung erfodert aber ein Start-Script und nochmal ein Script je Navigationsebene zum Ändern des enthaltenen Bildfensters, welche wirderum an das "Aufgebaut"-Ereignis jedes einzelnen Bildes der jeweiligen Navigationsebene projektiert werden müssen.
Zudem wird das "Aufgebaut"-Ereignis nicht ausgelöst wenn das mit "ChangeScreen" angesprochene Bildfenster bereits das gewünschte Bildfenster enthält (eigentlich logisch, aber für diese Lösung eher unschön).
In dem im ersten Post angestrebten Navigationspfad würde ich das "MainNav"-Bildfenster nicht ändern, was die Ereigniskette bereits auf der obersten Navigationsebene unterbrechen würde.
Sowas wie einen "lade das Fenster neu"-Befehl habe ich noch nicht gefunden.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Na das klingt doch schon ganz gut, ist zwar nicht die beste Lösung aber du weißt ja ... Unified eben ...

"Lade Fenster/Bild neu" sowas gibt es auch nicht, du kannst hier entweder mal einen Support Request eröffnen oder halt mit vielen weiteren Skripten probieren ein ähnliches Verhalten umzusetzen (aber ich persönlich würde mir von beidem nicht viel erhoffen).
 
So, liebe Kinder: ich hab zumindest mal eine funktionierende "QuickAndVeryDirty"-Lösung.

Ein grundlegendes Missverständnis meinserweis war, dass sich die Bilder nicht einen gemeinsamen Script-Ausführungskontext teilen, sondern jedes Bild, auch jedes Bildfenster, für sich einen eigenen Ausführungskontext besitzt.
Heißt: starte ich mit einem Button ein Script, welches den Inhalt des Bildes welches besagten Button enthält ändert, wird das Bild abgebaut (soweit logisch) und dessen Ausführungskontext incl. aller aktiven Scripte gelöscht (was mein erstes Problem war).
Die Promisses haben schon funktioniert, nur hat das Script beim ersten Bildwechsel seinen eigenen Ausführungskontext 6 damit sich selbst getoastet ¯\_(ツ)_/¯

Also musste ich das Lade-Script in einen Kontext bringen, der nicht während dem Neuladen des Bildschirminhalts neu geladen / gelöscht wird.
Praktischerweise: der einzige andere, "globale" Ausführungskontext ist der Aufgabenplaner, welcher nicht auf UI-Elemente zugreifen kann.
Also ein Script im Aufgabenplaner anzutriggern & damit die Bilder zu laden geht nicht.

Naheliegende Lösung:
1741707161804.png

Zudem: der einzige Weg von einen Ausführungskontext in den anderen sind anscheinend HMI-Variablen (oder ich hab was übersehen).
Im Prinzip habe ich das Script in zwei Teile gesplittet: eine Triggerüberwachung und das eigentliche Ladescript.
Zudem einige interne Variablen zur Übergabe des gewünschten Bild-Inhalts an das Lade-Script.
1741707319811.png
Zum Starten des Ladens wird einfach der jeweilige Bildname in die Strings geschrieben & anschließend der Trigger auf 1 gesetzt.

Dieser Trigger wird wiederrum von zyklisch von einem Script geprüft, dass beim Aufbau des Hauptbildes gestartet wird (das einzige Bild, welches devinitiv nicht neu geladen wird).
1741707528866.png

Besagtes Script startet beim Aufbau des Hauptbildes einen Intervall, der zyklisch die Triggervariable prüft & bei einem Wert != 0 das Ladescript startet.

Javascript:
export async function TriggerCheck(TagNameTrigger, CheckIntervall, TagNameNewSwContent, TagNameNewSwSubNavContent, TagNameNewSwThirdNavContent, TagNameNewSwInScreenTabContent) {
/*
Dieses Script muss in der Bildhierarchie auf dem obersten Bild aufgerufen werden (RootScreen).
Es erzeugt einen asynchron laufenden Intervall, der zyklisch entsprechend dem Parameter "CheckIntervall" (Angabe in ms) die Triggervariable auf einen Wert ungleich 0/false prüft.
 */
try {
    let intervallId = HMIRuntime.Timers.SetInterval(() => {
        try {
            let tag = Tags(TagNameTrigger);
            let triggerValue = tag.Read();
            let swNavLayer0;
            let swNavLayer1;
            let swNavLayer2;
            let swNavLayer3;

            //HMIRuntime.Trace("NavigationStackedScreen.TriggerCheck | Triggervariable wird geprüft. Triggervariable: " + TagNameTrigger + " | mit dem Wert: " + triggerValue, HMIRuntime.Trace.Enums.hmiSeverity.Info);
            if (triggerValue == true) {
                HMIRuntime.Trace("Navigation.StackedScreenWindow_TriggerCheck | Triggervariable wurde geändert => Trigger ausgelöst", HMIRuntime.Trace.Enums.hmiSeverity.Info);
                swNavLayer0 = Tags(TagNameNewSwContent).Read();
                swNavLayer1 = Tags(TagNameNewSwSubNavContent).Read();
                swNavLayer2 = Tags(TagNameNewSwThirdNavContent).Read();
                swNavLayer3 = Tags(TagNameNewSwInScreenTabContent).Read();
                HMIRuntime.Trace("NavigationStackedScreen.TriggerCheck | Versuche die Bildfenster-Verschachtelung mit folgendem Inhalt neu zu laden: swContent=" + swNavLayer0 + " | swSubNavContent=" + swNavLayer1 + " | swThirdNavContent=" + swNavLayer2 + " | swInScreenTabContent=" + swNavLayer3, HMIRuntime.Trace.Enums.hmiSeverity.Info);
                LoadNewContent_2(swNavLayer0, swNavLayer1, swNavLayer2, swNavLayer3);
                //Triggertag wieder zurücksetzen
                tag.Write(0);
            }
        } catch (ex) {
            HMIRuntime.Trace("NavigationStackedScreen.TriggerCheck | Beim Prüfen ist etwas schief gegangen. Triggervariable: " + TagNameTrigger + " Fehler: " + ex, HMIRuntime.Trace.Enums.hmiSeverity.Error);
        }

    }, parseInt(CheckIntervall));
    HMIRuntime.Trace("NavigationStackedScreen.TriggerCheck | Intervall mit der ID: " + intervallId + " wurde erzeugt", HMIRuntime.Trace.Enums.hmiSeverity.Info);
} catch (ex) {
    HMIRuntime.Trace("NavigationStackedScreen.TriggerCheck | Beim Erstellen des Intervalls ist etwas schief gegangen, Fehler: " + ex, HMIRuntime.Trace.Enums.hmiSeverity.Error);
}
}


Im Ladescript selbst hatte ich auch nochmal was lustiges.
Anscheinend wird das Promise von ChangeScreenAsync() nicht ganz am Schluss resolved oder nach dem "resolved" passiert noch irgendwas, was den folgenden Bildwechsel ins Straucheln bringt.
Witzigerweise bin ich immer zwei tatsächlich zu ändernde Bildfenster weit gekommen, bevor das Script mit einem "Pfad ungültig"-Fehler abgebrochen hat, keine Ahnung wieso.
Der Siemens-Service hat für eine weitere Diagnose auf den kostenpflichtigen Support verwiesen.
Muss noch schauen ob wir der Ursache auf den Grund gehen wollen oder ob wir es als "funktioniert doch" abhaken.
Der "dirty"-Teil der Lösung war die ChangeScreenAsync() nochmal per setTimeout() um ein paar Milisekunden zu verzögern.

Das Teil hat definitiv "Piramid of Doom"-Vibes, aber wuppt erstmal:
Javascript:
export function LoadNewContent(swContent_newScreen, swSubNavContent_newScreen, swThirdNavContent_newScreen, swInScreenTabContent_newScreen) {
const
mainNavContentSwPath = "~/swContent",
mainNavContentScreen = swContent_newScreen,
subNavContentSwPath = "~/swContent/swSubNavContent",
subNavContentScreen = swSubNavContent_newScreen,
thirdNavContentSwPath = "~/swContent/swSubNavContent/swThirdNavContent",
thirdNavContentScreen = swThirdNavContent_newScreen,
inScreenTabContentPath = "~/swContent/swSubNavContent/swThirdNavContent/swInScreenTabContent",
inScreenTabContentScreen = swInScreenTabContent_newScreen,
delay = 10; //Verzögerungs-Timeout für die Ausführung des nächsten Bildwechsels in ms

try {
    HMIRuntime.Trace("NavigationStackedScreen.LoadNewContent | Versuche swContent mit folgendem Inhalt zu laden: " + mainNavContentScreen + " Pfad: " + mainNavContentSwPath, HMIRuntime.Trace.Enums.hmiSeverity.Info);
    UI.SysFct.ChangeScreenAsync(mainNavContentScreen, mainNavContentSwPath)
    .then((result) => {
        HMIRuntime.Timers.SetTimeout(() => {
            HMIRuntime.Trace("NavigationStackedScreen.LoadNewContent | Result von Änderung swContent war: " + result + " | Versuche swSubNavContent mit folgendem Inhalt zu laden: " + subNavContentScreen + " Pfad: " + subNavContentSwPath, HMIRuntime.Trace.Enums.hmiSeverity.Info);
            UI.SysFct.ChangeScreenAsync(subNavContentScreen, subNavContentSwPath)
            .then((result) => {
                HMIRuntime.Timers.SetTimeout(() => {
                    HMIRuntime.Trace("NavigationStackedScreen.LoadNewContent | Result von Änderung swSubNavContent war: " + result + " | Versuche swThirdNavContent mit folgendem Inhalt zu laden: " + thirdNavContentScreen + " Pfad: " + thirdNavContentSwPath, HMIRuntime.Trace.Enums.hmiSeverity.Info);
                    UI.SysFct.ChangeScreenAsync(thirdNavContentScreen, thirdNavContentSwPath)
                    .then((result) => {
                        HMIRuntime.Timers.SetTimeout(() => {
                            HMIRuntime.Trace("NavigationStackedScreen.LoadNewContent | Result von Änderung swThirdNavContent war: " + result + " | Versuche swInScreenTabContent mit folgendem Inhalt zu laden: " + inScreenTabContentScreen + " Pfad: " + inScreenTabContentPath, HMIRuntime.Trace.Enums.hmiSeverity.Info);
                            UI.SysFct.ChangeScreenAsync(inScreenTabContentScreen, inScreenTabContentPath)
                            .then((result) => {
                                HMIRuntime.Trace("NavigationStackedScreen.LoadNewContent | Result von Änderung swInScreenTabContent war: " + result + " | Verschachtelung vollständig geladen", HMIRuntime.Trace.Enums.hmiSeverity.Info);
                            })
                            .catch((errorCode) => {
                                HMIRuntime.Trace("NavigationStackedScreen.LoadNewContent | swInScreenTabContent konnte nicht geladen werden, Fehler: " + HMIRuntime.GetDetailedErrorDescription(errorCode) + " Fehlercode: " + errorCode, HMIRuntime.Trace.Enums.hmiSeverity.Error);
                            });

                        }, delay);
                    })
                    .catch((errorCode) => {
                        HMIRuntime.Trace("NavigationStackedScreen.LoadNewContent | swThirdNavContent konnte nicht geladen werden, Fehler: " + HMIRuntime.GetDetailedErrorDescription(errorCode) + " Fehlercode: " + errorCode, HMIRuntime.Trace.Enums.hmiSeverity.Error);
                    });

                }, delay);
            })
            .catch((errorCode) => {
                HMIRuntime.Trace("NavigationStackedScreen.LoadNewContent | swSubNavContent konnte nicht geladen werden, Fehler: " + HMIRuntime.GetDetailedErrorDescription(errorCode) + " Fehlercode: " + errorCode, HMIRuntime.Trace.Enums.hmiSeverity.Error);
            });

        }, delay);
    })
    .catch((errorCode) => {
        HMIRuntime.Trace("NavigationStackedScreen.LoadNewContent | swContent konnte nicht geladen werden, Fehler: " + HMIRuntime.GetDetailedErrorDescription(errorCode) + " Fehlercode: " + errorCode, HMIRuntime.Trace.Enums.hmiSeverity.Error);
    });
} catch (ex) {
    HMIRuntime.Trace("NavigationStackedScreen.LoadNewContent | Fehler beim Bildwechsel: " + ex, HMIRuntime.Trace.Enums.hmiSeverity.Error);
}
}
 
Moin,

ich hab nochmal einen Nachtrag dazu wie man sowas besser/praktischer aufziehen kann.
Erstmal habe ich die als Zwischenspeicher zwischen den Ausführungskontexten genutzten HMI-Variablen und die Bildfenster-Pfade im globalen Definitionsbereich des Scripts deklariert => Bei Änderungen muss ich nur eine Stelle anpassen.
Javascript:
//====================================================================================================
NestedSwLoadContent
NestedSwSetNewContent
NestedSwTriggerCheck

Diese drei Scripts dienen dazu Verschachtelungen von Bildfenstern in einem Rutsch mit neuem Inhalt zu laden.
"NestedSwTriggerCheck" muss im "Aufgebaut"-Ereignis des Haupt-Bildes aufgerufen werden. Dies dient dazu das Lade-Script in einem Kontext zu starten, der beim Neuladen der Bilder nicht gelöscht wird.
"NestedSwLoadContent" Ist das eigentliche Lade-Script und wird von "NestedSwTriggerCheck" gestartet.
"NestedSwSetNewContent" ist das für den Anwender relevante Script zum Auslösen der Neubefüllung der Bildfenster-Verschachtelung.
Es wird als Verschachtelung folgende, maximale Pfad-Tiefe und Reihenfolge akzeptiert:
"~/swContent/swSubNavContent/swThirdNavContent/swInScreenTabContent"
Die Bearbeitung erfolgt hierarchisch absteigend und wird beim ersten nicht definierten Bildfenster-Parameter abgebrochen.
//====================================================================================================
 */
//#endregion


const //Globale Konstanten der Scripte definieren. Achtung: das globale Modul wird im jeweiligen Kontext immer lokal instanziert. Eine Übergabe von Variablen zwischen Kontexten erfordert zwingend den Umweg über die HMI-Variablen.
HmiTagTrigger = "NavigationStackedScreenTrigger",
HmiTagNameNewSwContent = "NavigationStackedScreenLayer0_swContent",
HmiTagNameNewSwSubNavContent = "NavigationStackedScreenLayer1_swSubNavContent",
HmiTagNameNewSwThirdNavContent = "NavigationStackedScreenLayer2_swThidNavContent",
HmiTagNameNewSwInScreenTabContent = "NavigationStackedScreenLayer3_swInScreenTabContent";

const //Deklaration der Bildfenster-Pfade. Angabe als globaler Pfad.
MainNavContentSwPath = "~/swContent",
SubNavContentSwPath = "~/swContent/swSubNavContent",
ThirdNavContentSwPath = "~/swContent/swSubNavContent/swThirdNavContent",
InScreenTabContentPath = "~/swContent/swSubNavContent/swThirdNavContent/swInScreenTabContent";


Für die Überwachung auf Wertänderung war die zyklische Prüfung innerhalb eines Intervalls zwar zweckdienlich, es gibt allerdings eine speziell dafür gedachte Funktion: Tags.CreateSubscription()
Hier hats eine ganze weile gedauert bis ich begriffen hab, dass der Satz in der TIA-Hilfe
Der Parameter "tagResult" ist ein Objekt von Typ "HMITagResult[]", der die Eigenschaften der geänderten HMI-Variablen enthält. bedeutet, dass "tagResult" immer ein Array ist, auch wenn kein Array übergeben wurde.
Hab das [] erst für einen Tippfehler oder Dreck auf dem Bildschirm gehalten ¯\_(ツ)_/¯

Javascript:
/**
* Prüft ob der Trigger für das Laden der Bildfenster ausgelöst wurde.
*/
export async function NestedSwTriggerCheck() {
    /*
    Dieses Script muss in der Bildhierarchie auf dem obersten Bild aufgerufen werden (RootScreen).
    Wird der Trigger vom Execute-Script oder manuell auf 1/true gesetzt, läd dieses Script die Bildnamen des neuen Inhalts aus den im globalen Definitionsbereich angegebenen Variablen und startet das eigentliche Lade-Script.
     */
    try {
        let SubsTo_HmiTagTrigger = Tags.CreateSubscription(HmiTagTrigger, (tagResult) => {
            try {
                HMIRuntime.Trace("NavigationStackedScreen.TriggerCheck | Triggervariable " + tagResult[0].Name + " wurde geändert, Wert " + tagResult[0].Value + " => Trigger ausgelöst.", HMIRuntime.Trace.Enums.hmiSeverity.Info);
                if (tagResult[0].Value != 0) {//Abfrage notwendig, da die Variable beim initialen Laden von null auf 0 wechselt und die Subscription damit auslöst.
                    const swNavLayer0 = Tags(HmiTagNameNewSwContent).Read();
                    const swNavLayer1 = Tags(HmiTagNameNewSwSubNavContent).Read();
                    const swNavLayer2 = Tags(HmiTagNameNewSwThirdNavContent).Read();
                    const swNavLayer3 = Tags(HmiTagNameNewSwInScreenTabContent).Read();
                    HMIRuntime.Trace("NavigationStackedScreen.TriggerCheck | Versuche die Bildfenster-Verschachtelung mit folgendem Inhalt neu zu laden: \n" +
                        " | swContent=" + swNavLayer0 + "\n" +
                        " | swSubNavContent=" + swNavLayer1 + "\n" +
                        " | swThirdNavContent=" + swNavLayer2 + "\n" +
                        " | swInScreenTabContent=" + swNavLayer3,
                        HMIRuntime.Trace.Enums.hmiSeverity.Info);
                    NestedSwLoadContent(swNavLayer0, swNavLayer1, swNavLayer2, swNavLayer3);
                    //Triggertag wieder zurücksetzen
                    Tags(tagResult[0].Name).Write(0, Tags.Enums.hmiWriteType.hmiWriteNoWait);
                }
            } catch (ex) {
                HMIRuntime.Trace("NavigationStackedScreen.TriggerCheck | Beim Prüfen ist etwas schief gegangen. Triggervariable: " + tagResult[0].Name + " Fehler: " + ex, HMIRuntime.Trace.Enums.hmiSeverity.Error);
            }

        });
        SubsTo_HmiTagTrigger.Start();
        HMIRuntime.Trace("NavigationStackedScreen.TriggerCheck | Subscription zu " + HmiTagTrigger + " wurde erzeugt", HMIRuntime.Trace.Enums.hmiSeverity.Info);
    } catch (ex) {
        HMIRuntime.Trace("NavigationStackedScreen.TriggerCheck | Beim Erstellen des Intervalls ist etwas schief gegangen, Fehler: " + ex, HMIRuntime.Trace.Enums.hmiSeverity.Error);
    }
}
 
Zurück
Oben