몇달 전에 알리 익스프레스에서 발견한 물건인데, 온습도계 및 시계입니다. 액정이 아니라 e-ink 패널이고, 백라이트는 없습니다.
으레 샤오미 제품군이 그렇듯이 초기화는 Mi Home 앱으로 연결 해줘야 합니다. 본체에 아무 버튼이 없어서 (리셋 버튼하나 있음) 본체만 가지고는 시간 동기화 및 시간대 설정도 못합니다.
다만 이 제품은 현재 중국 밖으로 수출하지 않는 제품이라서 Mi Home을 중국어로 변경해서 써야 인식됩니다. 이게 되게 찜찜해서 잘 쓰지 않는 구형 아이패드에다 Mi Home 앱을 깔아서 연동시켰습니다.
몇달 정도 써보니까, 시계는 한달에 10초 정도 오차가 있는거 같습니다. 시계는 여기저기 있는데다, 이거 산 목적이 온습도계라서 이 정도 오차는 크게 신경 쓰이지 않습니다.
여기까지가 일반 소비자로서의 상품에 대한 의견이었습니다.
이제부터는 프로그래머이기 때문에 발생하는 문제입니다.
집밖에도 하나 달아뒀는데, 온습도 정보를 긁어 와서 집 안에서 확인 해볼 수 있다면 어떨까.
온습도 정보가 애플 homekit에 통보가 되서 뭔가 자동화를 할 수 있다면 어떨까.
이 정도 레벨의 아이디어는 보통 누군가가 인터넷에 구현 해뒀지요. 조금 검색해보고 Bluetooth LE 를 이용해서 온습도 정보를 수신하는 코드를 두 개 찾았습니다. 이거 말고도 homebridge 랑 xiaomi 키워드로 검색해보면 homekit 에 호환 되도록 온습도 정보를 노출하는 방법을 찾을 수 있습니다.
https://github.com/nabice/Xiaomi-Mijia-Bluetooth-Temperature-and-Humidity-Sensor-V2
https://github.com/AlexanderZobkov/xiaomi-mijia-bluetooth-sensor
위의 링크 중에서 xiaomi-mijia-bluetooth-sensor 는 java 코드라서 python으로 다시 짜려고 패킷 분석을 합니다.
라즈베리 파이에다 shell 두개를 띄워서 하나는
sudo hcitool lescan --passive
를 다른 하나는
sudo hcidump --raw
를 먹이면 BLE advertisement packet의 날 덤프를 볼 수 있습니다. 그 중에서 온습도계의 MAC 주소랑 같은 녀석의 패킷을 찾아 보면 이런 느낌의 데이타를 얻을 수 있는데, 초록색=mac address, 04=온도 (그외에 06이면 습도, 0A이면 배터리 잔량), 00B8=온도값(0xB8=184, 18.4도)입니다.
04 3E 28 02 01 00 00 FF FF FF 00 2E E7 1C 02 01 06 03 02 1A
18 14 16 95 FE 70 20 5B 04 CB FF FF FF 00 2E E7 09 04 10 02
B8 00 BC
1분에 온습도 정보를 여러번 발신하네요. 이러고도 배터리가 1년이 간다니 현대 기술은 놀랍습니다.
윗방식은 프로세스 두개를 띄워야하기 때문에 crontab에 작업 등록하기가 애매합니다. 조금 찾아보니 python으로 BLE 패킷을 받을 수 있는 라이브러리가 있군요. bluepy를 설치해주고, 이런 느낌으로 개발새발 짜주면 온도 습도 데이타를 처리할 수 있습니다.
from bluepy.btle import Scanner, DefaultDelegate
def xiaomi_decode_service_16b(bytes):
dataType = bytes[14]
value1 = bytes[17]
if len(bytes) > 18:
value2 = bytes[18]
else:
value2 = 0
value = value2 * 256 + value1
if dataType == 4: # temperature
return { 'temperature': value / 10.0 }
elif dataType == 6: # humidity
return { 'humidity': value / 10.0 }
elif dataType == 10: # battery
return { 'battery': value }
else:
return { 'unknown': True }
class ScanDelegate(DefaultDelegate):
def __init__(self):
DefaultDelegate.__init__(self)
def handleDiscovery(self, dev, isNewDev, isNewData):
# 22번 데이타는 위에 날덤프에서 밑줄 그은 부분임.
# 중국애들 왠일로 표준 패킷 쓴 듯함.
value = dev.getValueText(22)
decoded = xiaomi_decode_service_16b(bytes.fromhex(value))
print("Device %s (%s), RSSI=%d dB, %s" % (dev.addr, dev.addrType, dev.rssi, decoded))
scanner = Scanner().withDelegate(ScanDelegate())
devices = scanner.scan(20.0)
이제 Mi home 앱 안 쓰고도 집 안에 앉아서 편안하게 집 밖의 온도를 확인할 수 있습니다. 편안 편안