Ask a questionAsk a question
 

AnswerESC/POS printer SO

  • Wednesday, August 05, 2009 6:49 AMavatarmoth Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     

    We need to develop a SO for ESC/POS printer under POS for .NET.
    We are new at this area and want to estimate how many effort will be cost to develop such a service object. (about how many weeks per person) Are there any reference code is this case??

Answers

  • Thursday, August 06, 2009 3:36 AMYortAnswererUsers MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Answer
    Hi,

    I doubt you could use the Epson SO, and even if you could it might not be 'legally' allowed. If it is a custom printer you're building then I wouldn't recommend it anyway.

    There really isn't anyway for us to determine how long it would take... it depends on your learning curve, how fast you write code, how good your test procedures are etc.

    It also depends on what features you plan to implement... direct io ? status and power notification ? multiple stations ? bitmap printing ? barcode printing ? print rotation ? two colour printing ? logo printing ? transactional printing ? slip printing ? page mode ?

    It also depends on how well you implement any given feature; if you're going to support bitmap printing for example, do you require the bitmap to be in a specific format ? If you're given it in another format will you automatically convert it, or error ? (TPG service objects seem to error, while Epson service objects seem to do the conversion for you... there doesn't appear to be a clear answer on what you should do). If you are going to convert it, that's extra code you have to write and it will therefore take you longer.

    I know this isn't what you want to hear, but I think you are the only person who can determine how long it will take you/your team.

    I think what you need to do is sit down with the Pos .Net SDK documentation and some samples, look at how application developers use a printer so you can see what features might be important and how they need to work, then look at the documentation/base classes/samples for building a service object, then look at your hardware and what it's protocols are like etc. and then plan out;

    1. What plumbing code is required, and how long that will take (estimated based on your teams skills).
    2. What features you are going to implement, in detail, how long each will take (estimated based on your teams skills).
    3. Add some time for testing, qa, documentation, unexpected issues etc.
    4. Add it all up.

    You might well be able to do it in three months with one person, it just depends... on the hardware, person and solution.

    One guy who has posted in this forum and is also writing a service object initially complained he hadn't made any progress in his first two days... like we told him, pos printers are complex animals and so are their service objects, you shouldn't expect it to be easy or quick and since it's not easy, it's not easy to predict either.

    • Marked As Answer byYortAnswererThursday, September 03, 2009 11:51 PM
    •  
  • Thursday, August 06, 2009 6:20 PMSean LimingMVP, AnswererUsers MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Answer
    Doing the service obejcts for a cash drawer and weight scale took a couple of hours. These are basic POS devices. Printer will take some time. Yort's recommendation of 3 months with all the conditions is a good estimate.

    -Sean

    www.sjjmicro.com / www.seanliming.com, Book Author - XP Embedded Advanced, XPe Supplemental Toolkit, WEPOS / POS for .NET Step-by-Step
    • Marked As Answer byYortAnswererThursday, September 03, 2009 11:51 PM
    •  
  • Friday, August 14, 2009 2:01 AMSylvester-MSFTMSFT, ModeratorUsers MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Answer
    Take a look at the POS for .NET SDK and samples.  In the case of the POS Printer, you have a choice between using a base class or the basic class.  You should take a look at the base class as this provides most of the UPOS required functionality leaving you to focus on the actual communications with the device.  If the device is USB then you also get some additional support (such as PnP). 

    There is also a Hands-on-lab that walks thru an example with a scanner on the team blog.
    • Marked As Answer byYortAnswererThursday, September 03, 2009 11:51 PM
    •  

All Replies

  • Wednesday, August 05, 2009 3:36 PMSean LimingMVP, AnswererUsers MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     

    There have been some recent posts on POS Printers in this forum. You can see that the information is limited, and creating an SO from scratch can be complex. It has been done for EPSON. The examples in the SDK are a start,  but you will need the whole command set for the printer.

    1. What is the interface? Serial, USB, other?
    2. Do you have all the printer commands and options? Do you need them all implemented or basic print?

    -Sean


    www.sjjmicro.com / www.seanliming.com, Book Author - XP Embedded Advanced, XPe Supplemental Toolkit, WEPOS / POS for .NET Step-by-Step
  • Thursday, August 06, 2009 2:02 AMavatarmoth Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    Yes, we need to implement all the commands. The interface will be serial. We cannot just use the EPSON SO, right? I also think the effort will be great, but have no clear thoughts for the develop period. One person 3 months will be enough?? (including the debugging and testing). Thanks.
  • Thursday, August 06, 2009 3:36 AMYortAnswererUsers MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Answer
    Hi,

    I doubt you could use the Epson SO, and even if you could it might not be 'legally' allowed. If it is a custom printer you're building then I wouldn't recommend it anyway.

    There really isn't anyway for us to determine how long it would take... it depends on your learning curve, how fast you write code, how good your test procedures are etc.

    It also depends on what features you plan to implement... direct io ? status and power notification ? multiple stations ? bitmap printing ? barcode printing ? print rotation ? two colour printing ? logo printing ? transactional printing ? slip printing ? page mode ?

    It also depends on how well you implement any given feature; if you're going to support bitmap printing for example, do you require the bitmap to be in a specific format ? If you're given it in another format will you automatically convert it, or error ? (TPG service objects seem to error, while Epson service objects seem to do the conversion for you... there doesn't appear to be a clear answer on what you should do). If you are going to convert it, that's extra code you have to write and it will therefore take you longer.

    I know this isn't what you want to hear, but I think you are the only person who can determine how long it will take you/your team.

    I think what you need to do is sit down with the Pos .Net SDK documentation and some samples, look at how application developers use a printer so you can see what features might be important and how they need to work, then look at the documentation/base classes/samples for building a service object, then look at your hardware and what it's protocols are like etc. and then plan out;

    1. What plumbing code is required, and how long that will take (estimated based on your teams skills).
    2. What features you are going to implement, in detail, how long each will take (estimated based on your teams skills).
    3. Add some time for testing, qa, documentation, unexpected issues etc.
    4. Add it all up.

    You might well be able to do it in three months with one person, it just depends... on the hardware, person and solution.

    One guy who has posted in this forum and is also writing a service object initially complained he hadn't made any progress in his first two days... like we told him, pos printers are complex animals and so are their service objects, you shouldn't expect it to be easy or quick and since it's not easy, it's not easy to predict either.

    • Marked As Answer byYortAnswererThursday, September 03, 2009 11:51 PM
    •  
  • Thursday, August 06, 2009 5:24 AMavatarmoth Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    Yes, I really understand that it depends...
    But I have to respond to my boss how long it would takes. It seems I need to estimate some longer time for the development. We are newer to the OPOS and POS for .NET and the resources are very limited. I hope EPSON SDK may give us a good start for the SO develop.
    Thanks for your detailed answer. We may have some detailed questions related to PosPrintBase class in the future:)
  • Thursday, August 06, 2009 6:20 PMSean LimingMVP, AnswererUsers MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Answer
    Doing the service obejcts for a cash drawer and weight scale took a couple of hours. These are basic POS devices. Printer will take some time. Yort's recommendation of 3 months with all the conditions is a good estimate.

    -Sean

    www.sjjmicro.com / www.seanliming.com, Book Author - XP Embedded Advanced, XPe Supplemental Toolkit, WEPOS / POS for .NET Step-by-Step
    • Marked As Answer byYortAnswererThursday, September 03, 2009 11:51 PM
    •  
  • Friday, August 14, 2009 2:01 AMSylvester-MSFTMSFT, ModeratorUsers MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Answer
    Take a look at the POS for .NET SDK and samples.  In the case of the POS Printer, you have a choice between using a base class or the basic class.  You should take a look at the base class as this provides most of the UPOS required functionality leaving you to focus on the actual communications with the device.  If the device is USB then you also get some additional support (such as PnP). 

    There is also a Hands-on-lab that walks thru an example with a scanner on the team blog.
    • Marked As Answer byYortAnswererThursday, September 03, 2009 11:51 PM
    •  
  • Saturday, October 31, 2009 6:00 AMHimanshu110 Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    Well thanks a lot


    I have developed my Custom Service object for my ink jet printer.

    Now if i fire posExplorer.GetDevices(), it is showing me that printer object.


    So now i think it has recognised my object. the problem now is if i call

     posPrinter.PrintNormal(PrinterStation.Slip, "fsome text to print");

    it is not giving any printing. Also i have changed the station to PrinterStation.Recipt, still the same.

    When i shift to PrinterStation.Journal, it throws me exception "journal station not present"


    Any idea ?

  • Sunday, November 01, 2009 6:49 AMYortAnswererUsers MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    Hi,

    First, this should really be a seperate thread in the forum, you shouldn't be hijacking someone elses.

    Second, we probably can't tell you what is wrong unless you post the code. I presume you aren't getting an error, since you don't mention one, so it's likely that your code is running but nothing is happening as as result. There could be many reasons for that, and we'll need the code to figure out why.

    Are you able to prove if the code is actually running ? Can you put some logging code in your service object methods to see if they are actually executing ?
  • Monday, November 02, 2009 10:25 AMHimanshu110 Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    Here is the code that i am using
    //MyPrinter.cs
        [ServiceObject(DeviceType.PosPrinter, "DemoPosPrinter", "A demo pos printer", 1, 12)]
        [HardwareId(@"USB\Vid_04a9&Pid_2676&Rev_0100")]
        public class MyPrinter : PosPrinterBase
        {

            #region PosPrinter Methods



            public override void Open()
            {
                // Device State checking done in base class
                base.Open();

                // Initialize the CheckHealthText property to an empty string
                checkhealthtext = "";

                // Set values for common statistics
                SetStatisticValue(StatisticManufacturerName, "Microsoft Corporation");
                SetStatisticValue(StatisticManufactureDate, "2009-03-01");
                SetStatisticValue(StatisticModelName, "Canon LBP2900");
                SetStatisticValue(StatisticMechanicalRevision, "1.0");
                SetStatisticValue(StatisticInterface, "Other");

              
                // set capabilities
                Properties.CapPowerReporting = PowerReporting.Standard;
                Properties.CapRecPresent = true;
                Properties.CapRecEmptySensor = true;
                Properties.CapRecNearEndSensor = true;
                Properties.RecEmpty = false;
                Properties.RecNearEnd = false;
                Properties.CapRecPaperCut = true;
                Properties.CapTransaction = true;
                Properties.CapRecRight90 = true;
                Properties.CapRecRotate180 = true;
                Properties.CapRecLeft90 = true;
                Properties.CapCoverSensor = true;
                Properties.CapSlpPresent = true;
                Properties.CapSlpEmptySensor = true;
                Properties.CapSlpNearEndSensor = true;
                Properties.SlpEmpty = false;
                Properties.SlpNearEnd = false;
                Properties.CapRecBarCode = true;
                Properties.CapMapCharacterSet = true;
                Properties.JrnLineChars = 10;
                
                Properties.RecBarCodeRotationList = new Rotation[] { Rotation.Normal, Rotation.Right90, Rotation.Left90, Rotation.Rotate180 };
            }
            public override void PrintNormal(PrinterStation station, string data)
            {
                base.PrintNormal(station, data);
                //this.PrintNormal(PrinterStation.Receipt, "dsgfdgdg");
            }
            protected override PrintResults CutPaperImpl(int percentage)
            {
                //Window.DisplayText("Paper cut: " + percentage.ToString(CultureInfo.CurrentCulture) + "%\r\n");
                //Thread.Sleep(printDelay);
                PrintResults pr = new PrintResults();
                pr.PaperCutCount = 1;
                return pr;
            }

            protected override PrintResults PrintNormalImpl(PrinterStation station, PrinterState printerState, string data)
            {

                if (station == PrinterStation.Receipt && (printerState.RecRotationMode & PrintRotation.Rotate180) == PrintRotation.Rotate180)
                    // Window.DisplayText("[Begin " + printerState.RecRotationMode.ToString() + " rotation]\r\n");
                    this.PrintNormal(PrinterStation.Receipt, "this is a test data");
                else if (station == PrinterStation.Slip && (printerState.SlpRotationMode & PrintRotation.Rotate180) == PrintRotation.Rotate180)
                    //Window.DisplayText("[Begin " + printerState.SlpRotationMode.ToString() + " rotation]\r\n");
                    this.PrintNormal(PrinterStation.Slip, "this is a test data");
                //Window.DisplayText(data);
                if (station == PrinterStation.Receipt && (printerState.RecRotationMode & PrintRotation.Rotate180) == PrintRotation.Rotate180)
                    //Window.DisplayText("[End " + printerState.RecRotationMode.ToString() + " rotation]\r\n");
                    this.PrintNormal(PrinterStation.Receipt, "this is a test data");
                else if (station == PrinterStation.Slip && (printerState.SlpRotationMode & PrintRotation.Rotate180) == PrintRotation.Rotate180)
                    this.PrintNormal(PrinterStation.Slip, "this is a test data");


                if (station == PrinterStation.Journal)
                {
                    this.PrintNormal(PrinterStation.Journal, "this is a test data");
                }

                if (station == PrinterStation.None)
                {
                    this.PrintNormal(PrinterStation.None, "this is a test data");
                }

                Thread.Sleep(printDelay);

                return GetPrintStats(station, data.Length);
            }

            private PrintResults GetPrintStats(PrinterStation station, int chars)
            {
                PrintResults pr = new PrintResults();
                if (station == PrinterStation.Journal)
                {
                    pr.JournalLinePrintedCount = 1;
                    pr.JournalCharacterPrintedCount = chars;
                }
                else if (station == PrinterStation.Receipt)
                {
                    pr.ReceiptLinePrintedCount = 1;
                    pr.ReceiptCharacterPrintedCount = chars;
                }
                else if (station == PrinterStation.Slip)
                {
                    pr.SlipLinePrintedCount = 1;
                    pr.SlipCharacterPrintedCount = chars;
                }

                
                return pr;
            }


            protected override PrintResults PrintImmediateImpl(PrinterStation station, string data, PrinterState state)
            {
                //Window.DisplayText(data);
                Thread.Sleep(printDelay);
                return GetPrintStats(station, data.Length);
            }

            protected override void ValidateDataImpl(PrinterStation station, string data)
            {
            }

            protected override void BeginInsertionImpl(int timeout)
            {

            }

            protected override bool EndInsertionImpl()
            {
                return true;
            }

            protected override void BeginRemovalImpl(int timeout)
            {

            }

            protected override bool EndRemovalImpl()
            {
                return true;
            }




            protected override PrintResults RotatePrintImpl(RotatePrintCollection collection)
            {
                int chars = DisplayRotatePrintTransaction(collection);

                Thread.Sleep(printDelay);
                return GetPrintStats(collection.Station, chars);
            }

            private int DisplayRotatePrintTransaction(RotatePrintCollection collection)
            {
                int chars = 0;
                Rotation rotation = collection.Rotation;
                //Window.DisplayText("[Begin " + rotation.ToString() + " rotation]\r\n");

                foreach (PrintOperation operation in collection)
                {
                    string s = "";

                    if (operation is PrintNormalOperation)
                        s = ((PrintNormalOperation)operation).Data;
                    else if (operation is PrintBitmapOperation)
                        s = "Bitmap: " + ((PrintBitmapOperation)operation).FileName + "\r\n";
                    else if (operation is PrintBarCodeOperation)
                        s = "BarCode: " + ((PrintBarCodeOperation)operation).Data + "\r\n";
                    else
                        s = "Unexpected operation type.\r\n";

                    //Window.DisplayText(s);
                    chars += s.Length;
                }
                //Window.DisplayText("[End " + rotation.ToString() + " rotation]\r\n");

                return chars;
            }

            protected override PrintResults TransactionPrintImpl(PrintOperationCollection collection)
            {
                int chars = 0;
                //Window.DisplayText("[Begin transaction]\r\n");
                foreach (PrintOperation operation in collection)
                {
                    string s = "";
                    Rotation rotation = operation.Rotation;

                    if (operation is PrintNormalOperation)
                        s = ((PrintNormalOperation)operation).Data;
                    else if (operation is CutPaperOperation)
                        s = "Cut paper at: " + ((CutPaperOperation)operation).Percentage.ToString(CultureInfo.CurrentCulture) + "%";
                    else if (operation is PrintBitmapOperation)
                        s = "Bitmap: " + ((PrintBitmapOperation)operation).FileName + "\r\n";
                    else if (operation is PrintBarCodeOperation)
                        s = "BarCode: " + ((PrintBarCodeOperation)operation).Data + "\r\n";
                    else if (operation is RotatePrintOperation)
                        chars += DisplayRotatePrintTransaction(((RotatePrintOperation)operation).Collection);
                    else
                        s = "Unexpected operation type.\r\n";

                    if (rotation == Rotation.Rotate180)
                        //Window.DisplayText("[Begin " + rotation.ToString() + " rotation]\r\n");

                    //Window.DisplayText(s);

                    if (rotation == Rotation.Rotate180)
                        //Window.DisplayText("[End " + rotation.ToString() + " rotation]\r\n");

                    chars += s.Length;
                }
                //Window.DisplayText("[End transaction]\r\n");
                Thread.Sleep(printDelay);
                return GetPrintStats(collection[0].Station, chars);
            }
            private string checkhealthtext;
            public override string CheckHealthText
            {
                get
                {
                    // Verify that device is open
                    VerifyState(false, false);

                    return checkhealthtext;
                }
            }


            public override string CheckHealth(HealthCheckLevel level)
            {
                // Verify that device is open, claimed and enabled
                VerifyState(true, true);

                // TODO: check the health of the device and return a descriptive string 

                // Cache result in the CheckHealthText property
                checkhealthtext = "Ok";
                return checkhealthtext;
            }

            public override DirectIOData DirectIO(int command, int data, object obj)
            {
                // Verify that device is open
                VerifyState(false, false);

                return new DirectIOData(data, obj);
            }


            private int printDelay = 0;
            protected internal int PrintDelay
            {
                get { return printDelay; }
                set { printDelay = value; }
            }

            public override bool DeviceEnabled
            {
                // Device State checking done in base class
                get
                {
                    return base.DeviceEnabled;
                }
                set
                {
                    if (base.DeviceEnabled != value)
                    {
                        base.DeviceEnabled = value;

                        if (PowerNotify == PowerNotification.Enabled)
                            QueueEvent(new StatusUpdateEventArgs((int)PowerState));
                    }
                }
            }

    } //end of class






    //On WPF Window button_click




    private void button1_Click(object sender, RoutedEventArgs e)
            {
                GetPrinter();
            }
     private void GetPrinter()
            {
                PosPrinter pos = null;
                DeviceInfo deviceInfo = null;
                PosExplorer posExplorer = null;
                try
                {

                    posExplorer = new PosExplorer();
                    DeviceCollection  dvInfoCol = posExplorer.GetDevices(DeviceType.PosPrinter, DeviceCompatibilities.OposAndCompatibilityLevel1);
                    pos = (PosPrinter)posExplorer.CreateInstance(dvInfoCol[1]); //this gives the reference for my custom printer service object
             
                    pos.Open();
                    pos.Claim(1000);
                    pos.PowerNotify = PowerNotification.Enabled;
                    
                    
                    bool result = pos.DeviceEnabled = true;

                    pos.JrnLetterQuality = true;               
                    pos.PrintNormal(PrinterStation.Receipt, "some text to print"); //here nothing happens and no exception
    pos.PrintImmediate(PrinterStation.Receipt, "some text to print");   //no output no exception
    pos.PrintNormal(PrinterStation. Journal, "some text to print"); //throws exception PosControlException : journal station not present
                }
                catch (PosControlException ex)
                {
                    MessageBox.Show(ex.ErrorCode.ToString());
                }
                catch (Exception Ex)
                {
                    MessageBox.Show(Ex.ToString());
                }
                finally
                {
                    pos.Release();
                    pos.Close();
                    posExplorer = null;
                    deviceInfo = null;
                }
               
            }