Calling a cicode function from a page event doesn't work at times

Further to an earlier post about passing a cicode global variable argument into a function that is called by a super genie graphic window, I have got all the code working properly thanks to the wonderful help from this community!

It seems now the problem I have is that the function is not always called when the supergenie window is called. I have created a variable on the supergenie window that tells me if the code has been executed and in some cases it has not.

The variable that is set true by the code, so I then created a 'while do' loop to try and execute the code continuously until the variable is set true.

I think the problem is that for some reason the page event doesn't always run when the page (supergenie) is called and leaves check variable false, indicating the code has not been executed.

I have read all the help documentation and believe everything is correct. The documentation notes that there can be issues when using the 'on page entry' event so I have used 'on page shown event'. I note that the 'while page shown' event does not at work at all and not sure why this is.

Any help appreciated

Regards

Daryl

  • Two possible causes I can think of right now:
    1. If no user is logged in when opening the page, the tag cannot be written to (standard security feature).
    2. The statements take too long (blocking) and the event is aborted while not finished. To overcome this you can put the statements in a cicode function and then call that function from the event using TaskNew().

  • In addition to moving the code to a function called by TaskNew, you could:

    1. Add the command: ErrSet(1) to the beginning of the function. That keeps citect from terminating the task if one of the commands causes a fatal error. 

    2. Add a TraceMsg() call to the beginning and end of the function. For example: 

    Tracemsg("TrendFn started");

    ...

    TraceMsg("TrendFn finished");

    That way you know for sure if the function gets called and finishes successfully. You could also check the return value from each BlockedTrnSetPen call or step into them in the debugger to make sure they are successful. 

    You could also consider using the Process Analyst trend viewer instead of the legacy trend viewer.

    With the legacy viewer, TrnSetPen will fail until the trend object initializes, which depends on the speed of the trend server and whether it is on the local machine. 

    Process analyst uses a different function to set pens and shouldn't have that problem. 

  • Patrick and Eric,

    Patrick,

    Thank you for your replies.

    I don’t think its login issue as the project start cicode logins the operators and they are never logged out.

    I did try calling the BlockedTrnSetPen function from the cicode where the TrnSetPen is called however it didn’t work because the TrnSetPen uses a negative AN number because the trendpage is super genie.

    Syntax

    TrnSetPen(nAN, Pen, Tag)

    AN:

    The AN where the trend is located.

    -1 - All trends on the current trend page.

    -2 - The function being called is using the special AN setup by the TrnSelect() function.

    The BlockedTrnSetPen wont work with a negative AN number so AVEVA’s recommendation was to call the function from the trend page so the actual AN number of the trend on that page can be used in BlockedTrnSetPen call arguments.

    Would using TaskNew() not give me the same issue of not being able to use the actual trend AN of the page in the BlockedTrnSetPen arguments?

     

    Eric,

    Apologies for programming ineptness but I’m a control engineer at core and not from a coding background.

    I implemented what I thought you suggested but cicode wont compile.

    Below is what I implemented.

    INT

    //PUBLIC

    FUNCTION

    ErrSet(1);

    TraceMsg("TrendFn started");

    BlockedTrnSetPen(INT hAN, INT nPen, STRING sTrend)

        INT timeout = 5000

        INT myhAN

        INT mynPen

        STRING mysTrend   

        INT sleepTime = 10

        INT error = -1

        INT elapsed = 0

        INT currentTime

        STRING sPenName

        INT ErrorVariable

        INT iTrendPenChkd = 0  

        mysTrend = sTrend

       myhAN = hAN

        mynPen = nPen

        error = TrnSetPen(hAN, nPen, sTrend)

        IF error = 0 THEN

            error = -1

            currentTime = SysTime()

            WHILE error <> 0 AND elapsed < timeout DO

                sPenName = TrnGetPen(hAN, nPen)

                ErrorVariable=IsError()

                IF sPenName = mysTrend THEN

                    error = 0

                    iTrendPenChkd = 1

                    TrendPenChkd = iTrendPenChkd

                ELSE

                    SleepMS(sleepTime)

                    elapsed = elapsed + SysTimeDelta(currentTime)

                END

            END

        END

        RETURN error

    TraceMsg("TrendFn finished");

    END

    Regards

     

    Daryl

  • Daryl,

    You need a name for your function for instance Test(), before you call the ErrSet(1);

  • Change:

    FUNCTION

    ErrSet(1);

    TraceMsg("TrendFn started");

    BlockedTrnSetPen(INT hAN, INT nPen, STRING sTrend)

    to

    FUNCTION

    BlockedTrnSetPen(INT hAN, INT nPen, STRING sTrend)

    ErrSet(1);

    TraceMsg("TrendFn started");

  • Thanks again for your help

    I have successfully added the trace messages as suggested.

    I have used the debugger to step through the code on the SCADA servers and looks to be working perfectly.

    The problem is only on the workstations which to not have studio installed, hence no access to debugger where the problem is occurring.

    The TraceMsg help says Displays a message in the Kernel and Debugger debug windows. Do you know which kernel window ?

    kindest regards

    Daryl

  • I've had problems like this associating trends top popups on page entry for decades.  Always solved it in a similar way - keep trying until it succeeds.  I suspect it may be taking some time to initialise the trend object or something.  ¯\_(ツ)_/¯

  • Hi Patrick, for No.1 when user is logged out, can this be allowed to run cicode when a user is logged out? I need a heartbeat to PLC running always to let the PLC know the client is online.

  • Running cicode will work when no user is logged in, but writing tags will not.

    To overcome this, there are a few options. I will list them in order of security (least secure at bottom):

    1. Create a mechanism on a server component (report server for example) that will check for online clients and set variables accordingly. This is the most secure, but also the most difficult solution.

    2. Create a dummy Role and User with no privileges and areas. On every Client, create a startup cicode script that will log in this user by default. Also make sure you create an alternative logout function as well that logs in this dummy user instead of logging out. This will allow clients to write to tags while "logged out".

    3. From the client call a function on a server component using RPC (ServerRPC / MsgRPC). The server function will write to the variable. For this you have to set "Allow RPC" to TRUE in configuration of the server component. Also, you have to create and use the dummy user and role descibed in option 2, and set "Allow RPC" to TRUE for this dummy Role as well.