Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Printer Stop before execution of cut command. #254

Open
Jawadahmed200 opened this issue Dec 22, 2023 · 2 comments
Open

Printer Stop before execution of cut command. #254

Jawadahmed200 opened this issue Dec 22, 2023 · 2 comments

Comments

@Jawadahmed200
Copy link

Hello,
My Problem is when I want print 2 receipt of same data. it prints first receipt and execute cut command but after printing second receipt it stop before executing cut command. meaning that it does not cut second receipt. Could you please reagrding this issue. Sample code is below:

Main Window File


public partial class MainWindow : Window
 {
private static BasePrinter _printer;
 private static bool _hasEnabledStatusMonitoring = false;
private static bool _monitor = true;
private static ICommandEmitter _emitter;


 public MainWindow()
        {
            DataContext = this;
            InitializeComponent();
            _printer = PrintJob.InitializePrinter();
            
                    }

                }
            }
        }


/When Button click, receipt printing process start.

private void btnReceiptPrintingProcess_Click(object sender, RoutedEventArgs e)
        {
            _emitter = new EPSON();
            if (_monitor)
            {
                _printer.Write(_emitter.Initialize());
                _printer.Write(_emitter.Enable());
                _printer.Write(_emitter.EnableAutomaticStatusBack());
            }
            Setup(_monitor, _printer, _emitter);
            PrintJob.RecieptData(_saleMaster);
            _printer.Write(PrintJob.PrintReceipt(_emitter));
            _printer?.Write(_emitter.PartialCutAfterFeed(5));
            _printer.Write(PrintJob.CashDrawerOpenPin2(_emitter));
            _printer.Write(PrintJob.PrintReceipt(_emitter));
            _printer?.Write(_emitter.PartialCutAfterFeed(5));
            Setup(_monitor, _printer, _emitter);
        }



public void Setup(bool enableStatusBackMonitoring, BasePrinter printer, ICommandEmitter emitter)
        {
            if (printer != null)
            {
                // Only register status monitoring once.
                if (!_hasEnabledStatusMonitoring)
                {
                    printer.StatusChanged += StatusChanged;
                    _hasEnabledStatusMonitoring = true;
                }
                printer?.Write(emitter.Initialize());
                printer?.Write(emitter.Enable());
                if (enableStatusBackMonitoring)
                {
                    printer.Write(emitter.EnableAutomaticStatusBack());
                }
            }
        }

        private void StatusChanged(object sender, EventArgs ps)
        {
            var status = (PrinterStatusEventArgs)ps;
            if (status == null)
            {
                Console.WriteLine("Status was null - unable to read status from printer.");
                return;
            }
           
            if (status is not null && status.IsCashDrawerOpen is not null)
            {
                //IsCashDrawerOpen = status.IsCashDrawerOpen.Value;
            }
            if (status is not null && status.IsCoverOpen is not null)
            {
                //IsPrinterCoverOpen = status.IsCoverOpen.Value;
            }

            if (status is not null && status.IsPaperOut is not null)
            {
               // IsOutOfPaper = status.IsPaperOut.Value;
            }
          
            if (IsCashDrawerOpen)
            {
            //Show Cash Frawer Open Error
            }
        }

}

PRINT JOB CLASS


public static class PrintJob
    {
        public static bool IsCashDrawerOpen = false;

        private static SaleMaster _saleMaster;


        public static BasePrinter InitializePrinter(string comPort = "COM4", int baudRate = 115200)
        {
            return new SerialPrinter(portName: comPort, baudRate: baudRate);
        }


        public static void RecieptData(SaleMaster saleMaster)
        {
            _saleMaster = saleMaster;
        }
        public static byte[][] PrintReceipt(ICommandEmitter emitter)
        {
            List<List<byte>> list = new List<List<byte>>();


            list.Add(emitter.CenterAlign().ToList());
            list.Add(emitter.PrintImage(File.ReadAllBytes("receiptLogo.jpg"), true).ToList());
            list.Add(emitter.PrintLine().ToList());eceiptNo).ToList());
            //list.Add(emitter.PrintLine("0010013110230012").ToList());
            list.Add(emitter.PrintLine().ToList());
            list.Add(emitter.SetStyles(PrintStyle.FontB).ToList());
            list.Add(emitter.PrintLine("Abc Address").ToList());
            list.Add(emitter.SetStyles(PrintStyle.None).ToList());
            list.Add(emitter.PrintLine().ToList());
            list.Add(emitter.LeftAlign().ToList());
            list.Add(emitter.PrintLine("Receipt #: " + _saleMaster.InvoiceNo).ToList());
            if (_saleMaster.TableNo > 0)
            {
                list.Add(emitter.PrintLine("Table #: " + _saleMaster.TableNo.ToString("00")).ToList());
            }

            list.Add(emitter.PrintLine("Served By: " + _saleMaster.CreatedByName).ToList());
            list.Add(emitter.PrintLine("Date: " + _saleMaster.CreatedAt.ToString("dd/MM/yyyy HH:mm")).ToList());
            list.Add(emitter.PrintLine().ToList());
            list.Add(emitter.PrintLine().ToList());
            list.Add(emitter.SetStyles(PrintStyle.FontB).ToList());
            list.Add(emitter.SetStyles(PrintStyle.Bold).ToList());
            //list.Add(emitter.SetStyles(PrintStyle.DoubleHeight).ToList());



            list.Add(emitter.PrintLine("#-DESC                                     TOTAL").ToList());
            ///Items
            list.Add(emitter.PrintLine("------------------------------------------------").ToList());
            for (int i = 0; i < _saleMaster.SaleDetails.Count; i++)
            {
                int no = 1;

                var itemDescWithNo = no + " - " + _saleMaster.SaleDetails[i].SubCategoryTitle;
                if (itemDescWithNo.Length > 48)
                {
                    itemDescWithNo = itemDescWithNo.Substring(0, 48);
                    list.Add(emitter.PrintLine(string.Format("{0}{1}", itemDescWithNo.PadRight(38, ' '), _saleMaster.SaleDetails[i].SalePrice.ToString().PadLeft(9))).ToList());

                }
                else if (itemDescWithNo.Length <= 48)
                {
                    list.Add(emitter.PrintLine(string.Format("{0}{1}", itemDescWithNo.PadRight(38, ' '), _saleMaster.SaleDetails[i].SalePrice.ToString().PadLeft(9))).ToList());
                }

                if (!string.IsNullOrEmpty(_saleMaster.SaleDetails[i].CookingInstructions) && !string.IsNullOrWhiteSpace(_saleMaster.SaleDetails[i].CookingInstructions))
                {
                    list.Add(emitter.PrintLine("    *" + _saleMaster.SaleDetails[i].CookingInstructions.PadRight(38)).ToList());
                }


                list.Add(emitter.PrintLine().ToList());

            }

            byte[][] bytes = list.Select(i => i.ToArray()).ToArray();
            return bytes;


        }


        public static byte[][] CashDrawerOpenPin2(ICommandEmitter e) => new byte[][] {
            e.CashDrawerOpenPin2()
        };

        public static byte[][] CashDrawerOpenPin5(ICommandEmitter e) => new byte[][] {
            e.CashDrawerOpenPin5()
        };


    }

Could you please guide about this ? Thank you

@igorocampos
Copy link
Collaborator

Hi there, have you tried to use PartialCut() instead of PartialCutAfterFeed() ?
I would also give FullCut() a try. I know in theory it doesn't make sense that it's working on the first time, but not the second. However, some models of printers intake different combinations of bytes for the commands, and it may very well be that your printer is requiring an extra byte after that partial cut after feed. To verify this you could also have the printer print 3 receipts instead of 2, if my theory is correct, only the last partial cut would fail.

Now if you want, I do have other suggestions regarding your code and totally unrelated to your issue:
1 - In the below lines _printer will never be null, so you can drop the null checker. If by all means _printer is null you will get an exception thrown on the first line (the one without the null-checker).

 _printer.Write(PrintJob.PrintReceipt(_emitter));
 _printer?.Write(_emitter.PartialCutAfterFeed(5));

Same goes for the following lines inside your Setup method

printer?.Write(emitter.Initialize());
printer?.Write(emitter.Enable());

printer will never be null there, because those lines are inside if (printer != null) so you can drop the null-checker there too.

2 - Why Initialize and Enable the emitter every single time you print a receipt? In my opinion your Setup method should be called just once, from the constructor, just like you are doing with the initialization of your printer _printer = PrintJob.InitializePrinter(); This will even save you a useless variable _hasEnabledStatusMonitoring.

3 - Also why instantiate a new emitter every time the button is clicked? You could have the emitter also instantiated just once (also in the constructor).

4 - Inside your StatusChanged method you have the following if

  if (status == null)
  {
      Console.WriteLine("Status was null - unable to read status from printer.");
      return;
  }

But then, after that you re-check over and over if status is not null again. It will never be null, because if it were, your first if would have already returned and exited the method.

5 - I see you are creating a list of lists of bytes List<List<byte>> list = new List<List<byte>>();. Don't do that, because as you can see, every single command you get back from the emitter will have to be converted to a new list, and after doing all that you iterate through all items in your list and convert them back to a byte array (same as originally returned by the emitter). In other words you are having the trouble of converting everything into lists, just to throw all that away and converting back to the expected byte array. Instead, take a look in this section of the README file and see how to properly compose ESCPOS commands from the emitter using ByteSplicer.Combine before printing all at once.

@lukevp
Copy link
Owner

lukevp commented Jan 14, 2024

Some printers also allow you to overrun the buffer and they'll just throw away extra bytes, so if it's sending both copies back to back that might be part of the problem (especially since you're sending image data). Epson printers don't seem to have this problem as often, but if it's a 3rd party printer that might be what you're running into. The app tries to buffer the bytes and write them as the printer accepts them, so if the printer is properly applying back pressure and not accepting bytes until it's ready and has room in the buffer (the Epsons do this) then you can send as much data as you want to the library and it'll flush the bytes over time as the printer acknowledges the writes. This specifically applies to the serial port version which you're using and not necessarily all the other printer implementations.

Have you tried sending the bytes more slowly? like put a Thread.Sleep(100) after each print command (this many sleeps isn't probably necessary in the long run but just to debug the issue) and a 1 second sleep between each prints?

Also I'm not sure about the lifecycle of your app, if you are doing a test where you boot up the app, print 2 receipts and then quit the app, then it's also possible that you are just not getting the last prints flushed properly to the printer before the app quits - you have to ensure your app gives the print queue enough time to flush. This is covered in the readme as well.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants