SQL Bridge Transaction & Custom Module-Exposed Scripts

I’ve created two modules that expose functionality that I’m leveraging within scripts. I’d like to find a way to leverage this exposed functionality within a transaction. I’m trying to create a transaction such that …

[ul]

  1. A tag triggers the transaction to execute
  2. A method my module exposes through script will be called, providing a value.
  3. The value generated by the method call will be pushed into another tag.
    [/ul]

Just as an initial test, I’ve tried the following …

[ul]

  1. Create a script module that def’s a method, performs an import, then returns the results of a call to my method

def getUuid(): import blah.bleh.bluh return blah.bleh.bluh.getUuid()2. Created a transaction and create an Expression Item. Within the Expression/SQL tab, I added a call to runScript() that calls the script module’s method.runScript("app.module.getUuid()")
[/ul]
When I attempt this, the item has an error when evaluating …

[code]com.inductiveautomation.ignition.common.expressions.ExpressionException: Error executing script for runScript() expression:app.module.getUuid()
Caused by: Traceback (most recent call last):
File “expression:runScript”, line 1, in
File “module:module”, line 2, in getUuid
ImportError: No module named blah

Caused by: Traceback (most recent call last):
File “expression:runScript”, line 1, in
File “module:module”, line 2, in getUuid
ImportError: No module named blah[/code]
If it helps, I’m using the addScriptModule() of the ScriptManager to expose things via script, (using RPC).

Thanks!

That last line got me. How exactly are you adding these to the script manager? From what hook? where?

[quote=“Carl.Gould”]That last line got me. How exactly are you adding these to the script manager? From what hook? where?[/quote]Sorry, just now noticed you responded to this …

Within our classes that extend AbstractGatewayModuleHook, AbstractClientModuleHook & AbstractDesignerModuleHook, we’re overriding the initializeScriptManager() method and calling addScriptModule() … @Override public void initializeScriptManager(ScriptManager manager) { super.initializeScriptManager(manager); manager.addScriptModule("potato.spuds", new ModuleRpcProxy()); }Ultimately, I’m trying to call methods from classes within my module using runScript() within a Triggered Expression Item in a transaction.

I was actually playing with this earlier and took our custom modules out of the equation entirely. I created a Script Module app.potato def getSpuds(): return "SPUDS!"I created a transaction, added a Run-Always Expression Item and set the expression to … runScript("app.potato.getSpuds()")I got an Evaluation Error. Looking at the Console, the error message was similar to the one I mentioned earlier, just complaining about No module named ‘app’. I tried creating an Expression Tag using this same expression, wasn’t successful. I created a Window, threw on a Label and bound the Label’s Text property to the expression … that worked. So, all that said, I’m assuming that a Script Module just isn’t available within a transaction’s execution scope?

Hmm, I just did a quick test, creating a custom script and calling from a group, and it was fine. The strange thing is that it’s telling you it can’t find “app”… if I deliberately set my name wrong, it is pretty specific in saying that there is no function by that name.

This is 7.4, right? On your simple test, is your module still trying to load its script modules? I’ll have to track down where app gets loaded and see if there is any conceivable way it could get lost.

Regards,

I just shifted to a different server/install and created the simple example (without my module) … works just fine :scratch: … both are running 7.4.2 (b953).

I’ll try to find time to create a simplistic module that illustrates the issue I’m having as opposed to using the full implementation of what I’ve got now, see if I can reproduce the issue … now to find time to actually do that …

Just thought I’d chime in here:

When you load your “potato.spuds” script manager into the ScriptManager, you access it at “potato.spuds”, not “app.potato.spuds”.

[quote=“Kevin.Herron”]When you load your “potato.spuds” script manager into the ScriptManager, you access it at “potato.spuds”, not “app.potato.spuds”.[/quote]Yeah, I’m accessing it with that approach within the Script Module def. The Expression Item’s call to runScript() is referencing the def, that’s where “app” comes into play.

I’ve created two dummy modules and I’m slowly adding to them to see where I’m going astray. So far, I’ve been able to get things working using the code I’ve listed below. Previously, I was making calls using RPC within the Expression Item. If a transaction’s executed on the Gateway, would this cause issues?

com.potato.Tader

[code]package com.potato;

import java.util.Random;
import java.util.UUID;

public class Tader {

public Tader() {}

public static Integer getCount() {
	return new Random().nextInt(100000);
}

public static String getString() {
	return UUID.randomUUID().toString().substring(0, 5);
}

}[/code]
com.potato.hooks.PotatoClient

[code]package com.potato.hooks;

import com.inductiveautomation.factorypmi.application.runtime.AbstractClientModuleHook;
import com.inductiveautomation.ignition.common.script.ScriptManager;
import com.potato.Tader;

public class PotatoClient extends AbstractClientModuleHook {

@Override
public void initializeScriptManager(ScriptManager manager) {
	super.initializeScriptManager(manager);
	manager.addScriptModule("com.potato.tader", Tader.class);
}

}[/code]
com.potato.hooks.PotatoDesigner

[code]package com.potato.hooks;

import com.inductiveautomation.ignition.common.script.ScriptManager;
import com.inductiveautomation.ignition.designer.model.AbstractDesignerModuleHook;
import com.potato.Tader;

public class PotatoDesigner extends AbstractDesignerModuleHook {

@Override
public void initializeScriptManager(ScriptManager manager) {
	super.initializeScriptManager(manager);
	manager.addScriptModule("com.potato.tader", Tader.class);
}

}[/code]
com.potato.hooks.PotatoGateway

[code]package com.potato.hooks;

import com.inductiveautomation.ignition.common.licensing.LicenseState;
import com.inductiveautomation.ignition.common.script.ScriptManager;
import com.inductiveautomation.ignition.gateway.model.AbstractGatewayModuleHook;
import com.inductiveautomation.ignition.gateway.model.GatewayContext;
import com.potato.Tader;

public class PotatoGateway extends AbstractGatewayModuleHook {

@Override
public void initializeScriptManager(ScriptManager manager) {
	super.initializeScriptManager(manager);
	manager.addScriptModule("com.potato.tader", Tader.class);
}

@Override
public void setup(GatewayContext arg0) {}

@Override
public void shutdown() {}

@Override
public void startup(LicenseState arg0) {}

}[/code]
Script Module > app.potato

[code]def getString():
import com.potato.tader
return com.potato.tader.getString()

def getInteger():
import com.potato.tader
return com.potato.tader.getCount()[/code]

I’ve lost the thread - what’s going wrong now with the example code you posted?

[quote=“Carl.Gould”]I’ve lost the thread - what’s going wrong now with the example code you posted?[/quote]Nothing :slight_smile:

The last code I posted works just fine and will likely be the solution I’ll go forward with. I’m traveling for work now, intend to revisit this next week to see if I can reproduce the original problem I had. I think my problem was initially the functionality I was exposing to scripting via ScriptManager was setup to utilize RPC (was invoked using GatewayConnectionManager.getInstance().getGatewayInterface().moduleInvoke). When I took that out of the equation, my problems went away. I’m going to try re-introducing that back into the Expression Item I’ve got to see if that brings back the initial problems I had. If it does, I’ll provide you guys with further information. If not, I’ll mark this as resolved. Thanks!