0xFF

RTL-SDR로 지상파 DMB 재난메시지 수신해보기 - 2 본문

개발 및 프로젝트/Safecast (졸업작품)

RTL-SDR로 지상파 DMB 재난메시지 수신해보기 - 2

캡스락 2026. 7. 8. 15:31

며칠간 DMB 재난메시지 수신 시험을 진행해 본 결과 한 가지 알게 된 것이 있다.

바로 단방향 방송망의 특성상 수신기가 메시지를 놓치는 경우를 줄이기 위해 같은 메시지를 적어도 100회 이상 반복 전송한다는 것이다.

실제로 측정해서 평균을 내본건 아니지만 대략 메시지당 150회 정도로 반복 전송하고 있는 것 같았고, 그 시간이 2분 정도 걸리도록 설계해 둔 것 같은 느낌이었다.

실제로 표준 규격서에서도 동일 메시지가 2분 이상 반복 수신되고 있는 게 아니면 해당 메시지를 표시하지 말라고 언급하고 있다.

따라서 코드에서도 하나의 재난메시지 조립이 완료되면 메시지 ID와 chrono::steady_clock::now()의 값을 static으로 남겨서 이미 수신 완료처리한 메시지가 무시되도록 처리했었다.

HRA(호우주의보 수신) 결과

그런데 테스트하던 중 메시지가 이렇게 캐러셀 형식으로 전송될 때에는 계속 새로운 메시지로 처리되어서 무력화되는 문제를 발견했다.

이렇게 여러개의 메시지가 동시에 전송되는 상황은 스펙만 보고는 짐작하기 어려웠는데 확실히 테스트해 보기 잘한 것 같다.

 

위 문제는 간단히 최근 수신한 메시지의 아이디와 아이디별 수신완료시각을 덱을 이용해 최대 10개까지 보관해두는 것으로 조치했다.

처음에는 STL 큐를 사용할까 했는데 큐는 순회를 원본 큐의 복사 및 pop으로 별도 구현해야 한다는 점 때문에 덱을 사용하기로 했다.

 

    ...
    recentIds.push_back(currUniqueId); // 지금 수신 완료한 ID 푸시
    recentTimes.push_back(chrono::steady_clock::now()); // 현재시각 푸시
    
    while (recentIds.size() > recentMax) // 10개를 넘으면 pop
    {
        recentIds.pop_front();
        recentTimes.pop_front();
    }
    ...

분할된 메시지의 조립이 끝나는 부분에서는 이렇게 메시지의 아이디와 현재 시각을 덱에 보관하고

10개가 넘는 순간 가장 오래된 요소를 pop 하여 최대 10개까지의 메시지 정보를 기록해 둔다.

 

...
// 최근 수신 메시지 중 같은 ID가 2분 미만 간격으로 재수신시 무시
auto currentTime = chrono::steady_clock::now();
for (size_t i = 0; i < recentIds.size(); i++)
    if (recentIds[i] == uniqueId &&
        currentTime - recentTimes[i] < chrono::minutes(2))
        return;
...

메시지 유효성 확인 후 파싱을 시작하는 부분에서는 덱을 순회하여 1) 지금 들어온 메시지가 최근 수신내역에 존재하면서 2) 그 수신시각이 2분 미만이면 무시되도록 했다.

여기서 중요한 것은 수신내역 배열을 무조건 끝까지 돌면서 조건에 맞지 않는 메시지가 하나라도 발견되면 수신을 취소한다는 것인데,

만약 위 조건문에서 무조건 배열을 모두 순환하지 않는다면 2분 이상 연속으로 메시지가 수신되는 경우

처음 2분에 한해서는 동시수신이 억제되는듯 보이지만 그 이후로는 위 호우주의보 안내처럼 문자폭탄이 떨어질 것이기 때문이다.

이제 어느정도 마무리 된 것 같으니 한번 더 테스트해보고 큰 문제가 없으면 DMB 수신 스택은 여기서 마무리하려고 한다.

 

2026. 07. 08 15:43 추가 - 검증 완료!!!

동일 메시지는 2분 이상 연속으로 수신되는 경우에만 중복 수신이 가능한 것을 확인하였다.