run control manager with callback from class

Discussions about product bugs & problems!
Note: This is no replacement for the Official ETM Support!
Search

Post Reply
4 posts • Page 1 of 1
svhsvh
Posts: 6
Joined: Tue Sep 19, 2023 3:04 pm

run control manager with callback from class

Post by svhsvh »

Hi,

I try to make a logger which hooks a callback on an element of a datapoint type.
When I run the query connect from the main function of a test script, it works (the testscript keeps running in the process monitor, status 2):

Code: Select all

main()
{
  string query = "SELECT '_online.._value' FROM '*.el1.el2' WHERE _DPT = \"MyDpType\" ";
  dpQueryConnectSingle("doIt", FALSE, "User Data", query);

  delay(0,250); //delay to be sure all loggings appear in log viewer
}

void doIt(string userData, dyn_dyn_anytype ddaTab)
{
  DebugTN("test");
}
When I put the logger in a class in a seperate file, the script runs once and ends. It doesn't keep listening to value changes. The dpQueryConnectSingle call returns value 0.

Code: Select all

//file1
class Logger
{
  public void Start()
  {
    DebugTN("Starting Trip History Collector");

    string query = "SELECT '_online.._value' FROM '*.el1.el2' WHERE _DPT = \"MyDpType\" ";
    int result = dpQueryConnectSingle("doIt", FALSE, "User Data", query);

    DebugTN("Query Connect Result: " + result);
  }

  private void doIt(string userData, dyn_dyn_anytype ddaTab)
  {
    DebugTN("test");
  }
};

//file2
main()
{
  Logger mylogger;
  mylogger.Start();
  
  delay(0,250); //delay to be sure all loggings appear in log viewer
}

Why is the behaviour different?

Kind regards,
Stef

User avatar
hpuchegger
Posts: 86
Joined: Fri Oct 08, 2021 10:38 am

Re: run control manager with callback from class

Post by hpuchegger »

I am not sure either and asked our 'WinCC OA AI Assistant' located at the online documentation page. It tells me following:

>>

The behavior you're experiencing is likely due to the scope and lifetime of the Logger class instance in your script. When you create an instance of Logger in the main() function, it goes out of scope once the main() function completes, which can lead to the logger being destroyed and thus stopping the callback from being executed.

In your first example, the callback works because it is directly in the main() function, which keeps the script running and allows the callback to be triggered. However, in the second example, since the Logger instance is local to the main() function, it is destroyed when main() exits, which is why the dpQueryConnectSingle call returns 0, indicating that the connection was not successful.

To resolve this issue, you can make the Logger instance a global variable or keep it alive in a way that it does not go out of scope. Here’s an example of how you can modify your code:

//file1

Code: Select all

class Logger
{
  public void Start()
  {
    DebugTN("Starting Trip History Collector");

    string query = "SELECT '_online.._value' FROM '*.el1.el2' WHERE _DPT = \"MyDpType\" ";
    int result = dpQueryConnectSingle("doIt", FALSE, "User Data", query);

    DebugTN("Query Connect Result: " + result);
  }

  private void doIt(string userData, dyn_dyn_anytype ddaTab)
  {
    DebugTN("test");
  }
};
// Declare the logger as a global variable
Logger mylogger;

//file2

Code: Select all

main()
{
  mylogger.Start();
  
  // Keep the script running to listen for value changes
  while (TRUE) {
    delay(0, 250); // delay to be sure all loggings appear in log viewer
  }
}
In this modified version, mylogger is declared as a global variable, ensuring that it remains in scope for the duration of the script's execution. The while (TRUE) loop keeps the script running, allowing the logger to continue listening for value changes.

Make sure to adjust the logic according to your application's needs, especially if you want to implement a clean exit strategy for your script.

>>

Would be interesting if AI gave a useful hint here.

Br, Herbert

gschijndel
Posts: 373
Joined: Tue Jan 15, 2019 3:12 pm

Re: run control manager with callback from class

Post by gschijndel »

I guess that because no instance is passed to the connect function the instance is destroyed and therefore also the connect.

Try it with 'this' as object parameter before the callback function parameter. An example with a control++ class would be helpful in the documentation, but luckily it can be found in the library 'examples/classes/opcuaStructuredData.ctl'.

svhsvh
Posts: 6
Joined: Tue Sep 19, 2023 3:04 pm

Re: run control manager with callback from class

Post by svhsvh »

The solution was to make the logger object a global variable.

Using "this" as object parameter did not work for me.

Post Reply
4 posts • Page 1 of 1