1
votes

I have a cash register I am trying to communicate with from C# (I am NOT using POS for .NET). Basically I want to have it pull items from my application database.

So the cash register sends this string to the application host computer through the serial port: • COMMAND: Item search packet

Command Short Description:          "Searches PC for a PLU code" 

Data Send Example Format:           ?/1234567890123/

"/" is the packet field separator. The number is the barcode of the item to search for. "?" is the packet descriptor which signifies that this is a packet that asks for item info.

To which I must respond with a REPLY DATA PACKET

Reply Packet Format:    "1/ITEM DESCRIPTION/1200.00/0.00/1/" if the item exists in the host database

OR

"0/"  if it does not exist in which it will search its internal memory for it

And the protocol specifies the communication rules:

ECR/POS    HOST COMPUTER

Idle    
               Idle
Enquire(ENQ)    
               Acknowledge(ACK) 
Packet("?/1234567890123/")  
               Acknowledge(ACK) 
               Packet("1/ITEM DESCRIPTION/1200.00/0.00/1/")
Acknowledge(ACK)    
Idle    
               Idle

ENQ, ACK are the ASCII control codes. If the packet is not crafted correctly I get a NAK back.

The field specifications are:

==== Field 1:       Found flag
Type:           FLAG
Length:         1
Notes:          This flag must be zero when item could not be found
            in the database, else (if found) it must be set to
            one. In the 1st case, the rest of the fields must
            not be sent. 

==== Field 2:       Item description
Type:           STRING
Length:         Variable, 1-20 characters
Notes:          The PLU description for the requested code

==== Field 3:       Item unit price
Type:           AMOUNT
Length:         Default
Notes:          This is the unit price for the requested code

==== Field 4:       Item discount amount
Type:           AMOUNT
Length:         Default
Notes:          This is an auto-discount value for this PLU

==== Field 5:       Department
Type:           INTEGER
Length:         1
Notes:                  It is the department index which the PLU belongs

I want it to get the price from the host app. Problem is the register accepts my response packet as valid (it sends ACK back through serial port) but in its own LCD screen I get "ERROR: NON EXISTENT ITEM". It as though I have sent a "0" flag.I have no idea what the problem can be. I am desperate.

Thing is the register asks the host computer for the price and if it cannot find one it queries it's own internal memory (can store up to 4000 items). If I store an item manually in the internal memory I can change it's attributes(price, description etc) from the host application.

I cannot even add an item programmatically in the internal memory although I also get an 'OK' (ACK) from the serial protocol communication. That way I could maybe add items programmatically and have it pull them from its own internal memory.

I can just store each item manually and then If it exists in the internal memory I can alter it however I want from the host application (change price, description etc). Then it can get the price I have set for it in the internal memory. This is really tedious though. I would have to initially store everything manually once and I have 2 cash registers of the same type. What I want is to store nothing internally but have pull everything from the host.

Please help. I am out of ideas.

EDIT: this is the packet capture I sniffed out

#      TIME          PORT      DATA                                            ASCII
000044 13:52:03.437  COM2   >> 05                                              .
000045 13:52:03.437  COM2   << 06                                              .
000046 13:52:03.453  COM2   >> 02 30 31 2F 30 31 2F 32 2F 30 30 2F 3F 2F 39 39 .01/01/2/00/?/99
                               39 20 20 20 20 20 20 20 20 20 20 2F 31 2F 34 38 9          /1/48
                               03 06                                           ..
000049 13:52:03.453  COM2   << 06 02 30 31 2F 30 31 2F 32 2F 30 30 2F 31 2F 54 ..01/01/2/00/1/T
                               45 53 54 20 49 54 45 4D 20 2F 30 30 30 30 2E 36 EST ITEM /0000.6
                               36 2F 30 2E 30 30 2F 31 2F 33 36 03             6/0.00/1/36.

The "01/01/2/00/" part is the online packet header which includes machine index number, clerk etc. Every packet begins with 0x02(STX) and ends with 0x03(ETX). The field prior to last is the packet checksum number which If I get wrong, it sends back NAK.

It seems it sends back ACK even if I get the fields wrong. It just checks the checksum. The protocol is here https://rapidshare.com/files/1772287788/DL_Protocol.doc

*UPDATE:*

It seems to behave rather weird. I can write to its internal memory (store an item) and modify any existing item's field except the item's barcode. I just store at any of the 4000 indices I want. However if I enter the register's menu externally (from it's own keyboard) to the item storing submenu, press "store new item" and then go back out at the "selling" screen WITHOUT actually storing anything at all, just cancelling all the way back, it actually stores every field the next time. That is, it also stores the barcode for the next Set_PLU() command I give it (exactly the same command that previously failed to store the barcode) regardless if it is a new record or modyfing an old one (essentially the index position I give it).

Funny thing is when I go to the "store new item menu" it gives me a new barcode to enter. If I type one it automatically stores it at the next available index. I just cancel without typing anything. The next Set_PLU() command works for ANY index I choose even if it is not the next available one. Can be an older one in which case it modifies everything or one that is bigger than the next.

It is really annoying to have to do that every time I need to store a product. What is this?

3
If it ACKs your response to the request for product information but then displays ERROR non existent item, there must be something else you are missing. Can you post the exact ASCII text of the packet the POS is sending as a information request packet, and the exact text you are sending in your response which is ACKed?Shane Wealti
Actually if you have a log or some kind of capture of the whole "conversation" that would be helpful also.Shane Wealti
Do you have a link for the protocol specification?dbasnett

3 Answers

2
votes

After reading your spec and the data i think there is a missing slash at the end. In your spec you wrote:

Reply Packet Format:    "1/ITEM DESCRIPTION/1200.00/0.00/1/" if the item exists in the host database

But in your naked data on the wire i'll see:

1/TEST ITEM /0000.66/0.00/1/36

So maybe the last slash is simply missing. Also the last parameter is the department index which the PLU belongs. Maybe this number has also some impact on what the cash register will show.

Update

Okay, this was just a try. Now the only thing that would come to my mind would be the question: "Do you have a system that is able to correctly transmit something to the register?" If yes you could attach it to a second serial port of your machine and write a little program that simply transfers the data between both com ports and additionally writes them into a file. So you could inspect the data the other system is sending or the manufacturer has a demo application from which you can sniff the exact data it sends.

Last but not least ask the manufacturer for some guidance, cause he should know how the data must look exactly (maybe by giving you an example?).

By the way, you already sniffed some serial data, so you should have an application for that. My favourite one is Free Serial Port Monitor.

1
votes

Make sure you are setting the serial port's encoding to an ASCII code page.

E.g.:

        port = new SerialPort("COM" + PortNum.ToString(), 
           9600, Parity.None, 8, StopBits.Two);
        port.Encoding = Encoding.GetEncoding(28591);

If you are sending out Unicode characters, that will probably confuse the device.

1
votes

OK people I did it. I actually have to be in the "store new item" (manually) menu in the cash register for the host app to be able to store the barcode properly. I don't know why this is (it does store all the other fields), it makes no sense. I imagine it must be the manufacturers ommission to be able to store the barcode as well through the serial port regardless of the manual entry.

As for the item price acquisition from the host app I must send just the plain response without the online header (machine number, clerk number etc) although in the specification it says I should. I actually have 3 protocol revisions and the most suitable one gets it wrong.

This means I cannot split the signal and have each cash register discard the response that is not meant for it. I guess I will buy an additional serial port for the PC. Thank you all for your responses.