Trying to decode serial data from cash register - crc?

I want to build portable device with arduino board to communicate with cash register. For servicing cash register, usual we using notebook with some java app from cash register manufacturer.

And now the problem. I capture serial data from app to serial port, and i cannot decode data intended to represent data and time. Few examples of captured data:

Date and time from app and type of service:

01.08.2016 12:00 and type:T

06 02 0a 62 00 96 f9 45 56 01 00 00 02 02 99
  1. 31.07.2014 22:00 type: B
06 02 0a 62 00 d3 5c a2 4a 01 00 00 03 02 8b

I get it first part: 06 02 0a 62, it is ascii code, and zero bytes in middle (probably space between data). But the rest i dont get it :). Maybe it some bcd data with crc encoding?

Manufacturer did not give any information about communication protocol.

Thanks for help.

have you asked the manufacturer? is that the whole output? what command did you type to get this out on the Serial console?

I did not ask manufacturer, can try. Yes it is whole output (input data to cash register). I captured that data with "Free serial analyzer" and when i copy that data to Serial console and send it to cash register, i get same results as from cash register windows application.

can you try to send other dates, may be

01.08.2016 12:01
01.08.2016 12:02
01.08.2016 12:03
01.08.2016 12:04

and see what changes... that will give you a hint on where to look for the date

can you pass seconds like?

01.08.2016 12:00:00
01.08.2016 12:00:01

and do you know what processor and OS is in the cash register?

Cash register is not currently with me, so i can try tomorrow other dates. No seconds, just plain date and time.

Cash register using some ajile aj-100 microprocessor, OS is probably of the same chip manufacturer.

Ok so embedded Java OS - they could have their own data structure though. Play around with multiple values that should give you hints

CRC usually only appears as appended characters, not within each byte (that's parity),

You may be looking at packed 6 or 7 bit data, which in itself may not be ASCII, but a proprietary binary format.

There is a small chance of encryption - to avoid people 'sniffing' the data in sensitive applications.

Fun project, but earlier suggestions are definitely worth following.

I did not expect to receive any answer from register manufacturer. Some highlights from them:

Short command:

#STX#LEN#DATA#CRC

STX is 0x02

LEN lenght of data section

DATA data section

CRC is sum of all bytes, not including STX and saved to two bytes. MSB,LSB

Example of test communication with device:

From PC: 02 01 65 00 66

0x02 - STX

0x01 - LEN

0x65 - DATA (CMD for test)

0x00 0x65 - CRC

Long commands:

#SOH#LEN1#LEN2#DATA#CRC#

SOH is 0x03

LEN(LEN2 << 8 | LEN1) length of data section

CRC is sum of all bytes, not including SOH and saved to two bytes. MSB,LSB

Long command:

example of time set of cash register:

06 02 09 01 82 01 f5 2a 48 00 00 00 01 f4

0x06 - SOH

0x02 0x09 - lengh

0x01 - cmd for time set

bytes: 0x82 0x01 0xf5 0x2a 0x48 0x00 0x00 0x00 date and time in milliseconds counting from 01.01.2000 GMT.

0x01 0xF4 - CRC

I am not used crc before, so i am gonna read little about crc. But if you have some guidance where to start, i will really appreciate.

at the first stage, you can try to decode the messages (CRC is only used to verify they were received correctly) - you can do that later once you get the feel for the messages you are seeing...
(But you will need to create valid CRC before you SEND commands -to- the register, as it will verify /ignore messages with incorrect CRC values.)

Receive CRC is a good idea once you know what you're looking at.

THE CRC is not a CRC, you can simple add all the values of the bytes (except for the first one and the CRC itself) and you will get the correct result

Short message

[s]02[/s] 01 65 [s]00 66[/s]

0x01 + 0x65 = 0x0066;

Long message
You will have to review the second example; SOH is not 0x03 nor is it 0x06 (and you mix them up in your explanation).

[s]06 02[/s] 09 01 82 01 f5 2a 48 00 00 00 [s]01 f4[/s]

0x09 + 0x01 + 0x82 + 0x01 + 0xf5 + 0x2a + 0x48 = 0x01f4

The length in your second example also does not make sense; either 0x0209 (or bytes swapped) or 0x0901 (or bytes swapped). The length of the message is (far) shorter.

This is (with 99.99% certainty) a short message; 0x06 is an ACK coming from somewhere (reply from register on previous message) and should not be counted. So the start is 0x02 followed by a length indication of one byte (0x09) followed by 9 data bytes followed by 2 crc bytes.

sterretje:
THE CRC is not a CRC, you can simple add all the values of the bytes (except for the first one and the CRC itself) and you will get the correct result

Short message

[s]02[/s] 01 65 [s]00 66[/s]

0x01 + 0x65 = 0x0066;

Long message
You will have to review the second example; SOH is not 0x03 nor is it 0x06 (and you mix them up in your explanation).

[s]06 02[/s] 09 01 82 01 f5 2a 48 00 00 00 [s]01 f4[/s]

0x09 + 0x01 + 0x82 + 0x01 + 0xf5 + 0x2a + 0x48 = 0x01f4

The length in your second example also does not make sense; either 0x0209 (or bytes swapped) or 0x0901 (or bytes swapped). The length of the message is (far) shorter.

This is (with 99.99% certainty) a short message; 0x06 is an ACK coming from somewhere (reply from register on previous message) and should not be counted. So the start is 0x02 followed by a length indication of one byte (0x09) followed by 9 data bytes followed by 2 crc bytes.

Yes, you are write. Thanks. But this is there example, that make me think wrong:

Date: 27.10.2009 12:33

[12:32:25:394] - Written data

06 02 09 01 82 01 f5 2a 48 00 00 00 01 f4 ....‚.o*H....ô

[12:32:25:400] - Read data

06 02 02 7f 67 00 e8 ...g.e

[12:32:25:416] - Written data

06

So, crc bytes are just sum from? I only need to sum this bytes and add two in the end of array?

And i try to convert milliseconds to date, with online converter, but i always get wrong result.

In last example date is: 27.10.2009 12:33

I take hex to dec from hex value: 8201f52a48 and dec value: 558378592840 and results is:

2017/09/10 16:09

What i am doing wrong?

adi__:
So, crc bytes are just sum from? I only need to sum this bytes and add two in the end of array?

Yes, just sum them; it's actually called checksum

adi__:
What i am doing wrong?

Unix timestamps run from 1970/01/01; according to your (or the manufacturers) description, the timestamp is since 2000/01/01. Try to subtract 946684800 (0x386D43800) before converting. I did try it but did not manage to get the correct result (either so not sure what's up.).

sterretje:
Yes, just sum them; it's actually called checksum
Unix timestamps run from 1970/01/01; according to your (or the manufacturers) description, the timestamp is since 2000/01/01. Try to subtract 946684800 (0x386D43800) before converting. I did try it but did not manage to get the correct result (either so not sure what's up.).

Mr. Sterretje,

many thanks for your help. Yes, manufacturer using timestamp 2000/01/01. I try everything, but, i cant get correct results.

Can you try to send 4 or 5 different dates all within 1 minute interval?

J-M-L:
Can you try to send 4 or 5 different dates all within 1 minute interval?

  1. 06 02 09 01 53 EC 6D FF 79 00 00 00 03 2E 2016-08-08 15:00:37
  2. 06 02 09 01 A1 64 6F FF 79 00 00 00 02 F6 2016-08-08 15:02:13
  3. 06 02 09 01 39 23 70 FF 79 00 00 00 02 4E 2016-08-08 15:03:02
  4. 06 02 09 01 E1 19 71 FF 79 00 00 00 02 ED 2016-08-08 15:04:05
  5. 06 02 09 01 81 14 72 FF 79 00 00 00 02 89 2016-08-08 15:05:09

This is all commands for setting only date and time.

Maybe milliseconds since 1-1-200**0** 00:00:00 GMT, with a 2-hour offset for local time?

    0x79FF6DEC53 = 523976436819ms
                 = 523976436s

Using this date/time calculator, it produces

    August 8, 2016 at 1:00:36 PM

...within one second of 15:00:07 minus 2 hours of the example. Other examples are spot on or off by one second.

Fun!
/dev

/dev:
Maybe milliseconds since 1-1-200**0** 00:00:00 GMT, with a 2-hour offset for local time?

    0x79FF6DEC53 = 523976436819ms

= 523976436s



Using [this date/time calculator](http://www.timeanddate.com/date/dateadded.html?m1=1&d1=1&y1=2000&type=add&ay=&am=&aw=&ad=&h1=0&i1=0&s1=0&ah=&ai=&as=523976436&rec=), it produces



August 8, 2016 at 1:00:36 PM



...within one second of 15:00:07 minus 2 hours of the example. Other examples are spot on or off by one second.

Fun!
/dev

Thanks man. I am f* blind. Is date in big endian format?

Is date in big endian format?

Nope, the date/time is little-endian: the least-significant byte is received first.

BTW, notice that there are at least 5 bytes, which means it won't fit in our favorite 4-byte uint32_t.

If you don't have a Time library yet, there's a Time class in my NeoGPS library that might be handy. It defaults to the Y2K epoch and is optimized for Arduinos. You could easily delete the includes, the NeoGPS namespace and the NEOGPS_PACKED at the end... just use Time.h and Time.cpp.

Cheers,
/dev