Read an incoming HEX packet from Serial - arduino

I'm coding a on an arduino and I am communicating with an other device in HEX. I would like to know how to read the data he sends me.
I am sending a HEX packet (everything good here, no problem)
//Ask for Data
Serial.write(askData, sizeof(askData));
After this I will receive data (in HEX). I need to store it all to use it later. The only thing I know is that it will end with a "16". I dont know the length of the packet in advance.
Here is an example or packet that I can reveive :
68 4E 4E 68 08 09 72 90 90 85 45 68 50 49 06 19 00 00 00
0C 14 02 00 00 00 8C 10 12 35 02 00 00 0B 3B 00 00 00 8C
20 14 02 00 00 00 8C 30 14 00 00 00 00 04 6D 2F 09 61 24
4C 14 02 00 00 00 42 6C 5F 2C 42 EC 7E 7F 2C 0A 92 2A 00
10 0A 92 2B 00 10 39 16
Can someone help me please ?

This arduino example slightly modified:
/* reserve 200 bytes for the inputString:
* assuming a maximum of 200 bytes
*/
uint8_t inputString[200]; // a String to hold incoming data
int countInput = 0;
bool stringComplete = false; // whether the string is complete
void setup() {
// initialize serial:
Serial.begin(115200);
}
void loop() {
// print the string when 0x16 arrives:
if (stringComplete) {
for (int i=0; i<countInput; i++) {
Serial.print(inputString[i], HEX);
Serial.print(" ");
}
// clear the string:
countInput = 0;
stringComplete = false;
}
}
/*
SerialEvent occurs whenever a new data comes in the hardware serial RX. This
routine is run between each time loop() runs, so using delay inside loop can
delay response. Multiple bytes of data may be available.
*/
void serialEvent() {
while (Serial.available()) {
// get the new byte:
inputString[countInput] = (uint8_t)Serial.read();
// if the incoming character is '0x16', set a flag so the main loop can
// do something about it:
if (inputString[countInput] == 0x16) {
stringComplete = true;
}
countInput++;
}
}

Related

Lua TCP communication

I have a proprietary client application that sends and receives TCP data packets to|from the network device like this:
Sent: [14 bytes]
01 69 80 10 01 0E 0F 00 00 00 1C 0D 64 82 .i..........d.
Received: [42 bytes] [+00:000]
01 69 80 10 01 2A 00 D0 DC CC 0C BB C0 40 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 .i...*.......#..................
00 00 00 00 00 00 1C 0D F6 BE ..........
or see the picture
I need to make same requests with Lua. I've found some working examples (for ex) for such communications, but I can't understand what string should I give as an argument for
tcp:send("string");
Should I give it a string of hex? I.e.
'01698010010E0F0000001C0D6482'
Or first convert hex to ACSII? If so, then how (zeroes doesn't convert to symbols)?
You should give it the string you want to send. If you write "016980..." it's a string containing decimal values 48 (ascii digit 0), 49 (ascii digit 1), 54 (ascii digit 6), and so on. Which is not what you want to send. You want to send decimal values 1, 105 (hex 69), 128 (hex 80) and so on.
Luckily, Lua strings can hold any bytes (unlike e.g. Python strings). So you just have to write a string with those bytes. You can write any byte into a string using \x and then a 2-digit hex code. So you could write your call like this:
tcp:send("\x01\x69\x80\x10\x01\x0E\x0F\x00\x00\x00\x1C\x0D\x64\x82")
If you are using a Lua version older than 5.2, \x is not available, but you can still use \ and a 3-digit decimal code.

Get consistent md5 checksum of gzipped file using data.table and R.utils

I'm trying to replicate the checksum of a compressed file with R.utils::gzip and the compress = "gzip" argument of data.table::fwrite but I keep getting different results. Here is an example
library(data.table); library(R.utils); library(digest)
dt <- data.frame(a = c(1, 2, 3))
fwrite(dt, "r-utils.csv")
gzip("r-utils.csv")
fwrite(dt, "datatable-v1.csv.gz", compress = "gzip")
digest(file = "r-utils.csv.gz")
#> [1] "8d4073f4966f94ac5689c6e85de2d92d"
digest(file = "datatable-v1.csv.gz")
#> [1] "5d58f9eeefb166c6d50ac00f3215e689"
Initially I though that fwrite was storing the filename and timestamp in the output file (per the usual gzip behaviour without the --no-name option), but that don't appear to be the case since I get the same checksum in different calls to fwrite
fwrite(dt, "datatable-v2.csv.gz", compress = "gzip")
digest(file = "datatable-v2.csv.gz")
#> [1] "5d58f9eeefb166c6d50ac00f3215e689"
Any ideas on what might be causing the difference?
PS. Incidentally, the checksum of the uncompressed files are the same
$ md5sum datatable-v1.csv
7e034138dc91aa575d929c1ed65aa67c datatable-v1.csv
$ md5sum r-utils.csv
7e034138dc91aa575d929c1ed65aa67c r-utils.csv
If you look at the bytes, you can see they are different
r-utils.csv.gz
Offset: 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
00000000: 1F 8B 08 00 00 00 00 00 00 06 4B E4 E5 32 E4 E5 ..........Kde2de
00000010: 32 E2 E5 32 E6 E5 02 00 21 EB 62 BF 0C 00 00 00 2be2fe..!kb?....
and
datatable-v2.csv.gz
Offset: 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
00000000: 1F 8B 08 00 00 00 00 00 00 0A 4B E4 E5 02 00 56 ..........Kde..V
00000010: EF 2F E3 03 00 00 00 1F 8B 08 00 00 00 00 00 00 o/c.............
00000020: 0A 33 E4 E5 32 E2 E5 32 E6 E5 02 00 49 C4 FF 4D .3de2be2fe..ID.M
00000030: 09 00 00 00 ....
So the data.table one is longer. This appears to be because the default compression settings are different. Specifically it looks like the two method use a different "window size" parameter. The data.table code uses a windowBits value of 31 (15+16) which will include "trailing checksum in the output" but the R.utils::gzip function uses the base R gzfile() function which uses a windowBits value of -15 (MAX_WBITS) and that negative value means a trailing checksum should not be used. So I think that accounts for the extra bytes in the in the data.table output.
Because you can use different compression level settings and checksums and gzip headers, it's not necessarily the case the you will get the same checksum for compressed versions of data files if two different compression pipelines are used. So it's possible for the data inside to be identical but the actual compressed files to be different.
Since these settings are part of the C code for the package and for base R this is not something you will be able to change in R code. It's not possible for these two different methods to return identical output.

gRPC message format

I'd like to know how to properly construct GRPC REQUEST and RESPONSE. There are only two resources that I found on the "codec" part:
Encoding: https://developers.google.com/protocol-buffers/docs/encoding
HTTP/2: https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md#message-encoding
I believe I understand both documents. I understand how the HTTP/2 framing works (I implemented my own HTTP/2 server and client in Rust so I understand it in detail) but the sent message is always somehow invalid.
Let's take for an example this simple message (proto3):
message Test1 {
int32 a = 1;
}
I'm dealing with the RESPONSE part only for now. The wire format for value 150 (as specified in the google's example) should be Hex[08, 96, 01] ([00001000, 10010110, 00000001]). I pack this into a DATA frame and send it as a RESPONSE back to the GRPC client. Here's what the response looks like:
...
[ 0.010] recv SETTINGS frame <length=0, flags=0x00, stream_id=0>
(niv=0)
00000000 00 00 00 04 01 00 00 00 00 |.........|
00000009
[ 0.010] recv SETTINGS frame <length=0, flags=0x01, stream_id=0>
; ACK
(niv=0)
[ 0.010] send SETTINGS frame <length=0, flags=0x01, stream_id=0>
; ACK
(niv=0)
00000000 00 00 0e 01 04 00 00 00 0d 88 5f 8b 1d 75 d0 62 |.........._..u.b|
00000010 0d 26 3d 4c 4d 65 64 |.&=LMed|
00000017
[ 0.012] recv (stream_id=13) :status: 200
[ 0.012] recv (stream_id=13) content-type: application/grpc
[ 0.012] recv HEADERS frame <length=14, flags=0x04, stream_id=13>
; END_HEADERS
(padlen=0)
; First response header
00000000 00 00 03 00 00 00 00 00 0d 08 96 01 |............|
0000000c
[ 0.016] recv DATA frame <length=3, flags=0x00, stream_id=13>
00000000 00 00 0f 01 05 00 00 00 0d 40 0b 67 72 70 63 2d |.........#.grpc-|
00000010 73 74 61 74 75 73 81 07 |status..|
00000018
[ 0.016] recv (stream_id=13) grpc-status: 0
[ 0.016] recv HEADERS frame <length=15, flags=0x05, stream_id=13>
; END_STREAM | END_HEADERS
(padlen=0)
[ 0.021] send GOAWAY frame <length=8, flags=0x00, stream_id=0>
(last_stream_id=0, error_code=NO_ERROR(0x00), opaque_data(0)=[])
There must be a missing header or I'm missing the message format. Can someone please post a working example using curl. Thank you!
I realized that the Length-Prefixed-Message is actually Length-Prefixed, Message so every DATA payload must be prefixed.

Problem with sending HDLC frames by using GSM modem

I have SL7000 meter and GSM Modem iRZ. When i send by using RS-485 cable - everything work. But when i'm trying to use GSM modem i'm getting issues.
When i send SNRM like this:
7E A0 0A 00 22 00 51 03 93 6A 34 7E
I get normal UA.
But when i try to send SNRM like this:
7E A0 21 00 22 00 51 03 93 6B 21 81 80 12 05 01 80 07 04 00 00 00 02 08 04 00 00 00 01 3D 93 7E (It's from DXDLMSDirector)
I get nothing. Absolutely!
Maybe there is some trick to use hdlc with gsm modem? Maybe special delays or something?
If both of these frames work via the RS-485, and not via the GSM, then there are a couple of possible answers:
1) the addressing you are using is not permitted if this is a seperate port
2) if it is the same port on the meter, then the GSM Modem is not directing traffic to the same RS485 address

Advertise Bluetooth LE Service using HCITool

I'm experimenting with creating a Bluetooth Low Energy Peripheral on my Linux computer (The goal is to send data over Bluetooth From an iPhone). Im currently using the Tools hciconfig, hcitool and hcidump.
My current experiment is to advertise a Service with a Specific UUID, that the iOS CoreBluetooth Library will pick up. (Note: I'm not trying to create an iBeacon).
Right now, it's actually as simple as One Single Command that is bugging me.
hcitool -i hci0 cmd 0x08 0x0008 15 02 01 1a 11 07 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50
What I think it should do is the following:
0x08: Setting Group to BLE
0x0008: Setting Command to HCI_LE_Set_Advertising_Data
0x15: Setting the Length of the Significant Bytes in the Header to 21. (3 Byte for the Flag packet, 18 Byte for the Service Structure)
0x02: Setting the Length of the Flags structure to 2 Bytes
0x01: Setting the structure Type to AD Flags
0x1a: Flag Value:
bit 0 (OFF) LE Limited Discoverable Mode
bit 1 (ON) LE General Discoverable Mode
bit 2 (OFF) BR/EDR Not Supported
bit 3 (ON) Simultaneous LE and BR/EDR to Same Device Capable (controller)
bit 4 (ON) Simultaneous LE and BR/EDR to Same Device Capable (Host)
(End of Flag)
0x11 Setting the Length of Service Structure to 17 Bytes
0x07 Setting the Structure Type to 128 Bit Complete Service UUID List
0x41 ... 0x50 Setting the UUID of the Test Service to ABCDEFGHIJKLMNOP
As far as I can see with hcidump, it's executed properly and looks the way I wanted to. But it's rejected with Error:
LE Set Advertising Data (0x08|0x0008) ncmd 1
status 0x12
Error: Invalid HCI Command Parameters
And I have spent a whole day trying to get it right. Does someone skilled see what I have done wrong? And is this the correct way to advertise a Service?
(Context for the Interested reader: I have successfully accomplished what I want to do using the Bleno Library in NodeJs. However, this will not fit into the bigger picture in our System. Using HCITool directly for advertising is just for experimentation and will be written in Python later)
The length of the the HCI_LE_Set_Advertising_Data payload should be exactly 32 bytes. Try zero padding the command to reach 32 bytes:
hcitool -i hci0 cmd 0x08 0x0008 15 02 01 1a 11 07 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50 00 00 00 00 00 00 00 00 00 00
You can gain some more insight using hcidump --raw.
Compare the output of the original command:
$hcidump --raw
HCI sniffer - Bluetooth packet analyzer ver 5.30
device: hci0 snap_len: 1500 filter: 0xffffffffffffffff
< 01 08 20 16 15 02 01 1A 11 07 41 42 43 44 45 46 47 48 49 4A
4B 4C 4D 4E 4F 50
> 04 0E 04 01 08 2
With the zero padded one:
HCI sniffer - Bluetooth packet analyzer ver 5.30
device: hci0 snap_len: 1500 filter: 0xffffffffffffffff
< 01 08 20 20 15 02 01 1A 11 07 41 42 43 44 45 46 47 48 49 4A
4B 4C 4D 4E 4F 50 00 00 00 00 00 00 00 00 00 00
> 04 0E 04 01 08 20 00
Another way to gain more insight is to run hciconfig hci0 leadv and use hcidump --raw to examine the payload of the SET_ADVERTISING_PARAMETERS command send by hciconfig.
By the way, I've noticed that sometimes a non zero padded command also works, it might depend on the bluez version you are using.

Resources