블루투스 메시 센서망 허브·수집 서버

저전력 블루투스 센서 장비의 펌웨어 개발 환경을 세우고, 메시 네트워크로 올라오는 측정값을 단일 보드 컴퓨터가 받아 기록하는 수집 서버와 파이썬 패키지를 만들었습니다.

연표로 돌아가기
문제
여러 저전력 센서의 측정값을 지속적으로 수집하고 잘못 해석된 필드를 바로잡아야 했습니다.
담당
펌웨어 개발 환경, 파이썬 연결 패키지, 패킷 파서와 수집 서버를 담당했습니다.
설계 판단
필드 규칙표로 패킷을 해석하고 파일(처음 설계는 하루 단위)로 저장하도록 연결·해석·기록을 나눴습니다. 파이썬 BLE 라이브러리는 세 번 바꿔 최종적으로 하나에만 의존하는 자체 패키지로 정리했습니다.
검증 기준
16진수 스트림과 장치 조작을 대조하여 필드 배치·폭을 수정하고 온도 변화가 값에 반영되는지 확인했습니다. 이산화탄소는 입김으로, 온도는 에어컨으로 값이 움직이는지 보았고, 습도는 반영 여부를 확신하지 못한다고 기록했습니다.
결과 범위
예약 실행을 통한 지속 수집과 개발 절차의 협력업체 개발자 대상 세미나 자료화를 수행했습니다. 2020년 11월에는 한 장비의 8개 항목을 약 59.5시간 동안 모은 기록이 남아 있습니다.

입사 직후 맡은 일은 저전력 블루투스 장비의 펌웨어를 다룰 수 있는 환경을 만드는 것이었습니다. 크로스 컴파일 도구와 디버거, 제조사 SDK 를 묶어 개발 환경을 세우고 무선 펌웨어 갱신 절차를 확인한 뒤, 같은 작업을 다른 사람도 할 수 있도록 협력업체 개발자 대상 세미나 자료로 남겼습니다.

장비를 여러 대 이어 통신 거리를 넓히는 메시 네트워크에서는 중계와 대리 역할을 맡는 노드 구성을 확인했습니다. 제품에 넣을 코드는 공개 예제의 라이선스를 그대로 쓸 수 없어 사내 라이선스 기준으로 다시 작성했습니다.

센서 값을 모으는 쪽은 단일 보드 컴퓨터가 맡았습니다. 장치를 이름으로 찾아 연결하고 알림을 구독하는 과정을 파이썬 패키지로 묶고, 장비가 보내는 패킷을 필드 규칙표로 해석하는 파서와 표 형태로 쌓는 기록 클래스를 붙여 처음에는 하루 단위 파일로 저장하도록 설계했습니다. 예약 실행을 걸어 24시간 수집이 이어지게 했습니다.

초기 데이터는 값이 맞지 않아 그대로 쓸 수 없었습니다. 스트림을 16진수 수준에서 늘어놓고 장비를 조작해 가며 필드를 하나씩 대조해, 배치가 어긋난 항목과 폭이 잘못 잡힌 항목을 바로잡은 뒤에야 온도 변화가 값에 제대로 반영되는 것을 확인했습니다.

파이썬 BLE 라이브러리는 세 번 바꿨습니다. 처음 쓴 프레임워크형 패키지는 완성도 문제와 시스템 버스 메인 루프 점유로 연산 여유가 줄고 데이터프레임 기록 코드를 끼우기 어려워 PyBluez 로 옮겼습니다. PyBluez 는 저에너지 지원이 부족해 광고 패킷을 소켓에서 바이트 단위로 직접 읽어 제어 헤더와 광고 데이터 구조(플래그, 전체 로컬 이름, 서비스 UUID 목록, 제조사 정의 데이터)로 분해했고, 제조사 정의 데이터는 회사 코드를 공개 목록에서 찾지 못해 해석을 보류한 채 로컬 이름으로 장치를 가렸습니다. 최종적으로 bluepy 하나에만 의존하는 자체 패키지로 정리했습니다.

센서 값의 정합성은 실제 자극으로 대조했습니다. 이산화탄소는 입김으로 증감을, 온도는 에어컨으로 낮춰 하강이 반영되는지를, 배터리 전압은 외부 전원을 끊어 시작값과 단위를 확인했고, 습도 하강이 반영됐는지는 확신하지 못한다고 기록했습니다. 수신 PC 시각 두 종류와 장비 타임스탬프를 한 줄에 찍어 비교하니 장비 값의 이웃 차이가 불규칙해 필드가 밀려 있을 가능성을 의심했고, 장비 값은 신호 구분용으로만 쓰고 수신 서버 시각을 별도 열로 기록했습니다. 센서 데이터시트의 환산식을 적용해도 값이 맞지 않아, 환산식 대신 필드 폭을 바꿔 납득할 값이 나오는 쪽으로 규칙을 확정했습니다.

수집 결과는 CSV 로 저장하고 파일 이름에 날짜와 수집 시작·종료 시각을 넣었습니다. 메모리 부담을 고려해 하루 단위로 저장하고 자정마다 예약 실행하도록 설계했으며, 확인하지 않은 데이터가 올라가지 않도록 자동 커밋·푸시는 일부러 걸지 않았습니다. 이 구성으로 2020년 11월 21일 저녁부터 24일 새벽까지 약 59.5시간 동안 한 장비의 8개 항목(온도·습도·기압·이산화탄소·일산화탄소·메탄·황화수소·산소)을 초당 1건 안팎으로 시간별 CSV 60개, 약 21만 4천 행으로 쌓았고 가장 긴 공백은 6초였습니다. 8월 시점에는 기압 값이 전혀 잡히지 않는 문제가 있었으나 11월 수집분에는 기압 값이 들어 있습니다.

메시 노드는 측정만 하는 노드, 중계만 하는 노드, 중계와 측정을 겸하는 노드로 나눠 소개했습니다. 광고 방식은 상대를 지정하지 않는 일방 통보라 보안 정보를 주고받는 용도에는 맞지 않고 한 번에 실을 수 있는 사용자 데이터도 31바이트 이하라는 한계를 정리했으며, 클라이언트는 장치 스캔, 연결 후 특성 읽기, 알림 활성화 뒤 주기 수신의 세 단계로 동작합니다. 주변에 다른 BLE 장비가 많아 수신 대상을 거르는 필터가 필요하다는 점은 10월 회의에서 확인했고, 패키지에는 이름 패턴으로 장치를 찾는 검색 기능이 이미 있었습니다.

칩 표면에 인쇄된 코드로 리비전을 읽어야 호환되는 SDK 와 소프트디바이스 조합이 정해져, 리비전별 대응표로 정리했습니다. 개발 키트 SDK 가 2015년판 구형 툴체인을 요구해 빌드 설정 파일의 툴체인 경로를 고쳐야 했고, 개발 환경은 편집기와 디버그 확장, 디버그 프로브 구성과 통합 개발 환경(무료 라이선스) 구성 두 가지를 모두 갖췄습니다. 무선 갱신은 2020년 2월부터 웹 블루투스 기반 갱신 도구로 시도해, 특정 제어 특성에 쓰면 갱신 전용 모드로 재부팅하는 동작과 웹 블루투스가 보안 연결이나 로컬호스트에서만 장치 연결을 요청할 수 있다는 제약을 정리했습니다. 2020년 6월 2일 협력업체 개발자 대상 세미나(약 3시간 실습) 자료에는 칩을 지운 뒤 공장 이미지를 올려 복구하는 실습과 메시 데모 빌드를 담았고, 펌웨어 구조를 응용·모듈(플래시·센서 드라이버·BLE 핸들러·BLE 서비스)·SDK·하드웨어의 네 층으로 설명했습니다.

그림

센서 노드에서 중계·대리를 거쳐 허브로 이어지는 구성과, 16진수 스트림의 필드를 잘못 나눴을 때와 바로잡았을 때를 견준 그림센서 노드에서 중계·대리를 거쳐 허브로 이어지는 구성과, 16진수 스트림의 필드를 잘못 나눴을 때와 바로잡았을 때를 견준 그림
허브가 하는 일과, 필드가 어긋났던 자리를 찾은 방법. 같은 스트림을 두 가지로 갈라 보며 배치와 폭을 맞췄습니다.

구조와 흐름

센서망과 수집 서버

블루투스 메시허브 (Raspberry Pi)알림 구독센서 노드중계 노드센서 노드대리 노드연결 · 구독파이썬 패키지패킷 파서필드 규칙표기록 클래스표 형태 누적기간별 파일예약 실행24시간 수집
패킷 필드는 규칙표로 해석합니다. 초기에 어긋난 배치를 16진수 수준에서 대조해 바로잡았습니다.
nRF52832nRF52840BLERaspberry PiPythonpandas