Home Assistant와 CVnet 월패드 연결용 Flask 서버 제작 Ver.1

쭌로그·2023년 3월 9일
1
post-thumbnail

(thumbnail image source1)
(thumbnail image source2)
(thumbnail image source3)

개인적으로 Home Assistant를 소소하지만 재밌게 세팅해서 사용중입니다. 개인적인 세팅에 대해서 기록겸 혹시 보실 분 있을까 겸사해서 올려보려고 합니다. ㅎㅎ
역시 많은 블로그를 통해서 flask 도커 구성 방법을 배워서 설정해보았습니다. 항상 지식 공유해주시는 분들 감사합니다.

구성 완성 형태

우선 누추하지만 제 메인 화면을 보여드리겠습니다.

ESP home을 이용한 온도센서, NEOPixel LED바, PC WOL, 보일러, LG 공기 청정기 구성입니다. 자동화 또한 몇 개 없어 누추합니다...

아무튼 이정도로 구성했고, 개인적으로 별거 없지만 만족하면서 사용중입니다. 하지만 제 구성에서 조금 특이한 점은, 월패드 보일러 제어 부분을 연결해서 보일러를 제어하지만, 월패드에 RS485 모듈을 붙이거나 하는 것이 아닌, 인터넷을 이용한다는 점일겁니다.

이 부분에 대해서 혼자 오래 삽질해서 구현했는데, 혹시 다른분들도 아이디어를 얻으실 수 있을까 해서 제 방법을 자세히 공유해봅니다.

월패드 앱 리버스 엔지니어링

먼저, 저희집은 CVnet 월패드이고, CVnet smart home 앱을 이용해서 제어합니다.

이 부분에서 큰 힌트를 얻었는데요, CVnet smart home 앱은 웹뷰 형식이라 사실 인터넷 사이트에 접속하는 것과 같습니다. 그래서 이 어플에서 접속하는 주소를 따서 접속해봤습니다.

PC로 접속해보니 태블릿모드의 화면이 뜨더군요. 스마트폰용앱에 비해서 인증이 덜 까다롭고, 그만큼 제어할 수 있는 부분이 적긴 합니다만, 난방이 목표였던 저에게는 이거면 충분해서 이 사이트를 3일간 분석해서 리버스 엔지니어링(...)끝에 웹에 로그인부터 제어 신호를 보내는 것까지 python 코드로 제작했습니다. 지식이 없었어서 삽질이 오래 걸려서 그렇지 매우 쉬웠습니다.

Home Assistant configuration 구성

그래서 이 부분을 어떻게 HA와 연결할 수 있을까 고민했는데, 자료를 뒤지던중 configuration에서 http requests를 보낼 수 있는 것을 발견해 이 부분을 이용해서 http 센서와 http 보내기를 만들었습니다. (이 부분도 시간을 상당히 소요했는데, 역시 지식이 없어서...)

서버와 주고받을 json 형태에 맞춰서 restful 요소 configuration을 작성해줍니다.

configuration.yaml >>

sensor:

  - platform: rest

    name: heater_get_all

    resource: http://loaclhost:7950/heater/get

    method: POST

    headers:

    Content-Type: "application/json"

    payload: '{ 
      "ID": "cvnet_id", 
      "PW": "cvnet_pw" 
    }'

    json_attributes:

      - room1

      - room2

      - room3

      - room4

      - room5

    value_template: "OK"


rest_command:

  heater_control:

  url: http://loaclhost:7950/heater/control

  method: POST

  payload: '{

    "ID": "cvnet_id",

    "PW": "cvnet_pw"

    "room_number": "{{room_number}}",

    "onoff": "on",

    "target_temperature": "{{temp}}",

  }'

  content_type: "application/json; charset=utf-8"
  
  
input_number:
  heater_slider_1:
    name: Slider
    initial: 18
    min: 18
    max: 32
    step: 1

슬라이더를 통해서 보일러 설정 온도를 제어하기 위해서 자동화를 추가해줍니다.

automation.yaml >>

- id:

  alias: 보일러 동작 트리거 (1)

  description: 슬라이더의 값이 바뀌면 보일러의 온도를 슬라이더의 값으로 설정합니다.

  trigger:

  - platform: state

    entity_id:

  - input_number.heater_slider_1

    condition: []

    action:

  - service: rest_command.heater_control

    data:

    temp: '{{ states(''input_number.heater_slider_1'') | int }}'

    room_number: '{{ 1 }}'

    mode: restart

Flask 빌드

다음으로 HA에서 전송하는 http request를 처리할 부분을 제작해야겠죠. flask를 이용해서 간단하게 http request를 전송하면 json으로 방별 현재 온도, 설정 온도 값을 리턴하고, 제어할 수 있도록 코드를 작성하였습니다.

flask.py >>


@app_route.route('/heater/get', methods=['POST'])

def heat_info():

  login(login_info)

  response = get_heater_reduced(ID)

  return jsonify(response)


@app_route.route('/heater/control', methods=['POST'])

def heat_control():

  if (request.is_json):

    login(login_info)

    control_heater_reduced(ID, room_number, onoff, target_temperature)

    return "Done!"

그리고 이 flask를 uwsgi 모듈과 연결하여 http로 서비스 하도록 연결해 도커 이미지를 빌드해서 올렸습니다. (처음 해봤는데 여러 블로거 분들의 글을 통해서 도움 많이 받았습니다. ㅎㅎ)

dockerfile >>

FROM python:3.8

WORKDIR /app

ADD . /app
RUN pip install -r requirements.txt

CMD ["uwsgi","uwsgi.ini"]

uwsgi.ini >>
* 웹서버를 따로 사용하지 않고 uwsgi단독 실행이므로 socket이 아닌 http-socket을 사용.

[uwsgi]
wsgi-file = app.py
callable = app
http-socket = :7950
processes = 4
threads = 2
master = true
vacum = true
chmod-socket = 660
die-on-term = true
logto = uwsgi_log/@(exec://date +%%Y-%%m-%%d).log
log-reopen = true

docker-compose >>

version: "3"

services:
    home_ws_controller:
        build: ./build
        container_name: home_ws
        volumes: 
          - ./logs:/app/uwsgi_log #로그 확인용
        restart: always
        environment:
            - PUID= 0
            - GUID= 0
            - APP_NAME=home_ws
        # expose:
        #     - 3032
        ports:
            - "7950:7950"

portainer 상에서 작동중이 확인되는 이미지

구성 설명

순서 다이어그램은 다음과 같습니다.

control sensor

단점

물론 단점도 있습니다. 보일러 슬라이더가 움직이면 보일러가 그 값으로 변하지만, 슬라이더가 초기화되면 그때는 슬라이더가 초기값에 가있고 보일러 값이 슬라이더와 맞지 않으니까요... 그래서 보일러 현재 설정 온도를 추가해서 확인할 수 있도록 만들었습니다. 그런데 이 http 센서는 HA상에 표시되는 값이 반영이 매우 느립니다.(로그를 확인해보니 대충 30초에 한 번 확인하는 것 같습니다.)

마치며

아무쪼록 혼자 멘땅에 헤딩하며 열심히 구성했던 것인데, 혹시 이걸보고 아이디어가 될 수 있을까 하여 올려봅니다.! 혹시 개선할 부분이 있다면 조언도 부탁드립니다!

끝까지 다 읽어보셨다면... 읽어주셔서 감사합니다.

profile
컴퓨터, 기계 등을 좋아하는 전자공학을 전공중인 대학생입니다.

4개의 댓글

comment-user-thumbnail
2023년 3월 20일

이해가 안 가요

1개의 답글
comment-user-thumbnail
2024년 2월 14일

안녕하세요 혹시 도움 좀 요청 할 수 있을까요?

1개의 답글