The way I do this is any component who has a value I care to scrape off a window, I give it a custom property called outValue
, bind that to data I want to get off the component, and then when I iterate components I try/except getting that value. That way you don't have to try/except getting text or getting data because what happens the moment you now need an integer or float value?
I put all these values into a dictionary of {'componentName':outValue, ...}
. I also then name my components to match my db columns - then I can feed this dictionary directly to named queries.
Here' sthe script I use - note that you can also add root container properties - if they have a _out_
suffix in their name, they will also be added to the dictionary
"""
Grabs all relevant data off of a window for database insert/updates.
"""
import com.inductiveautomation.factorypmi.application.components.BasicContainer
def parseContainer(rc, recursive=False, dataDictionary=None):
"""
Creates a dictionary that is to be used in conjunction of named queries.
Key values are the database column names, and the values are the database column values.
Looks to root container and grabs any custom properties that have a "_out_" prefix, strips that off an uses remained as the key name.
Iterates through all components and checks if there is an outValue. If so, the name of the component will be used as the key value,
and value of outValue as the value.
Args:
rc: root container of the window.
recursive: bool, if True, runs this same thing on any child containers down
dataDictionary: dictionary, key/values are added to this used in the case of recursive (though guess a coder could prepopultae a dictionary with other stuff
and feed it in if they so chose to but no real reason to)
Returns:
dictionary {"column_name_1":column_value_1, "columne_name_2":column_value_2, ...}
"""
if dataDictionary is None:
dataDictionary = {}
# Gets properties off of root container and parses name nicely
for prop in rc.properties:
propName = str(prop.getName())
if propName.startswith("_out_"):
keyName = propName.replace("_out_", "")
dataDictionary[keyName] = prop.getValue()
# Iterates through a flat window. Will need to modify this to search deeper into containers
for component in rc.components:
# Recursive step for inner containers
if isinstance(component, com.inductiveautomation.factorypmi.application.components.BasicContainer) and recursive:
parseContainer(component, dataDictionary=dataDictionary)
for prop in component.getProperties():
if str(prop.getName()) == 'outValue':
dataDictionary[component.getName()] = prop.getValue()
return dataDictionary
def getComponent(rc, nameOfComponent):
"""
Grabs a compoennt reference off of a given root container. Recursively searches for name. Returns first instance.
"""
if nameOfComponent=='rc':
return rc
else:
for component in rc.components:
if isinstance(component, com.inductiveautomation.factorypmi.application.components.BasicContainer):
getComponent(component, nameOfComponent)
if component.name == nameOfComponent:
return component
return None
Edit: Just noticing a few unused lines / unnecessary print statements you may want to remove.
I agree with your general idea of making a standardized way of scraping a window and this is my method after a few iterations of trying to do that.
Having said all that, I don't know that this is the right way to handle transalations.