Making use of the MongoDB connector and the data type "class java.util.ArrayList" efficiently

I will start off and say that I am a novice at scripting, in general. We recently purchased a license for Ignition 8.1 and we have great big plans for it but first, we must crawl before we can run.

With that being said, I have been playing around with the events configuration in a perspective project where I have a blank text field and when I click into it, it executes some script that I wrote. I will paste that in at the end because it is a small amount of code.

I was happy to see that the script did what I was expecting it to do, however I don't know exactly how to deal with the result in this environment. I tried to use the eval() method but it does not like the time and date format that all of the mongdb documents have.

Ultimately I would like to use some of the information that I am pulling from these (FANUC) signals for a performance display board. This signal give us an indication of how much life our cutting tools have left in them and at what time we could expect our CNC machine(s) to stop running due to an expired cutting tool.

I was building something using nodeJS and what seemed to be a basket full of other web development technologies but we were not confident in its sustainability. Additionally we had been eyeing up ignition as a solution to things like this and other SCADA applications.

I'm happy to add information as need for this conversation. I imagine more experienced folk will wonder why I am doing the things I am doing at this point. Any sort of advice or guidance would be greatly appreciated!

Here is the tiny bit of script I put together for this test, it is an "onClick" mouse event

def runAction(self, event):
	system.perspective.print("Hello World")
	connector = str(system.mongodb.listConnectorInfo())
	connector = connector.replace("[", "")
	connector = connector.replace("]", "")
	res = eval(connector)
	
	for values in res.values():
		system.perspective.print(values)
	
	filter = {
		"L1Name": "MATS-2101",
		"signalname": {"$regex": "PMC_"}
	}
	documents = system.mongodb.find(res['name'], "L1Signal_Pool_Active", filter)
	system.perspective.print(type(documents))
	system.perspective.print(documents)

The time and date format used by monogodb is highlighted in this screen capture.

Tip:

1 Like

I don't know what you're trying to do with the eval stuff, but it looks like you're successfully getting back a List<PyDocument> from system.mongdob.find() like the documentation suggests.

What information are you trying to get out of those documents?

2 Likes

In other words, you should be able to just iterate over the values returned by these mongodb functions like any other Python sequence:

def runAction(self, event):
    system.perspective.print("Hello World")
    for connector in system.mongodb.listConnectorInfo():
        system.perspective.print(connector)

    f = {
        "L1Name": "MATS-2101",
        "signalname": {"$regex": "PMC_"}
    }

    for document in system.mongodb.find(res['name'], "L1Signal_Pool_Active", f):
        system.perspective.print(document)
1 Like

So I first used the eval() method to turn a string into a dictionary. That let me print out the values or keys individually or I can target them directly in subsequent lines of code. like I did when I ran the find() method on the mongodb.

I would like to get this filtered list to clean up nicely so I could do the same thing. These matsuura CNC machines have had some extra signals added that we can monitor. As an example, I will take 3 signals out of 1200 or so available to determine what tool is in pot 1 of the CNC machine, how many times that tool has been used, how many times it can be used, and how much time is left until it needs to be change. Each of our machines has 90 pots worth of tools.

Each entry in the list has some information related to a signal for a CNC machine. In the case of the first item it gives me the cutting tool number which is u'value':136

I'm not sure why the u is showing up, I've never seen that before.

{
u'TypeID': None,
u'Warning': None,
u'Error': None,
u'timespan': 0.0,
u'filter': None,
u'signalname': u'PMC_D20000_D_path1_MATS-2101',
u'enddate': None,
u'updatedate': Wed Jul 26 15:17:09 CDT 2023,
u'L1Name': u'MATS-2101',
u'_id': 64c17f4528269207206d9b81,
u'value': 136,
u'Judge': None
}

I have a feeling that someone is going to say "make a for loop"... I just wonder if there is a better way..

And there it is! I have nothing against writing for loops, and python makes them super easy from the looks of it.

That does clean up the text nicely when it is printed to console. I'll have to do some more reading on this stuff. But for now, that gets me one step further down the long road.

Thanks guys! I surely thought I was going to get roasted on my first post..

In general, while eval exists in Python, pretend that it doesn't. Same with exec, and even ast.literal_eval. They're conceptually evil, performance nightmares, and if you know enough to use them, you know enough to override my advice to never use them :slight_smile:

That's just an artifact of printing. The actual data inside the dictionary is a unicode Python string (instead of an ASCII Python string) so it's prefixed with the u. The actual data inside the string is what matters, and it's the same. You only get the u when you stringify the 'container' or call repr on the string.

2 Likes

Also note that the date you highlighted as being in a particular string format is not quoted. Meaning, it isn't a string. It is likely an actual date object that was stringified by your print operation, and therefore you cannot see its real nature.

Don't convert objects to and from strings unless you absolutely have to, or you are displaying to a user, or parsing user input. You should never be parsing the result from a database. MongoDB or otherwise.

1 Like

Got it, eval() no longer exists and don't parse the result from a database.

My real goal then should be to learn how to query properly so that I am getting only the result I am looking for... and NOT pulling the entire document (or row in a sql case) only to parse out what I want?

Then I can use that result in a perspective component to populate a table of data or to style a progress bar?

I do appreciate everyone's' patience and support, this is all great stuff for me. I am a one man show at the moment. My employer has not taken on something like this before, but as we grow I imagine ignition will start to play a larger roll in how we operate.

Just wanted to come back and close this thing out and say thanks for the guidance!

I took what you and @PGriffith said and put it to good use! Below I and running a "findOne" on the mongodb and assigning its value to a memory tag.

connector = system.mongodb.listConnectorInfo()
	
filter1 = {
    "L1Name": "MATS-2101",
    "signalname": {"$regex": "MacroVar_747"}
}

project = {
	"value":1,
}

document = system.mongodb.findOne(connector[0]['name'], "L1Signal_Pool_Active", filter1, project)
system.tag.writeBlocking("customTags/2100cell/currentMaterial_2101", document['value'])

I am starting to build something that will have our AGV change scrap bins if the material being machined changes while no one is in the building.

...still a long way to go yet.

2 Likes