ESC/POS printer SO
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??- Changed TypeTerry Warwick - MicrosoftMSFT, OwnerTuesday, August 25, 2009 2:29 PMThis is a question not a discussion
Answers
- 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
- 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
- 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
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- 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.
- 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
- 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:) - 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
- 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
- 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 ?
- 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 ? - 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 Methodspublic override void Open(){// Device State checking done in base classbase.Open();// Initialize the CheckHealthText property to an empty stringcheckhealthtext = "";// Set values for common statisticsSetStatisticValue(StatisticManufacturerName, "Microsoft Corporation");SetStatisticValue(StatisticManufactureDate, "2009-03-01");SetStatisticValue(StatisticModelName, "Canon LBP2900");SetStatisticValue(StatisticMechanicalRevision, "1.0");SetStatisticValue(StatisticInterface, "Other");// set capabilitiesProperties.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";elses = "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);elses = "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 openVerifyState(false, false);return checkhealthtext;}}public override string CheckHealth(HealthCheckLevel level){// Verify that device is open, claimed and enabledVerifyState(true, true);// TODO: check the health of the device and return a descriptive string// Cache result in the CheckHealthText propertycheckhealthtext = "Ok";return checkhealthtext;}public override DirectIOData DirectIO(int command, int data, object obj){// Verify that device is openVerifyState(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 classget{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_clickprivate 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 objectpos.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 exceptionpos.PrintImmediate(PrinterStation.Receipt, "some text to print"); //no output no exceptionpos.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;}}


