anastaciocintra / escpos-coffee

Java library for ESC/POS printer
https://anastaciocintra.github.io/escpos-coffee
MIT License
280 stars 74 forks source link

How to make genral setting to find printer terminal with one command #74

Open mikebgrep opened 3 years ago

mikebgrep commented 3 years ago

I like the library but I can't understand how to set a method with witch will connect to the terminal printer.If the printer is network based with Ip and port or the printer is connected to laptop/pc with a cable I am not very familiar with the connection types.I need this for a project witch the user can use what terminal printer he have.I need with one general setting the user can connect the printer.I am open to any suggestions.

If I use this example I need to change only the printer name value with the name of actual printer

PrintService printService = PrinterOutputStream.getPrintServiceByName("printerName");
  PrinterOutputStream printerOutputStream = new PrinterOutputStream(printService);
  EscPos escpos = new EscPos(printerOutputStream);
  escpos.writeLF("Hello Wold");
  escpos.feed(5);
  escpos.cut(EscPos

if so what printers support can you give me live example for printer name

anastaciocintra commented 2 years ago

hi @mikebgrep, take a look at these links: https://github.com/anastaciocintra/escpos-coffee/wiki/OutputStreams

https://github.com/anastaciocintra/escpos-coffee-samples/blob/master/usual/getstart/src/main/java/GetstartSample.java

https://github.com/anastaciocintra/escpos-coffee-samples/blob/master/usual/tcpip-stream/src/main/java/TcpIpSample.java

mikebgrep commented 2 years ago

Thank you actually is very simple to configure.Just one more question do in this case will print correct I don't have printer to test: If not how to print data from arraylist pos

anastaciocintra commented 2 years ago

I don't know if it exists escpos printer emulator or simulator, but it is possible. For now, the best way to test it is sending the content to one "real thermal printer"

mikebgrep commented 2 years ago

Ok thank you I found emulator Just another question when i print the recipient when i don''t do escpos.close() it appear this in the emulator to much free space between each print (I don't know maybe is from emulator) and the name of the market got in cut_full section.If i close escpos.close(); I can't print again any hint here.Regards

<>M0My Market

Client: John Doe

Product Demo product 1 name x3 17.97


TOTAL 17.97

Date: 06-11-2021 Time: 12:06:57

mikebgrep commented 2 years ago

`M0E !"-0a12B My Market M0E ! -0a02B

M0E! -1a03 B RECEIPT M0E! -1a03 B -----------------
M0E ! -0a02B

M0E ! -0a02B Item Unit Price Amount M0E ! -0a02B ---------------------------------------- M0E ! -0a02B

M0E ! -0a02B Product Demo product 1 name 5.99 17.97 Product Promo Demo product 2 65.99 131.98 Product Promo Demo product 3 10.99 21.98

M0E ! -0a02B ---------------------------------------- M0E ! -0a02B

M0E! -0a03 B TOTAL 171.93 M0E ! -0a02B ---------------------------------------- M0E ! -0a02B Thank you for shopping with us
M0E ! -0a02B Have a nice day
M0E ! -0a02B `

this is my system.out output how do you think this will print ok on real printer?

anastaciocintra commented 2 years ago

Hi @mikebgrep If you want, you can share your piece of code, and I will print and will send one photo.

Just for fun ...

mikebgrep commented 2 years ago

Hello again @anastaciocintra Here is the code https://paste.ofcode.org/zdycXYvJQSWvXRpuLAzakE Thank you for support.

anastaciocintra commented 2 years ago

hi, @mikebgrep, for compiling purposes, I made some modifications

import com.github.anastaciocintra.escpos.EscPos;
import com.github.anastaciocintra.escpos.EscPosConst;
import com.github.anastaciocintra.escpos.Style;
import com.github.anastaciocintra.output.PrinterOutputStream;

import javax.print.PrintService;
import java.io.IOException;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;

class Order {
    public String tableNumber;
    public ArrayList<OrderProduct> products;
    public double totalPrice;

    public Order(String tableNumber, ArrayList<OrderProduct> products){
        this.tableNumber = tableNumber;
        this.products = products;
        totalPrice = 143.0;
    }
}

class OrderProduct {
    public String productCode;
    public String productName;
    public int productQty;
    public double productPrice;

    public OrderProduct(String productCode, String productName, int productQty, double productPrice) {
        this.productCode = productCode;
        this.productName = productName;
        this.productQty = productQty;
        this.productPrice = productPrice;

    }

    public double getPrice(int qty) {
        return this.productPrice *= qty;
    }

    @Override
    public String toString() {
        String productPriceStr = String.format("%.2f", productPrice);
        String qtyPriceStr = String.format("%.2f", productPrice / productQty);
        return "Product " + productName + " " + qtyPriceStr + "  " + productPriceStr + "\n";
    }

}

    public class MikebGrep {

    void printRecipent(String printerName){

//        public void loadData() {
            ArrayList<OrderProduct> products = new ArrayList();
            OrderProduct orderProd = new OrderProduct("4324", "demo product 1", 1,14.4);
            OrderProduct orderProd1 = new OrderProduct("4324", "demo product 2", 1,14.4);
            OrderProduct orderProd2= new OrderProduct("4324", "demo product 3", 1,14.4);
            products.add(orderProd);
            products.add(orderProd1);
            products.add(orderProd2);

            Order order = new Order("1", products);
//        }

        //this call is slow, try to use it only once and reuse the PrintService variable.
        PrintService printService = PrinterOutputStream.getPrintServiceByName(printerName);
        try {
            PrinterOutputStream printerOutputStream = new PrinterOutputStream(printService);
            EscPos escpos = new EscPos(printerOutputStream);

            Style title = new Style()
                    .setFontSize(Style.FontSize._3, Style.FontSize._3)
                    .setJustification(EscPosConst.Justification.Center);

            Style subtitle = new Style(escpos.getStyle())
                    .setBold(true)
                    .setUnderline(Style.Underline.OneDotThick);
            Style bold = new Style(escpos.getStyle())
                    .setBold(true);

            escpos.writeLF("My Business")
                    .feed(3)
                    .writeLF(subtitle, "       RECEIPT")
                    .writeLF(subtitle," -----------------             ")
                    .feed(2)
                    .writeLF("Item          Unit Price          Amount")
                    .writeLF("----------------------------------------")
                    .feed(2)
                    .writeLF(order.products.toString().replace("[", "").replace("]", "").replace(",", "") + "\n")
                    .writeLF("----------------------------------------")
                    .feed(2)
                    .writeLF(bold,
                            "TOTAL                            $" + order.totalPrice)
                    .writeLF("----------------------------------------")
                    .writeLF("     Thank you for shopping with us     ")
                    .writeLF("            Have a nice day             ")

                    .feed(8)
                    .cut(EscPos.CutMode.FULL);

            // do not forget to close...
            escpos.close();

        } catch (IOException ex) {
            Logger.getLogger(MikebGrep.class.getName()).log(Level.SEVERE, null, ex);
        }

    }

    public static void main(String[] args) {
        if(args.length!=1){
            System.out.println("Usage: java -jar getstart.jar (\"printer name\")");
            System.out.println("Printer list to use:");
            String[] printServicesNames = PrinterOutputStream.getListPrintServicesNames();
            for(String printServiceName: printServicesNames){
                System.out.println(printServiceName);
            }

            System.exit(0);
        }
        MikebGrep obj = new MikebGrep();
        obj.printRecipent(args[0]);

    }
}

mikebgrep_output

mikebgrep commented 2 years ago

Okay that's look kind of good just curious do the second receipt print the same.Because on the emulator cut paper command appear in the market name line.Thank you again is looking nice if you decide to test it with two recipient in a row message me if its ok or not.(Maybe is from emulator ).I see you close the escpos at the end when I do that i got java.io.IOException: Pipe closed and I can't print anymore what I need to do to print again I reuse tcpOutputStream.Thank you

mikebgrep commented 2 years ago

I am on Ubuntu maybe this is the problem I see same issue described

anastaciocintra commented 2 years ago

I see you close the escpos at the end when I do that i got java.io.IOException: Pipe closed and I can't print anymore what I need to do to print again I reuse tcpOutputStream.Thank you

Answer: Yeap, its necessary to close and its not reusable,

"Streams have a BaseStream.close() method and implement AutoCloseable, but nearly all stream instances do not actually need to be closed after use. Generally, only streams whose source is an IO channel (such as those returned by Files.lines(Path, Charset)) will require closing. Most streams are backed by collections, arrays, or generating functions, which require no special resource management. (If a stream does require closing, it can be declared as a resource in a try-with-resources statement.)"

the stream can be reused?

"A stream should be operated on (invoking an intermediate or terminal stream operation) only once. This rules out, for example, "forked" streams, where the same source feeds two or more pipelines, or multiple traversals of the same stream. A stream implementation may throw IllegalStateException if it detects that the stream is being reused"

source: https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html

in this case, you need to re-create the instance... you can make something like this:

            // another ticket ... another time...
            printerOutputStream = new PrinterOutputStream(printService);
            escpos = new EscPos(printerOutputStream);

            escpos.writeLF(title,"My Market")
                    .feed(3)
                    .write("Client: ")
                    .writeLF(subtitle, "John Doe")
                    .feed(3)
                    .writeLF("Cup of coffee                      $1.00")
                    .writeLF("Botle of water                     $0.50")
                    .writeLF("----------------------------------------")
                    .feed(2)
                    .writeLF(bold,
                            "TOTAL                              $1.50")
                    .writeLF("----------------------------------------")
                    .feed(8)
                    .cut(EscPos.CutMode.FULL);
            escpos.close();

            // another ticket ... another time...
            printerOutputStream = new PrinterOutputStream(printService);
            escpos = new EscPos(printerOutputStream);
            escpos.writeLF(title,"My Market")
                    .feed(3)
                    .write("Client: ")
                    .writeLF(subtitle, "John Doe")
                    .feed(3)
                    .writeLF("Cup of coffee                      $1.00")
                    .writeLF("Botle of water                     $0.50")
                    .writeLF("----------------------------------------")
                    .feed(2)
                    .writeLF(bold,
                            "TOTAL                              $1.50")
                    .writeLF("----------------------------------------")
                    .feed(8)
                    .cut(EscPos.CutMode.FULL);
            escpos.close();
anastaciocintra commented 2 years ago

Hey, did you find any escpos emulator? is it open source? can you share any tip with the us?

mikebgrep commented 2 years ago

Yes is this one https://github.com/dacduong/escpos-printer-simulator is working like tcpip terminal, Just run the jar file and set to port 9100 host localhost and its printing in emulator but its not like with real terminal printer

mikebgrep commented 2 years ago

Its work fine I miss to re-create the instance.

anastaciocintra commented 2 years ago

Yes is this one https://github.com/dacduong/escpos-printer-simulator is working like tcpip terminal, Just run the jar file and set to port 9100 host localhost and its printing in emulator but its not like with real terminal printer

good, thank you

anastaciocintra commented 2 years ago

Its work fine I miss to re-create the instance.

nice, count on me if you have any other problematic situation.

mikebgrep commented 2 years ago

@anastaciocintra I just noticed on your receipt amount of the products its not double instead of 14.40 is 1440 and end price must be 14.40 x 3 not $143.00 witch on the emulator is not like this.Can you make a test again the problem must be on that line order.products.toString().replace("[", "").replace("]", "").replace(",", "") + "\n") try to remove replace("," "") if its appear like this again.If you have time Thank you

Edit 143.00 is right but why dot in Amount and Unit Price don't show can you check this thank you

mikebgrep commented 2 years ago

@anastaciocintra can you propose some solution for printing from list not with the toString() method. Regards, Mike

anastaciocintra commented 2 years ago

Hi @mikebgrep, You are saying about transform one list of content like {item1, item2...} to something like:

(PRINTED CONTENT)
list of products:
- item1
- item2
- item3

isn't it?

mikebgrep commented 2 years ago

@anastaciocintra yes do you have a solution of it.With toString() method the values of the double don't show properly on the receipt.At least I see in the test you make for me.

anastaciocintra commented 2 years ago

Sure man, we have some, for example map with streams, but I think that your algorithm is pretty good and I made some little trick format adjusts , congrats, you have made a good printed receipt work!

receipt

import com.github.anastaciocintra.escpos.EscPos;
import com.github.anastaciocintra.escpos.EscPosConst;
import com.github.anastaciocintra.escpos.Style;
import com.github.anastaciocintra.output.PrinterOutputStream;

import javax.print.PrintService;
import java.io.IOException;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;

class Order {
    public String tableNumber;
    public ArrayList<OrderProduct> products;
    public double totalPrice;

    public Order(String tableNumber, ArrayList<OrderProduct> products){
        this.tableNumber = tableNumber;
        this.products = products;
        totalPrice = 143.0;
    }
}

class OrderProduct {
    public String productCode;
    public String productName;
    public int productQty;
    public double productPrice;

    public OrderProduct(String productCode, String productName, int productQty, double productPrice) {
        this.productCode = productCode;
        this.productName = productName;
        this.productQty = productQty;
        this.productPrice = productPrice;

    }

    public double getPrice(int qty) {
        return this.productPrice * qty;
    }

    @Override
    public String toString() {
        String productPriceStr = String.format("%.2f x %d", productPrice,productQty);
        String qtyPriceStr = String.format("%.2f", getPrice(productQty));
        return String.format("%-15s%12s   %10s",productName,productPriceStr, qtyPriceStr );
    }

}

    public class MikebGrep {

    void printRecipent(String printerName){

//        public void loadData() {
            ArrayList<OrderProduct> products = new ArrayList();
            OrderProduct orderProd = new OrderProduct("4324", "demo product 1", 1,14.4);
            OrderProduct orderProd1 = new OrderProduct("4324", "demo product 2", 2,30.4);
            OrderProduct orderProd2= new OrderProduct("4324", "demo product 3", 8,74.8);
            products.add(orderProd);
            products.add(orderProd1);
            products.add(orderProd2);

            Order order = new Order("1", products);
//        }

        //this call is slow, try to use it only once and reuse the PrintService variable.
        PrintService printService = PrinterOutputStream.getPrintServiceByName(printerName);
        try {
            PrinterOutputStream printerOutputStream = new PrinterOutputStream(printService);
            EscPos escpos = new EscPos(printerOutputStream);

            Style title = new Style()
                    .setFontSize(Style.FontSize._3, Style.FontSize._3)
                    .setJustification(EscPosConst.Justification.Center);

            Style subtitle = new Style(escpos.getStyle())
                    .setBold(true)
                    .setUnderline(Style.Underline.OneDotThick);
            Style bold = new Style(escpos.getStyle())
                    .setBold(true);

            escpos.writeLF(title,"Mikebgrep\n")
                    .writeLF(title,"C o f f e e")
                    .feed(3)
                    .writeLF(subtitle.setJustification(EscPosConst.Justification.Center), "R E C E I P T")
                    .feed(2)
                    .writeLF("Item              Unit Price      Amount")
                    .writeLF("----------------------------------------")
                    .feed(2);
            order.totalPrice =0;
            for(OrderProduct product: order.products){
                escpos.writeLF(product.toString());
                order.totalPrice += product.getPrice(product.productQty);
            }

            String total = String.format("$ %.2f", order.totalPrice);
            escpos.writeLF("----------------------------------------")
                    .feed(2)
                    .writeLF(bold,
                            "TOTAL                         " + String.format("%10s",total))
                    .writeLF("----------------------------------------")
                    .writeLF("     Thank you for shopping with us     ")
                    .writeLF("            Have a nice day             ")

                    .feed(8)
                    .cut(EscPos.CutMode.FULL);

            // do not forget to close...
            escpos.close();

        } catch (IOException ex) {
            Logger.getLogger(MikebGrep.class.getName()).log(Level.SEVERE, null, ex);
        }

    }

    public static void main(String[] args) {
        if(args.length!=1){
            System.out.println("Usage: java -jar getstart.jar (\"printer name\")");
            System.out.println("Printer list to use:");
            String[] printServicesNames = PrinterOutputStream.getListPrintServicesNames();
            for(String printServiceName: printServicesNames){
                System.out.println(printServiceName);
            }

            System.exit(0);
        }
        MikebGrep obj = new MikebGrep();
        obj.printRecipent(args[0]);

    }
}
mikebgrep commented 2 years ago

@anastaciocintra Thank you man that is awesome.I actually try one time to do for each loop in the builder but I don't know why everything was red.But this is proper receipt.Thank you again. ps: I was missing a ; to can make the for loop