Yaong

Written by a cat

미에어

질의응답만 하면 심심하니 집에 있는 미에어를 제어해보기로 했다. 샤오미 기기를 컨트롤하는 라이브러리인 python-miio 가 있어 내게 필요한 기능만 구현하면 되었다.

구조

질의 응답의 데이터 구조에 행동을 추가했다. 행동에는 지정한 기기의 ID와 실행할 메소드를 입력한다. 실행된 메소드는 값을 리턴하며, 이 값을 답 문장에 넣어 음성으로 재생한다.

- keywords: 'group:home, 습도'
  actions:
    - device: 'mi_air'
      action: 'get_humidity'
  answers: '현재  습도는 {} 퍼센트 입니다.'

미에어는 모터 속도를 1~17단계로 작동시킬 수 있다. 특정 단계로 실행시키려면 문장에서 값을 알아내어 메소드로 전달해야한다. 어떤 값을 전달할지는 일단의 문장의 품사로 지정하도록 하였다.

이는 매우 임시방편이다. 품사 뿐 아니라 의미 단위(조금, 많이 등)로 지정할 수 있도록 하고, 필요한 정보가 부족하면 되묻는 기능도 추가해야 한다.

- keywords: 'group:mi_air, group:level'
  actions:
    - device: 'mi_air'
      action: 'be_custom'
      params: 'number'
  answers: '공기청정기 {} 단계로 작동시켰어요.'

반응성을 위한 작은 노력

미에어는 항상 깨어있지 않다. 깨어있지 않을 때 명령을 내리면 기기를 찾을 수 없다는 에러가 뜬다. discover() 로 기기를 깨운 후에 명령을 내려야하는데, 기기가 깨어있는데 또 깨우면 응답이 느리게 된다.

시간을 재어보니 300초가 지나면 대기 상태로 들어가는 것을 알 수 있었다. 마지막으로 깨운 시간을 기록한 후에 300초가 지난 경우에만 discover() 하는 식으로 응답 속도를 조금이나마 높혔다.

def discover_required(func):
    def wrapper(self, *args, **kwargs):
        now = time.time()
        if now - self.last_discovered > TTL:
            self.device.discover()
            self.last_discovered = now
        return func(self, *args, **kwargs)
    return wrapper

@discover_required
def get_aqi(self):
    return self.status.aqi

결과

미세먼지가 심한 날의 출근길에 슬랙으로 집의 공기질을 확인하고 원격으로 틀 수 있게 되었다. 이건 Mi Home 앱으로도 할 수 있는 것이기는 하다. 하지만 게임 중에 목이 칼칼할 때 음성으로 공기질을 확인하고 공기청정기를 세게 트는 것은 꽤 유용했다.

슬랙 기기 제어