구형 공기 청정기 IOT 기기로 개조
(사진 출처: https://www.blueair.com/ 블루에어 공식 페이지)
내가 일하는 사무실에서 약 5년간 공기 청정을 담당하다가 얼마 전 집으로 오게 된 구형 공기청정기 블루에어 Pure211. 이 녀석을 구글 홈에 붙여서 음성으로 컨트롤하거나 원하는 시간에 꺼지거나 켜지게 할 수 있도록 인터넷을 연결해 보았다.
1. 기기 분석 - 개조 가능한지 살펴보기
첫 번째 할 일은 공기청정기를 분해해서 개조가 가능한지 살펴보는 것이다. 내가 생각했던 제일 좋은 개조 방법은 스위치 케이블을 ESP8266(아두이노를 탑재한) 에 연결하고, 다시 아두이노에서 공기청정기로 스위치 신호를 보내는 방법이다. 그렇게 되려면 구조가 간단해야 하는데...
기판을 분해해서 스위치 쪽 케이블 커넥터를 살펴보니 친절하게 설명까지 되어있다 ㅠ_ㅠd 5V 와 GND, 그리고 아마도 스위치 신호를 받아오는 KEY 를 따서 쓰면 될 것 같다.
KEY가 버튼에서 나온 신호가 맞는지 확실히 확인하기 위해서 기기에 전원이 들어온 상태에서 KEY 와 GND를 쇼트시켜봤다. 이어서 공기청정기 팬이 동작하는 것을 확인하였다. 케이블이 연결된 상태에서 KEY 와 전원(5V)의 저항 값도 찍어보았다. 연결된 상태에서 찍었기 때문에 6.71K옴이 나왔지만, 실제로는 10K 옴이다. 어쨌든 이것으로 풀업(pull up) 스위치를 사용한다는 것을 확인하였다.
2. 개조 시작 - 하드웨어
우선 기기에 ESP8266을 연결하고(ESP32 를 사용하고 싶지만, 집에 여분의 ESP8266 부품들이 많다...) 릴레이를 붙여서 스위치 신호를 보내고, 외부에 달린 스위치는 ESP8266에 붙이는 것이 계획이다. ESP8266에 아두이노 코드를 올려서 MQTT로 서버에 상태를 전송하거나 명령을 받을 수 있도록한다. 그리고, 기기 상태를 알려줄 수 있는 스피커를 붙여서 소리를 통하여 인터넷, 서버 연결과 설정, 모드 진입 상태를 알려줄 수 있도록 한다.
이제 5V, GND, KEY 케이블을 따서 연장선을 붙였다. 겨우 이 세 가닥의 라인을 이용해서 인터넷으로 공기청정기를 제어할 수 있다니.... ㅠ_ㅠ 잠시 기쁨의 눈물을 흘려보았다.
컨트롤러를 만들 때 사용한 부품은 다음과 같다.
- NodeMCU v1.0 (ESP8266)
- 3.3v 옵토 커플러 릴레이
- 스피커
- 터미널 블록과 기타 부품류
회로도를 그려보면 아래와 같다.
버튼이 5V 를 사용하고 ESP8266 은 3.3v 를 사용하기 때문에 버튼 신호를 받기 위해서 10K, 20K 저항을 이용여 전압을 낮춰줘야한다.
2. 소프트웨어
우선 지난번에 구현한 Web 설정 마법사 라이브러리를 활용한다. 최초 기동하거나, 버튼을 10초 이상 눌렀을 경우 스마트폰으로 연결하여 WiFi 와 Mqtt 서버 주소를 설정할 수 있다. 그뿐만 아니라, WiFi 혹은 Mqtt 서버와의 연결에 장애가 생길 경우 자동으로 재접속을 시도하는 기능도 제공한다.
ESP8266 에 웹 설정 마법사 붙이기 (dev.re.kr)
이 공기 청정기의 풍속 조절 방법은 매우 단순한데, 버튼을 한 번 누르면 1단, 그다음 누르면 2단, 그리고 3단 마지막으로 전원이 꺼진다. 버튼 조작 사이사이에 아주 약간의 딜레이가 있으며, 5초 이상 누르고 있으면 필터 교체 알람(LED 붉은색 교체) 기능이 꺼진다. 따라서 온라인 조작 프로토콜도 매우 단순하게 만들 수 있다. 다만, 현재 풍속에서 목표 풍속으로 만들기 위해서 약간의 시간이 필요할 수 있으니 이것을 감안하여 만들어야 할 것이다. (예를 들어 현재 2단 상태에서 1단 상태로 만들기 위해서 릴레이를 "3단->전원 끄기->1단" 순으로 총 3번 동작 시켜야한다.) 그래서 목표 풍속을 담는 변수를 하나 만들고 현재 풍속을 담는 변수를 만들었다. 현재 풍속이 목표 풍속과 같아질때까지 +1 을 반복한다. 상태가 바뀔 때마다 상태 이벤트를 MQTT로 전송한다.
다음으로 고민해야 할 사항은 서버와 통신할 때 사용할 데이터 포맷인데, JSON 으로 처리하려고 했다가 단순 Key:Value 만 전달하면 되는데 JSON을 쓰는 것은 좀 오버인 것 같아서 쿼리 스트링을 사용하기로 하였다. 쿼리 스트링을 처리하기 위하여 그냥 아주 간단하고 비효율적인 링크드 맵과 동적 버퍼를 구현하였다. 또 데이터를 쿼리 스트링 포맷으로 내보내거나 파싱 할 수 있는 기능도 구현하였다. 대충 만든 탐색 방법이 거슬리지만 귀찮아서 여기까지...
이렇게 구현된 코드는 이곳에 올려뒀다.
ice3x2/IOTForBlueAirPure: Converted "BlueAir Pure XXX" into an IOT device.... (github.com)
MQTT 로 전달되는 데이터 프로토콜은 다음과 같다.
명령 (publish)
- 풍속 변경
- Topic: [디바이스 키]/qstate
- Value: cmd=mode&tm=[목표 풍속 0-3]
- 차일드 락
- Topic: [디바이스 키]/qstate
- Value: cmd=childLock&cl=[끄기,켜기 0,1]
- 산토끼 재생(아들을 위한 이스터에그)
- Topic: [디바이스 키]/qstate
- Value: cmd=tp_stk_bp
이벤트 (subscribe)
- heartbeat - 5초간격
- Topic: [디바이스 키]/heartbeat
- Value: cmd=hb&t=[디바이스 동작시간(분)]
- 상태 이벤트
- 상태가 바뀔때 전송
- Topic: [디바이스 키]/state
- Value: cmd=state&tm=[목표 풍속 0-3]&cm=[현재 풍속 0-3]&cl=[차일드락 0,1]&fr=[필터 리셋 모드 0,1] &v=[버전]&ip=[ip 주소]
3. 실사용
MQTT 명령어를 전송하여 테스트 하는 모습.
이제 본격적으로 사용하기 위해서 구글 홈에 붙여보았다.