Welcome to our new forum
All users of the legacy CODESYS Forums, please create a new account at account.codesys.com. But make sure to use the same E-Mail address as in the old Forum. Then your posts will be matched. Close

Using VisuUserManagement Functions within a Program

kebek007
2021-04-16
2021-04-25
  • kebek007

    kebek007 - 2021-04-16

    Hello Forum,

    I am building a Visualization Library made out of custom Visualization Elements.

    Right now I would like to use the UserManagement functionality within my functions similar to the way it is used in the codesys library.

    For example:

    How could I call this function from User Management ?

    I have seen the post regarding the KeySwitch_VisuClient but I am still not sure how to really implement that. ( I also think it isn't the same thing I want to implement, but highlights a bit how the VisuUserManagement works)

    Could someone please provide more info regarding the best practices when using the VisuUserManagement function OpenLoginDialog for example.

    I would like to do something like this - For example the xFoo is set when a button is clicked:

    pClientData     : POINTER TO VisuElems.VisuStructClientData;
    xFoo : BOOL;
    
    IF xFoo = True THEN
        VisuUserManagement.OpenLogInDialog(pClientData := This^.pClientData)
    END_IF
    

    Basically I would like to pass the event to openLogInDialog. So far when I do this, I get a dialogbox which gets stuck and I can not manage to get rid of it. Mainly it is because I have yet not understood how the VisuUserManagement functionalities really tick, or maybe I am not handling it the way it is meant to be handled.

    I would appreciate any answer to this topic.

    Thanks,

    KBK

     

    Last edit: kebek007 2021-04-16
    • m.prestel - 2021-04-22

      Could you maybe explain why you dont want to use the input actions?

      Could you please describe what you are trying to do?

      Best regards,
      Marcel

       
  • kebek007

    kebek007 - 2021-04-21

    Ok after tinkering a little bit and I understood how this works. This opened other questions.

    so basically one has to get all connected clients by doing the following - This was taken from VisuClientIPAdresse_v1.1 Project so I do not take credit for that (but I will comment it):

    VisuElems.g_ClientManager.BeginIteration();
    
    // get next client 
    pClient := VisuElems.g_ClientManager.GetNextClient();
    
    WHILE pClientData <> 0 DO
        // as long as a client is available do
        IF( pClientData^.GlobalData.ClientType = VisuElems.Visu_ClientType.Targetvisualization )THEN
            pClientDatatTargetVisu := pClientData;  // assign it to a Global variable if its target visu
        ELSIF ( pClientData^.GlobalData.ClientType = VisuElems.Visu_ClientType.Webvisualization )THEN
                pClientDatatWebVisu := pClientData; // assign it to a Global variable if its web visu
        END_IF
    // get next client
        pClientData := VisuElems.VisuElemBase.g_ClientManager.GetNextClient();
    
    END_WHILE
    

    What I am trying to do is the following:

    1 - I have created a library with a drop down list (which is conform to our own Style)

    2 - I use an FB within the library that manages the click events

    -> I extend the click event function within my project in order to call the Login Dialog from the UserManagement library. Now here is the tricky part. Usually our display is given out to all the clients. We have a total of 1 Target Visualization and up to 2 Web Visualizations (we limited it for performance reasons).

    For the login event we would like however to differentiate between which request came from where. So if someone is on the target visu entering the credentials , the login dialogue doesn't pop up on our web visualization and vice versa.

    I added the Library VisuGlobalClientManager in order to use CURRENTCLIENTID. However I checked all the information and all Clients have the Currentclientid = -1.


    Am I missing anything ? why are all the currentclientid = -1 ? How can I get some kind of unique Identification based on a click event to know where the click came from, from Target Visu ? or WebVisu ?

     

    Last edit: kebek007 2021-04-21
  • barton - 2021-04-21

    I have struggled with this myself. My solution is to broadcast the dialog to all clients then, upon receiving confirmation from the active client, close the dialog on the remaining clients.

    Open the dialog on all clients:

    METHOD OpenWarningDialog
    VAR_INPUT
        DialogName: STRING(128);
    END_VAR
    
    VAR
        isDialogOpen: BOOL;
    
    //  visuMgr: VU.IVisualizationClientIteration;
        dlogMgr: VisuElems.IDialogManager;
        clientDataPtr: POINTER TO VisuElems.VisuStructClientData;
        warningDlog: VisuElems.IVisualisationDialog;
    END_VAR
    
    dlogMgr:= VisuElems.g_VisuManager.GetDialogManager();
    warningDlog:= dlogMgr.GetDialog(DialogName);
    
    VisuElems.g_ClientManager.BeginIteration();
    clientDataPtr:= VisuElems.g_ClientManager.GetNextClient();
    
    WHILE clientDataPtr <> 0 DO
        isDialogOpen:= VisuDialogs.VisuDlgUtil_IsDialogOpen(warningDlog, clientDataPtr, dlogMgr);
        IF (NOT isDialogOpen) THEN
            dlogMgr.OpenDialog(dialog:= warningDlog, pClient:= clientDataPtr, bModal:= TRUE, pRect:= 0);
        END_IF
        clientDataPtr := VisuElems.g_ClientManager.GetNextClient();
    END_WHILE
    

    Close the dialog on all remaining clients.

    METHOD CloseWarningDialog
    VAR_INPUT
        DialogName: STRING(128);
    END_VAR
    
    VAR
        isDialogOpen: BOOL; 
        //visuMgr: VU.IVisualizationClientIteration;
        dlogMgr: VisuElems.IDialogManager;
        clientDataPtr: POINTER TO VisuElems.VisuStructClientData;
        warningDlog: VisuElems.IVisualisationDialog;
    END_VAR
    
    dlogMgr:= VisuElems.g_VisuManager.GetDialogManager();
    warningDlog:= dlogMgr.GetDialog(DialogName);
    
    VisuElems.g_ClientManager.BeginIteration();
    clientDataPtr:= VisuElems.g_ClientManager.GetNextClient();
    
    WHILE clientDataPtr <> 0 DO
        isDialogOpen:= VisuDialogs.VisuDlgUtil_IsDialogOpen(warningDlog, clientDataPtr, dlogMgr);
        IF (isDialogOpen) THEN
            dlogMgr.CloseDialog(dialog:= warningDlog, pClient:= clientDataPtr);
        END_IF
        clientDataPtr := VisuElems.g_ClientManager.GetNextClient();
    END_WHILE
    
     

    Last edit: barton 2021-04-21
  • kebek007

    kebek007 - 2021-04-21

    @barton Thanks a lot for your answer. I'm afraid that is a nightmare. There is no way of identifying where the click came from ? either some kind of function which returns the ID ? do you know where the USERCLIENTID comes from and if it is somehow during initialization set? Or is it provided by the OEM ?

    Thanks

     
  • barton - 2021-04-21

    I'm going to use this to determine if a particular client is currently displaying the visualization that I'm interested in. You could use this if the the event that you are seeking takes place only on a certain visualization. Inside the loop previously posted, find the name of the current visualization:

        currentVisu: VisuElems.VisuElemBase.IVisualisation;
        currentVisuName: STRING;
        fullNameFlag: BOOL:= FALSE;
    
    WHILE clientDataPtr <> 0 DO
        currentVisu:= clientDataPtr^.GlobalData.LastVisu;
        currentVisuName:= currentVisu.GetName(fullNameFlag);
        isDialogOpen:= VisuDialogs.VisuDlgUtil_IsDialogOpen(warningDlog, clientDataPtr, dlogMgr);
        IF (NOT isDialogOpen) THEN
            dlogMgr.OpenDialog(dialog:= warningDlog, pClient:= clientDataPtr, bModal:= TRUE, pRect:= 0);
        END_IF
        clientDataPtr := VisuElems.g_ClientManager.GetNextClient();
    END_WHILE
    
     

    Last edit: barton 2021-04-21
  • m.prestel - 2021-04-22

    I am sorry but I dont really get what you are trying to do? Why is the input action not good enough? What trigger are you trying to use then? Why do you have to iterate over all clients?

     
    • kebek007

      kebek007 - 2021-04-22

      Hello @m.prestel,

      Why would I use this you ask?

      Well we have for example a drop down list that is custom (not the one from codesys) within a library that we also had for our use.

      This drop down list has been created to be very basic in use and has only the basic functionalities. Now if we want more functionalities we would extend the function block and handle click events through its method which we created.

      • Why is the input action not good enough:

      This is why we can not use the input action, otherwise we would copy the dropdownlist in our application and lose the sense of the library in the first place. Which for this case to call the login function would be the solution because I have wasted enough time on it.

      • What trigger are trying to use then ?

      According to which selected drop down list item then the login dialog will open only for the client that requested it. The other clients won't have another login dialog to see.

      • Why do you have to iterate over all the clients ?

      I actually don't want to. I just want to know how can I find out where did the request come from? If I use the input action within the properties of the visu element I would get that what I want to do. now why can't it work within iec code.

      This would have been avoided if everything is well documented. I am not convinced that I am the first person who wants to do something like this

       
      • m.prestel - 2021-04-22

        hey @kebek007,

        so you are using a visualization(drop down list) and a fb is containing all the logic. This is in a lib.

        I would assume that you then reference this visualization with a frame.
        Depending on your configuration, a specific element? would then react on a click and would try to open the login dialog.

        Then you could e.g. add an invisible input to your visualization and react to the click, if the configuration matches.

        If that is not an option and you call a function in the "Execute ST Code" action, just add an additional argument "pClientData" of type POINTER TO VisuElems.VisuStructClientData;

        If I am totally off, please attach a project archive.

        Best regards,
        Marcel

         

Log in to post a comment.