[WizFi360] 응답 관련 질문

펌웨어 버전 정보는 아래와 같습니다.

AT+GMR
AT version:1.0.7.0(Jan 29 2020 16:16:25)
SDK version:3.2.0(a0ffff9f)
compile time:Jan 29 2020 16:16:25

WiFi 모듈 응답을 사람이 처리하는 것이 아니기 때문에 코딩을 통해 문자열을 파싱하려고 한다면 WiFi 모듈의 응답에 규칙성이 있어야 한다고 생각합니다.

TCP connection 을 맺는 것까지 몇 개의 명령을 테스트해본 결과
UART_CUR? 이라는 query 문을 제외하고는 과 OK 메시지 사이가 0x0d, 0x0a, 0x0d, 0x0a 로 구분이 됩니다. 그런데 UART_CUR? query 만 0x0d, 0x0a 로 구분이 되네요.

command: [AT+UART_CUR?]

uwizfi response =====> [
AT+UART_CUR?
+UART_CUR:115200,8,1,0,0
OK
]

이것은 의도된 것인가요? 오류인가요?

가끔 OK 메시지 이후에 쓰레기 문자열이 따라붙는 것 같습니다. CWMODE_CUR? 퀘리에 대한 응답입니다.

정상적인 응답
wizfi response: [AT+CWMODE_CUR?
+CWMODE_CUR:1

OK
]

다음은 비정상적인 응답으로 보이는 사례입니다.
[AT+CWMODE_CUR?
+CWMODE_CUR:1

OK
AT+]

모든 응답은 0x0d, 0x0a 로 끝나는 것으로 보이는데 비정상적인 응답에서는 AT+ 로 끝나고 있습니다.

제가 사용하는 코드의 일부입니다.
ret = UART_READ(device, wifiRXbuf, sizeof(wifiRXbuf));
wifiRXbuf[ret] = ‘\0’;
CONSOLE_PRINTF(“wizfi response: [%s]\n”, wifiRXbuf);

이 문제가 리포트된 적이 있나요?

답변 기다리겠습니다.

질문 작성자입니다.

위에 질문 중에 2번째 질문은 취소하는 것이 맞을 듯 합니다. 여러 번의 명령/퀘리가 연속적으로 내려질 때 첫번째 명령의 응답 뒤에 그 다음 명령/퀘리에 대한 답변이 따라붙는 것으로 보입니다.

추가 질문(혹은 제안)이 있습니다.

AT 명령을 처리하다보니 line by line 으로 처리하는 것이 제일 효율적인 듯 합니다. 그런데 명령/퀘리의 종류에 따라 응답 포맷에 약간씩 차이가 있어 응답을 처리하기 위한 로직이 복잡해지는 듯 합니다.

처음 커넥션을 맺기 위한 동작까지는 어떻게 해도 큰 지장이 없습니다만 커넥션을 맺은 이후 +IPD 와 +CIPSEND 가 관건인 것으로 생각됩니다.

현재 binary file 을 WizFi 를 통해 보내려고 하고 있습니다. AT 명령을 통해야 하니 바이너리 그래도 보내진 못할 것이고 base64 인코딩을 통해서 보내려고 합니다. base64 인코딩 이전에 데이터 통신 방식은…

after TCP connection established.
단말 → 서버: 파일 전송 요청
서버 → 단말: 일정량의 데이타 전송
서버 → 단말: data integrity 체크 요청
단말: CRC 체크.
단말 → 서버: 파일의 다음 파트 전송 요청.
서버 → 단말: 일정량의 데이타 전송.

대체적으로 이런 식으로 통신이 이루어질 것인데요. WizFi 의 +IPD 형식이 불만족스럽습니다. 왜냐하면 기존 명령/퀘리 형식과 달리 <0x0d><0x0a> 가 없어서 line by line 처리가 어렵기 때문입니다. 즉 +IPD 스트링과 명령/퀘리 응답이 버퍼에 섞여 있다고 할 때 그 구분이 쉽게 되지 않습니다. 불가능하다는 얘기는 아닙니다. 되긴 하지만 로직을 더 쉽게 할 수 있는 방법이 있다고 생각하기 때문입니다.

인터넷에서 검색을 해보니 어떤 WiFi 모듈은 아래의 형식을 가지고 있더군요. 다른 명령/퀘리와 동일한 포맷을 가지고 있어서 명령/퀘리 처리 루틴을 가지고 서버에서 보내는 메시지를 쉽게 처리할 수 있습니다.
<0x0d><0x0a>+IPD,0,1:A<0x0d><0x0a>OK<0x0d><0x0a>

그에 반해서 WizFi 의 +IPD 포맷은 라인별로 처리를 할 수 없습니다.
+IPD,0,1:A

만약 아래와 같은 형식을 지원해준다고 한다면 별도로 +IPD 를 처리하기 위한 루틴을 만들지 않아도 됩니다. 왜냐하면 명령/퀘리와 동일하게 처리가 가능하기 때문에 서버 메시지를 매우 쉽게 분리할 수 있습니다.
+IPD,0,512,AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA…AAAA<0x0d><0x0a>
혹은
+IPD,0,512,AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA…AAAA<0x0d><0x0a>OK<0x0d><0x0a>

현재 상황에서 SEND OK 메시지를 파싱하지 않기 위해서 “transparent transmission mode” 를 사용할 수 밖에 없다는 결론을 얻었습니다. 하지만 send 결과를 알 수 없다는 것은 좋은 일이 아니죠.

이것에 대한 의견을 듣고 싶습니다.

안녕하세요 위즈네트 입니다.

좋은 의견 대단히 감사합니다.
다만, 출력 문자열을 바꾸는 F/W Update는 이미 WizFi360을 사용 중인 고객들의 제품과
호환성 문제가 발생하므로 상당히 민감한 문제 입니다.

제품 Revision 또는 신제품 출시시 말씀 주신 사항을 고려해 보겠습니다.
만족스러운 답변을 드리지 못한 점 양해 부탁 드리겠습니다.

감사합니다.

원래 목표했던 작업을 마무리하고 보니 +IPD 에 <0x0d><0x0a> 존재해야 하는 이유가 더욱 분명합니다. 단순히 고려할 문제가 아니라 그 방향이 맞다고 생각합니다.

왜냐하면… 누군가 line by line 파싱을 하려고 한다고 가정합니다. 다음 pseudo code 를 보시죠.

len = blocked_read(buffer, size)
push_into_ring_buffer(ring, buffer, len);
/* skip garbage 0x0d, 0x0a /
skip_0x0d_0x0a_in_ring(ring);
peek_ring_buffer(ring, &byte, 1);
if(byte == ‘+’) {
len = recv_svrmsg(device, ring, buffer1, size1);
return len;
}
ret = get_a_single_line_from_ring_buffer(ring, buffer1, size1);
if(ret > 0) {
/
a single line provided by the ring buffer. */
parse_a_single_line();
}

recv_svrmsg()가 호출되는 시점에서 ring_buffer 가 아래와 같다고 하면…
+IPD,10:012345

recv_svrmsg() 는 컬렉트해야할 데이타가 부족하기 때문에 결국 리턴을 해서 state 를 관리함으로써 blocked_read()가 호출되도록 하거나… 자신의 내부에서 blocked_read() 를 다시 호출해야 합니다. 개발자는 안 좋은 두 개의 선택에서 더 나은 것을 선택해야합니다. 실제 파싱을 하기 전에 length field 를 파싱할 것이냐 혹은 recv_svrmsg() 내에서 blocked_read() 를 다시 호출 할 것이냐.

아래와 같은 형식을 제공한다고 치죠.

+IPD,10:0123456789<0x0d><0x0a>OK<0x0d><0x0a>

그러면 하나의 라인을 잘라내서 parse_a_single_line() 에 던져주면 됩니다. parse_a_single_line() 명령/퀘리 응답과 함께 IPD 메시지라는 것을 알고 필드를 분석해서 잘라낸 데이타를 리턴해주면 그만입니다.

버퍼에 아래의 데이타만 존재한다면 라인이 만들어지지 않습니다.
+IPD,10:012345
따라서 다시 맨 윗줄의 blocked_read() 를 호출하도록 하면 됩니다.

소프트웨어 개발자들이 두 가지 IPD 응답 중에서 어떤 것을 선택할지는 명확합니다.

AT command 에서 +IPD 포맷이 어떻게 정의되어 있는지 찾아보려 했지만 찾을 수 없네요.

하지만 저와 비슷하게 CRLF 를 넣어달라고 간청하는 글은 보이네요. 현재의 +IPD 포맷에 불만을 가진 사람이 저뿐만이 아닐 것이라는 것을 말하고 싶습니다.

https://bbs.espressif.com/viewtopic.php?t=2415

저희 연구원이 말씀드렸다시피 기존 제품과의 호환성 문제로 쉽사리 변경할 수 없는 점 양해 부탁드립니다.
wizfi360 펌웨어 커스터마이징을 원하신다면 위즈네트 대리점들을 통해 문의해주시기 바랍니다.
감사합니다.

저도 compatibility 문제는 이해하고 있습니다.

답변 감사합니다.

안녕하세요

Str 데이터만을 사용한다면 위와 같은 방법이 사용자에게는 편할 수는 있으나 Hex 데이터를 전송할 때에는 혼란을 야기할 수도 있습니다. 데이터 중간에 <0x0d><0x0a> 자체가 데이터가 되어 버린다면 어떤게 데이터고 어떤 것이 종료 구분자인지 파악할 수 없게 되어 버립니다.

문제가 되지 않습니다. 지금 주장하시는 내용은 +IPD 뒤에 있는 length 를 고려하시지 않는 것 같은데요. length 의 값이 10 으로 되어 있고… 언급하신 예에서 메시지 내용은 "0123456789"으로 <0x0d><0x0a>를 포함하고 있지 않습니다.

TCP single connection 에서 다음과 같은 시나리오를 생각해보도록 하죠.

host 가 0123456789 를 보냈습니다. 그리고 WizFi360 이 그 데이타를 받아서 UART 에 다음과 썼습니다.

+IPD,10:0123456789

보드는 그것을 읽어서 보드의 지정된 버퍼에 저장하였습니다.

그리고 보드는 abcd 라는 데이타를 쓰기 위해서… “AT+CIPSEND=4\r\n” 을 UART 에 썼습니다. 그리고 WizFi360 이 다시 CIPSEND 응답으로 UART 에 다음과 같이 썼습니다.

AT+CIPSEND=12<0x0d><0x0a><0x0d><0x0a>OK<0x0d><0x0a>><0x20>

이제 보드의 버퍼에 다음과 같이 저장이 되었습니다.

+IPD,10:0123456789AT+CIPSEND=12<0x0d><0x0a><0x0d><0x0a>OK<0x0d><0x0a>><0x20>

보드에서 uart_read() 명령으로 버퍼의 내용을 모두 읽어서 파싱을 해야 합니다. 이미 버퍼에 <0x0d><0x0a> 가 많이 들어 있습니다. 하지만 파싱하는데 문제가 없습니다.

마찬가지로 +IPD 명령 응답이 아래와 같고 message 내용 중에 <0x0d><0x0a> 가 있다고 해도 상관이 없습니다.

+IPD,(length):(message)<0x0d><0x0x>OK<0x0d><0x0a>

왜냐하면 length field 가 있기 때문이죠.

안녕하세요

제가 말씀 드린것은 Hex 데이터일때의 0x0d,0x0a 구분을 이야기 드린것입니다.
또한 수신하실때 수신데이터에서 0x0d, 0x0a로 구분자로 데이터를 파싱한다고 하셔서 한 말씀입니다.
length field로 하신다면 0x0d 0x0a를 마지막 구분자로 사용할 필요가 없지 않을 까요?
length 까지만 데이터를 받으면 되지 않을까요?
그리고 구분자를 넣으시고 싶으시면 데이터를 보내실때 구분자를 포함해서 전송하시면 그것으로 데이터를 파싱하시는게 편하실것 같습니다.

제가 <0x0d><0x0a>를 넣었으면 좋겠다는 내용에 대해서는 충분히 설명했다고 생각합니다만.

그런데 전혀 이해를 못하고 계시는 군요. 만약 제가 사용하는 구분자에 맞춰서 IPD 메시지가 딱 끝난다면 여기와서 이런 얘기할 필요가 없습니다. 그렇지 못하기 때문에 length field 를 파싱하기 전에 +IPD 메시지의 끝을 알고 싶은 겁니다. 그래야 전체적인 파싱 루틴이 더 효율적이기 때문입니다.

저는 넣었으면 좋겠다는 주장을 하는 것일 뿐이고요. 넣고 싶지 않다는 말씀이 하고 싶다면 거절하시면 됩니다.

안녕하세요

메세지의 딱 끝을 확인 하고 싶으시다면 데이터 프로토콜에 0x0d 0x0a를 넣어서 보내시는 것이 말씀하시는대로 효휼적일것 같아 말씀 드리는 겁니다. 0x0d 0x0a까지 받아 확인 되면 전체 데이터 길이를 확인 하는 것이 확실 할 것 같습니다. 굳이 0x0d 0x0a OK 0x0d 0x0a 이메세지가 따로 없다고 해도 말이죠

이야기가 산으로 가고 있어서 더 이상 이야기 하고 싶지 않은데 왜 자꾸 더 글을 다시는지 잘 모르겠습니다.

제 계획은 이렇습니다. WizFi 는 이것을 고칠 계획이 없다는 것은 잘 알았습니다. 그러니 저는 아래 포맷을 지원하는 모듈을 사용하도록 하겠습니다.

+IPD,(length):(message)<0x0d><0x0x>OK<0x0d><0x0a>

WizFi 는 고치지 않아도 되고 저는 위 포맷을 지원하는 모듈을 사용하니 각자 제 갈 길을 가는 셈입니다. 모두 행복하죠. 됐나요?

위 포맷을 지원하는 모듈 모델 이름도 알고 싶다면 알려드리죠.