Difference between revisions of "Setting up a VISTA Printer"

From VistApedia
Jump to: navigation, search
(A new simpler way of doing GT.M pipes for printing)
(Setting Up a Printer in VISTA)
 
(23 intermediate revisions by 2 users not shown)
Line 2: Line 2:
 
__TOC__
 
__TOC__
  
=== A new simpler way of doing GT.M pipes for printing ===
+
This is an updated page. See [[Setting_up_a_Linux_Printer_Old|this page]] for old content.
The old way of doing GT.M pipes for printing requires you to use pre-open execute and post-close execute. This is a way to do it with just the open parameters.
+
 
 +
== Setting Up a Printer in VISTA ==
 +
In order to set-up a printer in VISTA, there are three steps:
 +
 
 +
* Add printer to CUPS or to Windows Printer list. The printers may be on remote servers, as long as the VISTA machine can access them.
 +
* In VISTA, you need to create an entry that represents the printer formatting characteristics in the terminal type file (#3.2)
 +
* Then you need to create an entry in the device file (#3.5) that corresponds to the printer
 +
 
 +
In practice, you don't need to do the second step because there are only about 5 commonly used subtypes in VISTA which you reuse.
 +
 
 +
A Subtype is a file entry that contains the code to send to the printer, to open the printer, reset the printer, select the page size, adjust the margins, select the font etc.
 +
 
 +
=== Subtypes ===
 +
 
 +
Information about subtypes, including the most common subtypes, is listed [[VISTA_Printing_Printer_Subtypes|here]].
 +
 
 +
=== Caché/Windows Printing ===
 +
When you specify a printer name in $I, Caché/Windows sends raw input directly to the printer, bypassing the driver. This makes setting up a printer on Windows easy:
 +
 
 +
<pre>
 +
NAME: BROTHER                          $I: |PRN|\\VXQA\HL2270DW
 +
  LOCATION OF TERMINAL: QA              SUBTYPE: P-HP-LASER
 +
  TYPE: TERMINAL
 +
</pre>
 +
 
 +
As you can see, all you have to do is put the printer name after |PRN| in $I. You can specify local printers; or you can specify shared printers using a UNC path (as shown above).
 +
 
 +
=== Caché/Linux Printing ===
 +
You can use Pipes in Cache to print on Linux/Unix. Here's an operative example. Based on my experience, this is the best way to do it.
 +
 
 +
<pre>
 +
NAME: SAM'S PHARMACY PRINTER            $I: /usr/bin/lpr -PSAN_FL6 -l
 +
  OPEN PARAMETERS: "QW"                SUBTYPE: P-HPLJ4SI-P12
 +
  TYPE: TERMINAL
 +
</pre>
 +
 
 +
Please note that there is a bug in DEVOK^%ZOSV (ZOSVONT) that prevents it from checking the device properly. This will show up if you misconfigure a device and then use it in Taskman. Short of fixing this, here is how to remove the bad prints from Taskman:
 +
 
 +
<pre>
 +
S (DEV,ZTIME,ZTSK)="" F  S DEV=$O(^%ZTSCH("IO",DEV)) Q:DEV=""  F  S ZTIME=$O(^%ZTSCH("IO",DEV,ZTIME)) Q:'ZTIME  F  S ZTSK=$O(^%ZTSCH("IO",DEV,ZTIME,ZTSK)) Q:'ZTSK  D DQ^%ZTLOAD
 +
</pre>
 +
 
 +
You can also use the method developed but not adopted by the VA in patch [http://foia-vista.osehra.org/Patches_By_Application/XU-KERNEL/XU-8_SEQ-485_PAT-585.TXT XU*8.0*585]. After attempting to use this method in production, I would recommend against it, because a. CPRS and BCMA code is not configured to pick up PQ devices and b. %ZISC has issues with PQ devices. I have fixed both of these issues; but the code for this is not in VISTA yet.
 +
 
 +
Here's a sample device that uses the XU*8.0*585 method:
 +
 
 +
<pre>
 +
NAME: PRINTER_NAME                          $I: PRINTER_NAME
 +
  PURGE OLD PRINT QUEUE FILES: YES      LOCATION OF TERMINAL: Cups Device
 +
  SUBTYPE: P-HP-LTR-POR-C17L7-W128-NOFF TYPE: PRINT QUEUE
 +
</pre>
 +
 
 +
=== Caché IP Direct ===
 +
Some cool way to do it, bypassing the operating system and talking directly to the printer.
 +
 
 +
<pre>
 +
NAME: ZEBRA                            $I: |TCP|101092252
 +
  LOCATION OF TERMINAL: XXXX
 +
  OPEN PARAMETERS: ("10.10.10.1":9100:"+Q+C"):2
 +
  SUBTYPE: P-ZEBRA                      TYPE: TERMINAL
 +
</pre>
 +
 
 +
=== GT.M/Linux Printing ===
 +
Pipes again; just like Cache.
  
 
<pre style="padding:1em;border:1px dashed #2f6fab;color:black;background-color:#f9f9f9;line-height:1.1em">
 
<pre style="padding:1em;border:1px dashed #2f6fab;color:black;background-color:#f9f9f9;line-height:1.1em">
 
NAME: PHAR-IP-DM                        $I: PHAR-IP-DM
 
NAME: PHAR-IP-DM                        $I: PHAR-IP-DM
 
   LOCATION OF TERMINAL: Inpatient Pharmacy Dot-Matrix
 
   LOCATION OF TERMINAL: Inpatient Pharmacy Dot-Matrix
   OPEN PARAMETERS: (shell="/bin/bash":comm="lpr -l -P PHAR-IP-DM 2>/dev/null":WRITEONLY)::"pipe"
+
   OPEN PARAMETERS: (shell="/bin/sh":comm="lpr -l -P PHAR-IP-DM 2>/dev/null":WRITEONLY)::"pipe"
 
   SUBTYPE: P-EPSON-DM-P15-5L
 
   SUBTYPE: P-EPSON-DM-P15-5L
 
   TYPE: TERMINAL
 
   TYPE: TERMINAL
Line 15: Line 78:
 
NAME: PHAR-IP-LS                        $I: PHAR-IP
 
NAME: PHAR-IP-LS                        $I: PHAR-IP
 
   LOCATION OF TERMINAL: Inpatient Pharmacy Landscape
 
   LOCATION OF TERMINAL: Inpatient Pharmacy Landscape
   OPEN PARAMETERS: (shell="/bin/bash":comm="lpr -P PHAR-IP -l":WRITEONLY)::"pipe"
+
   OPEN PARAMETERS: (shell="/bin/sh":comm="lpr -P PHAR-IP -l":WRITEONLY)::"pipe"
 
   SUBTYPE: P-HPLJ4SI-P13-LS
 
   SUBTYPE: P-HPLJ4SI-P13-LS
 
   TYPE: TERMINAL
 
   TYPE: TERMINAL
Line 22: Line 85:
 
NAME: PHAR-IP-POR-P12                  $I: PHAR-IP
 
NAME: PHAR-IP-POR-P12                  $I: PHAR-IP
 
   LOCATION OF TERMINAL: Inpatient Pharmacy Portrait (PL)
 
   LOCATION OF TERMINAL: Inpatient Pharmacy Portrait (PL)
   OPEN PARAMETERS: (shell="/bin/bash":comm="lpr -P PHAR-IP -l":WRITEONLY)::"pipe"
+
   OPEN PARAMETERS: (shell="/bin/sh":comm="lpr -P PHAR-IP -l":WRITEONLY)::"pipe"
 
MNEMONIC: PL
 
MNEMONIC: PL
 
   SUBTYPE: P-HPLJ4SI-P12                TYPE: TERMINAL
 
   SUBTYPE: P-HPLJ4SI-P12                TYPE: TERMINAL
Line 29: Line 92:
 
NAME: PHAR-IP-POR-P16                  $I: PHAR-IP
 
NAME: PHAR-IP-POR-P16                  $I: PHAR-IP
 
   LOCATION OF TERMINAL: Inpatient Pharmacy Portrait (MAR)
 
   LOCATION OF TERMINAL: Inpatient Pharmacy Portrait (MAR)
   OPEN PARAMETERS: (shell="/bin/bash":comm="lpr -P PHAR-IP -l":WRITEONLY)::"pipe"
+
   OPEN PARAMETERS: (shell="/bin/sh":comm="lpr -P PHAR-IP -l":WRITEONLY)::"pipe"
 
MNEMONIC: MAR
 
MNEMONIC: MAR
 
   SUBTYPE: P-HPLJ2-P16                  TYPE: TERMINAL
 
   SUBTYPE: P-HPLJ2-P16                  TYPE: TERMINAL
 
</pre>
 
</pre>
  
 +
=== How Does Printing from VISTA Work? ===
 
How does this work?
 
How does this work?
 
The way this works is that $I becomes the IO variable. The open
 
The way this works is that $I becomes the IO variable. The open
Line 39: Line 103:
  
 
Vista does this:
 
Vista does this:
<pre style="padding:1em;border:1px dashed #2f6fab;color:black;background-color:#f9f9f9;line-height:1.1em">
+
<pre>
 
S IO=[$I]
 
S IO=[$I]
 
S param=[OPEN PARAMETERS]
 
S param=[OPEN PARAMETERS]
Line 54: Line 118:
 
</pre>
 
</pre>
  
No need to do pre-open and post-close executes on the device which dynamically change IOs.
+
No need to do pre-open and post-close executes on the device which dynamically changes IOs.
 
 
=== GT.M pipe for print DEVICE (older way): ===
 
 
 
With the introduction of the pipe device to GT.M (version V5.3-003) this simple, secure, and elegant method can be used:
 
 
 
* To begin, [[Begin_Configuration_of_Vista#Update_the_Devices,_Start_Taskman_and_Mail_a_Message|Update the Devices]] file. To create a new DEVICE, enter an unused NAME of your choice.
 
 
 
                  NAME: HP-PHOTOSMART                   
 
                    $I: <pipe>
 
      PRE-OPEN EXECUTE: X "o ""p"":(command=""lpr"")::""pipe"" s IO=""p"""
 
    POST-CLOSE EXECUTE: X "c ""p"""                 
 
                SUBTYPE: P-OTHER80
 
                  TYPE: OTHER
 
 
 
Note: We use [[FILE_3.5|TYPE:OTHER]] rather than Host File Server. No host file needed; output will be "piped" to the default CUPS printer. Also the fancy stuff is in the PRE-OPEN EXECUTE. For example, one can write:
 
 
 
      PRE-OPEN EXECUTE: X "o ""p"":(command=""lpr -P Photosmart_@192.168.5.103 -o cpi=12 -o lpi=8 -o page-left=72"")::""pipe"" s IO=""p"""
 
 
 
In human (ok in geekspeak), this last PRE-OPEN EXECUTE says, "Open a pipe device named "p" with the command to print to the CUPS printer named "Photosmart_@192.168.5.103". Set it to give us 12 characters/inch, 8 lines/inch and a 1 inch left margin). And then set IO to that device."
 
 
FileMan will then send his output to that IO device, the just-defined pipe.
 
 
Finally, the POST-CLOSE EXECUTE simply closes the pipe. And it's gone. No Linux /tmp/print.txt file to clean up. No fuss, no muss.
 
 
 
Another option is to define the device with option raw:
 
PRE-OPEN EXECUTE: X "o ""p"":(command=""lpr -P 1100A -o raw"")::""pipe"" s IO=""p"""
 
And then the SUBTYPE can manage the details of formating... Portrait vs Landscape and fonts, etc.
 
----
 
==== [[pipe to identify CUPS printers]] ====
 
 
 
--[[User:JohnLeoZ|JL.Z]] Aug 2009
 
----
 
 
 
=== VistA output to a temporary Linux file (Calling ^TMGPRNTR) (older) ===
 
 
 
Below is an older way of setting up a Linux printer.
 
 
Here is the DEVICE file entry:
 
 
                        NAME: S121-LAUGHLIN-LASER
 
                          $I: <TO BE SET IN PRE-OPEN EX.>   
 
        LOCATION OF TERMINAL: Laughlin_Office
 
  SUPPRESS FORM FEED AT CLOSE: YES 
 
                  PAGE LENGTH: 70                 
 
            PRE-OPEN EXECUTE: SET IO='''$$GETJOBNM^TMGPRNTR()'''
 
          POST-CLOSE EXECUTE: DO '''FINISH^TMGPRNTR("laughlin_laser")'''
 
                      SUBTYPE: P-OTHER80         
 
                        TYPE: HOST FILE SERVER
 
 
 
Here are the supporting calls to routine ^TMGPRNTR that create a file for writing, and then send the output file to the Linux lpr system
 
 
 
GETJOBNM()
 
        ;"Purpose: To create a unique printer job name. 
 
        ;"        This will be used during a printing process
 
        ;"        that writes the printer file to the host file system,
 
        ;"        then passes file to Linux
 
        ;"        printing system.
 
        ;"Output: Returns name of file to put output into
 
       
 
        ;"UNIQUE will generate a filename based on time and job number
 
        ;"    i.e. 'Print-Job-628233034.tmp
 
       
 
        ;"write !,"here in GETJOBNM^TMGPRNTR",!
 
        new cJobs set cJobs="PRINT JOBS"
 
        new Filename set Filename=$$UNIQUE^%ZISUTL("/tmp/Print-Job.tmp")
 
       
 
        ;"Now store Filename for later transfer to Linux lpr
 
        new index set index=$order(^TMP("TMG",cJobs,$J,""))
 
        if index="" set index=1
 
        set ^TMP("TMG",cJobs,$J,index)=Filename
 
       
 
        ;"write !,"Print job name will be:",Filename,!
 
        quit Filename  ;"result returned by altering Filename
 
 
 
 
 
FINISH(Printer)
 
        ;"Purpose: to complete the printing process by sending the now-created file
 
        ;"        to Linux CUPS (the printing system).
 
        ;"Note: The lpr system itself will delete this print file when
 
        ;"      done (option -r)
 
        ;"Input: Printer OPTIONAL -- the name of the linux printer to send the job to.
 
       
 
        new cJobs set cJobs="PRINT JOBS"
 
        new index set index=$order(^TMP("TMG",cJobs,$J,""))
 
        new Filename set Filename=$get(^TMP("TMG",cJobs,$J,index))
 
       
 
        close IO
 
        kill IO(1,IO)
 
       
 
        kill ^TMP("TMG",cJobs,$J,index)
 
        if Filename'="" do
 
        . new CmdStr
 
        . set CmdStr="lpr "
 
        . if $get(Printer)'="" set CmdStr=CmdStr_"-P "_Printer
 
        . ;"option -r --> lpr deletes file after printing done.
 
        . set CmdStr=CmdStr_" -r "_Filename_" &"
 
        . ;"write !,"Here is where I call:",!,"ZSYSTEM "_CmdStr,!
 
        . zsystem CmdStr
 
        . ;"write "Back from zsystem.  Returning to Fileman.",!
 
       
 
        quit
 
 
 
--[[User:Kdtop|Kdtop]] 10:34, 18 Sep 2005)
 
----
 
=== '''Linux /tmp/file (With ZSYSTEM call)''' (older) ===
 
 
 
On a Linux system with CUPS.
 
 
 
                  NAME: PRINTSERVER                     
 
                    $I: /tmp/vistaprint.txt
 
  LOCATION OF TERMINAL: lpr         
 
            OPEN COUNT: 1
 
    POST-CLOSE EXECUTE: X "ZSYSTEM ""lpr -r /tmp/vistaprint.txt"""
 
                SUBTYPE: P-OTHER80               
 
                  TYPE: HOST FILE SERVER
 
 
 
And for an elaboration of this method
 
 
 
                  NAME: HP-PHOTOSMART                   
 
                    $I: <TO BE SET IN PRE-OPEN EXECUTE>
 
      PRE-OPEN EXECUTE: S IO="/tmp/"_$J_"print.txt"
 
    POST-CLOSE EXECUTE: X "ZSYSTEM ""lpr -P Photosmart_@192.168.5.103 -r /tmp/""_$J_""print.txt"""
 
                SUBTYPE: P-OTHER80
 
                  TYPE: HOST FILE SERVER
 
 
 
Note: This DEVICE does not require the calls to ^TMGPRNTR. And, by exposing the lpr call in the POST-CLOSE EXECUTE, it allows more flexibility. For example, this relatively simple change will direct output to the default CUPS printer with 12 characters/inch, 8 lines/inch and a 1 inch left margin. :
 
  
      POST-CLOSE EXECUTE: X "ZSYSTEM ""lpr -o cpi=12 -o lpi=8 -o page-left=72 -r /tmp/""_$J_""print.txt"""
+
=== Avoiding the Staircase Effect When Printing from GT.M/Caché on *Nix with Laser Printers ===
 
 
----
 
=== Avoiding the Staircase effect when printing from GT.M on *Nix ===
 
 
For an explanation of the Staircase effect, see this:
 
For an explanation of the Staircase effect, see this:
 
http://www.digitalissues.co.uk/html/os/unix/stair.html
 
http://www.digitalissues.co.uk/html/os/unix/stair.html
  
Basically, the new line doesn't do a carriage return with it, so our output just flows off the page. So when you print a 10 line document, you may only see one line, as the rest was printed outside of the margin.
+
Basically, the new line doesn't include a carriage return, so our output just flows off the page. So when you print a 10 line document, you may only see one line, as the rest was printed outside of the margin.
  
 
If you are sending raw output (lpr with the -l option) from VISTA to any PCL compatible printer (and VISTA by and large uses PCL for formatting plain text output), you need to add this to your open execute:
 
If you are sending raw output (lpr with the -l option) from VISTA to any PCL compatible printer (and VISTA by and large uses PCL for formatting plain text output), you need to add this to your open execute:
  
 
<pre style="padding:1em;border:1px dashed #2f6fab;color:black;background-color:#f9f9f9;line-height:1.1em">
 
<pre style="padding:1em;border:1px dashed #2f6fab;color:black;background-color:#f9f9f9;line-height:1.1em">
W $C(27),"&k2G".
+
W $C(27),"&k2G"
 
</pre>
 
</pre>
  
 
This tells the PCL compatible printer to append a CR to each LF or FF.
 
This tells the PCL compatible printer to append a CR to each LF or FF.
  
On the other hand, if you are asking cups to handle the formatting (lpr without the -l option), cups properly formats the line returns through a cups filter, so you don't have to do anything.
+
On the other hand, if you are asking CUPS to handle the formatting (lpr without the -l option), CUPS properly formats the line returns through a CUPS filter, so you don't have to do anything.
 +
 
 +
=== Advanced Printing Topics ===
 +
[[VISTA_Advanced_printing_topics|Advanced printing topics]]

Latest revision as of 18:01, 9 December 2016

Back to Programming VistA Issues

This is an updated page. See this page for old content.

Setting Up a Printer in VISTA

In order to set-up a printer in VISTA, there are three steps:

  • Add printer to CUPS or to Windows Printer list. The printers may be on remote servers, as long as the VISTA machine can access them.
  • In VISTA, you need to create an entry that represents the printer formatting characteristics in the terminal type file (#3.2)
  • Then you need to create an entry in the device file (#3.5) that corresponds to the printer

In practice, you don't need to do the second step because there are only about 5 commonly used subtypes in VISTA which you reuse.

A Subtype is a file entry that contains the code to send to the printer, to open the printer, reset the printer, select the page size, adjust the margins, select the font etc.

Subtypes

Information about subtypes, including the most common subtypes, is listed here.

Caché/Windows Printing

When you specify a printer name in $I, Caché/Windows sends raw input directly to the printer, bypassing the driver. This makes setting up a printer on Windows easy:

NAME: BROTHER                           $I: |PRN|\\VXQA\HL2270DW
  LOCATION OF TERMINAL: QA              SUBTYPE: P-HP-LASER
  TYPE: TERMINAL

As you can see, all you have to do is put the printer name after |PRN| in $I. You can specify local printers; or you can specify shared printers using a UNC path (as shown above).

Caché/Linux Printing

You can use Pipes in Cache to print on Linux/Unix. Here's an operative example. Based on my experience, this is the best way to do it.

NAME: SAM'S PHARMACY PRINTER            $I: /usr/bin/lpr -PSAN_FL6 -l
  OPEN PARAMETERS: "QW"                 SUBTYPE: P-HPLJ4SI-P12
  TYPE: TERMINAL

Please note that there is a bug in DEVOK^%ZOSV (ZOSVONT) that prevents it from checking the device properly. This will show up if you misconfigure a device and then use it in Taskman. Short of fixing this, here is how to remove the bad prints from Taskman:

S (DEV,ZTIME,ZTSK)="" F  S DEV=$O(^%ZTSCH("IO",DEV)) Q:DEV=""  F  S ZTIME=$O(^%ZTSCH("IO",DEV,ZTIME)) Q:'ZTIME  F  S ZTSK=$O(^%ZTSCH("IO",DEV,ZTIME,ZTSK)) Q:'ZTSK  D DQ^%ZTLOAD

You can also use the method developed but not adopted by the VA in patch XU*8.0*585. After attempting to use this method in production, I would recommend against it, because a. CPRS and BCMA code is not configured to pick up PQ devices and b. %ZISC has issues with PQ devices. I have fixed both of these issues; but the code for this is not in VISTA yet.

Here's a sample device that uses the XU*8.0*585 method:

NAME: PRINTER_NAME                          $I: PRINTER_NAME
  PURGE OLD PRINT QUEUE FILES: YES      LOCATION OF TERMINAL: Cups Device
  SUBTYPE: P-HP-LTR-POR-C17L7-W128-NOFF TYPE: PRINT QUEUE

Caché IP Direct

Some cool way to do it, bypassing the operating system and talking directly to the printer.

NAME: ZEBRA                             $I: |TCP|101092252
  LOCATION OF TERMINAL: XXXX
  OPEN PARAMETERS: ("10.10.10.1":9100:"+Q+C"):2
  SUBTYPE: P-ZEBRA                      TYPE: TERMINAL

GT.M/Linux Printing

Pipes again; just like Cache.

NAME: PHAR-IP-DM                        $I: PHAR-IP-DM
  LOCATION OF TERMINAL: Inpatient Pharmacy Dot-Matrix
  OPEN PARAMETERS: (shell="/bin/sh":comm="lpr -l -P PHAR-IP-DM 2>/dev/null":WRITEONLY)::"pipe"
  SUBTYPE: P-EPSON-DM-P15-5L
  TYPE: TERMINAL


NAME: PHAR-IP-LS                        $I: PHAR-IP
  LOCATION OF TERMINAL: Inpatient Pharmacy Landscape
  OPEN PARAMETERS: (shell="/bin/sh":comm="lpr -P PHAR-IP -l":WRITEONLY)::"pipe"
  SUBTYPE: P-HPLJ4SI-P13-LS
  TYPE: TERMINAL


NAME: PHAR-IP-POR-P12                   $I: PHAR-IP
  LOCATION OF TERMINAL: Inpatient Pharmacy Portrait (PL)
  OPEN PARAMETERS: (shell="/bin/sh":comm="lpr -P PHAR-IP -l":WRITEONLY)::"pipe"
MNEMONIC: PL
  SUBTYPE: P-HPLJ4SI-P12                TYPE: TERMINAL


NAME: PHAR-IP-POR-P16                   $I: PHAR-IP
  LOCATION OF TERMINAL: Inpatient Pharmacy Portrait (MAR)
  OPEN PARAMETERS: (shell="/bin/sh":comm="lpr -P PHAR-IP -l":WRITEONLY)::"pipe"
MNEMONIC: MAR
  SUBTYPE: P-HPLJ2-P16                  TYPE: TERMINAL

How Does Printing from VISTA Work?

How does this work? The way this works is that $I becomes the IO variable. The open parameters tells VISTA how to open the device.

Vista does this:

S IO=[$I]
S param=[OPEN PARAMETERS]
O IO:param
U IO
Send Open Execute from Subtype
U IO(0)
Interact with user; open another job, etc...
U IO
write write write
Send Close Execute from Subtype
C IO
etc.

No need to do pre-open and post-close executes on the device which dynamically changes IOs.

Avoiding the Staircase Effect When Printing from GT.M/Caché on *Nix with Laser Printers

For an explanation of the Staircase effect, see this: http://www.digitalissues.co.uk/html/os/unix/stair.html

Basically, the new line doesn't include a carriage return, so our output just flows off the page. So when you print a 10 line document, you may only see one line, as the rest was printed outside of the margin.

If you are sending raw output (lpr with the -l option) from VISTA to any PCL compatible printer (and VISTA by and large uses PCL for formatting plain text output), you need to add this to your open execute:

W $C(27),"&k2G"

This tells the PCL compatible printer to append a CR to each LF or FF.

On the other hand, if you are asking CUPS to handle the formatting (lpr without the -l option), CUPS properly formats the line returns through a CUPS filter, so you don't have to do anything.

Advanced Printing Topics

Advanced printing topics