반응형

안녕하세요. 

 

요즘 LoRa에서 End Device에서 바이트형식으로 오는 데이터를 파싱하기 위해 bytearray로 골머리를 썩고 있는데, 연구실 형님이 Python Struct을 추천해서 알게 되었습니다.

 

Python이 굉장히 잘 만든 언어이지만, 바이트나 비트를 처리하기에는 너무 까다롭습니다. 

 

bytearray를 이용해 데이터를 파싱하거나 checksum 계산을 수행할 때 PTSD가 왔는데, Python Struct는 정말 신세계에 가까웠습니다.

checksum
bytearray

 


파이썬 Struct는 C언어 Struct와 비슷합니다. 자세한 내용은 공식문서를 통해 참고하시면 됩니다.

https://docs.python.org/3/library/struct.html

 

struct — Interpret bytes as packed binary data — Python 3.9.7 documentation

struct — Interpret bytes as packed binary data Source code: Lib/struct.py This module performs conversions between Python values and C structs represented as Python bytes objects. This can be used in handling binary data stored in files or from network c

docs.python.org

 

https://coding-yoon.tistory.com/120

 

[C] UNION 공용체와 Struct 구조체를 이용해 간단한 패킷 만들기

안녕하세요. 오늘은 UNION과 STRUCT에 대해 이야기 하겠습니다. coding-yoon.tistory.com/119 [C] 구조체 포인터 접근과 최적화 요즘 기본기가 중요함을 느끼고 C를 공부하고 있습니다. 1. 구조체 단순히접근

coding-yoon.tistory.com

 

위 내용을 이해할 수 있다면, 저 말이 무슨 말인지 쉽게 이해할 수 있습니다. 

 

아래와 같은 하나의 14바이트의 packet을 전송했다고 가정합니다. ( 아래 코드는 실제 패킷 중 하나이다. 쉬운 이해를 위해 그림으로)

위 union을 설명하는 블로그에서는 __attribute__에 대해 이야기하지 않았습니다. __attribute__는 패딩 비트가 생기지 않도록 합니다. 그러므로 16바이트가 아닌 14바이트로 메모리가 할당됩니다. 

Packet

파이썬에서 위 같은 바이트로 이루어진 패킷을 받을려면 어떻게 해야하나? bytearray를 쓰려고 하면 정신이 혼미해지지만,  Python Struct를 사용하면 머리의 두통이 사라진다.

 

사용법은 간단하다. 한 줄이면 위 데이터를 쉽게 파싱할 수 있다.

 

from struct import *

"""
Do Something
"""

data = "14바이트패킷" # stirng 아님 # <class 'bytes'>

payload = unpack('<Hfff',data)

u_cnt = payload[0]
lat = payload[1]
long_ = payload[2]
alt = payload[3]

unpack 명령어 한 줄로 파싱이 가능하다.

 

'<Hfff' 의 foramt 형식만 사용할 줄 알면 된다. 간단하다. 위 python 공식 문서에 나와 있는 내용이다. 

 

1. 맨 처음쓰는 것은 바이트 정렬이다. 위 사진의 패킷은 litte endian이므로 '<' 를 추가한다. 

byteorder

2. 바이트 정렬을 적었다면, 데이터의 타입이 나오게 된다. 패킷의 구성은 unsigned int(2), float(4), float(4), float(4)의 순서로 아래 표의 C Type을 보고 해당하는 format을 적으면된다.  'HFF'

결과적으로 unpack은 list 형태로 payload를 반환하게 된다. 

 

 

728x90
반응형
반응형

 

 

안녕하세요. 오늘은 UNION과 STRUCT에 대해 이야기 하겠습니다. 

 

coding-yoon.tistory.com/119

 

[C] 구조체 포인터 접근과 최적화

요즘 기본기가 중요함을 느끼고 C를 공부하고 있습니다. 1. 구조체 단순히접근 #include //Struct packet 선언 typedef struct packet { int data0; int data1; int data2; }Packet; int main() { Packet p; //Str..

coding-yoon.tistory.com

구조체에 대한 이야기는 위에 작성했지만, 저보다 훨씬 자세히 적은 블로그 분들이 많기 때문에 따로 찾아보시길 바랍니다.

 

UNION의 구조를 먼저 알아보겠습니다. 

 

UNION은 가장 사이즈가 큰 변수와 메모리를 공유합니다.

 

이게 무슨 말인가 하면

#include <stdio.h>

// 공용체 선언
typedef union data
{
	char a; 
	char b; 
	char c[2]; 
}Data;

int main(){

	Data data; // 공용체 data 정의

	data.c[0] = 'a';
	data.c[1] = 'b';

	printf("data.a = %c\n", data.a);
	printf("data.b = %c\n", data.b);
	printf("data.c[0] = %c\n", data.c[0]);
	printf("data.c[1] = %c", data.c[1]);
	

	return 0;
}


 

이런 간단한 코드에서  결과는 어떻게 나올까요?

 

왜 이런 결과가 나오느냐. 그림을 보시면 바로 이해할 수 있습니다.

 

이런 구조로 메모리를 서로 공유하고 있습니다. 주소를 찍어보면 더 확실하게 알 수 있습니다. 

 

#include <stdio.h>


typedef union data
{
	char a; 
	char b; 
	char c[2]; 
}Data;

int main(){

	Data data; 

	data.c[0] = 'a';
	data.c[1] = 'b';

	printf("data.a = %p\n", &data.a);  // a 주소 출력
	printf("data.b = %p\n", &data.b);  // b 주소 출력
	printf("data.c[0] = %p\n", &data.c[0]);  // c[0] 주소 출력
	printf("data.c[1] = %p", &data.c[1]);  // c[1] 주소 출력
	

	return 0;
}


출력

Union의 사이즈는 가장 사이즈가 큰 변수이며, 메모리를 공유합니다. 

 

Union은 어디에 많이 쓰일까요? 대표적으로 통신 분야로 가장 많이 사용됩니다. 

 

통신에서는 데이터를 전송을 잘하는 것도 중요하지만, 데이터를 수신해서 제대로 분해하는 것도 굉장히 중요합니다. 

 

꼭 이렇게 사용한다는 아니지만, 구조체와 적절히 사용하면 송신부분 수신부분을 만들 수 있습니다.  

 

#include <stdio.h>
#include <stdint.h>


// Struct Packet_s 선언
typedef struct packet_s
{
	uint8_t data0;
	uint8_t data1;
	uint8_t data2;
	uint8_t data3;

}Packet_s;

typedef union packet_u
{
	Packet_s ps;  // Struct Packet_s ps 정의 // 송신
	uint8_t pu[4];  // 수신
}Packet_u;



int main()
{
	Packet_u packet_data;

	packet_data.ps.data0 = 0;  // 예를 들어 uuid
	packet_data.ps.data1 = 1;  // minor
	packet_data.ps.data2 = 2;  // tx power
	packet_data.ps.data3 = 3;  // rssi

	printf("pacekt_data size = %d bytes\n\n", sizeof(packet_data));

	printf("송신 사이즈 : %d bytes\n\n", sizeof(packet_data.ps));

	
	printf("------송신 준비 완료------\n");
	printf("--------------------------\n");
	printf("--------------------------\n");
	printf("-------송수신 완료--------\n\n");

	printf("수신 사이즈 : %d bytes\n", sizeof(packet_data.pu));
	printf("uuid = %d\n", packet_data.pu[0]);
	printf("minor = %d\n", packet_data.pu[1]);
	printf("tx power = %d\n", packet_data.pu[2]);
	printf("rssi = %d\n", packet_data.pu[3]);


	

	return 0;
}

 

 

이런식으로 재밌게 구조체와 공용체를 관계를 적절히 사용하여 통신 패킷을 만들어 보았습니다.

 

그 외에도 Union은 다양한 방법으로도 유용하게 사용되고 있습니다. 

728x90
반응형

+ Recent posts