[3.16] UiConnect and triggerEvent

Discussion about recent product features & solutions!
Search

Post Reply
7 posts • Page 1 of 1
moto3101
Posts: 37
Joined: Tue Aug 22, 2017 2:04 pm

[3.16] UiConnect and triggerEvent

Post by moto3101 »

Hello together,

I have a question regarding triggerEvent and UiConnect.

What is your proposed way of implementing an information exchange between panels which are loaded within a MasterModule with several SubModules using the "triggerEvent" functionality. (In previous WinCC versions, the internal _UI Datapoint was usually used for information exchange, which of course has a lot of limitations and disadvantages like not being able to pass on complex datatypes).

Please consider the following example

Image

I have a module M1 which again contains two modules M1A and M1B (i.e. panels which only contain a module).
Module M1A contains a Panel "M1AP1", which loads 4 Panels dynamically using "addSymbol" on init (lets call them M1AP1S1 to M1AP1S4). Furthermore there is a button "Button1" in M1. M1B just contains another Panel M1BP1, which is not to be further considered in this example.

Now lets assume all involved panels have the same event

Code: Select all

#event onDataChanged(string data)
UseCase U1:
Lets say I want to transfer information from M1AP1S4 to M1 (and vice versa) using the triggerEvent function (e.g. assuming M1AP1S4 is some kind of a selectable setting I want to set with Button1).

UseCase U2:
Transfer information from M1AP1S4 to M1AP1S3 using the triggerEvent function

Questions:
  • If I understood it correctly, when being in the scope of M1AP1S4 there is no way to directly trigger the event in M1, correct?
  • If the direct triggering is not possible, it would require some kind of a chain-of-responsibility, which passes each data on to its parent and to its children until it finds its final recipient
  • So, if I can only trigger events in my own panel scope, I would need my parent panel and all my childPanels to "uiConnect" to my #event and I would need to connect to my parents panel #event (if existing), correct? (In this case, I would need to pass on my Panel name to my Children)
  • As a result, all involved panels need to have an #event and to have a "onDataChanged" function which is triggered whenever one of my childPanels or my parent Panel triggers an event
  • Considering useCase U2, I would need to trigger the event in M1AP1S4, which is then passed on to the parent panel M1AP1, which then triggers its #event, which passes the data to M1A (where its actually not needed), M1AP1S1,M1AP1S2, M1AP1S3 and of course also to M1AP1S4 (where it should not trigger an event again, maybe by using some kind of identifier)
I hope I could describe the problem sufficiently, if not please let me know!

Please let me know if my assumptions are correct or if there is a different way I did not consider.

Thanks!

mikek10
Posts: 20
Joined: Wed Jun 26, 2019 4:05 pm

Re: [3.16] UiConnect and triggerEvent

Post by mikek10 »

Hi, not a resident guru, but I had a very similar requirement, and had to implement exactly what you describe. i.e. a daisy chain of events connected to their parent panel by uiConnect until reaching the required level.

I am sure you could find an alternate, easier to implement, solution by use of datapoints but that approach seemed extremely "hacky" to me and to bypass the more object orientated approach it seems we have both taken.

I have found that the documentation for some of the functionality is sketchy at best and that there are differences between what works in 3.15 and 3.17, 3.16 may be the same as either of these or different again.. but be prepared for some rework if you change wincc oa version in future.

Feel free to message me if you need working examples (for 3.15 and 3.17 at least!)

moto3101
Posts: 37
Joined: Tue Aug 22, 2017 2:04 pm

Re: [3.16] UiConnect and triggerEvent

Post by moto3101 »

mikek10 wrote: Mon Jan 18, 2021 7:23 am Hi, not a resident guru, but I had a very similar requirement, and had to implement exactly what you describe. i.e. a daisy chain of events connected to their parent panel by uiConnect until reaching the required level.

I am sure you could find an alternate, easier to implement, solution by use of datapoints but that approach seemed extremely "hacky" to me and to bypass the more object orientated approach it seems we have both taken.

I have found that the documentation for some of the functionality is sketchy at best and that there are differences between what works in 3.15 and 3.17, 3.16 may be the same as either of these or different again.. but be prepared for some rework if you change wincc oa version in future.

Feel free to message me if you need working examples (for 3.15 and 3.17 at least!)
Thanks, Mike, I appreciate your support!

I wanted to prevent the use of datapoints as it puts unnecessary load to the EvtMgr and becomes more and more complicated the more (separate) panels are using this structure at the same time. Furthermore, when passing complex datatypes (like objects of your own created classes), you need to serialise again, which does not work very well in WinCC with jsonEncode and jsonDecod (unfortunately).

For me there also rose different other questions during prototype testing like
  • ,,Do I need to disconnect an #event if I close a panel?"
  • "When does the disconnect exactly happen in case it happens automatically?"
, and most importantly:
  • "As a parent panel, when can I connect to my ChildPanels #event (especially when it has some time intensive initialisation)? Is there a specific check I could perform to be sure that I can use "uiConnect" on the panel I just loaded in my embedded module (like shapeExists() on the panel itself or ??)
I think the whole topic deserves more information to be provided by ETM, especially since its a nice feature which offers a lot more possiblities and allows proper encapsulation of information transfer between panels.

It would be great if you could provide your working examples. I will try to work on a prototype with my approach as well and add it here.

User avatar
adaneau
Posts: 310
Joined: Tue Feb 21, 2012 9:49 am

Re: [3.16] UiConnect and triggerEvent

Post by adaneau »

Hi,

Raising interesting topic here. I also had my own look in the topic in the past years. Ideas was to build a MVVM.

So to give some answers from my own knowledge:

- You can access event in deeper nested modules, as far as you know the module name and the panel name. You can nest names like Module1.Module2....ModuleN.PanelName
- The method below requires the module and panel to exist which leads you to one of the point. You need your deepest module to send an "ack" in init to validate its existence to above modules (submodules can always access parent modules).
- I would advice to always go bottom up, it is more flexible (ie module call methods from parent).
- Event are disconnected when the containing panel is closed (panelOff, close module, close window)
- You can have global event which allows you quite interesting creations.

TL;DR : This is doable, biggest challenge is to know when event is accessible and thus when connect can be executed.

mikek10
Posts: 20
Joined: Wed Jun 26, 2019 4:05 pm

Re: [3.16] UiConnect and triggerEvent

Post by mikek10 »

I agree entirely with your logic relating to use of data points, I also shunned that idea for similar reasons.

So I have some nested panels, multiple instances of the lower level panels can exist within a higher level panel.

I had many issues relating to resizing of dynamically loaded panels appropriately, depending on how they are loaded the ability to resize and scale is changed, the method of referencing the panel for UIConnect is slightly different for each method of loading. So I would try to get the display sorted first before looking into the events which is contrary to how I would normally work. I generally used addSymbol to load the subPanels as this gave me the best results for my application.

Hopefully the below is enough to give you an idea, I have other examples if not? I have tried to skinny down the post by removing parts that aren't relevant, hopefully I haven't being over zealous. I did not need any code for disconnecting the events. Generally I perform UIConnect immediately after loading the panel (within the loop if appropriate) so the check is redundant. You do need to ensure that any existing instances of the panel with the desired name are removed prior to trying to load a new instance (if that makes sense), I used shapeExists for that:

Code: Select all

   for (int i=1; i<=99; i++)
   {
        if (shapeExists(myModuleName()+"." +myPanelName()+":position_"+(string)i))
        {removeSymbol(myModuleName(), myPanelName(), "position_"+(string)i);}

   }
I did find a bit of an issue with shapeExists in at least one version of WinccOA, it generates a warning in the log file if the shape does not exist, however the basic functionality works.

My lowest level panel is "clickArea" which essentially just displays some data and reports back a user mouse press so that the UI can take appropriate action.

The scopeLib for this panel is simply:

Code: Select all

int Segment;
int Place;

string area;

#event areaPressed(int segment, int place)

Clicking within this panel has the following:

Code: Select all

main(mapping event)
{
  triggerEvent("areaPressed",Segment, Place);

}

Several clickArea panels are loaded into a overview panel which has the ScopeLib:

Code: Select all

#event areaPressed(int segment, int place)

HandleClick(int segment, int place)
{
  DebugTN("Overview event", segment, place);
  triggerEvent("areaPressed", segment, place);
}

clickarea panels are loaded as below, storages is a list of custom structs containing data relevant to each individual instance:

Code: Select all

for(int i=1;i<=dynlen(storages);i++)

{
addSymbol(myModuleName(), myPanelName(), "clickarea.pnl", "area_"+storage.Name,
               makeDynString("$Name:"+storage.Name, "$Width:"+storage.OverviewWidth* scalefactorx,
                               "$Height:"+storage.OverviewHeight* scalefactory
                               , "$Segment:"+storage.Segment, "$Place:"+storage.Place
                               , "$FilePath:"+storage.ImagePath, "$Rotation:"+storage.Rotation
                               , "$X:"+(X-36), "$Y:"+(Y-32))
                               ,X,Y,storage.Rotation,0,0,"");

uiConnect("HandleClick", myModuleName()+"."+myPanelName()+":area_"+storage.Name, "areaPressed");

}


The overview panel is loaded into a newtrayview panel:

Code: Select all

 addSymbol(myModuleName(), myPanelName(), "Overview.pnl", "topOverview",
              makeDynString("$X:"+(600), "$Y:"+0, "$ScaleFactorX:"+scalefactorx,"$ScaleFactorY:"+scalefactory ),641,39,0,scalefactorx,scalefactory,"");

    uiConnect("HandleAreaPressed",  "topOverview", "areaPressed");

Code: Select all

HandleAreaPressed(int segment, int place)
{
  DebugTN ("New Area Selected By User", segment, place);

  Segment = segment;
  Place=place;
  //code removed 
}

mikek10
Posts: 20
Joined: Wed Jun 26, 2019 4:05 pm

Re: [3.16] UiConnect and triggerEvent

Post by mikek10 »

Also note this thread: viewtopic.php?f=15&t=11062

Functionality not working in 3.15, this may or may not also apply to 3.16.

moto3101
Posts: 37
Joined: Tue Aug 22, 2017 2:04 pm

Re: [3.16] UiConnect and triggerEvent

Post by moto3101 »

Thanks for your example, Mike!

I will look at it and try to create another prototype with the approach I had in mind.

Also, it would be great if one of the ETM colleagues would share his/her ideas on this topic :)

Post Reply
7 posts • Page 1 of 1