Creating global variable in generateScript

Hello,
In my URCap I am trying to add a global variable, that should be set to e.g. ‘false’ every time the ProgramNode is run, i.e. the user pushes the ‘Play’ button.
Doing so should be possible with the VariableFactory as far as i understand. However, if I add the following code to my generateScript method and run my ProgramNode, I get a compile error, telling me that ‘testVariable’ is not defined. If I run the program again though, without changing anything, everything succeeds and i can see the ‘testVariable’ under the ‘Variables’ tab.
Am I missing something, or is this a bug? The documentation is a bit vague on the ‘generateScript’ part :slight_smile:

try {
    VariableFactory variableFactory = api.getVariableModel().getVariableFactory();
    GlobalVariable variable = variableFactory.createGlobalVariable("testVariable",
            api.getValueFactoryProvider().createExpressionBuilder().append("True").build());
    
    model.set("var", variable);        
     
} catch (VariableException e) {
    e.printStackTrace();
} catch (InvalidExpressionException e1) {
    e1.printStackTrace();
}

writer.appendLine("if testVariable == True:");
writer.appendLine("    popup(\"Hello\", \"Test\", False, False, blocking=True)");
writer.appendLine("end");

writer.writeChildren();

you run the Variable creation Block inside the generateScript Method so this will be called while running the program the first time. try using it in the constructor of your programnodecontribution or in the openview method.

1 Like

Yep, the point is that I want to create it (or at least modify it), everytime the program is run. If I put it in the constructor it will only be created once when the ProgramNode is created, and in the openView it will be created everytime I open the tab, which is also not the behavior I want.

you may define the variable inside the constructor (so you wont get the undefined exception) and assign it to a value inside the generateScript. I think another much easier way is to just assign the Variable (after it is defined) to False inside the generated URScript.
e.g. scriptWriter.appendLine(“yourVar = False”);

Creating the variable in the constructor and modifying it in the GenerateScript method unfortunately leaves me with the same problem, as the modification of the variable again happens after the script is generated - and therefore doesn’t happen until I run the program the second time.
I can’t put it in the generated script either, as the variable would be set every time the program loops and reads that piece of script, which is not what I want - I only want the variable to be set when the ‘Play’-button is pressed and the program is started.

Take a Look at @jbm’s example: Can urcap send and execute ur script within the program node? - #12 by jbm

You can use this class to send a urscript command when the button is pressed

Thanks, I actually thought that would have done the trick. But adding the line:

clientSendScript.sendToSecondary("global testVariable = False");

seems to create the variable in another instance(?).
If, for example, the line is added to the openView() method, the variable appears in the Variable tab (but all other variables disappear) when the tab is opened, and when the program is then run all the old variables reappear along with the original value of testVariable.

Furthermore I still don’t understand why my original solution doesn’t work - adding the global variable before generating the script when the program is started, should add the variable before running the URScript on the controller.

You can look up the example URCap for functionModel. I will give you details on how to use it. Essentially within the constructor of the program node you add functions to the function model. You would have a addFunction function to add a String functionName to function model. This is shown in the URCap example and another post I made in the past → [IMPLEMENTED] Adding variables - #8 by roman.reiner

So now on your program execution you can do something like this

writer.appendLine("def functionName(): ");
writer.appendLine(“local testVariable == true”);
writer.appendLIne(“return testVariable”);
writer.appendLine(“end”);

So now within the program tree of the UR you can just assign testVariable = functionName(). This method might not be what you’re looking for but there are a lot of issues that can arise from using global variables and using a local variable method with these functions is more secure so operators can not adjust boolean value. Within your URcap you can always adjust this value and set it within the function.