0xFF
RTL-SDR로 지상파 DMB 재난메시지 수신해보기 - 2 본문
며칠간 DMB 재난메시지 수신 시험을 진행해 본 결과 한 가지 알게 된 것이 있다.
바로 단방향 방송망의 특성상 수신기가 메시지를 놓치는 경우를 줄이기 위해 같은 메시지를 적어도 100회 이상 반복 전송한다는 것이다.
실제로 측정해서 평균을 내본건 아니지만 대략 메시지당 150회 정도로 반복 전송하고 있는 것 같았고, 그 시간이 2분 정도 걸리도록 설계해 둔 것 같은 느낌이었다.

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

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

그런데 테스트하던 중 메시지가 이렇게 캐러셀 형식으로 전송될 때에는 계속 새로운 메시지로 처리되어서 무력화되는 문제를 발견했다.
이렇게 여러개의 메시지가 동시에 전송되는 상황은 스펙만 보고는 짐작하기 어려웠는데 확실히 테스트해 보기 잘한 것 같다.

위 문제는 간단히 최근 수신한 메시지의 아이디와 아이디별 수신완료시각을 덱을 이용해 최대 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분 이상 연속으로 수신되는 경우에만 중복 수신이 가능한 것을 확인하였다.
'개발 및 프로젝트 > Safecast (졸업작품)' 카테고리의 다른 글
| 전국 통합대피소(한파쉼터, 무더위쉼터, 지진옥외대피장소, 지진해일긴급대피장소) 데이터셋 (0) | 2026.07.13 |
|---|---|
| 지도 API 없이 내부망에서 자체 지도 페이지 구축하기 (0) | 2026.07.03 |
| Safecast 하우징 디자인 및 부품 정리 (0) | 2026.07.02 |
| RTL-SDR로 지상파 DMB 재난메시지 수신해보기 - 1 (0) | 2026.07.01 |