올해 초부터 CoAP 기반의 Firmware-over-the-Air 솔루션을 독자적으로 개발하고 있다. 사실 핵심 기술은 거의 완성했다. 델타 스크립트 생성기술, 델타 전달 프로토콜, 데이터 저장 및 무결성 확인 절차, 그리고 델타 업데이트와 복구를 지원하는 부트로더까지. 나는 2019년 11월 13일 뉴욕에서 열리는 ACM SenSys 2019 에서 이 기술을 시연하려고 한다.

나는 이 기술이 절실했기 때문에 개발했다. 대규모 무선 센서 네트워크 기술을 개발 중, 소스코드를 수정할 때마다 IoT 디바이스 100대의 펌웨어를 업데이트시켜야 했다. 유선 펌웨어 업데이트는 노가다였다. 한 번에 한 디바이스씩 업데이트할 수밖에 없었다. 기기 하나씩 하나씩 손수 JTAG선을 연결해서 업로드했다.  100대 디바이스를 모두 업데이트 하는데 보통 40분씩 걸렸다. 그렇게 업데이트를 해서 네트워크가 제대로 동작하면 좋은데…. 보통은 그렇지도 않았다. 코드 한 줄만 실수해도 다시 40분을 버리는 것이었다. 이런 시간 낭비를 없애고 싶었다.

앞으로 내 FOTA 프로토콜에 대해서 글을 써 보려 한다. 아직 미흡한 부분들이 많은데, 글을 쓰면서 그 부분들을 채우는 방법도 고민해볼 것이다.





 

 

 

IEEE 논문은 형식에 맞춰 제출해야 한다.

IEEE 에서 제공하는 논문 템플릿은 2단 레이아웃에 각주는 왼쪽 단에만 있다.


그런데 이 소프트웨어는 저장만 하면 지멋데로 레이아웃을 수정한다.

각주가 두 단에 걸쳐 나타나는 것이다.


이런 문제에 대한 해결법을 찾고자 했다.

공식 홈페이지에 비슷한 질문이 여럿 나와있는데, .doc 로 저장하라는 둥 수준 이하의 답변밖에 없었다.


영문 홈페이지에서 해결법을 찾았다.

방법을 요약하겠다.


1. ALT+F11 누름 -> VBA Editor 열림

2. CTRL+G 누름 -> 하단에 "직접 누름" 창 열림 

3. "직접 누름" 창에 다음을 입력 후 엔터: ActiveDocument.SetCompatibilityMode 14

4. VBA Editor 닫고, 파일->옵션->고급->호환성 옵션->다음 프로그램에서 만든 것처럼 레이아웃 저장-> Microsoft Word 2010 ->확인 



이 작업을 마치면 각주가 왼쪽 단에 고정된다.

문서가 워드2010에서 편집된것처럼 레이아웃이 재정렬되기 때문이다.



이 문제로 고생하는 사람에게 이 글이 도움되길 바란다.

ETag 는 시간에 따라 변화하는 동일 자원의 표현형을 구별하기 위한 자원-로컬 식별자로서 사용합니다.

ETag 는 리소스를 제공하는 서버에서 생성되며, 버전, 체크섬, 해시 또는 시간을 포함하여 여러 가지 요소를 통해 생성 할 수 있습니다.

ETag 를 수신하는 종단점은 그 내용이나 구조에 대해 아무런 가정을 하지 않아야 합니다 (MUST).

ETag 를 생성하는 종단점은 가능한 한 가장 간단한 표현을 사용하는 것이 좋습니다.

이는 특히 여러 ETag 값을 저장하려는 클라이언트 및 중개자를 고려해야 하기 때문입니다.

응답속 ETag

응답속 ETag 옵션은 "태그된 표현"에 대한 ETag 의 현재 값을 제공합니다. location URI가 존재할 경우, 응답속 ETag 옵션은 location URI 로의 GET 요청에 의해 검색되는 표현에 대한 ETag 입니다.

ETag 옵션은 태그된 표현이 포함될 수 있는 모든 응답에 포함될 수 있습니다.

ETag 옵션은 하나의 응답에서 두 개 이상 있어서는 안됩니다.

ETag 옵션은 기본값이 없습니다.

요청속 ETag

GET 요청시, 해당 리소스에서 종전에 취득한 표현을 갖고있고, 이와 함께 ETag 응답 옵션을 얻었던 종단점은 이러한 저장된 응답 중 하나 이상에 대해 ETag 옵션의 인스턴스를 지정할 수 있습니다.

서버는 주어진 ETag 중 하나가 현재 표현을 위한 엔티티 태그라면 (즉, 유효한 경우) 2.05 Content 응답 대신 2.03 Valid 응답을 발행 할 수 있습니다. 이 경우, 해당 유효 ETag 를 응답 옵션에 되담아 보냅니다.

결과적으로, 클라이언트는 저장된 표현을 다시 전송하지 않고도 현재 저장된 표현이 현재값 (유효한 값)인지 판별 할 수 있습니다.

'[RFC7252] CoAP' 카테고리의 다른 글

CoAP Server Error 5.xx 분석  (0) 2016.11.23

이 응답 코드 클래스는 서버에서 오류가 발생했거나 요청을 수행 할 수 없는 경우를 나타냅니다. 이 응답 코드는 모든 요청 메소드에 대해 적용 할 수 있습니다. 서버가 이 유형의 응답을 보낼땐 진단 페이로드를 포함해서 전송해야 합니다. 이 유형의 응답은 캐시 형태로도 구현이 가능합니다만 기존의 캐싱처럼 validation 모델을 적용할 순 없습니다.

*RFC에선 이 유형의 응답에 대한 설명이 HTTP 의 오류 응답과 매우 유사하다고 언급만 할 뿐이여서, 이해를 돕기위해 HTTP 의 지침을 바탕으로 각 응답 코드에 대해 설명합니다.

  • 5.00 Internal Server Error (내부 서버 오류)

    서버에서 예기치 않은 조건이 발생하여 요청을 수행 할 수 없었음을 의미합니다.

  • 5.01 Not Implemented (구현되지 않음)

    서버가 요청 수행하는 데 필요한 기능을 지원하지 않음을 의미합니다. 서버가 해당 요청 메소드를 인식하지 못하고 어떤 자원도 이를 지원할 수 없을 때 사용하기 적절한 응답입니다.

    예를들어, POST 기능을 지원하지 않는 Constrained Thing이 POST 요청을 받았을 시 이 응답을 요청자에게 보낼 수 있습니다.

  • 5.02 Bad Gateway (잘못된 게이트웨이)

    서버가 게이트웨이 또는 프록시 역할을 수행하는 동안 요청을 수행하기 위해 액세스 한 업스트림 서버에서 잘못된 응답을 받았음을 의미합니다.

  • 5.03 Service Unavailable (서비스를 사용할 수 없음)

    서버가 일시적인 과부하 또는 서버 유지 관리로 인해 요청을 처리 할 수 없음을 의미합니다. 이것은 곧 해결될 수 있는 일시적 조건이라는 것을 의미합니다. 서비스가 다시 재개되기까지 남은 시간을 알 수 있는 경우, Max-Age Option을 사용하여 클라이언트가 다시 시도할 수 있는 시간(초 단위)을 알립니다. Max-Age Option이 없는 응답을 수신한 클라이언트는 5.00 응답을 수신한 것처럼 응답을 처리해야 합니다.

    주: HTTP 에서는 이 코드가 서버 과부하시 반드시 사용할 필요는 없다고 설명하므로, CoAP 에서도 단순히 연결을 거부하는 방식으로 서버를 구현할 수 있습니다.

  • 5.04 Gateway Timeout (게이트웨이 시간 초과)

    게이트웨이 또는 프록시 역할을하는 서버가 요청 처리 도중 접근해야 하는 지정된 URI 또는 다른 보조 서버로부터 적시에 응답을 받지 못했음을 의미합니다.

  • 5.05 Proxying Not Supported (프록시가 지원되지 않음)

    서버가 Proxy-Uri Option 또는 Proxy-Scheme 에 지정된 URI에 대해 프록시의 역할을 하지 않거나 할 수 없음을 의미합니다.

'[RFC7252] CoAP' 카테고리의 다른 글

ETag란?  (0) 2016.12.29

이번 포스트에선 Stateless 방식으로 구현된 Block1 옵션을 사용한 PUT 요청과 그에 대한 응답이 어떻게 이루어지는지 예제를 통해 확인해 봅니다.

요청에 대한 설정

블록단위길이: 128 바이트

전송페이로드: 800 바이트

결과는 다음과 같습니다.

이번 예제는 Stateless 블록 전송으로 구현된 코드를 바탕으로 작동하였기 때문에 매 블록 요청마다 2.04 Changed 응답을 수신하는 것을 확인할 수 있습니다.

Stateless 방식과 atomic 방식의 차이는 이전 포스트를 참고하십시오.

'[RFC7959] 블록형 전송' 카테고리의 다른 글

CoAP Block2 옵션 사용하기  (0) 2016.11.21
CoAP Block1 옵션 사용하기  (0) 2016.11.21

M 비트가 설정된 Block2 옵션이 포함된 응답을 수신한 요청자는 초기 요청과 동일한 옵션으로 추가 요청을 보내고 블록 번호와 블록 크기를 제공하는 Block2 Option을 보내어 자원 표현의 추가 블록을 검색 할 수 있습니다. 요청시 클라이언트는 반드시 Block2 옵션의 M 비트를 0으로 설정해야 하며 서버는 수신시 반드시 이를 무시해야 합니다.

CLIENT                                                    SERVER
|                                                            |
| CON [MID=1234], GET, /status                       ------> |
|                                                            |
| <------ ACK [MID=1234], 2.05 Content, 2:0/1/128            |
|                                                            |
| CON [MID=1235], GET, /status, 2:1/0/128            ------> |
|                                                            |
| <------ ACK [MID=1235], 2.05 Content, 2:1/1/128            |
|                                                            |
| CON [MID=1236], GET, /status, 2:2/0/128            ------> |
|                                                            |
| <------ ACK [MID=1236], 2.05 Content, 2:2/0/128            |
Simple Block-Wise GET

응답에서 사용되는 블록 크기를 조절하기 위해, 요청자는 초기 요청에서 Block2 Option 을 사용할 수 있습니다. 이 때 옵션값에는 원하는 크기, 블록 번호 0, M 비트에는 0을 넣습니다. 서버는 반드시 표시된 크기 또는 더 작은 크기의 블록을 사용합니다. 첫 번째 요청 블록 다음의 블록 단위 요청들은 반드시 서버로부터 온 첫번째 응답에서 받은 Block2 Option에서 제공된 사이즈를 나타내야 합니다.

CLIENT                                                     SERVER
|                                                          |
| CON [MID=1234], GET, /status, 2:0/0/64           ------> |
|                                                          |
| <------ ACK [MID=1234], 2.05 Content, 2:0/1/64           |
|                                                          |
| CON [MID=1235], GET, /status, 2:1/0/64           ------> |
|                                                          |
| <------ ACK [MID=1235], 2.05 Content, 2:1/1/64           |
:                                                          :
:                          ...                             :
:                                                          :
| CON [MID=1238], GET, /status, 2:4/0/64           ------> |
|                                                          |
| <------ ACK [MID=1238], 2.05 Content, 2:4/1/64           |
|                                                          |
| CON [MID=1239], GET, /status, 2:5/0/64           ------> |
|                                                          |
| <------ ACK [MID=1239], 2.05 Content, 2:5/0/64           |
Block-Wise GET with Early Negotiation

일단 요청자가 Block2 Option을 사용하였고 블록 사이즈가 조정되었을 수 있는 첫번째 응답을 받았다면, 단일 블록 방식 전송 내 모든 이후의 요청은 마지막 블록의 내용이 적은 경우 (M 비트가 0) 를 제외하고 궁극적으로 같은 크기를 이용하게 될 것입니다. (클라이언트는 Block2 옵션없이 보낸 첫 번째 요청이 Block2 옵션이 포함된 응답을 받은 경우 두 번째 요청부터 Block2 옵션을 사용할 수 있다는 점을 참조하십시오.) 서버는 요청 내 옵션에서 표기된 것보다 작거나 같은 블록 사이즈를 사용하지만, 요청자는 반드시 초기 요청에 대한 응답에서 사용된 실제 블록 사이즈를 기록하여 후속 요청에서 이를 사용하도록 진행해야 합니다. 서버는 반드시 이러한 클라이언트의 동작으로 인해 한 시퀀스 내 모든 응답들이 같은 블록 사이즈를 갖도록 보장하도록 동작해야 합니다. (M 비트가 0인 마지막 블록과 초기 요청에 Block2 옵션이 없는 경우의 첫 번째 블럭을 제외)

블록 방식 전송은 완전히 정적인 표현형 (디바이스를 설명하는 스키마와 같이 시간에 따라 전혀 변하지 않는 값) 을 가진 자원을 GET 하거나, 동적으로 변화하는 자원을 위해 사용될 수 있습니다.후자의 경우, Block2 옵션은 재 조립되는 블록이 동일한 표현 버전에서 나온 것인지 확인하기 위해 ETag 옵션 ([RFC7252])과 함께 사용해야 합니다. 이 경우, 서버는 각 응답에 ETag를 포함해야 합니다. ETag 옵션을 사용할 수 있는 경우 클라이언트는 교환중인 블록의 표현을 재조합 할 때 반드시 ETag 옵션을 비교해야합니다. ETag 옵션이 GET 전송에서 일치하지 않으면, 요청자는 우선 검색했던 블록들의 갱신된 값을 검색하려고 시도 할 수 있습니다. 비효율성을 최소화하기 위해, 서버는 진행중인 요청 시퀀스에 대한 표현의 현재 값을 캐시에 보관할 수 있습니다. (서버는 요청하는 엔드 포인트와 각 블록 단위 요청에서 동일한 URI의 조합에 의해 시퀀스를 식별 할 수있습니다.) 이 명세가 서버에게 상태를 확립하라는 요구를 하지 않는다는 점을 짚어야 합니다. 그러나, 빠르게 변화하는 자원을 제공하는 서버는 클라이언트가 일관된 블록 집합을 검색하는 것을 불가능하게 만들 수 있습니다. 자원의 모든 블록을 검색하고자하는 클라이언트는 과도한 지연없이 그렇게 하려고 노력해야 합니다. 서버는 해당 상태에 대한 마지막 접근 후 EXCHANGE_LIFETIME ([RFC7252]) 시간이 지나면 자유롭게 캐시된 상태를 버릴 수 있다고 예상되나 항상 상태를 그렇게 오래 유지할 필요는 없습니다.

Block2 옵션은 단일 종단점이 동일한 리소스에 대해 동시에 다중 블럭 방식 응답 페이로드 전송 (예컨대, GET) 동작을 수행 할 방법을 제공하지 않습니다. 이것은 요구가 거의 없는 사항이지만 이를 해결 방법으로 클라이언트가 캐시 키를 변경하는 방법을 생각해 볼 수 있습니다 (예 : 같은 시맨틱으로 리소스에 액세스하는 여러 URI 중 하나를 사용하거나 프록시 안전 선택 옵션을 변경하는 방식으로).


서버에서 atomic 방식의 블록형 요청 페이로드(예: PUT/POST) 를 수신하는 경우, 최종 블록, 즉 M 비트가 0 인 Block1 옵션을 포함한 블록이 수신되었을 때 실제 작성/대체가 이루어집니다. 이 경우, 최종 블록이 아닌 모든 성공 응답은 응답 코드 2.31 (Continue)을 반환합니다. 마지막 블록을 처리 할 때, 서버에서 모든 이전 블록들이 가용하지 않다면, 전송은 실패하며 오류 코드 4.08 (Entity Incomplete Request)이 반드시 반환되어야 합니다. 서버는 비순차적인 임의의 (최종 또는 비 최종) Block1 전송에 대해 4.08 오류 코드를 반환할 수도 있습니다. 따라서, 이 경우를 처리할 특정 메커니즘이 없는 클라이언트는 항상 블록 0 을 시작으로 블록들을 순서대로 전송해야 합니다.

   클라이언트                                                     서버
     |                                                          |
     | CON [MID=1234], PUT, /options, 1:0/1/128    ------>      |
     |                                                          |
     | <------   ACK [MID=1234], 2.31 Continue, 1:0/1/128       |
     |                                                          |
     | CON [MID=1235], PUT, /options, 1:1/1/128    ------>      |
     |                                                          |
     | <------   ACK [MID=1235], 2.31 Continue, 1:1/1/128       |
     |                                                          |
     | CON [MID=1236], PUT, /options, 1:2/0/128    ------>      |
     |                                                          |
     | <------   ACK [MID=1236], 2.04 Changed, 1:2/0/128        |
Simple Atomic Block-Wise PUT

클라이언트가 4.08 오류 코드를 수신하는 이유중 하나는, 서버에서 시간이 초과되어 부분 요청 내용을 폐기했기 때문입니다. 클라이언트는 과도한 지연없이 요청을 구성하는 모든 블록을 보내려고 노력해야 합니다. 서버는 가장 최근 블록이 전송 된 후 EXCHANGE_LIFETIME 이 경과하면 부분 요청 본문을 마음껏 버릴 수 있습니다. 그러나 서버에서 항상 부분 요청 본문을 오래 보관할 필요는 없습니다.

   클라이언트                                                     서버
     |                                                          |
     | CON [MID=1234], PUT, /options, 1:0/1/128    ------>      |
     |                                                          |
     | <------   ACK [MID=1234], 2.31 Continue, 1:0/1/128       |
     :                                                          :
     :                          ...                             :
     :                                                          :
     |                                                        폐기
     :                                                          :
     :                          ...                             :
     :                                                          :
     | CON [MID=1235], PUT, /options, 1:1/1/128    ------>      |
     |                                                          |
     | <------   ACK [MID=1235], 4.08 Request Entity Incomplete |
Expired Request Response in Atomic Block-Wise PUT

atomic 방식의 블록형 요청 페이로드 전송에서, 서버는 블록 저장에 필요한 자원이 없는 경우 오류 코드 4.13 (요청 엔티티가 너무 큼) 을 언제든지 반환 할 수 있습니다. (Block1 을 사용하지 않는 요청에 대한 4.13 응답은 클라이언트에게 Block1 로 전송해보라고 하는 힌트이며, 요청한 SZX 보다 더 작은 SZX이 들어있는 Block1 옵션이 포함된 4.13 응답은 더 작은 SZX 로 요청해 달라는 힌트임을 유의하십시오.)

   클라이언트                                                     서버
     |                                                          |
     | CON [MID=1234], PUT, /options, 1:0/1/128    ------>      |
     |                                                          |
     | <------   ACK [MID=1234], 2.04 Changed, 1:0/0/128        |
     |                                                          |
     | CON [MID=1235], PUT, /options, 1:1/1/128    ------>      |
     |                                                          |
     | <------   ACK [MID=1235], 2.04 Changed, 1:1/0/128        |
     |                                                          |
     | CON [MID=1236], PUT, /options, 1:2/0/128    ------>      |
     |                                                          |
     | <------   ACK [MID=1236], 2.04 Changed, 1:2/0/128        |
Simple Stateless Block-Wise PUT

stateless 방식의 블록형 요청 페이로드 전송에서, 서버는 전송이 진행중이거나 클라이언트로부터 전송이 완료되지 않은 동안 비일관적 상태에서 운영될 수 있습니다.  이 특성은 전송 중 서버에 state 가 항상 유지되는 HTTP 보다는 원격 파일 시스템의 특성에 더 가깝습니다. 공유 파일 액세스 (예: 클라이언트 특정 임시 리소스)에서 잘 알려진 기술을 사용하여 HTTP 와의 차이를 완화 할 수 있습니다.

  클라이언트                                                     서버
     |                                                          |
     | CON [MID=1234], PUT, /options, 1:0/1/128    ------>      |
     |                                                          |
     | <------   ACK [MID=1234], 2.31 Continue, 1:0/1/32        |
     |                                                          |
     | CON [MID=1235], PUT, /options, 1:4/1/32     ------>      |
     |                                                          |
     | <------   ACK [MID=1235], 2.31 Continue, 1:4/1/32        |
     |                                                          |
     | CON [MID=1236], PUT, /options, 1:5/1/32     ------>      |
     |                                                          |
     | <------   ACK [MID=1235], 2.31 Continue, 1:5/1/32        |
     |                                                          |
     | CON [MID=1237], PUT, /options, 1:6/0/32     ------>      |
     |                                                          |
     | <------   ACK [MID=1236], 2.04 Changed, 1:6/0/32         |
Simple Atomic Block-Wise PUT with Negotiation

Block1 옵션은 단일 종단점이 동일한 자원에 대해 동시에 여러 개의 블록 방식 요청 페이로드 전송 (예 : PUT 또는 POST) 작업을 수행 할 수있는 방법을 제공하지 않습니다. 동일한 종단점의 이전 시퀀스가 완료되기 전에 동일한 자원에 대한 새로운 블록 단위의 요청을 시작하면 서버가 계속 유지할 수있는 컨텍스트를 단순히 덮어 씁니다.

+ Recent posts