Passing data between windows

I am still playing with your software. So far I find it fairly functional and friendly but as a beginner I stumble on something every now and then.

I have created a window where the user can assemble a dataset by selecting columns (thanks for the help!) from a couple of tables and restrict number of values based on date/time. He can then study this data in table format and a couple of statistical values. I have also created some windows containing the different chart types that you support (one per window) and a button on the main window for calling up each chart window. So far everything works fine.

I am, however, unable to find a working solution to passing the selection parameters to the child window containing the chart. The passed parameters should also update dynamically to reflect any modifications to selections on the parent window.

I have tried to read up on the documentation but I have not found anything that could be viewed as “global” (project common) data. I have also tried to use the parameter passing options available to fpmi.gui.openWindow (not dynamic I know) but I get barked at as soon as I reference variable data from the main window. I would like to stay away from using the SQL database for the parameters since such a solution will then need to handle a varying number of simultaneous users.

Sorry for being so long winded. A native English speaker could probably have described this in 5 or less lines.

Hope you can point me in the right direction!

Regards

/T

You definitely can do this by using passed parameters in windows. You are getting “barked at” simply because you are doing something wrong syntactically. If you post your script, I can take a look at it for you.

You should also check out this thread that talks about this very issue (passing parameters to a window based on table selection) http://www.inductiveautomation.com/forum/viewtopic.php?t=436

Also, take a look at the Skeleton Project goodie - it has examples of passing parameters as well. You can find it here: http://www.inductiveautomation.com/products/factorypmi/goodies/

Hope this helps,

Carl,

Thank you so much for the pointers. I studied the discussion in the thread and that sure did it for me. I guess my mistake was to try to reference the source components directly in the function call.

Still missing is the automatic updating of the parameters in the child window when the user changes something in the parent. If I understand it correctly the function call “openWindow” passes the parameters at call time only. Can you suggest a way to create dynamic updating of the passed parameter values?

I will now take some time and study the goodies section.

Regards

/T

Actually, the openWindow call (with parameter passing dictionary) opens the window, and then sets the parameters. If the window is already open, it will still set the parameters! So, you can simply use openWindow() in the parent window to re-set the parameters even if the window is already open.

Now, your idea of a project-global space for bindable properties is definitely a good one, and is part of a major upcoming feature we’re calling SQLTags.

Hope this helps,

Carl,

Yes I have noticed that the parameters get updated when performing an openWindow on an already open window. The drawback to using this is that the child window immediately moves to the front.

SQLTags sounds good!

Again, thank you for your support. I have a few more things I want to accomplish and there is a big risk that I will need additional help as I get stuck…

Regards

/T

Ah, yes, the window will be moved to the front. SQLTags will make this (and many other tasks) far easier.

Now, there is one other way to do this, but it isn’t as easy. You can write a global script module that has a function that the parent window calls when it wants to set these properties. The function then checks to see if the child window is open, and if so, writes the values into properties on the window. Not too hard, but involves a bit of scripting. I can help you with this if this is a route you want to take.

As always, questions are welcome,

I will take that as an excersice for the student to get my hands dirty and I will gladly accept your offer if and/or when I fail.

Regards

/T

If I might chime in-

I just did a quick test that seemed to work well for this:

Though “openWindow” brings the window to the front, you can use “getWindow” and “setPropertyValue” to do the same thing without changing focus.

I created a base window with a text box, and a window called “popup”. Popup has a property called “inVal”. I placed the following code in the PropertyChanged event of the text box:

if event.propertyName=='text':
	try:
		window = fpmi.gui.getWindow('popup')
		window.rootContainer.setPropertyValue('inVal', event.source.text)
	except:
		pass

The only trick to this code is the Try/except. Since getWindow throws an error if the window is not already open, we need to catch it so that a big error window isn’t display. The negative side to this is that if you have an error in your assignment code, you won’t see it. Therefore, I recommend leaving out the Try/Except handler when you’re first working on it, and then adding it back in.

UPDATE: I just read carl’s post, this is more or less what he’s talking about, except that it does it on a per-item basis. His solution of a central function where you pass all of the values to would be better, but hopefully this will get you started in that direction.

Hope this helps!

I sure am grateful for the competent support you guys provide and I will play with your suggestion later.

Having moved on a bit with my learning I am trying to create functionality that allows me to select several datasets and combine them into one dataset for display in the table discussed earlier and ultimately in graphs called up from the window containing the table.
As an example of the use for this I have historical data of performance for furnaces stored in a table. The information is stored daily and the user should be able to compare different furnaces or even the same furnace behaviour at different time ranges (how did it behave in September compared to July). So far I have managed to create the functions for:

  1. Selecting Tags (furnace ID)
  2. Select different start dates for each dataset
  3. Select the number of samples to retrieve
  4. Query the database for the datasets
  5. Combine the datasets into one dataset for display in a table

Still remaining to manage is (I have not even begun to try to push the data into a graph):

  1. Compensate for missing samples in a dataset by filling in the correct date and an invalid value
  2. Get the table component to be stable in column width when displaying varying Tag data in a column

Please do not laugh at my try at this. Here is the script for retrieving and combining the data:

root = fpmi.gui.getParentWindow(event).rootContainer
Col1Start = root.getComponent("Col1StartDateSelector").text
Col1Tag = root.getComponent("Col1TagSelector").selectedStringValue
Col2Start = root.getComponent("Col2StartDateSelector").text
Col2Tag = root.getComponent("Col2TagSelector").selectedStringValue
Col3Start = root.getComponent("Col3StartDateSelector").text
Col3Tag = root.getComponent("Col3TagSelector").selectedStringValue
Duration = root.getComponent("Antal").intValue
RepType = root.getComponent("RappTyp").selectedStringValue

Col1Query = "SELECT t_stamp, " + Col1Tag + " FROM orreforsdaily"
Col1Query += " WHERE t_stamp BETWEEN '" + Col1Start
Col1Query += "' AND ADDDATE('" + Col1Start + "', INTERVAL " + str(Duration - 1) + " " + RepType + ")"
Col1Query += "ORDER BY t_stamp ASC"
Col1Dat = fpmi.db.runQuery(Col1Query)

Col2Query = "SELECT t_stamp, " + Col2Tag + " FROM orreforsdaily"
Col2Query += " WHERE t_stamp BETWEEN '" + Col2Start
Col2Query += "' AND ADDDATE('" + Col2Start + "', INTERVAL " + str(Duration - 1) + " " + RepType + ")"
Col2Query += "ORDER BY t_stamp ASC"
Col2Dat = fpmi.db.runQuery(Col2Query)

Headers = ["Col1Date", Col1Tag, "Col2Date", Col2Tag]
Data = []
for i in range(Duration):
	Data.append([Col1Dat[i][0], Col1Dat[i][1], Col2Dat[i][0], Col2Dat[i][1]])

root.getComponent("Table").data = fpmi.db.toDataSet(Headers, Data)

Can you assist me, please?

Regards

/T

Hello,

Your code looks great! I think your approach on this is fine.

I’m assuming what you posted works already, and you need help with your remaining items.

Compensating for missing values: There are 2 approaches you could take here. One is to let SQL do this for you. This would involve making a table that held one row per unit of time that you are interested in and doing a left join with that table. That way, if your history table was missing a value for a date, the left join would ensure that the date was there and you’d get null for your values. If you’re new to SQL, left joins may sound intimidating, but they’re really not that that hard.

If you want to compensate for the missing values in script, I guess that in your loop you need to look at the values for that row in both datasets, and make sure that the dates are the dates that they should be. If they aren’t, you need to insert dummy values for that row. I think the SQL method might be easier.

Column width: if you adjust the column width in preview mode in the designer, it should stick when you save the window.

Graphing: this will actually be easier than the table. The graph component will happilly accept two different datasets, which means the graph can skip this entire dataset joining logic. The only trick will be to get different time periods to display on top of each other. The easiest way to do this is to add another X axis and map your two datasets to different X axes. The other way is to in your SQL query add the difference between the starting dates to the lower date value. This might give a more accurate overlap if there are missing values.

Hope this helps,

Thanks Carl,

Yes the code I posted does work.

My knowledge of SQL is minimal but I will try to create a table with dates and read up on “left join”. Do you have a good idea for creating all those dates automatically? It is two years worth of data and I hate the thought of typing them in manually!

For the table column widths I have set Auto-Resize Mode to “Off” and I have also adjusted the column widths in preview. The problem I have is that the set width somehow seems to be related to the data displayed in the column. If I adjust the column width when displaying the table column “V2FQI1” and then select “V3FQI1” the column width is reset. The funny thing is that if I re-select “V2FQI1” for display in this column it automatically adjusts back to the width I set when viewing the Tag the first time.

Regards

/T

OK, for filling in the table I would write a script to do it. You can do it in your favorite language, or in the FPMI scripting language with something like this:

[code]from java.util import Calendar
calendar = Calendar.getInstance()

Set the calendar to Jan 1st 2000, 00:00:00

calendar.set(2000, 0, 1, 0, 0, 0)

insert 10 years of data

for i in range(365*10):
date = fpmi.db.dateFormat(calendar.getTime(), “yyyy-MM-dd HH:mm:ss”)
query = “INSERT INTO MyDateTable (TheDate) VALUES (’%s’)” % date
fpmi.db.runUpdateQuery(query)
calendar.roll(Calendar.DAY_OF_MONTH, 1)[/code]

As far as the table widths, I’m afraid table widths are set statically based on the column. My advice would be to fill in your table with a select * in the designer so that you can set the column widths for each column. that way, in the runtime each column will have a width configured.

Hope this helps,

Thanks for the information. Should I understand “table widths are set statically based on column” such that the table width for a given column is remembered for every possible column name from the dataset? This is how it seems to work for me, since when I fill the table with data from a given table column it adjusts the width according to what I have set when displaying that table column before. If that is the case, is there then a limit to the number of unique such settings that can be “remembered”? Potentially I have somewhere around 2000 candidate column names.

Also many thanks for the date filling script. I now see that I must obviously read up on java as well so that I know about things such as the Calendar object.

Regards

/T

The table remembers the width of each column it sees at the time it was saved in the designer. As such, having 2000 possible columns is going to be awkward, to say the least. I’ll see what we can do about getting some scripting functionality in there to programmatically set the width of a column.

I wouldn’t worry about learning Java - heck, Python probably has similar functionality (to Java’s Calendar object), I’m just more familiar with Java so I use it from within Python because it is quicker for me.

Hope this helps,

Carl,

Either I do not understand what you write or I see an odd behaviour here.
Can I call you to sort this out?

Regards

/T

Sure, I’m extension 26