Notice
Recent Posts
Recent Comments
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
Tags
- RS-485
- 매터
- ConnectedHomeIP
- Bestin
- 배당
- 미국주식
- 현대통신
- 해외주식
- 퀄컴
- 파이썬
- 홈네트워크
- 공모주
- 애플
- esp32
- 코스피
- 티스토리챌린지
- 엔비디아
- 나스닥
- 힐스테이트 광교산
- Home Assistant
- MQTT
- Apple
- homebridge
- raspberry pi
- Python
- matter
- 오블완
- 국내주식
- Espressif
- 월패드
Archives
- Today
- Total
YOGYUI
광교아이파크::환기(전열교환기) Apple 홈킷 연동 (2) 본문
반응형
[2] Homebridge 설정
1. Homebridge 플러그인 설치
플러그인 검색 키워드로 ventilation/ventilate로 검색해보니 적당한 결과가 없어서 일반 선풍기처럼 사용하고자 Fan 키워드로 검색, @Tommorodrigues의 homebridge-web-fab 플러그인을 발견
https://github.com/Tommrodrigues/homebridge-web-fan
(난방 제어 시 사용한 web-thermostat 플러그인의 개발자가 유사한 방식으로 올려두었기에 채택 - 개발 편의상)
2. 액세서리 등록
{
"accessory": "WebFan",
"name": "ventilator",
"apiroute": "http://localhost:9999/ventilator",
"rotationSpeed": true,
"listener": true,
"port": 12348,
"manufacturer": "Bestin",
"serial": "yogyui ventilator",
"model": "Bestin",
"pollInterval": 60
},
풍량이 있기 때문에 rotationSpeed 속성을 true로 설정
>> 아쉽게도 풍량 Min, Max 값 설정은 미구현 상태, default 0 ~ 100이라 값 변환이 필요할듯, TODO: 소스코드 변경
테스트는 필요하겠지만, index.js에 다음 코드 추가하면 될듯?
// plugin source code (index.js)
function WebFan (log, config) {
// 중략
this.rotationSpeedMin = config.rotationSpeedMin || 0
this.rotationSpeedMax = config.rotationSpeedMax || 100
// 중략
this.service.getCharacteristic(Characteristic.RotationSpeed).setProps({
minValue: this.rotationSpeedMin,
maxValue: this.rotationSpeedMax
})
// 중략
}
3. 서버 코드 수정
# app.py
# ventilator 연관 부분만 발췌
from typing import List
from Serial485.SerialComm import SerialComm
from Serial485.ControlParser import ControlParser
class Ventilator:
init: bool = False
state: bool = False
state_prev: bool = False
speed: int = 0
speed_prev: int = 0
listener_port: int = 0
packet_off: str = ''
packet_on: str = ''
packet_get_status: str = ''
packet_set_rotation_speed: List[str]
PORT_485_CONTROL = '/dev/ttyUSB1'
ventilator = Ventilator()
ventilator.packet_off = '02 61 01 4C 00 00 01 00 00 2F'
ventilator.packet_on = '02 61 01 E3 00 01 01 00 00 89'
ventilator.packet_get_status = '02 61 00 F1 00 00 00 00 00 9A'
ventilator.packet_set_rotation_speed[0] = '02 61 03 EB 00 00 01 00 00 8A'
ventilator.packet_set_rotation_speed[1] = '02 61 03 94 00 00 02 00 00 00'
ventilator.packet_set_rotation_speed[2] = '02 61 03 9F 00 00 03 00 00 FC'
ventilator.listener_port = 12348
ser_control = SerialComm()
par_energy = EnergyParser(ser_energy)
def parse_control_result(chunk: bytearray):
if len(chunk) < 10:
return
header = chunk[1]
if header == 0x61 and chunk[2] in [0x80, 0x81, 0x83, 0x84, 0x87]:
# 환기 관련 패킷
ventilator.state = bool(chunk[5] & 0x01)
ventilator.speed = chunk[6]
if ventilator.state != ventilator.state_prev or ventilator.speed != ventilator.speed_prev or not ventilator.init:
url = "http://0.0.0.0:{}/".format(ventilator.listener_port)
url += "state?value={}".format(int(ventilator.state))
requests.get(url)
print('Control Notify (ventilator): {}'.format(url))
url = "http://0.0.0.0:{}/".format(ventilator.listener_port)
url += "rotationSpeed?value={}".format(int(ventilator.speed / 3 * 100))
requests.get(url)
print('Control Notify (ventilator): {}'.format(url))
ventilator.init = True
ventilator.state_prev = ventilator.state
ventilator.speed_prev = ventilator.speed
def checkSerialControlConn():
if not ser_control.isConnected():
ser_control.connect(PORT_485_CONTROL, 9600)
def sendSerialControlPacket(packet: str):
checkSerialControlConn()
ser_control.sendData(bytearray([int(x, 16) for x in packet.split(' ')]))
class MyFlaskApp(Flask):
def run(self, host=None, port=None, debug=None, load_dotenv=True, **options):
with self.app_context():
checkSerialControlConn()
super(MyFlaskApp, self).run(host=host, port=port, debug=debug, load_dotenv=load_dotenv, **options)
app = MyFlaskApp(__name__)
@app.route('/ventilator/status', methods=['GET'])
def ventilator_get_status():
obj = {
'currentState': int(ventilator.state),
'rotationSpeed': int(ventilator.speed / 3 * 100)
}
print('ventilator_status response: {}'.format(obj))
return jsonify(obj)
@app.route('/ventilator/setState', methods=['GET'])
def ventilator_set_status():
value = request.args.get('value', default=0, type=int)
if value == 1:
while not ventilator.state:
sendSerialControlPacket(ventilator.packet_on)
time.sleep(0.5)
sendSerialControlPacket(ventilator.packet_get_status)
time.sleep(0.5)
elif value == 0:
while ventilator.state:
sendSerialControlPacket(ventilator.packet_off)
time.sleep(0.5)
sendSerialControlPacket(ventilator.packet_get_status)
time.sleep(0.5)
return ''
@app.route('/ventilator/setRotationSpeed', methods=['GET'])
def ventilator_set_rotation_speed():
value = request.args.get('value', default=0, type=int)
conv = min(3, max(0, int(value / 100 * 3) + 1))
while ventilator.speed != conv:
sendSerialControlPacket(ventilator.packet_set_rotation_speed[conv - 1])
time.sleep(0.5)
sendSerialControlPacket(ventilator.packet_get_status)
time.sleep(0.5)
return ''
if __name__ == '__main__':
par_control = ControlParser(ser_control)
par_control.sig_parse.connect(parse_control_result)
app.run(host='0.0.0.0', port=9999, debug=False)
ser_control.release()
4. 액세서리 확인
방 추가(다용도실) 후 액세서리 이름 변경 (전열교환기)
[시리즈 링크]
광교아이파크::환기(전열교환기) Apple 홈킷 연동 (1)
반응형
'홈네트워크(IoT) > 광교아이파크' 카테고리의 다른 글
광교아이파크::가스 Apple 홈킷 연동 (1) (0) | 2021.01.06 |
---|---|
광교아이파크::환기(전열교환기) Apple 홈킷 연동 (3) - Final (0) | 2021.01.05 |
광교아이파크::환기(전열교환기) Apple 홈킷 연동 (1) (0) | 2021.01.04 |
광교아이파크::난방 Apple 홈킷 연동 (5) - Final (0) | 2021.01.03 |
광교아이파크::난방 Apple 홈킷 연동 (4) (0) | 2021.01.02 |