Automatic Popups and Print jobs

I have this “PANELVIEW” made by a WONDERFUL company… lol… I am now trying to do away with it and replace it with a touchscreen computer.

The only REAL function of this PV is to display a flow chart based on an ALARM it recieves VIA MSG from a PLC5. So, 10 alarms = 10 different flowcharts. They automatically POPUP and display and THEN they print.

I would like to accomplish this with FPMI.

Any suggestions?

-Chris

Well, FactoryPMI isn’t going to directly consume messages from a PLC5. Your best bet would be to put a touch-computer out there and have the whole stack (OPC-FactorySQL-DB-FactoryPMI) and have [del]in[/del] it running one client.

Can you explain what you mean by flow-chart as it applies to alarms?

ok… lets say i have 10 alarms and each one requires you to take specific actions. I have already created sqltags for them by the way. For each alarm, exists a “slide” if you will created in visio. i can make it html or a picture or anything. what i need to do is trigger a POPUP window when an alarm becomes active. and in that window there will be a corresponding Slide that is specific for that alarm. Also, i will need it to print and then close the window. So lets say alarm happens, window opens, five seconds later it prints and then 5 seconds later it closes. Thats just an example. I am willing to do what it takes and I will understand if there are limitations

Oh, ok, I’m with you now. In this case its not very hard, other than the somewhat odd requirement of having 1 and exactly 1 FactoryPMI client running all the time.

You basically just need to run a timer script that is checking the current alarm state or monitoring the alarm log (via SQL queries) and opening the correct window, printing your flow chart, and closing it. You’ll want to make use of the fpmi.system.invokeLater function.

Here is a slight modification that will also hopefully simplify the process. I dont NEED a popup, I just need to FIRST have a dynamic property that lists the alarm, time and batch info as a header if you will. Second, print “SOME FILE” ie: picture, html, word…

So looking at the supposed printed page, at the top would be our header consisting of dynamic properties and below it would be our “Flow chart”.

A code snippet might also help me to understand how you propose I should go about this.

Thanks,

-Chris

The way I would go about this would be to add an extra column to the alarm log table, like
printed INTEGER DEFAULT 0

That way our script can definitively tell whether each alarm in the alarm log has been printed or not. Then you would run a timer script that went something like this:

[code]

Get a list of the alarms that have not yet been printed

alarms = fpmi.db.runQuery(“SELECT * FROM alarmlog WHERE printed = 0”)

for alarm in alarms:

Loop through the alarms, open a window associated with each one

and print it out.

id = alarm[“alarmlog_ndx”]
name = alarm[“item_name”]
window = (somehow associate name with a window to open)
def openAndPrint(windowName=window):
import fpmi
fpmi.nav.openWindow(windowname)
def printLater(windowName=windowName):
import fpmi
window = fpmi.gui.getWindow(windowName)
printJob = fpmi.print.createPrintJob(window.rootContainer)
printJob.showPrintDialog = 0
printJob.print()
fpmi.system.invokeLater(printLater, 5000)
fpmi.system.invokeLater(openAndPrint)

fpmi.db.runPrepStmt(“UPDATE alarmlog SET printed=1 WHERE alarmlog_ndx = ?”, id)[/code]

Hope this helps,

Awesome, Thank you Carl. Now, as with all thing, I want MORE. :smiley:

Instead of def printLater(windowName=windowName): import fpmi window = fpmi.gui.getWindow(windowName) printJob = fpmi.print.createPrintJob(window.rootContainer) printJob.showPrintDialog = 0 printJob.print()

I now am using a Report for my flowcharts and want to use the PRINT feature of the Report. LOL

[code]# Get a list of the alarms that have not yet been printed
alarms = fpmi.db.runQuery(“SELECT * FROM alarmlog WHERE printed = ‘0’ AND severity = ‘1’”)

for alarm in alarms:

Loop through the alarms, open a window associated with each one

and print it out.

id = alarm[“AlarmLog_ndx”]
name = alarm[“item_name”]
window = “Report”
def openAndPrint(Report=window):
import fpmi
fpmi.nav.openWindow(Report)
def printLater(Report=Report):
import fpmi
window = fpmi.gui.getWindow(Report)
printJob = window.getRootContainer().getComponent(‘Report Viewer’)
printJob.print()
fpmi.system.invokeLater(printLater, 1000)
fpmi.system.invokeLater(openAndPrint)
def closeAfterPrint(Report=window):
import fpmi
fpmi.nav.closeWindow(Report)
fpmi.system.invokeLater(closeAfterPrint, 5000)
fpmi.db.runPrepStmt(“UPDATE alarmlog SET printed=1 WHERE alarmlog_ndx = ?”, [id]) [/code]

I can now make the Report print, but now I can not specify “printJob.showPrintDialog = 0”
Any ideas?

Sure, the report.print() has some overloads, one of which supresses the dialog and takes the name of the printer to print to, or None for the default. You should also be able to close the window right after printing.

[code]# Get a list of the alarms that have not yet been printed
alarms = fpmi.db.runQuery(“SELECT * FROM alarmlog WHERE printed = ‘0’ AND severity = ‘1’”)

for alarm in alarms:

Loop through the alarms, open a window associated with each one

and print it out.

id = alarm[“AlarmLog_ndx”]
name = alarm[“item_name”]
window = “Report”
def openAndPrint(Report=window):
import fpmi
fpmi.nav.openWindow(Report)
def printLater(Report=Report):
import fpmi
window = fpmi.gui.getWindow(Report)
report = window.getRootContainer().getComponent(‘Report Viewer’)
report.print(None, 0)
fpmi.nav.closeWindow(Report)
fpmi.system.invokeLater(printLater, 1000)
fpmi.system.invokeLater(openAndPrint)
fpmi.db.runPrepStmt(“UPDATE alarmlog SET printed=1 WHERE alarmlog_ndx = ?”, [id])[/code]

Thank you very much, I have used the

print(None, 0) on other things before yet it seemed to have slipped my mind yesterday. LOL

I have been reading some other postings on the forum concerning printing, and have a question. Is it possible yet to SPECIFY the orientation in CODE?

Thanks,

-Chris

The orientation of a report is part of the design of the report - you set it in the report designer (the report panel’s customizer)

Thanks Carl.

Ok… Now the easy stuff is all working, when I get an alarm, the report pops up, it prints automatically, and the window closes.

NOW comes the hard part. First of all, when I have lets say 3 alarms come up at once, I notice the report pops up, prints then closes. I get three print outs, but I only see one popup. I am sure there is some TIMER or invoke later that I am missing, but I can’t be sure.

So, what I feel this global timer needs to do is only select ONE alarm at a time not select ALL, then once the query is ran, I need it to SOME HOW pass certain column info, like

id = alarm["AlarmLog_ndx"] name = alarm["item_name"]

into dynamic properties now contained in my report.

I already use a couple of windows that pass parameters to another window and OPEN said window. Of course this is “Configure action” and then using the NAV tab. But i imagine the code would be similar.

Used and proven in OTHER project:

# This script was generated automatically by the navigation
# script builder. You may modify this script, but if you do,
# you will not be able to use the navigation builder to modify
# this script without overwriting your changes.

param1 = event.source.parent.GanntTable

param2 = event.source.parent.getComponent('Filter').getComponent('Line').selectedLabel


fpmi.nav.swapTo('Delay Chart', {'GanntTable' : param1, 'linename' : param2})

Now, what i have tried but does not work (my Dynamic property I have in the report is ‘Alarm’:

# Get a list of the alarms that have not yet been printed
alarms = fpmi.db.runQuery("SELECT * FROM alarmlog WHERE printed = '0' AND severity = '1'")

for alarm in alarms:
   # Loop through the alarms, open a window associated with each one
   # and print it out.
   id = alarm["AlarmLog_ndx"]
   name = alarm["item_name"]
   window = "Report"
   def openAndPrint(Report=window):
      import fpmi
      fpmi.nav.openWindow(Report,  {'Alarm' : name}))
      def printLater(Report=Report):
         import fpmi
         window = fpmi.gui.getWindow(Report)
         report = window.getRootContainer().getComponent('Report Viewer')
         report.print(None, 0)
      fpmi.system.invokeLater(printLater, 1000)
   fpmi.system.invokeLater(openAndPrint)
   def closeAfterPrint(Report=window):
      import fpmi
      fpmi.nav.closeWindow(Report)
   fpmi.system.invokeLater(closeAfterPrint, 3000)
   fpmi.db.runPrepStmt("UPDATE alarmlog SET printed=1 WHERE alarmlog_ndx = ?", [id])

The error i get is

Traceback (innermost last): File "<TimerScript:alarm_log_print (20000) [Delay, Shared]>", line 12, in openAndPrint NameError: name

Thanks,

-Chris

Ok, here are some changes that will

  1. only do one at a time. Make sure to run the script slow enough so that each popup has time to open, print, and close before the script runs again.
  2. pass info into the window using parameters. See the user manual for more on passing parameters into windows.

[code]# Get a list of the alarms that have not yet been printed
alarms = fpmi.db.runQuery(“SELECT * FROM alarmlog WHERE printed = 0 AND severity = 1 LIMIT 1”)

if len(alarms)>0:
alarm = alarms[0]
id = alarm[“AlarmLog_ndx”]
name = alarm[“item_name”]
window = “Report”
def openAndPrint(Report=window):
import fpmi
# pass alarm name in as parameter to report window
fpmi.nav.openWindow(Report, {“alarmName”:name})
def printLater(Report=Report):
import fpmi
window = fpmi.gui.getWindow(Report)
report = window.getRootContainer().getComponent(‘Report Viewer’)
report.print(None, 0)
fpmi.nav.closeWindow(Report)
fpmi.system.invokeLater(printLater, 1000)
fpmi.system.invokeLater(openAndPrint)
fpmi.db.runPrepStmt(“UPDATE alarmlog SET printed=1 WHERE alarmlog_ndx = ?”, [id])[/code]

I used your code:

# Get a list of the alarms that have not yet been printed
alarms = fpmi.db.runQuery("SELECT * FROM alarmlog WHERE printed = 0 AND severity = 1 LIMIT 1")

if len(alarms)>0:
   alarm = alarms[0]
   id = alarm["AlarmLog_ndx"]
   name = alarm["item_name"]
   window = "Report"
   def openAndPrint(Report=window):
      import fpmi
      # pass alarm name in as parameter to report window
      fpmi.nav.openWindow(Report, {"Alarm":name}) 
      def printLater(Report=Report):
         import fpmi
         window = fpmi.gui.getWindow(Report)
         report = window.getRootContainer().getComponent('Report Viewer')
         report.print(None, 0)
         fpmi.nav.closeWindow(Report)
      fpmi.system.invokeLater(printLater, 1000)
   fpmi.system.invokeLater(openAndPrint)
   fpmi.db.runPrepStmt("UPDATE alarmlog SET printed=1 WHERE alarmlog_ndx = ?", [id])

Now i get the red error box with this in it:


Traceback (innermost last):
  File "<TimerScript:alarm_log_print (20000) [Delay, Shared]>", line 12, in openAndPrint
NameError: name

	at org.python.core.Py.NameError(Py.java)
	at org.python.core.PyFrame.getglobal(PyFrame.java)
	at org.python.pycode._pyx435.openAndPrint$1(<TimerScript:alarm_log_print (20000) [Delay, Shared]>:12)
	at org.python.pycode._pyx435.call_function(<TimerScript:alarm_log_print (20000) [Delay, Shared]>)
	at org.python.core.PyTableCode.call(PyTableCode.java)
	at org.python.core.PyTableCode.call(PyTableCode.java)
	at org.python.core.PyTableCode.call(PyTableCode.java)
	at org.python.core.PyFunction.__call__(PyFunction.java)
	at com.inductiveautomation.factorypmi.application.script.ScriptManager.runFunction(ScriptManager.java:255)
	at com.inductiveautomation.factorypmi.application.script.builtin.SystemUtilities$1.run(SystemUtilities.java:164)
	at java.awt.event.InvocationEvent.dispatch(Unknown Source)
	at java.awt.EventQueue.dispatchEvent(Unknown Source)
	at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
	at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
	at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
	at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
	at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
	at java.awt.EventDispatchThread.run(Unknown Source)

Oh, yeah, you’ll have to pass the alarm name into the scope of the print function, like this:

   def openAndPrint(Report=window, name=name):

Thanks… lol but before I got your reply, I tried this:

# Get a list of the alarms that have not yet been printed
alarms = fpmi.db.runQuery("SELECT * FROM alarmlog WHERE printed = 0 AND severity = 1 LIMIT 1")

if len(alarms)>0:
   alarm = alarms[0]
   id = alarm["AlarmLog_ndx"]
   name = alarm["state_name"] 
   time = alarm["active_time"]
   line = alarm["point_path"]
   item = alarm["item_name"]
   window = "Report"
   fpmi.nav.openWindow("Report", {"Alarm" : name, "active_time" : time, "line" : line, "item_name" : item})
   def openAndPrint(Report=window):
      import fpmi
      # pass alarm name in as parameter to report window
      def printLater(Report=Report):
         import fpmi
         window = fpmi.gui.getWindow(Report)
         report = window.getRootContainer().getComponent('Report Viewer')
         report.print(None, 0)
         fpmi.nav.closeWindow(Report)
      fpmi.system.invokeLater(printLater, 1000)
   fpmi.system.invokeLater(openAndPrint)
   fpmi.db.runPrepStmt("UPDATE alarmlog SET printed=1 WHERE alarmlog_ndx = ?", [id])

I know I am opening the window before i get to my “openAndPrint”, but other than that, is there anything wrong with doing it that way? Could it possibly cause problems?

Also on a related note, I have a STRING that I am passing to my report.
These are from the “point_path” column in the “alarmlog” table.
I will list 4 examples:
“L11 Lab Alarms/Lab_Alarm_02”
“L12 Lab Alarms/Lab_Alarm_02”
“L13 Lab Alarms/Lab_Alarm_02”
“L14 Lab Alarms/Lab_Alarm_02”

Based on those tags, I need to query only ONE of four tables:
“l11_batch”
“l12_batch”
“l13_batch”
“l14_batch”

[quote=“chris_d_sanders”]Thanks… lol but before I got your reply, I tried this
…[snip]…
I know I am opening the window before i get to my “openAndPrint”, but other than that, is there anything wrong with doing it that way? Could it possibly cause problems?[/quote]

Sounds fine to me.

[quote=“chris_d_sanders”]Also on a related note, I have a STRING that I am passing to my report…
Based on those tags, I need to query only ONE of four tables:[/quote]

I would have a query binding on that window whose table was dynamic, like:

SELECT * FROM {Root Container.TableName}

And have TableName be a dynamic string property on the root container that had an expression binding that resolved your point path to a table name (maybe using a switch expression)

Ok, I can now query other tables in MYSQL based off of my ACTIVE_TIME that I am passing to the report window, BUT I have one problem. I have 8 different tables:

l11_batch
l11_recipe
l12_batch
l12_recipe
l13_batch
l13_recipe
l14_batch
l14_recipe

I’m having a problem getting the right TABLE to query.
I am attaching the project so you can see my GLOBAL SCRIPT TIMER and my REPORT window.

I know that I am just having some sort of TIMING issue with it POPPING up the window, querying, and populating the dynamic properties and then print and close.

Just cant figure out HOW to fix it.
reportWindow.fwin (151 KB)
lab_alarms.fpmi (315 KB)

[quote=“chris_d_sanders”]I’m having a problem getting the right TABLE to query.
I am attaching the project so you can see my GLOBAL SCRIPT TIMER and my REPORT window.

I know that I am just having some sort of TIMING issue with it POPPING up the window, querying, and populating the dynamic properties and then print and close.

Just cant figure out HOW to fix it.[/quote]

Can you describe to me the problem you’re having. I don’t have your database so I can’t really run your project and figure out what problem it is that you’re talking about.