Self.props.params.value does not exists, but it does exists (?)

This is the error:

Traceback (most recent call last): File "", line 7, in transform AttributeError: 'com.inductiveautomation.perspective.gateway.script' object has no attribute 'value'. It's ocurring on a binding of a embedded view.

The parameters to the embedded view are 3:

{
	"label": "text",
B	"value": 0,			# indirect path to tag
B	"color": "#cf7911"	# indirect path and script
}

The color script:

1 def transform(self, value, quality, timestamp):
2	value = system.util.jsonDecode(value) # value: [{"0":"#cf7911"},{"75":"#ffff00"},{"90":"#58d68d"}]
3	low = value[0]
4	med = value[1]
5	good = value[2]
6
7	current = self.props.params.value
8
9	if current < int(med.keys()[0]):
10		return low.values()[0]
11	elif current < int(good.keys()[0]):
12		return med.values()[0]
13	else:
14		return good.values()[0]

Dependes on the value of "value" to set red, green or yellow (or what is configured in the tag).
Sometimes, and only sometimes, the line 7 gives out an error.

No idea why the reference is failing...

Any idea?
Thx!

Note: I just notice that the binding is not set to persistent. Could this be?

Use the property browser to find the actual path to the param.

The one you have looks wrong. Try self.view.params.value

Also, may I say that this transform looks overly complex for what it does ?
Why is value a list containing single-value dicts, instead of just a dict ?
Why are you passing json instead of an actual data structure ?
Where does this value come from ?

Also, I suggest you use a structure binding and bind to both params instead of pulling the value in the transform.

This seems like an XY problem. That transform scripts looks like it shouldn't be a thing and that you should be using expressions instead, but I could be wrong.

I’m confused how your two snippets tie together, and about your setup in general. Can you use screenshots of the important pieces instead?

What is self ?

Typical usage would not have params as a child of props, but as a child of view. That is, self.view.params.value (unless self is a view).

1 Like

This was it. As I could see, the value param is not loaded when the script is getting executed and that is why it gives an error.

Also, the params value is to the Embedded View. Is not referenced wrong.

self ← The Embedded Component
.props ← Insidide the component
.params ← The category
.value ← The value that we pass as parameter

1 Like

If anyone is still curious I could show you what I'm doing. ^^

2 Likes

I’m still not convinced there’s not a better way to do whatever it is you're doing, but at this stage I still don’t know what it is you’re trying to do :face_with_peeking_eye:

We have a gauge that could be from 0% to 100%.

The user can configure what is "bad", "regular" and "good".
For some product, for example, a 50% performance could be "good", but for other product 90% is "bad" and 95% is "good". The gauge needs to have the color of what is considered for that product.

[
    {"0": "#cf7911"},  # bad color
    {"75": "#ffff00"}, # regular color
    {"90": "#58d68d"}  # good color
]

In this case, the bad goes from 0 to 74, regular from 75 to 89 and good from 90 upwards.
It's an array so I always know in what position is the bad, regular and good and the key for that dictionar is the value of the range.

In the gauge I have 2 params, the value and the color. Before the color property needed the value property to execute (inside of the script). So sometimes when the script was trying to execute, it will search for the "value" property and it will fail.

Now the value property is in a custom (indirect path), the color property is in a custom (indirect path), and the bindings for the gauge are expression structure that look for the custom.

Note: As you could see there is a "params". This is because the gauge is inside another view, so we use an embedded view and the params are passed to the gauge inside the view.

Hope I explain myself now ^^

I suggest this to make things clearer:

{
	'bad': {
		'threshold': 0,
		'color': '#cf7911'
	},
	'average': {
		'threshold': 75,
		'color': '#ffff00'
	},
	'good': {
		'threshold': 90,
		'color': '#58d68d'
	}
}
def transform(value):
	if value.value >= value.thresholds['good']['threshold']:
		return value.thresholds['good']['color']
	elif value.value >= value.thresholds['average']['threshold']:
		return value.thresholds['average']['color']
	else:
		return value.thresholds['bad']['color']

We are at a point in the project that changes like that can't be done. I promise you I trully regret a lot of things I did in this project and that I would change.

If I can in the future I will try to do it in another way.

Thanks for the feedback!