WinCC Unified Schnittstelle aus Faceplate bei Bildwechsel übergeben

Pegelsau

Level-2
Beiträge
8
Reaktionspunkte
6
Zuviel Werbung?
-> Hier kostenlos registrieren
Moin zusammen,
ich versuche in WinCC Unified V20 über ein Faceplate ein Bild aufzurufen.

Hier in dem Faceplate ist der Button inklusive Status-Anzeige.
Der Status wird über die Variablen-Schnittstelle "type_motor" übergeben.
uebersichtsbild.png

Wenn ich den Button drücke, möchte ich im Bildfenster "window_main" ein neues Bild öffnen: "function_motor".
Gleichzeitig möchte ich an das Faceplate "fp_header" innerhalb von "function_motor" die Variablen-Schnittstelle "type_motor" übergeben.
Ziel-Bild:
ziel_bild.png
Hierzu rufe ich folgendes Script auf:
Javascript:
export function button_foreground_OnTapped(item, x, y, modifiers, trigger) {
try
{
  /// Einschränkung des Faceplates umgehen
  let ui = HMIRuntime.UI;
  let sys = ui.SysFct;
 
  /// Lese die Eigenschaft "screen_title"
  let titletext = Faceplate.Properties.screen_title;
  if (titletext !== undefined)
    {
    /// Setze "screen_title" im globalen Header im Objekt "Text"
    sys.SetPropertyValue("~/header/screen_title", "Text", titletext);
    }

  /// Lese die Variable "type_motor"
  let motorData = Faceplate.Properties.type_motor;
 
  if (motorData !== undefined)
    {
    /// Setze "type_motor" aus dem aktuellen Faceplate im Ziel-Faceplate
    sys.SetPropertyValue("~/function_motor/fp_header", "type_motor", motorData);
    }

  // 3. Screen-Wechsel
  sys.ChangeScreen("function_motor", "~/window_main");
}
catch (err)
{
  HMIRuntime.Trace("Fehler beim fensterübergreifenden Zugriff: " + err.message);
}
}

Den Bildtitel bekomme ich ohne Probleme im Header geschrieben, das funktioniert.
Ich bekomme "type_motor" aber einfach nicht übergeben:

session: 0011, trace: SystemFunction 'SetPropertyValue' failed! screenItemPath=~/header/screen_title screenItemPropertyName=Text value=Startbild error=ResultCode: 0x80000006 Error: CF_R_INVALID_POINTER Description: The component reported a general error (File: D:\agent\_work\157\s\source\ScriptSysFctPlugins\SysFct\GfxUISysFct.cpp, Func: HmiGfx::CHmiUISysFct::SetPropertyValue)

Ich habe zwei Vermutungen: Ich kann nicht auf das Objekt zugreifen, weil es noch nicht geladen ist oder ich kann kein UDT übergeben?

Ich könnte natürlich in dem Faceplate mit dem Button noch einen String als Schnittstelle beschreiben und die Schnittstelle über eine globale Variable weiterleiten.
Das funktioniert auch.
Nur müsste ich dann bei Änderung der Variablen-Schnittstelle dann auch die String-Schnittstelle ändern.

Ich habe auch schon versucht, per Skript den Text der Schnittstelle "type_motor" als String auszulesen, aber das habe ich überhaupt nicht hinbekommen.

Hat jemand einen Ansatz für mich?
Vielleicht auch eine ganz andere Idee, wie ich die Aufrufe am besten löse?
 
Wäre es hier nicht besser du machst das Bild auch als Faceplate und dann per "Open Faceplate as Popup"?
So würde ich es jedenfalls lösen. Dann werden auch die Parameter mit übergeben.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Leider lag ich jetzt eine ganze Woche flach und konnte es nicht testen.

Der Ansatz, ein Faceplate als Popup zu öffnen, gefällt mir grundsätzlich ganz gut.
Problem bei mir grad: Wenn ich innerhalb des "Button"-Faceplates ein Popup öffne, wird die Position des Popups relativ zum "Button"-Faceplate gesetzt.
Wenn der Button also z.b. unten rechts liegt, wird das Popup entsprechend unten rechts geöffnet und muss erst verschoben werden.

Hat jemand einen Ansatz, wie ich die Position mit einem "globalen" Positionswert setze?
 
Müsste gehen indem du z.B. die Position des Parens liest & relativ dazu negative Koordinaten angibst.

Hast du dir das Tipps&Tricks zu Faceplates schon durchgelesen?
Leider ist es teilweise echt erschlagend für mich, wo ich passende Informationen für meine spezifischen Probleme in meiner spezifischen Version suchen kann.

Falls mal jemand hier landen sollte: Hiermit öffne ich ein Faceplate als Popup, mit einem Versatz von -200/-200 zum Faceplate, in dem der Button liegt.
Außerdem wird sichergestellt, dass das Popup mindestens 10/10 Pixel Abstand zum absoluten Bildrand hat.
Javascript:
try {
    // Wunsch-Versatz relativ zum Button
    let offset_x = -200;
    let offset_y = -200;
    let min_global = 10;

    // Aktuelle Position des Icons im Bild abrufen
    let button_x = Faceplate.Parent.Left;
    let button_y = Faceplate.Parent.Top;

    // Versatz korrigieren, damit absolute Pos nicht < 20 wird
    if (offset_x < (min_global - button_x)) {
      offset_x = min_global - button_x;
    }

    if (offset_y < (min_global - button_y)) {
      offset_y = min_global - button_y;
    }

    // Popup öffnen
    let po = Faceplate.OpenFaceplateInPopup("container_popup_V_0_0_2", Faceplate.Properties.screen_title, { type_container: Faceplate.Properties.type_container }, false, true);
   
    if (po) {
      // Position anwenden (Relativ zum Button)
      po.Left = offset_x;
      po.Top = offset_y;
      po.Visible = true;
     
      HMIRuntime.Trace("Popup positioniert: " + offset_x + "/" + offset_y);
    }
  }
  catch (e) {
    HMIRuntime.Trace("Fehler bei Positionierung: " + e.message);
  }
 
Genau, der Button sitzt in einem Faceplate mit einer Schnittstelle vom UDT type_motor.
Das Popup ist jetzt auch ein Faceplate mit einer Schnittstelle vom UDT type_motor und bekommt diese vom Button weitergegeben.
Ist das eine dumme Idee? 🤔

Leider habe ich jetzt selber ein bisschen Chaos bezüglich der Codes reingebracht. Alle Komponenten gibt es sowohl für Container als auch für Motoren.
 
Genau, der Button sitzt in einem Faceplate mit einer Schnittstelle vom UDT type_motor.
Das Popup ist jetzt auch ein Faceplate mit einer Schnittstelle vom UDT type_motor und bekommt diese vom Button weitergegeben.
Ist das eine dumme Idee? 🤔

Leider habe ich jetzt selber ein bisschen Chaos bezüglich der Codes reingebracht. Alle Komponenten gibt es sowohl für Container als auch für Motoren.
Nein, ist ein gute idee. Ich hatte auch sowas vor
 
Leider ist es teilweise echt erschlagend für mich, wo ich passende Informationen für meine spezifischen Probleme in meiner spezifischen Version suchen kann.
Kann ich & ging mir ebenfalls so.
Eigenwerbung: Ich hab mal hier eine Linksammlung angefangen um etwas mehr Übersicht über die vorhandenen, nützlichen Beiträge zu dem Thema zu bekommen.
if (po) { // Position anwenden (Relativ zum Button) po.Left = offset_x; po.Top = offset_y; po.Visible = true; HMIRuntime.Trace("Popup positioniert: " + offset_x + "/" + offset_y); }
Gibts einen speziellen Grund wieso du dich hier auf if(po) beziehst?
Der Rückgabewert ist ja ein Object vom Typ HmiPopupScreenWindow, wird also immer truthy sein *kopfkratz*.
 
Zuletzt bearbeitet:
Kann ich & ging mir ebenfalls so.
Eigenwerbung: Ich hab mal hier eine Linksammlung angefangen um etwas mehr Übersicht über die vorhandenen, nützlichen Beiträge zu dem Thema zu bekommen.

Gibts einen speziellen Grund wieso du dich hier auf if(po) beziehst?
Der Rückgabewert ist ja ein Object vom Typ HmiPopupScreenWindow, wird also immer truthy sein *kopfkratz*.
Zur Linksammlung: Danke für den Hinweis und für die Sammlung im Allgemeinen (y).

Mein Faceplate für den Button hat mittlerweile die Version 179. Ich habe also viel probiert und hatte zwischenzeitlich irgendein Problem damit abgesichert.
Danke für den Hinweis, das habe ich gar nicht mehr wirklich wahrgenommen und konnte ich rauskicken.

Idt das Skript wie im erste Beitrag? Wie sehen die aktuelle Skripte aus?
Ich musste noch die Übergabe der Schnittstelle korrigieren. Beim type_container brauchte er Anführungszeichen, was ihn bei type_motor komischerweise nicht gestört hat.

Das wäre jetzt meine Variante. Je nach Button muss ich nur noch das Faceplate und die Schnittstellen anpassen.
Javascript:
try
{
  // Versatz relativ zum Button
  let offset_x = -300;
  let offset_y = -300;
  // Mindestabstand zum Rand für das globale Bild
  let min_global = 10;

  // Aktuelle Position des Buttons im globalen Bild abrufen
  let button_x = Faceplate.Parent.Left;
  let button_y = Faceplate.Parent.Top;

  // Versatz korrigieren, damit absolute Position nicht < min_global wird
  if (offset_x < (min_global - button_x))
  {
    offset_x = min_global - button_x;
  }

  if (offset_y < (min_global - button_y))
  {
    offset_y = min_global - button_y;
  }

  // Popup öffnen
  let po = Faceplate.OpenFaceplateInPopup("motor_popup_V_0_0_29", Faceplate.Properties.screen_title, { "type_motor": Faceplate.Properties.type_motor }, false, true); 
  // Position anwenden (Relativ zum Button)
  po.Left = offset_x;
  po.Top = offset_y;
  // Nach Anwenden aller Parameter Popup sichtbar machen
  po.Visible = true;
 
  // Trace-Meldung bei erfolgreichem Öffnen des Popups
  HMIRuntime.Trace("Popup positioniert: " + offset_x + "/" + offset_y);
}

catch (e)
{
  // Trace-Meldung bei Fehler
  HMIRuntime.Trace("Fehler bei Positionierung: " + e.message);
}
 
Zurück
Oben