YOGYUI

광교아이파크::조명 Apple 홈킷 연동 (6) 본문

홈네트워크(IoT)/광교아이파크

광교아이파크::조명 Apple 홈킷 연동 (6)

요겨 2021. 1. 1. 11:54
반응형

[6] Notification Server 도입하기

외부에서 조명을 제어했을 경우 (ex: 사용자가 월패드로 제어) switch status는 url 호출 전까지 갱신되지 않는 문제가 있다

config.json 스위치 액세서리의 pullInterval 속성을 변경해서 자주 갱신해도 되지만 (클라이언트가 나 혼자니깐!), 빠른 응답속도 및 서버 부하를 고려해서 Notification Server를 도입하도록 하자

 

앞서 설치한 homebridge-http-switch 플러그인의 개발자(@supereg)가 만든 homebridge-http-notification-server 플러그인을 설치해주자

https://github.com/Supereg/homebridge-http-notification-server#readme

 

Supereg/homebridge-http-notification-server

An http/https server inside Homebridge to receive notifications from external programs - Supereg/homebridge-http-notification-server

github.com

homebridge-http-notification-server 플러그인 설치

설정법은 간단하다.

(1) homebridge 설치 경로에 notification-server.json 파일을 만든다

* homebridge 기본 설치 경로: /var/lib/homebridge/

(2) notification-server.json에 포트 정보를 기입한다

{
    "port": 9998
}

사용자 인증 (ssl)도 설정할 수 있으나, 테스트 단계에서는 패스

(3) 스위치 액세서리에 notification 관련 속성을 추가한다

        {
            "accessory": "HTTP-SWITCH",
            "name": "Test Switch",
            "switchType": "stateful",
            "onUrl": "http://localhost:9999/light/on",
            "offUrl": "http://localhost:9999/light/off",
            "statusUrl": "http://localhost:9999/light/status",
            "notificationID": "switch_test_noti",
            "notificationPassword": "12345678"
        },

(4) Flask 서버 코드를 다음과 같이 구현한다

import time
import requests
from SerialComm import SerialComm
from EnergyParser import EnergyParser
from flask import Flask, render_template, redirect, url_for

ser_energy = SerialComm()
par_energy = EnergyParser(ser_energy)
light_status = False
prev_light_status = False

def parse_energy_result(packet: bytearray):
    global light_status
    global prev_light_status
    if len(packet) < 7:
        return
    if packet[1] == 0x31 and packet[3] == 0x91:
        room_idx = packet[5] & 0x0F
        if room_idx == 3:
            light_status = bool(packet[6] & 0x1)
            if light_status != prev_light_status:
                # 현재 상태가 바뀌었을 경우 homebridge notify
                url = "http://0.0.0.0:9998/"
                url += "switch_test_noti?password=12345678"
                json_obj = {"characteristic": "On", "value": light_status}
                requests.post(url, json=json_obj)
            prev_light_status = light_status

par_energy.sig_parse.connect(parse_energy_result)
app = Flask(__name__)

def checkConn():
    if not ser_energy.isConnected():
        ser_energy.connect('/dev/ttyUSB0', 9600)

def sendPacket(packet: str):
    checkConn()
    ser_energy.sendData(bytearray([int(x, 16) for x in packet.split(' ')]))

@app.route('/')
def index():
    global light_status
    checkConn()
    return render_template('index.html', light_on=light_status)

@app.route('/light/on', methods=['GET'])
def light_turn_on():
    global light_status
    checkConn()
    while not light_status:
        sendPacket('02 31 0D 01 3B 03 81 00 00 00 00 04 97')
        time.sleep(0.5)
    return redirect(url_for('index'))

@app.route('/light/off', methods=['GET'])
def light_turn_off():
    global light_status
    checkConn()
    while light_status:
        sendPacket('02 31 0D 01 43 03 01 00 00 00 00 00 8B')
        time.sleep(0.5)
    return redirect(url_for('index'))

@app.route('/light/status', methods=['GET'])
def light_get_status():
    global light_status
    return "{}".format(int(light_status))

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=9999, debug=True)

RS485 패킷 파싱 결과 처리 함수에서, 방의 조명 상태가 바뀌었을 경우 notification server에 상태 정보를 담은 json을 post하면 된다 (characteristic 속성을 "On"으로 하면 bool 변수를 정수형으로 변환하지 않고 보낼 수 있다)

(5)  테스트

외부 제어로 상태가 변한 경우, Notification 테스트

외부에서 변경한 스위치 상태에 대해서 빠르게 반응하는 것을 확인

 

집안 조명 제어를 위한 모든 준비가 완료되었다!

 

[시리즈 링크]

광교아이파크::조명 Apple 홈킷 연동 (1)

광교아이파크::조명 Apple 홈킷 연동 (2)

광교아이파크::조명 Apple 홈킷 연동 (3)

광교아이파크::조명 Apple 홈킷 연동 (4)

광교아이파크::조명 Apple 홈킷 연동 (5)

광교아이파크::조명 Apple 홈킷 연동 (6)

광교아이파크::조명 Apple 홈킷 연동 (7)

반응형