Writting values to a Text list looking at a DB

Hi,

I have a big DataBlock consisting of integer Tags(R001-R985 tag format). Each tag represents a value that I would like to write to with a multi-State button that writes 0 1 or 2. Is there a quick way first of all to create a text list displaying each tag of the DB so the user can navigate and select which tag to write to?

I am currently trying with text fields and numeric entries but doesn’t seem to be working. I have set biderectional indirect tag property on the button looking at a text field that the user can write the name of the tag but not able to write on the tag itself.

I.E user writes R0056 on the Text Field and then by pressing the 1of the 3 buttons next to it,should write the value 2 for instance on the R0056 Tag.

[default]/TestTags/{text} is binded on the Multi-State Button Request parameter i have created to write 0 1 or 2 for each of the 3 buttons.

I hope this makes sense.

If there is a different easier way to design this would be much appreciated.

Thanks

I would just use a dropdown list for this, unless you really need something more complex.
Based on your test tag path, I set this up:
screenshotiupEUU
The multi-state button has a straightforward indirect binding:


Formatting the data for the dropdown is the ‘hardest’ part, but isn’t actually too complicated. I’m using a feature of Python called a list comprehension here, but you can do it ‘imperatively’ as well:

	return [
		{
			"value": tag,
		 	"label": tag
		}
		for tag in ("R{:03d}".format(i) for i in range(1, 985, 1))
	]
	ret = []
	for i in range(1, 985, 1):
		tag = "R{:03d}".format(i)
		ret.append({
					"value": tag,
				 	"label": tag
		})
	return ret
2 Likes

Are the 2 scripts seperate transfrom scripts binded on the options property of the Dropdown?

It’s two separate scripts that do the same thing; the first is the way I’d do it (more idiomatic Python) but may be less readable if you’re not used to Python. The second is the more ‘imperative’ way, where you create the list, then modify it.

You only need one or the other.

1 Like

That looked very helpful indeed. However I might need to include more factors here. In my DB I have tags starting with different letters and not all of them increment properly. I think it is easier if I share my tag folder to see what I mean.
tags.json (303.5 KB)

Would it still be possible to implement that the same way or would it matter as my DB starts with a few Tags starting with letter A then further on with M and R etc. , considering positioning looking at the certain Tag starting on different letter.

For some reason starting from the MS button it game me InvalidPathSyntax Error as you see on the screenshot:

As you see my Tags also have more numbers(not R001 but R0001) would that be affected?

At the moment I am not able to do any changes on the DB so if not I will go the basic way creating 1024 Multi-State buttons :joy:

If you don’t expect the tags to change (often) you can do the easy thing; use a script to generate a hardcoded list of paths, copy it to the clipboard, then paste it onto the dropdown component’s value property:

import json

options = []
for tag in system.tag.browse("[default]Maint Requests"):
	options.append({"value": tag["name"], "label": tag["name"]})

print json.dumps(options)

image
You can directly paste any JSON string from the clipboard onto a Perspective property.

Hi Paul,

I appreciate your time on this but I’m not sure if I’m doing this properly.

I am not sure where to paste your script: ```import json

options =
for tag in system.tag.browse("[default]Pick Tower/Maint Requests"):
options.append({“value”: tag[“name”], “label”: tag[“name”]})

print json.dumps(options, indent = 2)``` as it throws me an error if I paste it onto “options” or “value”.

However I selected all 1024 tags from my Tagfolder I need to display on the dropdown component, copied as JSON, and pasted it onto the options as your screenshot. I do have all tags there not sure if on the very right format though. However I do see an error on the top right corner saying
" options:object found,array, dataset expected ".

Would that be why when I simulate it I am not able to find any of my tags when I search for them?

Would the first property of my dropdown “value” need any binding or editing?

Where would i have the MultiState button looking at in order to write “0”,“1” or “2” on any tags of the dropdown selected?

Thanks for your time

Take the script I posted and paste it into the script console.
Grab the output (not the >>> part before or after) and copy it to the clipboard.
Right click the 'options' element in the dropdown list and paste. If what you copied to the clipboard was correct, it should automatically create an option in the dropdown for each tag in the Maint Requests folder.

That's what I mean by doing it manually; this isn't an automated process where adding new tags will automatically update the dropdown. But, if you don't expect to add or remove tags very frequently, this is the easy way to get the information you want into the dropdown.

That would be handled by the indirect binding explained above. Notice that the 'Bidirectional' binding is checked. A normal binding will update its target property when the source (in this case, the tag) changes. A bidirectional binding does that, and the other direction - when the target property changes, so does the tag.

Can’t use cntr+A to mark it all and the output script ends like that so not sure If I am able to copy the right part?

Try removing the indent = 2 part of the code snippet so it doesn’t try to pretty-print the output.

import json

options =
for tag in system.tag.browse("[default]/Maint Requests"):
options.append({“value”: tag[“name”], “label”: tag[“name”]})

print json.dumps(options)

No luck…

screenshotiVGh9S
options.json (69.8 KB)

1 Like

Would this be implemented the exact same way if the dropdown was a multiselection one as I would need to select several tags and write them statically 0 1 or 2 and not change them until I stop them from the MSbutton if that makes sense? I believe that’s the reason I get error on my Multistate button on the indirect tag see below:

However it works perfectly only with single selection dropdown list.

If you want a multiselect dropdown, things immediately get a lot more complicated.

For one, what ‘Indicator Value’ would you display? You’re selecting multiple (possibly/probably contradictary) values - which one ‘wins’ and gets display on the HOA?
Also, as you noticed, writing will no longer work via a simple bidirectional binding. You have to use scripting to do the writing in that case.

A somewhat different option for the UI here:
Use a table, with an HOA button in a subview:
hoa-table.zip (30.3 KB)
screenshotJYsVZ2

This might not suit your needs, but there’s no ‘perfect’ paradigm to display (and control) ~1050 tags on the same screen, in my opinion.

1 Like

In fact, I will be able to use the single selection dropdown, it can be changed from the PLC code easily. thanks for the info though.

Last question for this, regarding on the script for inserting the integers from a DB onto a dropdown’s option property. Would that still work with a “document” data type as well? If not how would the script be changed?

Thanks for your support , it has been great help indeed!

You could modify that script to write the options directly to a document tag, yes. That might be a good way to run the browse operation periodically (so you always have an accurate list of tags in the dropdown) without too much performance impact (you don't want to be continuously calling a browse operation on a large flat folder for each Perspective session you have open).

Hi,

I am looking to create a table displaying the state of the tags. The table needs to display the name of the Tags as well as their states. So if a tag=0 print “OFF”, if tag=1 print “Slow Speed” and when tag=2 print “Production Speed”. Is there a quick way to implement this on the 1049 tags? Possibly by modifying the script above? If not would there be another way to achieve this task? Thanks

Yes, it would be possible using the script above, but it’s somewhat tricky to bring in ‘live’ values in that case. I would recommend hardcoding the list of tagpaths somewhere, (i.e. in a script library) instead of running browse each time you need to list out these tag’s values.
To get updated tag values you should issue a single system.tag.readBlocking for all 1049 values; this is vastly more efficient than reading one at a time.
So, you should have a structure in a project script (let’s call it constants):

maintenanceTags = [
    "R001",
    "R002",
    etc
]

Then on a table component, you could bring in the data in a variety of ways.
One would be an expression binding with a script transform. The expression isn’t very important, it’s basically just being used to fire a script.
The script would be something like this:

states = {
	0: "OFF",
	1: "Slow Speed",
	2: "Production Speed"
}

values = [qv.value for qv in system.tag.readBlocking(constants.maintenanceTags)]

options = []
for tag, value in zip(constants.maintenanceTags, values):
	options.append({
		"name": tag,
		"state": states.get(value, "Unknown")
	})

return options

You use a separate dictionary to encode the integer : state description mapping.

2 Likes