Error in the gateway script

I am trying to write a gateway timer script but getting the following error:

AttributeError: ‘com.inductiveautomation.ignition.common.script.Imm’ object has no attribute ‘gui’

What can be the possible reasons for this type of error?

The gateway runs as a service and therefore has no GUI. No windows or templates or components or any visuals at all.

1 Like

I am reading and writing the tags in my script, inserting it into the database.

can you post your script?

1 Like

To expand on Phil a bit - you're trying to a call a system.gui.* scripting function from the gateway scope - which doesn't work. I'm not sure what you're doing, exactly; which is why having your script would be the most useful.

The error should give you a line number, however - whatever you're doing on that line will have to be changed to not use a system.gui function.

1 Like

Something that has bit me in the past is piling lots of useful functions in just one shared or project script. If there are client/designer scope imports in such a script to support gui stuff, and you try to call a generic function in the same script from gateway scope, the import for the other functions will break the entire script.
Try to keep your script modules organized by the scope(s) you intend to use them in.

3 Likes

Does this scope difference cause errors the other way around?:

I’m calling system.db.runQuery from a button event handler script
this query is a stored procedure I AM HAVINGtrouble getting to execute, more to the point is that when the button is pushed, the result of the stored procedure (inserts 1 row into mysql table) is not observed until roughly a minute later.
AttributeError: ‘com.inductiveautomation.ignition.designer.gui.tool’ object has no attribute 'RunQuery

Without the complete script and error, it is tough to be certain, but the capital 'R' is suspicious. Case matters.

Case matters indeed, that turned out to be the issue, although the script seems to execute some time after event fires. Really want to get the stored procedure to be run at login and be run as close to button press time as possible…Event handler script:

username = event.source.parent.getComponent('USN').text
print username



userIP = str(system.net.getIpAddress())

print("\n  *\n  *\n  *\n User IP was: ", userIP)

password = event.source.parent.getComponent('Password Field').text
print password
print("\n  *\n  *\n  *\n Validating user credentials")
success= system.security.switchUser(username,password,event)
print("\n  *\n  *\n  *\n fetching user roles.")	
roles = system.security.getUserRoles(username, password)
strmessage = ''

# Log the user's name and IP address for possible future troubleshooting.
if success:
	strMessage = str("\n\n  User [%s] successfully authenticated in from [%s] " % (username, userIP))
	print("\n  *\n  *\n  *\n Success: ", strMessage)
else:
	strMessage = str("\n\n  User [%s] failed to  authenticate from [%s] " % (username, userIP))
	print("\n  *\n  *\n  *\n No Success", strMessage)
	
	print("\n\n  ", strMessage)
	print(roles)
		


	if success and ("Controls User" in roles) and (userIPAddress.find("192.168.100.*") > 0):
		
		strSql = str('call log_message("%s")' % strMessage)
		print("\n\n $$  \n\n  ##\n\n  ^^\n\n  *\n\n  *\n\n **\n\n using SLQ stmt ", strSql)
		system.db.runQuery(strSql)

Please put triple back-quotes on lines by themselves above and below your code so we can read it. Like so:

```
Your code here
```

Edit your comment to include these, no need to repost.

I bet that's the actual source of the slowdown, not the query. Try using system.tag.read("[System]Client/IPAddress").value - the call to getIpAddress() is issuing a call out to a Java method that has to run native code to determine the actual IP address, and doesn't cache.

1 Like

Your final “if success” block is indented such that it is part of the else clause of the “if success” block above it. I have no idea how that runQuery is ever called.

Along with what both Paul and Phil said, print statements will slow down any scripting as well.

1 Like

Even if that block did execute it would croak

if success and ("Controls User" in roles) and (userIPAddress.find("192.168.100.*") > 0):

1) userIPAddress would raise a NameError (it's defined as userIP above), and b) str.find() does not work like that

My best unsolicited advice would be to drop all of the fluff on the debug output, it makes the code and output both needlessly difficult to read

def logToSQL(message):
	""" log stuff because knowledge is power """
	query = 'call log_message("%s")' % message
	print("running SQL query: %s" % query)
	system.db.runQuery(query)

username = event.source.parent.getComponent("USN").text
password = event.source.parent.getComponent("Password Field").text
userIP   = system.tag.read("[System]Client/Network/IPAddress").value

print("validating credentials") 
success = system.security.switchUser(username,password,event)
print("fetching user roles")
roles   = system.security.getUserRoles(username, password)
print(username, userIP, password, success, roles)


if success and "Controls User" in roles and userIP.startswith("192.168.100."):
	# % substitutions inherently stringify things
	logToSQL("User [%s] successfully authenticated from [%s]" % (username, userIP))

## is everything else a failure? are you wanting to log which type of failure?
elif not success:
	logToSQL("User [%s] failed to authenticate. Bad credentials")

elif not "Controls User" in roles:
	logToSQL("User [%s] failed to authenticate from [%s]. User does not have 'Controls User' role. Current roles: %s" % (username, userIP, roles))

elif not userIP.startswith('192.168.1.'):
	logToSQL("User [%s] failed to authenticate from [%s]. User not within the specified IP range" % (username, userIP))

@MMaynard

print statements will slow down any scripting as well

@shared.utility.timer
def printstuff(x):
	for i in range(x): print i
printstuff(1000)
{'calledBy': 'printstuff', 'response': None, 'runTime': 0.06399989128112793}

printstuff(5)
{'calledBy': 'printstuff', 'response': None, 'runTime': 0.0009999275207519531}

I mean... you're not wrong... :wink: