How to handle ISO8583 bitmaps with non-hex characters - python-3.x

I'm trying to correctly parse an ISO8583(1987) message in Python 3 using the py8583 package. After running into some issues with the parser I've realized that the bitmap in the ISO8583 message seems to not be formatted correctly.
This is the ISO8583 bitmap in question:
P8P1211661684989
This is the entire ISO8583 message. It's using trash test data so don't need to worry about sensitive info.
NP0100P8P1211661684989300000000000002004914104019041104009904SHDPf406c431Cashier_01 01301001000200491665D9832B92FD380C
From what I understand the bitmap should only contain 1-9/A-F hex characters, yet as you can see it begins with "P8P12...".
Is there something I'm missing here? These ISO8583 messages are currently being used within an enterprise-level company. Additionally, while some online parsers throw the bitmap error, I've found one that seems to be parsing it just fine (link below). I can't figure out how it's doing the parsing.
http://www.fintrnmsgtool.com/decode-iso87-bitmap.html
(Edit: It was correctly pointed out by glhr that this site doesn't allow you to type non-hex characters, only copy/paste them, so it's probably no longer relevant to the question.)
Hex dump below:
0010 08 00 45 00 00 ab 03 b1 00 00 3c 06 fa 89 c0 a8
0020 15 02 40 87 69 e1 81 1c 0b bb b7 b9 78 55 c7 86
0030 4a 2c 50 18 12 24 2f d3 00 00 4e 50 00 00 00 7d
0040 30 31 30 30 50 38 00 01 80 c0 00 50 31 32 31 31
0050 36 36 31 36 38 34 39 38 39 33 30 30 30 30 30 30
0060 30 30 30 30 30 30 30 32 30 30 34 38 31 34 30 39
0070 35 39 31 39 30 34 31 31 30 34 30 30 39 39 30 34
0080 53 48 44 50 66 34 30 36 63 34 33 31 43 61 73 68
0090 69 65 72 5f 30 31 20 20 20 20 20 30 31 33 30 31
00a0 30 30 31 30 30 30 32 30 30 34 38 31 36 36 35 44
00b0 39 38 33 32 42 39 32 46 44 33 38 30 43
Any help from ISO8583 experts would be greatly appreciated!

Something seems amiss.
From the hex dump it looks like some kind of 0800 network message. That would make the bitmap starting with 0x45. This would be a binary bitmap of 0100 0101, indicating bits 2, 6, and 8 are present. ISO 8583 bit 2 is always a PAN (card number), so that does not make much sense. Bit's 6 and 8 don't seem to make sense in the context of a network message either as the former is cardholder billing amount, and the latter is cardholder amount fee.

Related

How to retrieve human readable data from MMA8451 accelerometer using nodejs

I receive via serial port data from an accelerometer module MMA8451.
I'm using nodejs to capture data from serial and do the parsing work.
The payload I get seems to be an hex
d40 14fc 88c0
540 800 c8c0
840 340 20c0
b0fc c80 d8c0
200 700 68c0
800 480 acc0
100 c0 c0c0
Which I suppose are the three axis values
If I simply try to convert in binary and the decimal using hex2bin and parseint I get values that are ranging from 0 to 256 but they don't make sense.
XYZ 248 16 184
XYZ 252 64 192
XYZ 128 64 192
XYZ 0 192 192
XYZ 252 64 192
XYZ 0 192 192
XYZ 64 0 192
XYZ 0 128 192
XYZ 128 64 192
XYZ 0 0 192
How I can get human readable values from this data?
UPDATE:
As NikaTheEngineer pointed out I've looked at the accelerometer datasheet https://www.nxp.com/docs/en/data-sheet/MMA8451Q.pdf (see chapter 5.2) and the data I'm receiving seems to be the raw data from those registers OUT_X_MSB, OUT_X_LSB, OUT_Y_MSB, OUT_Y_LSB, OUT_Z_MSB
Those are 14bit so this imply some sort of data manipulation with by bites shift am I correct?
If I print the stream directly from the serialport (removing the hex conversion) I receive this kind of payload
<Buffer 65 33 38 30 20 36 38 66 63 20 34 38 30 20 61 38 63 30 20 31 30 38 33 0d 0a 65 33 38 30 20 37 34 66 63 20 39 38 30 20 61 38 63 30 20 31 30 38 34 0d 0a>
<Buffer 65 33 38 30 20 38 66 63 20 35 63 30 20 37 30 63 30 20 31 30 38 35 0d 0a>
<Buffer 65 33 38 30 20 61 63 66 63 20 63 34 30 20 63 38 63 30 20 31 30 38 36 0d 0a>
<Buffer 65 33 38 30 20 37 30 66 63 20 37 38 30 20 37 30 63 30 20 31 30 38 37 0d 0a>
<Buffer 65 33 38 30 20 36 30 66 63 20 36 38 66 63 20 66 34 63 30 20 31 30 38 38 0d 0a>
<Buffer 65 33 38 30 20 63 38 66 63 20 61 30 30 20 37 30 63 30>
<Buffer 20 31 30 38 39 0d 0a 65 33 38 30 20 30 66 63 20 37 38 30 20 62 63 63 30 20 31 30 39 30 0d 0a 65 33 38 30 20 37 34 66 63 20 34 30 30 20 61 38 63 30 20 ... 6 more bytes>
<Buffer 65 33 38 30 20 35 30 66 63 20 34 63 30 20 35 38 63 30 20 31 30 39 32 0d 0a>
<Buffer 65 33 38 30 20 38 63 66 63 20 37 38 30 20 37 38 63 30 20 31 30 39 33 0d 0a>
<Buffer 65 33 38 30 20 36 30 66 63 20 38 30 30 20 62 30 63 30 20 31 30 39 34 0d 0a>
<Buffer 65 33 38 30 20 32 38 66 63 20 33 30 30 20 37 38 63 30 20 31 30 39 35 0d 0a 65 33 38 30 20 64 38 66 63 20 37 30 30 20 37 30 63 30 20 31 30 39 36 0d 0a>
<Buffer 65 33 38 30 20 34 30 66 63 20 61 30 30 20 64 30 63 30 20 31 30 39 37 0d 0a 65 33 38 30 20 39 63 66 63 20 37 38 30 20 37 30 63 30 20 31 30 39 38 0d 0a ... 25 more bytes>
<Buffer 65 33 38 30 20 62 63 66 63 20 36 34 30 20 39 38 63 30>
<Buffer 20 31 31 30 30 0d 0a 65 33 38 30 20 34 38 66 63 20 36 38 30 20 38 30 63 30 20 31 31 30 31 0d 0a 65 33 38 30 20 34 66 63 20 32 63 30 20 61 30 63 30 20 ... 6 more bytes>
<Buffer 65 33 38 30 20 34 38 66 63 20 37 38 30 20 36 38 63 30 20 31 31 30 33 0d 0a 65 33 38 30 20 32 38 66 63 20 61 30 30 20 61 30 63 30 20 31 31 30 34 0d 0a>
<Buffer 65 33 38 30 20 35 30 66 63 20 39 38 30 20 38 30 63 30 20 31 31 30 35 0d 0a>
<Buffer 65 33 38 30 20 36 34 66 63 20 31 63 30 20 37 30 63 30 20 31 31 30 36 0d 0a 65 33 38 30 20 33 30 66 63 20 38 38 30 20 61 30 63 30 20 31 31 30 37 0d 0a>
<Buffer 65 33 38 30 20 38 66 63 20 62 38 30 20 35 34 63 30 20 31 31 30 38 0d 0a 65 33 38 30 20 64 34 66 63 20 63 30 30 20 64 30 63 30 20 31 31 30 39 0d 0a 65 ... 48 more bytes>
<Buffer 65 33 38 30 20 66 38 66 63 20 37 38 30 20 34 34 63 30 20 31 31 31 32 0d 0a 65 33 38 30 20 31 30 66 63 20 38 30 30 20 38 38 63 30 20 31 31 31 33 0d 0a ... 49 more bytes>
<Buffer 65 33 38 30 20 66 30 66 63 20 35 30 30 20 38 38 63 30 20 31 31 31 36 0d 0a 65 33 38 30 20 34 38 66 63 20 34 34 30 20 61 38 63 30 20 31 31 31 37 0d 0a ... 25 more bytes>
<Buffer 65 33 38 30 20 32 38 66 63 20 38 63 30 20 62 38 63 30 20 31 31 31 39 0d 0a 65 33 38 30 20 32 38 66 63 20 36 38 30 20 39 30 63 30 20 31 31 32 30 0d 0a>
<Buffer 65 33 38 30 20 65 38 66 63 20 66 38 30 20 32 38 63 30 20 31 31 32 31 0d 0a>
<Buffer 65 33 38 30 20 63 38 66 63 20 39 30 30 20 64 34 63 30 20 31 31 32 32 0d 0a>
<Buffer 65 33 38 30 20 35 34 66 63 20 36 34 30 20 66 38 63 30 20 31 31 32 33 0d 0a 65 33 38 30 20 38 30 66 63 20 37 30 30 20 33 38 63 30 20 31 31 32 34 0d 0a ... 50 more bytes>
<Buffer 65 33 38 30 20 35 63 66 63 20 32 30 30 20 63 63 63 30 20 31 31 32 37 0d 0a>
<Buffer 65 33 38 30 20 64 38 66 63 20 35 38 30 20 36 30 63 30 20 31 31 32 38 0d 0a 65 33 38 30 20 66 30 66 63 20 38 30 30 20 61 38 63 30 20 31 31 32 39 0d 0a>
<Buffer 65 33 38 30 20 65 30 66 63 20 64 63 30 20 62 30 63>
<Buffer 30 20 31 31 33 30 0d 0a 65 33 38 30 20 36 30 66 63 20 36 63 30 20 39 38 63 30 20 31 31 33 31 0d 0a>
<Buffer 65 33 38 30 20 33 30 66 63 20 35 30 30 20 36 30 63 30 20 31 31 33 32 0d 0a>
<Buffer 65 33 38 30 20 62 30 66 63 20 64 30 30 20 63 34 63 30 20 31 31 33 33 0d 0a>
I guess this is the stream of raw data in bytes.
I suppose the first step is to distinguish every single chunk samples composed by xmsb-xlsb ymsb-ylsb zmsb-zlsb, but at this point I have no idea how to do it, there should be some kind of delimiter?
I need to work blindly on the buffer just trusting the datastructure pointed in the datasheet?
First of all, you do not need to convert hex number to binary. Function parseInt can convert hex to decimal.
Check this out!
Secondly, if you parsed your data correctly, it should not be in range(0, 256); The last hex number you recived is c0c0, which in decimal is 49344 (unsigned value).
Go ahead and test it on this site!
Lastly, are you sure you are reading data from hardware correctly? I found the datasheet of the accelerometer and it is written there that data is stored in 14 bits for each axis. The highest unsigned value in hex that can be stored in 14 bits is 3FFF, which is far less than some of your data; for example: c0c0, acc0...
You can find the datasheet here!
If u let me know how u read data from the hardware, I might be able to help you :)
Good luck!

How do you find the largest product of 4 consecutive numbers in a grid? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
Here's the problem:
Find the largest product of a horizontal or vertical line of four consecutive numbers in this grid. Here, "consecutive" means four numbers that lie next to each other in the same row or column. For example, the top row starts with the four consecutive numbers 8, 2, 22, and 97. Consecutive numbers do not "wrap around" sides of the grid.
I know that I should convert the grid into a number of lists and kind of go through each quad (pairs except 4 instead of 2). But I'm not sure how to save it as a file and how to do anything with this to code to the answer.
My SPECIFIC question is what exactly is the problem asking me to do and what would be the pseudocode? Taking 4 two-digit numbers and multiplying them does not give an 8-digit number (unless I'm crazy).
I have no code as of now.
Here is the 20x20 grid:
It should output an 8-digit number.
import numpy as np
np.random.seed(10)
a = np.random.randint(1,10,(6,7))
func = lambda arr,n:(arr[:,np.arange(arr.shape[1]-n+1)[:,None] + np.arange(n)]).prod(2).max()
np.r_[func(a,4),func(a.T,4)].max()
Now Using the GRID:
import io
grid = np.loadtxt(io.StringIO(GRID))
np.r_[func(grid,4),func(grid.T,4)].max()
Out: 51267216.0
Without using numpy, you could do:
from functools import reduce
prod = lambda lst: reduce(lambda x,y:x*y,lst)
def slice_grid_max(grid,n):
n_cols = len(list(zip(*grid)))
f = lambda grid: max([prod(j[i:i+n]) for j in grid for i in range(n_cols-n+1)])
return max((f(grid),f(zip(*grid))))
slice_grid_max(grid,4)
Out: 51267216.0
If you would like to solve this problem using Python's standard library without having to resort to any third-party modules, you can use the following program as a demonstration of how you could go about doing that:
#! /usr/bin/env python3
import enum
# The grid was converted here: https://easypdf.com/ocr-online
# After some manual cleanup of the conversion, you have this:
GRID = '''\
08 02 22 97 38 15 00 40 00 75 04 05 07 78 52 12 50 77 91 08
49 49 99 40 17 81 18 57 60 87 17 40 98 43 69 48 04 56 62 00
81 49 31 73 55 79 14 29 93 71 40 67 53 88 30 03 49 13 36 65
52 70 95 23 04 60 11 42 69 24 68 56 01 32 56 71 37 02 36 91
22 31 16 71 51 67 63 89 41 92 36 54 22 40 40 28 66 33 13 80
24 47 32 60 99 03 45 02 44 75 33 53 78 36 84 20 35 17 12 50
32 98 81 28 64 23 67 10 26 38 40 67 59 54 70 66 18 38 64 70
67 26 20 68 02 62 12 20 93 63 94 39 63 08 40 91 66 49 94 21
24 55 58 05 66 73 99 26 97 17 78 78 96 83 14 88 34 89 63 72
21 36 23 09 75 00 76 44 20 45 35 14 00 61 33 97 34 31 33 95
78 17 53 28 22 75 31 67 15 94 03 80 04 62 16 14 09 53 56 92
16 39 05 42 96 35 31 47 55 58 88 24 00 17 54 24 36 29 85 57
86 56 00 48 35 71 89 07 05 44 44 37 44 60 21 58 51 54 17 58
19 80 81 68 05 94 47 69 28 73 92 13 86 52 17 77 04 89 55 40
04 52 08 83 97 35 99 16 07 97 57 32 16 26 26 79 33 27 98 66
88 36 68 87 57 62 20 72 03 46 33 67 46 55 12 32 63 93 33 69
04 42 16 73 38 25 39 11 24 94 72 18 08 46 29 32 40 62 76 36
20 69 36 41 72 30 23 88 34 62 99 69 82 67 59 83 74 04 36 16
20 73 35 29 78 31 90 01 74 31 49 71 48 86 81 16 23 57 05 34
01 70 54 71 83 51 54 69 16 92 33 48 61 43 52 01 89 19 67 48'''
CONSECUTIVE = 4
def main():
matrix = convert_grid_to_matrix()
products = {}
calculate_horizontal_products(matrix, products)
calculate_vertical_products(matrix, products)
largest_products = calculate_largest_products(products)
display_largest_products(matrix, largest_products)
def convert_grid_to_matrix():
return tuple(tuple(map(int, line.split())) for line in GRID.splitlines())
def calculate_horizontal_products(matrix, products):
calculate_all_products(matrix, products, Orientation.HORIZONTAL)
def calculate_all_products(matrix, products, orientation):
for row, column in generate_starting_coordinates(matrix, orientation):
products[(row, column, orientation)] = calculate_product(
get_numbers(matrix, row, column, orientation)
)
def calculate_product(numbers, start=1):
for value in numbers:
start *= value
return start
def generate_starting_coordinates(matrix, orientation):
if orientation is Orientation.HORIZONTAL:
for row in range(len(matrix)):
for column in range(len(matrix[row]) - CONSECUTIVE + 1):
yield row, column
elif orientation is Orientation.VERTICAL:
for row in range(len(matrix) - CONSECUTIVE + 1):
for column in range(len(matrix[row])):
yield row, column
else:
raise ValueError(f'{orientation!r} is not a valid orientation')
def get_numbers(matrix, row, column, orientation):
if orientation is Orientation.HORIZONTAL:
return matrix[row][column:column + CONSECUTIVE]
if orientation is Orientation.VERTICAL:
return tuple(
matrix[row + offset][column] for offset in range(CONSECUTIVE)
)
raise ValueError(f'{orientation!r} is not a valid orientation')
def calculate_vertical_products(matrix, products):
calculate_all_products(matrix, products, Orientation.VERTICAL)
def calculate_largest_products(products):
max_value = max(products.values())
for key, value in products.items():
if value == max_value:
yield key
def display_largest_products(matrix, largest_products):
print('The largest product(s) can be found here:')
for coordinate in largest_products:
print(' Row: {}, Column: {}, {}'.format(*coordinate))
display_calculation(matrix, *coordinate)
def display_calculation(matrix, *coordinate):
numbers = get_numbers(matrix, *coordinate)
operation = ' * '.join(map(str, numbers))
print(f' {operation} = {calculate_product(numbers):,}')
#enum.unique
class Orientation(enum.Enum):
HORIZONTAL = enum.auto()
VERTICAL = enum.auto()
if __name__ == '__main__':
main()

Hi, I want to know how can we insert binary data between a binary string in python 3.7?

So, here is something I want to do;
binary_string_data_input = '00 AE 65 67 32 2F 33 3A 54 20 46'
and I want to insert the following bytes BETWEEN the string like this:
binary_string_data_output = '00 AE 65 67 **55 06 33 55 FF** 32 2F 33 3A 54 20 46'
Help would be much appreciated thanks!
You can split (or slice) to get the first part:
>>> string_data_input[:12]
'00 AE 65 67 '
and similarly the last part:
>>> string_data_input[12:]
'32 2F 33 3A 54 20 46'
So, you can join these with your new "inner" part:
>>> string_data_input[:12] + '55 06 33 55 FF ' + string_data_input[12:]
'00 AE 65 67 55 06 33 55 FF 32 2F 33 3A 54 20 46'

Strange Payload when generating raw packet with Scappy

I am having an strange problem trying to generate a raw packet with Scappy.
I am doing the following:
eee=Ether(dst='08:00:11:11:11', src='08:00:11:11:22:22', type=0x888)/Raw(load='112233445566778888776655443322110901')
But when I do a hexdump of the newly created packet:
hexdump(eee)
0000 08 00 11 11 11 00 08 00 11 11 22 22 08 88 **31 31** ..........""..11
0010 **32 32** 33 33 34 34 35 35 36 36 37 37 38 38 38 38 2233445566778888
0020 37 37 36 36 35 35 34 34 33 33 32 32 31 31 30 39 7766554433221109
0030 30 31
It look like it is appending a 3 to the hexdump version of the payload. I really do not know from where that 3 is appearing.
Thanks in advance for any hint.
The Raw layer takes the binary representation of the load argument. Since the ascii value of the character 1 is 0x31 and the ascii value of the character 2 is 0x32, the binary representation of the string 1122 is 0x31313232. That's what you see as the output of hexdump.
What you need to do is decode the string before transferring it as the load argument to the Raw layer:
In [1]: from scapy.all import *
WARNING: No route found for IPv6 destination :: (no default route?)
In [2]: eee=Ether(dst='08:00:11:11:11', src='08:00:11:11:22:22', type=0x888)/Raw(load='112233445566778888776655443322110901'.decode("HEX"))
In [3]: hexdump(eee)
0000 08 00 11 11 11 00 08 00 11 11 22 22 08 88 11 22 ..........""..."
0010 33 44 55 66 77 88 88 77 66 55 44 33 22 11 09 01 3DUfw..wfUD3"...

How to decode the TCP buffer data

I am trying to write a tcp server to get the data from Heacent 908 GPS tracker. After establishing the connection from the tracker I am getting the following buffer output.
<Buffer 78 78 0d 01 03 87 11 31 20 86 48 42 00 06 64 be 0d 0a>
<Buffer 78 78 0d 01 03 87 11 31 20 86 48 42 00 06 64 be 0d 0a>
<Buffer 78 78 0d 01 03 87 11 31 20 86 48 42 00 06 64 be 0d 0a>
<Buffer 78 78 0d 01 03 87 11 31 20 86 48 42 00 06 64 be 0d 0a>
<Buffer 78 78 0d 01 03 87 11 31 20 86 48 42 00 06 64 be 0d 0a>
<Buffer 78 78 0d 01 03 87 11 31 20 86 48 42 00 06 64 be 0d 0a>
<Buffer 78 78 0d 01 03 87 11 31 20 86 48 42 00 06 64 be 0d 0a>
I am not sure how to decode this data into proper readable format.
Note: Off course I have tried to reach the manufacture but they are not responding at all.
What type of possible encoding formats are there for TCP protocol?
On next day I got data like this
<Buffer 78 78 0d 01 03 87 11 31 20 86 48 42 00 07 75 37 0d 0a>
<Buffer 78 78 0d 01 03 87 11 31 20 86 48 42 00 07 75 37 0d 0a>
<Buffer 78 78 0d 01 03 87 11 31 20 86 48 42 00 07 75 37 0d 0a>
<Buffer 78 78 0d 01 03 87 11 31 20 86 48 42 00 07 75 37 0d 0a>
<Buffer 78 78 0d 01 03 87 11 31 20 86 48 42 00 07 75 37 0d 0a>
<Buffer 78 78 0d 01 03 87 11 31 20 86 48 42 00 07 75 37 0d 0a>
<Buffer 78 78 0d 01 03 87 11 31 20 86 48 42 00 07 75 37 0d 0a>
<Buffer 78 78 0d 01 03 87 11 31 20 86 48 42 00 07 75 37 0d 0a>
<Buffer 78 78 0d 01 03 87 11 31 20 86 48 42 00 07 75 37 0d 0a>
<Buffer 78 78 0d 01 03 87 11 31 20 86 48 42 00 08 8d c0 0d 0a>
<Buffer 78 78 0d 01 03 87 11 31 20 86 48 42 00 08 8d c0 0d 0a>
<Buffer 78 78 0d 01 03 87 11 31 20 86 48 42 00 08 8d c0 0d 0a>
<Buffer 78 78 0d 01 03 87 11 31 20 86 48 42 00 08 8d c0 0d 0a>
<Buffer 78 78 0d 01 03 87 11 31 20 86 48 42 00 08 8d c0 0d 0a>
<Buffer 78 78 0d 01 03 87 11 31 20 86 48 42 00 08 8d c0 0d 0a>
<Buffer 78 78 0d 01 03 87 11 31 20 86 48 42 00 08 8d c0 0d 0a>
<Buffer 78 78 0d 01 03 87 11 31 20 86 48 42 00 08 8d c0 0d 0a>
<Buffer 78 78 0d 01 03 87 11 31 20 86 48 42 00 08 8d c0 0d 0a>
<Buffer 78 78 0d 01 03 87 11 31 20 86 48 42 00 08 8d c0 0d 0a>
<Buffer 78 78 0d 01 03 87 11 31 20 86 48 42 00 08 8d c0 0d 0a>
<Buffer 78 78 0d 01 03 87 11 31 20 86 48 42 00 08 8d c0 0d 0a>
<Buffer 78 78 1f 12 0e 02 14 13 01 14 c8 03 5f a6 50 07 f7 f8 c1 32 35 39 01 9a 04 0f a2 00 b0 5a 00 1a 9b 7a 0d 0a>
<Buffer 78 78 1f 12 0e 02 14 13 01 1e c8 03 5f ad bc 07 f7 f0 76 41 35 40 01 9a 04 0f a2 00 b0 5a 00 1b b6 31 0d 0a>
Something is being changed but not sure what is it...
You ask what possible encoding formats there are for TCP. That's a bit of an odd question: there are an unbounded number of encoding formats using TCP as the underlying protocol. But no matter, we can try to figure out this one!
You've posted some sample messages. Let's see if we can translate them:
byte 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
rev 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
----------------------------------------------------------
hex 78 78 0d 01 03 87 11 31 20 86 48 42 00 06 64 be 0d 0a
text x x \r -- -- -- -- 1 -- H B -- -- d -- \r \n
dec 13 1 3 17 0 6 100 13 10
be32 [218170247] [288432262] [ 419006]
----------------------------------------------------------
hex 78 78 0d 01 03 87 11 31 20 86 48 42 00 07 75 37 0d 0a
text -- u 7
dec 7 117 55
be32 [ 488759]
----------------------------------------------------------
hex 78 78 0d 01 03 87 11 31 20 86 48 42 00 08 8d c0 0d 0a
text -- -- --
dec 8 141
be32 [ 560576]
----------------------------------------------------- byte 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
hex 78 78 1f 12 0e 02 14 13 01 14 c8 03 5f a6 50 07 f7 f8 c1 32 35 39 01 9a 04 0f a2 00 b0 5a 00 1a 9b 7a 0d 0a
text -- -- -- -- -- -- -- -- -- -- _ -- P -- -- -- -- 2 5 9 -- -- -- -- -- -- -- -- -- xx -- z \r \n
----------------------------------------------------------
hex 78 78 1f 12 0e 02 14 13 01 1e c8 03 5f ad bc 07 f7 f0 76 41 35 40 01 9a 04 0f a2 00 b0 5a 00 1b b6 31 0d 0a
text -- -- -- A 5 # -- xx -- 1
Some potentially interesting facts:
Starts with "xx\r\01" which more or less seems like a possible header. But later messages start with "xx" and something else. Anyway, given that NMEA has a prefix of "GP" I wouldn't be shocked if these devices used "xx" for "something that's not NMEA."
Has "HB" in the middle, which could mean "heartbeat" since this is repeating, perhaps waiting for a reply from the server.
Ends with "\r\n" which is a common line ending (on Windows in particular), though the rest doesn't appear to be entirely textual.
The earlier messages are 18 bytes long and the later ones 36 bytes. A guess would be the short ones are status updates or heartbeats and the long ones are actual location information. 36 bytes is enough if we figure:
4 byte latitude: 24 bits if you pinch (see), 25-32 bits more likely
4 byte longitude: same as latitude
6 byte timestamp: 39 bits if using epoch time with centiseconds, 32/48/64 bits more likely
2 byte altitude: I suspect this device doesn't publish altitude at all, given some of the docs
So I think what is going on is that these messages you see are just the device "pinging" the server and waiting for a response. What sort of response? Well, you could try to brute force it, but far, far easier would be to set up a bridge in your program that takes whatever it receives from the device, sends it to the manufacturer's server, and does the same thing in reverse for the responses to the device. This way you will quickly be able to gather a corpus of valid messages which will be very helpful if we really do need to reverse engineer this thing. Or if you're lucky it will turn out to use some standard protocol like NMEA after negotiating the initial session.
Edit: now that you've given us more messages from the device, we can see that it does seem to send something else with variable content. Maybe that's the location data, but I don't have time to try to reverse engineer it right now. One idea is to physically move the unit from west to east or north to south and capture the messages it sends during that time, to try to isolate which parts of the messages are the longitude and which are the latitude (and perhaps timestamp too).
I think it's fairly clear that the first two bytes are "xx" as a header, and the last two are "\r\n" as a terminator. That leaves 32 bytes of payload in the longer messages, all of which appears to be binary data.
It's the GT06 protocol and you can find it's specs here:
http://www.traccar.org/devices/
http://www.traccar.org/docs/protocol.jsp
https://dl.dropboxusercontent.com/s/sqtkulcj51zkria/GT06_GPS_Tracker_Communication_Protocol_v1.8.1.pdf
You can do it this way:
client.on('data', (buffer) => {
const decodedData = buffer.toString('utf8')
console.log(decodedData)
})

Resources