2015년 5월 3일 일요일

아두이노 심플파서

 던전워즈
간단하게 텍스트 형식으로 데이터 전달이 필요할때 심플하게 이용할 수 있는 파서이다.

#define MAX_DATA_BUFFER 100 //파서 임시 버퍼 사이즈, 자신의 환경에 맞게 적절히 길이를 조정
#define MAX_WORD_LENGTH 50  //한단어의 최대길이, 자신의 환경에 맞게 적절히 길이를 조정
#define SEPARATOR_MARK ';' //각 단어사이를 구분하는 구분자

/*
세미콜론 기호를 구분자로 전송된 데이터를 파싱하는 클래스

데이터 전송측에서 

data;1.5;3.5;ffffffffffffff;

등과 같이 각 데이터 사이를 세미콜론으로 구분하여 전송하는 경우, 수신된 순서되로 데이터를 분리해낼 수 있다.

위 데이터 전송예시의 경우

GetBlock()함수의 매 호출마다 얻어지는 결과는

data
1.5
3.5
ffffffffffffff
등과 같다.

*/

class CSimpleParser
{
char m_cArrLastWord[MAX_WORD_LENGTH];
char m_cArray[MAX_DATA_BUFFER]; //시리얼로부터 수신받은 데이터를 저장하는 버퍼
int m_iPos; //다음 저장할 위치

public:

CSimpleParser()
{
m_iPos = 0;
m_cArray[0] = 0;
}


//시리얼로부터 수신받은 데이터에서 수신이 완료된 한단어 블록을 가져옴
//수신받은 명령이 없으면 null을 리턴
char* GetBlock()
{

int tagpos = FindSeparator();

if (tagpos < 0)

return NULL;

if (tagpos != 0)
{
memcpy(m_cArrLastWord, m_cArray, tagpos);
m_cArrLastWord[tagpos] = 0;
}

if ((tagpos + 1) < m_iPos)
CopyData(0, tagpos + 1, m_iPos - tagpos - 1);

m_iPos -= tagpos + 1;  

if (tagpos != 0)
return m_cArrLastWord;

return NULL;
}

//수신된 정수 값을 얻음, 수신된 데이터가 없는경우나 올바르지 않은 포맷인경우에도 0을 리턴하므로 주의가 필요함
int GetInt()
{
char* pValue = GetBlock();

if (pValue != NULL)
return atoi(pValue);

return 0;
}

//수신된 실수 값을 얻음, 수신된 데이터가 없는경우나 올바르지 않은 포맷인경우에도 0을 리턴하므로 주의가 필요함
float GetFloat()
{
char* pValue = GetBlock();

if (pValue != NULL)
return (float)atof(pValue);

return 0.0f;
}

//시리얼로부터 데이터를 수신하여 버퍼에 쌓는다.
void ProcessSerial()
{
int receivedbytes = Serial.available();

if (receivedbytes > 0)
{

for (int i = 0;i < receivedbytes; ++i)
{
PushData(Serial.read());
}
}
}

protected:


//프로토콜에서 정의한 명령의 끝을 찾는다. 즉 버퍼에서 ;의 위치를 찾음
int FindSeparator()
{
for (int i =0;i < m_iPos; ++i)
{
if (m_cArray[i] == SEPARATOR_MARK)
return i;
}

return -1;
}

//한 바이트를 버퍼에 삽입
void PushData(int data)
{
if (m_iPos < MAX_DATA_BUFFER)
m_cArray[m_iPos++] = (unsigned char)data;
}


//srcindex위치에서 datasize바이트 만큼 destindex위치에 복사한다.
void CopyData(int destindex, int srcindex, int datasize)
{
for (int i = 0;i < datasize; ++i)
{
m_cArray[destindex + i] = m_cArray[srcindex + i];
}
}
};

CSimpleParser g_Parser;

void setup()
{
  Serial.begin(9600);
}


void loop()
{
//시리얼에서 데이터 수신을 처리한다.
  g_Parser.ProcessSerial();


  //주신완료된 단어가 있으면 가져와서 시리얼에 다시 전송한다.
  char* pWord = g_Parser.GetBlock();

  if (pWord == NULL)
    return;
   

    Serial.print("received word : ");

    Serial.println(pWord);

}

댓글 없음:

댓글 쓰기