반응형

부제: usb 선풍기를 wifi 로 제어하고 home assistant 에 연동하기 (ESPHome, Wemos d1 mini)

 

집에 장미를 들였는데 흰가루 병에 걸렸다.

수국 흰가루병

 

 

바람을 자주 쐬어줘야 좋다는 이야기를 듣고 굴러다니는 usb 선풍기를 찾아서 켜주곤 했는데,

매일 켜고 끄는것도 일이어서 자동화를 시동해 보았다.

 

먼저 선풍기를 뜯어서 어떤식으로 동작을 해야할지 생각해야 한다.

딱 보니까 뜯어서 푸쉬버튼을 누르는 동작을 릴레이나 트랜지스터로 구현하면 될 것 같다.

 

선풍기

 

 

뜯어봤다.

 

usb를 통해서 5v 입력을 받는데 여기서 선을 따서 wemos d1 mini(esp8266) 을 구동하면 될듯 싶다.

그리고 푸쉬버튼과 기판 프린팅을 보고 연결해야 할 부위를 찾는다.

 

아래 그림에서 보듯이 푸쉬버튼을 누를때 하나가 빨간선 두쌍을 연결해준다.

 

 

준비물

  1. 인두
  2. wemos d1 mini  ( + 롬라이팅용 usb 케이블 )
  3. 2n2222A BJT 트렌지스터 3개 또는 필요 수량
  4. 저항 1k옴 전후 3개 또는 필요 수량
  5. 연결용 전선
  6. 잘 셋팅된 Home assistant 와 esphome 애드온

 

 

 

작업사진

wemos d1 mini d5 와 d6 를 켜줄때만 push 버튼 양단이 통전 되도록 해준다.

보통때는 잘 열리지 않도록 d5, d6에 저항을 물려줬다.

 

 

 

D5(또는 D6) 가 트랜지스터 2번 핀에 연결되어야 하고, 1,2 는 push 버튼 양단에 연결해주면 된다.

보통은 3->1 방향으로 전류가 흐르기 때문에 3번을 ground 에 연결해주면 된다.

(반대로 해도 큰 상관 없을 것 같다.)

 

트랜지스터 구조

 

 

건전지 넣는 위치를 뜯어서 선을 빼주자.

 

 

 

이제 esphome 롬파일을 만들자.

 

esphome 에 들어가서 우측 하단 +를 눌러서 Create New node 를 해보자.

1. node name은 원하는 내용을

2. device type 은 wemos D1 mini 를 고르고

3. wifi는 사용하는 와이파이를 누르고 

4. finish 를 하면 완성이 된다.

 

그리고 아래와 같이 넣어줬다. 버튼 하나는 켜고 하나는 끄는 버튼을 할당해줬다.

당연히 계속 버튼이 눌려있으면 안되니까 시간 간격을 두고, 혹시 모르니 두번씩 눌리게 했다.

 

 

esphome:
  name: usb_fan
  platform: ESP8266
  board: d1_mini

wifi:
  ssid: "YOUR_SSID"
  password: "YOUR_PASSWORD"

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Mini-Usb-Fan Fallback Hotspot"
    password: "YByZ8eeeekW"

captive_portal:

# Enable logging
logger:
  level: DEBUG #기본값

# Enable Home Assistant API
api:
  password: "YOUR_API_PASSWORD"

ota:
  password: "YOUR_API_PASSWORD"


switch:
- platform: gpio
  pin: D6
  id: btn_off
- platform: gpio
  pin: D5
  id: btn_on

- platform: template
  name: "Usb Fan"
  optimistic: true
  turn_on_action:
  - switch.turn_on: btn_on
  - delay: 0.1s
  - switch.turn_off: btn_on
  - delay: 0.3s
  - switch.turn_on: btn_on
  - delay: 0.1s
  - switch.turn_off: btn_on
  turn_off_action:
  - switch.turn_on: btn_off
  - delay: 0.1s
  - switch.turn_off: btn_off
  - delay: 0.3s
  - switch.turn_on: btn_off #press off button twice just in case
  - delay: 0.1s
  - switch.turn_off: btn_off

 

 

 

이제 home assistant 에서 통합구성요소를 추가하면 된다.

esphome 을 찾아서 선택하고 위에서 만들어진 녀석 ip를 넣어주면 된다.

 

 

이제 home assitant 에서 switch 로 인식이 된다.

끄고 켜는것 모두 잘 된다. 이제 자동화나 스케쥴 등록이 가능하다.

 

 

반응형
반응형

HA+ESP8266+CC2530+CC2591 = Zigbee2Mqtt

 

 

home assistant 에서 zigbee2mqtt 를 사용중이다.

zigbee 장치는 보통 전용 브랜드의 게이트웨이나 브릿지에 연결된다 (휴 브릿지, 트로드프리 게이트웨이 등)

당연히 다른 회사 장비들 끼리는 호환이 제대로 되지 않고 브릿지도 비싸다.

Home assistant 를 꾸미고 범용으로 사용할 수 있는 zigbee coordinator 를 사용하는 방법이 몇가지 있는데 지원하는 장치가 많은 방식으로 가장 유명한게 ZHA와 Zigbee2mqtt 가 있다.

이번에 꾸민 HA+ESP8266+CC2530+CC2591 의 대략적인 동작 형태를 먼저 설명해보자면 아래와 같다.

동작 형태 HA+ESP8266+CC2530+CC2591

  1. Coordinator (CC2530+CC2591)를 serial 로 ESP8266 에 연결
  2. ESP8266 은 tcp serial server 로 동작
  3. zigbee2mqtt 는 hass.io 애드온으로 동작, ESP8266 tcp 서버에서 데이터 받아서 mqtt 서버로 보내줌
  4. hass.io 에 설치한 mqtt broker(서버) 에서 수신
  5. Home asssitant 통합구성요소에서 mqtt 장치 확인 및 사용
    + zigbee 장치 coordinator 와 페어링. zigbee2mqtt 프론트 페이지에서 페어링 모드 설정 및 결과 확인 가능

보통 CC2531 을 USB에 꽃아서 사용하는데 위와 같이 진행 한 이유는 NAS는 신발장 안에 있어서 zigbee 장치를 사용하 는 위치가 너무 멀어서다. 이렇게 esp8266과 합체하면 wifi로 연결되니 멀리 던져놓아도 된다. 그리고 CC2530+CC2591 이 무선 신호 증폭이 되어서 사용 가능 범위가 훨씬 넓다. (대략 2~3배)


생각보다 해야 할 일들이 많다.

준비물

  1. CC2530+CC2591 : 알리 익스프레스에서 구입 (약 8$ + 배송비 2$)
  2. ESP8266 또는 ESP32 구입 : ESP32가 더 좋긴 한데 집에 굴러다니는 wemos d1 mini(esp8266) 사용. (약 2$ + 배송비 0~2$)
  3. 점퍼 케이블, 인두와 납 : ESP8266 핀이 납땜 안되있을 경우 납땜이 필요하다.
  4. CC 디버거 또는 라즈베리파이 또는 ESP8266 : CC2530 에 펌웨어를 넣기 위해 필요하다. 나는 라즈베리파이 사용

진행방법

  1. 라즈베리파이로 펌웨어를 넣어준다.
    아래와 같이 연결해줘야 한다. 핀맵 그림을 참조하자.
Raspberry Pi        CC2531
GND            GND
Pin 38            DD
Pin 36            DC
Pin 35            RST

  1. ESP8266 펌웨어를 TASMOTA ZBbridge 버전으로 넣어준다. (이 버전만 tcp server 사용 가능하다)
    아래 사이트에서 tasmota-zbbridge.bin.gz 를 받아서 라이팅 하면 된다.
    http://ota.tasmota.com/tasmota/release/
  2. 라이팅은 https://github.com/tasmota/tasmotizer 를 설치하고 esp8266(wemos d1 mini) 를 usb로 연결하고 바로 라이팅 하면 된다.
  3. wemos d1 mini가 재부팅 되면 wifi 로 TASMOTA 에 접속한 후 사용할 와이파이 SSID 와 비밀번호를 넣어준다.
    그리고 재부팅 되는데 config에서 module 설정, General(18)로 재빨리 바꾸고 저장해준다.
    1분쯤 지나면 wemos d1 mini가 초기화된다. zigbee 장치가 아니라서 그런 듯 싶다.
  4. wemos d1 mini 와 CC2531을 연결해준다
    여기서는 wemos d1 mini 의 D7, D8 을 TX RX 로 활용하였다.
    ESP8266 CC2530
    3v3 VCC
    GND GND
    TX P02
    RX P03
    GND P20

  1. TASMOTA 설정
    라이팅된 wemos d1 mini의 TASMOTA 로 접속해서 "Configuration", "configure Module" 에서 Rx, Tx pin을 맞게 지정해준다.
    그리고 Tasmota 메인 화면에서 Console 로 들어가서 아래와 같이 입력해놓자.
  2. Rule1 ON System#Boot do TCPStart 8888 endon Rule1 1
  3. 이제 Zigbee2mqtt 의 configuration.yaml 파일을 열어서 해당 wemos d1 mini 에 연결되도록 ip와 포트를 지정해준다.
  4. serial: port: 'tcp://192.168.2.13:20108'

 

이상하게도 Wemos d1 mini는 espeasy 에서 잘 안되더라....

기본 rx, tx pin을 사용해도 안되서 TASMOTA 로 진행했다.

 

이제 원하는 장소에서 usb 전원만 공급하면 원격 zigbee2mqtt 코디네이터로 사용하면 된다.

 

 

참조 링크 : https://www.zigbee2mqtt.io/information/connecting_cc2530.html

반응형
반응형

home asssitant 사용 중 센서나 전등 등의 상태 변화나(로그북) 그래프를 확인하고 싶을때가 많다.

처음에는 별 상관 없는데 등록된 디바이스들이 많을 수록 데이터베이스 용량이 커져서 검색이 오래걸린다.

 

내 경우에는 전등 20개, 스위치 10개, 디바이스 트래커 30개, 센서류 20개 뭐 이정도 등록된거 같은데 home-asistant_v2.db 파일 용량이 2gb 가 넘었다. 물론 7일마다 삭제 되도록 옵션을 넣었지만...

 

해결 방법으로는 recoder 에서 include, exclude를 적절히 사용해서 필요 없는 내용을 기록하지 않거나(근데 지정하는것도 귀찮다)

www.home-assistant.io/integrations/recorder/

 

db 를 바꿔서 검색 속도를 빠르게 하는 방법이 있다.

 

 

당연히 귀찮으니까 db를 사용해보자.

 

물론 편리함을 위해 hass.io 쓰고 있다는 가정하에..

 

supervisor 에서 MariaDB add-ons 을 깔아준다.

 

config 는 아주 간단하게만 적용해주자.

자동시작 등록해놓고, 시작해주자.

databases:
  - homeassistant
logins:
  - username: yourID
    password: yourPassword
rights:
  - username: homeassistant
    database: homeassistant

 

이제 home assistant 에서 config 파일을 수정해보자.

 

HA 설정 폴더에서 configuration.yaml 파일을 열고 아래처럼만 넣어주면 된다.

물론 다른 recoder 옵션들을 사용해도 된다.

recorder:
  db_url: mysql://yourID:yourPassword@core-mariadb/homeassistant?charset=utf8mb4

 

이제 home assistant 를 재시작 하면 mariaDB가 적용되서 모든 기록들 검색이 매우매우 빨라진다.

 

 

 

꼭 적용해둘것!

반응형
반응형

 새로 이사온 아파트는 요새 트렌드인지 베란다는 확장되어 있고 조명과 벽지는 밝은 하얀색-베이지색으로 가득 차 있습니다. 어두침침한 예전 집들과는 다른 분위기입니다. 다만 저는 저녁때 집에서 쉴때는 은은한 전구색을 선호해서 많이 아쉬웠습니다. 대신 스탠드 조명이나 벽에 쏘는 스팟 조명같은걸 구해서 전구색과 주광색으로 사용하고 있었지요.

 

 예전 집에서 사용했던 조명들은 이케아 조명과 필립스 휴 스마트 전구 조합으로 만들어서 썼습니다.

qsurf.tistory.com/34

 

IKEA 스탠드 조명을 스마트 조명으로 - hue bridge

 제작년에 거실을 꾸미고 있을 때 이케아에서 스탠드 조명을 하나 샀습니다.  집에 오는 사람마다 이 조명 예쁘다고 한마디씩 해줬었는데요. 기존에는 스마트 플러그를 이용해서 on/off 만 자동�

qsurf.tistory.com

 

 그래도 조명이 계속 아쉬웠는데 그중 가장 아까운게 거실 창문쪽에 있는 천장 다운라이트 조명이었습니다. 기본으로 들어있는 조명은 아주 밝은 흰색이어서 그걸 켜놓으면 거실에서 도무지 아무것도 할 수 없었거든요. 어찌나 쨍하고 밝은지 눈을 자꾸 찔러대는 요녀석 때문에 힘들었습니다.

 

눈을 찌르는 천장 다운라이트

 도저히 이건 아니겠다 싶어서 천장 다운라이트를 빼내고 지금 타공되어있는 사이즈에 맞는 조명을 검색했습니다. 조건은 더 깊은 위치에서 조명을 쏘아주는것과 밝기와 색온도 조절이 가능할 것 입니다. 사실 밝기 조절만 하는 경우에 디머  를 설치하면 되는데 문제는 저 세개의 조명이 한줄로 연결되어 있는데 디머 한개로 3개 조명을 제어할 수 있도록 설치하려고 했는데 배선이 애매합니다. 스위치쪽에 설치하기엔 공간이 부족하고 천장에서 뜯어서 보면 각자 선이 하나씩만 나와있어서 공통 배선을 찾기가 힘들더라구요.

 거기다 색온도 조절까지 하려면 스마트 조명이 아니면 선택지가 없습니다. 현재 사용하고 있는 필립스 휴 조명중 적용할 수 있는 항목이 있는지 확인해 봤습니다. 아펠리온이라는 조명이 있네요? 가격은 오만원정도. 많이 비싸지만 필립스 조명이 연색성이나 편의성이 나쁘지 않아서 고민해봤습니다.

휴 아펠리온, 5만원

 문제는 현재 타공 지름이 9cm 인데 이녀석은 12.5cm 입니다. 타공을 다시 하려면 장비가 있어야 하는데 참 난감합니다. 거기다 요녀석도 천장 안쪽으로 깊숙히 들어가지는 않아서요.

 

 다시 검색을 시작합니다. 없는거 빼고 다 있는 알리 익스프레스에 들어가서 한참 검색하니 하나 보이네요.

 일단 사용 가능한 전구 타입은 Gu10 입니다. 필립스 휴와 이케아 트로드프리에서 나오는 스마트 조명은 요너석이거든요.

 

 

 타공 사이즈 완벽하고 원하는대로 깊이 들어가서 눈부심 방지도 되고 딱 좋습니다.

 

 이제 전구를 구입합니다. 일단 필립스 휴 Gu10 을 찾아보는데 한국에서는 정식 발매가 되지 않았습니다. 한국과 전압이 동일한 아마존 독일에서 주문을 해봅니다. 2개에 33.6 유로에 배송비 하면 한개에 3만 5천원 정도 하네요.

 

뭐지? 왜 Refund?

 무려 2주를 기다렸습니다. 배송이 되서 프랑스로 날아가더니.. 갑자기 배송 문제가 생겼다고 환불해버립니다. 기다리다 환장합니다. 물품 파손이 된건지 도무지 알 수 없습니다. 너무 지루한 기다림이 싫어서 이번엔 이케아 트로드프리 Gu10 조명을 구매했습니다. 가격은 조금 더 싸네요. 한개에 2만원. 다만 요너석은 블루투스 연결은 안되고 필립스 휴 브릿지와 제한적으로 연결될겁니다.

 

 그리고 다시 시작된 기다림

 

 

 다 왔습니다! 

 

 설치완료 후 모습입니다. 원하는대로 조도 변화가 잘 되네요. 눈부심이 훨씬 줄어들고 전구색으로 분위기도 좋아져서 행복합니다.

 

 

 성공적인 설치!

 하지만 실제로는 필립스 휴 브릿지와 연결이 잘 안되서 고생했습니다. 터치링크로 해야만 조명 추가가 되더라구요. 거기다 휴에 있는 씬이 비 정상적으로 적용됩니다. 색온도와 밝기가 동시에 바뀌어야 하는데 색온도만 바뀌고 밝기는 따로 신호를 줘야만 바뀌더라구요.

 휴 어플을 버리고 Home assistant 카드 뷰를 예쁘게 만든후에 요녀석을 이용해야 할거 같네요. 아쉽습니다.

반응형
반응형

 

 제작년에 거실을 꾸미고 있을 때 이케아에서 스탠드 조명을 하나 샀습니다.

 집에 오는 사람마다 이 조명 예쁘다고 한마디씩 해줬었는데요. 기존에는 스마트 플러그를 이용해서 on/off 만 자동화 했습니다. 저녁 6시에 자동으로 켜지고, 밤 11시쯤 자동으로 꺼지구요. 구글홈/빅스비로 음성으로 켜고 끄기도 되서 잘 쓰고 있었습니다.

 하지만 쓰다보면 만족하지 못하는게 있었는데, 바로 밝기 조절이 안된다는 사실이었습니다. 다른 간접 조명들은 Philps 의 Hue 조명을 사용하고 있어서 밝기조절(dimmable)과 색온도(color temp)조절까지 되는데 이녀석은 아무것도 안되서 불만족 스럽더라구요.

셰펜나 조명 - IKEA

 많이 사용하는 일반적인 E26 전구 소켓이면 좋을텐데.. gx53이라는 듣도보도 못한 소켓을 쓰고 있어서 답이 없습니다. gx53 소켓을 e26으로 변환하는게 있긴 한데 웹서핑해서 결과물을 보니 빛이 퍼져나가는 모습이 아름답지 않더라구요.

 그러다 문득 생각난 사실이 있었는데 원래 구입했던 LED 전구가 밝기조절은 된다는 사실이었죠. 그런데 어디를 봐도 밝기 조절을 하는게 보이지 않고 그냥 켜고 끄는 스위치만 보입니다. 알고보니 밝기 조절을 위해서는 조광기(dimmer)를 따로 설치하거나 연결해야 하는 거였죠. 

밝기 조절 됩니다!

 

 

 그럼 조광기만 있으면 되겠네요? 당연히 스마트한 조광기를 찾아봅니다. 네이버 스마트씽스 카페에서 사용기가 있는 zigbee 3.0 dimmer switch가 눈에 들어옵니다. 기존에 zigbee bridge 가 있어야 연결 가능합니다.

cafe.naver.com/stsmarthome/19714

 

Zigbee 3.0 dimmer switch

안녕하세요​갓북왕 입니다!​​오늘의 설정기는 zigbee 3.0 dimmer switch 입니다.원본링크 : https://blog.naver.com/godlastoise/2...

cafe.naver.com

 

aliexpress 에서 구입합니다. 디머 스위치는 무료배송 19.9달러. 조금 비싼데요?

ko.aliexpress.com/item/32954762426.html?spm=a2g0s.9042311.0.0.7c714c4dlumSab

 

US $17.95 50% OFF|Zigbee 3.0 스위치 DIY 홈 장치 스마트 원격 제어 Smartthings 에코 플러스 정장 지그비 허�

Smarter Shopping, Better Living! Aliexpress.com

ko.aliexpress.com

 

배송은 넉넉히 2주정도 걸렸습니다.

 

 

바로 설치합니다.

 

꾸깃꾸깃 설명서를 봅니다.

 대충 중간에 선을 짤라서 들어오는 선은 디머에 인풋단에 넣고 등으로 가야 하는 선은 output에 넣으면 되네요.

사실 집에서 쓴느 전기 배선도 활성선(Live, 파란선 또는 흰선) 과 중성선(Neutral, 검은선 또는 갈색선) 이 있지만 교류라서 대부분의 장비는 그냥 꽃아도 됩니다. 다만 조명을 스위치에 연결할때는 활성선과 중성선을 구분해 줘야 하는데요. 이유는 다음번에 설명하도록 하고.. 이 디머의 경우에는 뒤집어 꽃으면 안켜질거 같네요. 동작 안아면 코드를 뽑아서 반대로 넣어주면 될거 같습니다. 쉽죠?

 

 준비물은 드라이버와 가위(선 스트리퍼가 있으면 더 좋습니다)만 있으면 됩니다. 그리고 디머를 조명 아래에 부착하기 위해서 3m 양면테이프와 벨크로 테이프를 사용했습니다. 선을 자르고 가위로 열심히 피복을 벗기고 선을 끼우고 나사를 조여봅시다. 

 

 

 제어를 위해서는 기존에 사용하는 ZigBee 장비가 있어야 하는데 저는 Philips hue bridge 가 있으니까 여기다 연동시켜보겠습니다.

 

 Hue 앱에서 설정 -> 조명 설정 -> 조명 추가 를 누르고 검색해서 나오는 등을 추가하면 됩니다.

 

 

조명 검색 

 

 

추가된 조명

 

 조명이 추가되서 이제 hue 앱에서 제어 가능합니다. hue switch 에 등록해서도 제어 가능합니다.

 단점이라면 빛의 밝기가 너무 급격하게 변하는 느낌을 받습니다. hue의 경우에는 천천히 밝기가 변해서 자연스러운 느낌을 최대한 주거든요. 이런 디테일이 있어서 비싸도 hue를 쓰나 봅니다.

 

제어 가능

 

 

 이제 밝기 조절도 가능하고 스마트하게 켜지고 늦은 밤에는 어둡게 켜지고 아침엔 꺼지게 만들어야겠습니다. hue 앱에서 다 됩니다. 아니면 smartthings 나 homeassistant 와 연동해서 자동화 해도 됩니다.

 

 

구석에 짱박혀 있는 조명

 

 

다음번에는 천장에 있는 다운라이트를 hue 조명으로 바꾸려 합니다. 그런데 amazone 독일에 배송시킨 조명이 안오네요...다음달에 해야할듯 싶습니다. 

반응형
반응형

아파트 월패드용 스마트폰 어플이 있으나 도저히 사용할 수 없는 속도다.

프로그램 실행하는데 하세월 걸리고 버튼 누르고 변경되는걸 확인하는데도 몇초씩 걸린다.

 

불편함에 찾아보니 이미 선구자들이

월패드와 전등, 보일러 등 연결된 장치간 통신이 RS485 이며 해당 패킷을 분석하고 패킷을 보내서 제어를 하고 있다.

 

 

기본적으로 서버가 필요하며 라즈베리 파이나 도커 설치 가능한 NAS를 주로 사용한다.

 

RS485 제어 방법은 크게 아래 3가지다.

  • 서버에 직접 RS485-USB 장치를 연결 (패킷 제어 프로그램 필요. node.js나 파이썬 버전으로 제작되어있음)
  • RS485 to wifi 장치를 연결 (패킷 제어 프로그램 필요. node.js나 파이썬 버전으로 제작되어있음 )
  • ESPHome 장치를 이용한 제어 (Home assistant 플러그인 있음)

 

 

 

자세한 내용은 아래를 읽어보며 따라가면 된다.

 

cafe.naver.com/stsmarthome/12973

 

월패드 연동 ESPHOME RS485...

2020-04-01 업데이트 1. 체크섬 2byte 대응 checksum2 옵션 추가 (a...

cafe.naver.com

 

cafe.naver.com/stsmarthome/18238

 

[ESPHome] 현대통신 월패드 R...

대한민국 모임의 시작, 네이버 카페

cafe.naver.com

 

 

 

본인은 HA(Home assistant) 에서 가장 간편하게 사용 할 수 있는 ESPhome 버전으로 사용하고 있다.

사용을 위한 준비 과정을 요약하면 아래와 같다. 

1. 준비물

  • NAS (또는 라즈베리파이) 
  • Wemo d1 mini (RS8266 장치, 와이파이 가능한 프로그래밍 보드)
  • RS485 to UART
  • 납땜 장비, 소량의 전선
  • ESPeasy 펌웨어
  • HASS.io 설치 (home assistant 와 기타 애드온 관리 프로그램 통합된 버전)
  • 5V 1A 정도의 usb 충전기

2. 사용방법 요약

 

 

3. 사용중인 설정 내용

같은 imazu 여도 아파트마다 조금씩 패킷이 다르다. 참조할 것..

 

백업을 위해서 사용중인 esphome 데이터를 아래와 같이 붙여넣는다.

substitutions:
  node_name: rs485
  device_name: "RS485 Controller"
  
esphome:
  name: imazu_home_kks
  platform: esp8266
  board: d1_mini

wifi:
  ssid: "SSID"
  password: "PASSWORD"
  manual_ip:
    static_ip: 192.168.1.4 #(YOUR IP)
    gateway: 192.168.1.1
    subnet: 255.255.255.0
  reboot_timeout: 10min
  
  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Fallback Hotspot"
    password: "FALLBACK HOTSPOT PASSWORD"

captive_portal:


debug:
# Enable logging
logger:
  baud_rate: 0
  level: DEBUG #기본값
  #level: VERBOSE #사용하지 않는 패킷만 출력
  #level: VERY_VERBOSE #전체 패킷 출력 (초기 설정시에 추천)

# Enable Home Assistant API
api:
  reboot_timeout: 0s

ota:
  password: "PASSWORD"

status_led:
  pin: 
    number: GPIO2
    inverted: True


# RS485 Component (for ttl to rs485 module)
#  - esp8266: UART0 (TX: GPIO1, RX: GPIO3)
#  - esp32: UART2 (TX: GPIO17, RX: GPIO16)
rs485:
  baud_rate: 9600 #Required
  data_bits: 8    #Option(default: 8)
  parity: 0       #Option(default: 0)
  stop_bits: 1    #Option(default: 1)
  
  rx_wait: 10     #Option(default: 10ms)  -> 수신 메시지 대기시간 (10ms 미만으로 수신된 메시지만 한 패킷으로 판단)
  tx_interval: 50 #Option(default: 50ms) -> 발신 메시지 전송 간격 (패킷 수신 후 50ms 대기 후 전송)
  tx_wait: 100    #Option(default: 100ms) -> 발신 메시지 Ack 대기시간
  tx_retry_cnt: 3 #Option(default: 3)     -> 발신 메시지 Ack 없을 경우 재시도 횟수
  prefix: [0xF7]  #Option -> 값 세팅시 모든 수신 패킷 Check, 발신 패킷에 Append
  suffix: [0xEE]  #Option -> 값 세팅시 모든 수신 패킷 Check, 발신 패킷에 Append

  checksum: True      #Option(default: False) -> 체크섬 사용여부 (lambda 사용시 세팅 불필요)
  # checksum_lambda: |- #Option -> Default(CheckSum8 Xor) 체크섬 아닐 경우 직접 로직 구현(아래 값은 Default 로직임)
  #   // @param: const uint8_t *data, const unsigned short len
  #   // @return: uint8_t
  #   uint8_t crc = 0xF7; // data 변수에는 prefix 제외되어 있음
  #   for(num_t i=0; i<len; i++)
  #     crc ^= data[i];
  #   return crc;
  
  checksum2: False  #Option(default: False) -> ADD 체크섬 사용여부
  # checksum2: !lambda |- #Option -> Default(CheckSum8 Add) 체크섬 아닐 경우 직접 로직 구현(아래 값은 Default 로직임)
  #   // @param: const uint8_t *data, const unsigned short len, const uint8_t checksum1
  #   // @return: uint8_t
  #   uint8_t crc = 0xF7; // data 변수에는 prefix 제외되어 있음
  #   for(num_t i=0; i<len; i++)
  #     crc += data[i];
  #   crc += checksum1; // 첫번째 체크섬 계산 결과
  #   return crc;
  
#  state_response: #Option -> 값 세팅시 response 패킷 수신 후에 명령 패킷 송신
#    data: [0x04]
#    offset: 3
#    and_operator: False #Option(default: False) 수신패킷의 offset 위치와 data[0] And 비트연산 (비트위치-1: 0x01, 2: 0x02, 3: 0x04, 4: 0x08, 5: 0x10, 6: 0x20, 7: 0x40, 8: 0x80)
#    inverted: False #Option(default: False) 결과 값 반전(일치하지 않을 경우 참)
    
    
#  packet_monitor: #Option -> 패킷 모니터: Array 없으면 전체 출력, 있을 경우 or 조건 (logger level DEBUG 추천)
#   - [0x0c, 0x01, 0x2b]  # offset: 0
#   - data: [0x19, 0x04, 0x40, 0x23]
#     offset: 2

# RS485 Device 셋팅 팁
# 1. 상태 확인용(수신) Schema
#   - 대상: device(Required), sub_device(Option), state*
#   - 조건: device and sub_device 일치할때만 해당 Device에 패킷 전달됨
#   - 예시:
#     device: 
#       offset: 0 # 수신 패킷 비교 위치 (prefix 제외)
#       data: [0x0b, 0x01, 0x19, 0x04, 0x40, 0x23, 0x00] # hex array
#       and_operator: False # And 비트연산 사용여부
#       inverted: False #Option(default: False) 결과 값 반전 여부
#     #alias schema
#     device: [0x0b, 0x01, 0x19, 0x04, 0x40, 0x23, 0x00] # offset: 0, data: hex array
#
# 2. 명령용(발신) Schema
#   - 대상: command*
#   - 예시:
#     command:
#       data: [0x0b, 0x01, 0x1f, 0x02, 0x40, 0x21, 0x01, 0x00]  # prefix, checksum, suffix 제외
#       ack: [0x0b, 0x01, 0x1f, 0x04, 0x40, 0x21, 0x01, 0x01]   # prefix, checksum, suffix 제외
#     # Ack 없을 경우
#     command: [0x0b, 0x01, 0x1f, 0x02, 0x40, 0x21, 0x01, 0x00]
#     # Template(lambda): command_on, command_off
#     command_on: !lambda |-
#       uint8_t flag = id(balcony).state ? 0x02 : 0x01;
#       return {
#                 {0x0b, 0x01, 0x19, 0x02, 0x40, 0x23, flag, 0x00},
#                 {0x0b, 0x01, 0x19, 0x04, 0x40, 0x23, 0x01, 0x01}
#              };
#     command_off: !lambda |-
#       uint8_t flag = id(balcony).state ? 0x02 : 0x01;
#       return {
#                 {0x0b, 0x01, 0x19, 0x02, 0x40, 0x23, flag, 0x00},
#                 {0x0b, 0x01, 0x19, 0x04, 0x40, 0x23, 0x02, 0x02}
#              };
#     # 상태확인 요청 (Sensor 포함 모든 Device에 사용 가능)
#     command_state: [0x0B, 0x01, 0x19, 0x01, 0x40, 0x23, 0x00, 0x00] #Option
#     update_interval: 30s #Option(default: 60s)
#
# 3. Automation Schema
#   - rs485.write:
#       data: [0x0b, 0x01, 0x19, 0x02, 0x40, 0x23, 0x01, 0x00]
#       ack: [0x0b, 0x01, 0x19, 0x04, 0x40, 0x23, 0x01, 0x01]
#   - rs485.write: !lambda return {{0x0b, 0x01, 0x19, 0x02, 0x40, 0x23, 0x01, 0x00}, {0x0b, 0x01, 0x19, 0x04, 0x40, 0x23, 0x01, 0x01}};
#   # Ack 없는 경우
#   - rs485.write: [0x0b, 0x01, 0x19, 0x02, 0x40, 0x23, 0x01, 0x00]
#   - rs485.write: !lambda return {{0x0b, 0x01, 0x19, 0x02, 0x40, 0x23, 0x01, 0x00}, {}};



# RS485 Sensor

globals:
  - id: EV_CALL_COUNT
    type: int
    initial_value: '0'
  - id: EV_CALLING
    type: bool
    initial_value: 'false'

sensor:
  #엘리베이터 방향 정보
  - platform: rs485
    id: EV_ARRIVE
    device: [0x0D, 0x01, 0x34, 0x01, 0x41, 0x10, 0x00]
    #device: [0x0D, 0x01, 0x34, 0x01, 0x41, 0x10, 0x00]  kks 
    data:
      offset: 7
      length: 1
    on_value:
      then:
        - text_sensor.template.publish:
            id: EV_DIRECTION
            state: !lambda |-
              if (x == 0x01) return "도착";
              else if (x == 0xA6) return "UP";
              else if (x == 0xB6) return "DOWN";
              else return "";
  # 엘리베이터 층수 정보
  - platform: rs485
    id: EV
    device: [0x0D, 0x01, 0x34, 0x01, 0x41, 0x10, 0x00]
    #device: [0x0D, 0x01, 0x34, 0x01, 0x41, 0x10, 0x00]  kks
    lambda: !lambda |-
      if(len < 9) return {};
      char buf[3];
      sprintf(buf, "%02X ", data[8]);
      if(buf[0] == 'F')
        if(buf[1] == 'F') return -1.0;
        else return -2.0;
      else
        return atof(buf);
    on_value:
      then:
        - text_sensor.template.publish:
            id: EV_TEXT
            state: !lambda |-
              char result[10];
              if(x == 0) sprintf(result, "");
              else if(x > 0) sprintf(result, "%1.0f층", x);
              else sprintf(result, "지하 %1.0f층", -x);
              return result;

text_sensor:
  - platform: homeassistant
    name: Google Home mini TTS state
    icon: "mdi:speaker"
    entity_id: sensor.tts_state
    id: TTS_STATE

  # 엘리베이터 층수 정보
  - platform: template
    name: Elevator Floor
    icon: "mdi:elevator"
    id: EV_TEXT
    on_value:
      then:
        - if:
            condition:
              lambda: |-
                return ( "" != id(EV_TEXT).state );
            then:
              # 층수 정보가 업데이트 될 경우 엘리베이터 호출에 성공한 것으로 판단
              - globals.set:
                  id: EV_CALLING
                  value: 'false'
              # TTS로 엘리베이터 층수 방송
              - if:
                  condition:
                    lambda: |-
                      return ( "off" == id(TTS_STATE).state );
                  then:
                    - homeassistant.service:
                        service: media_player.turn_on
                        data:
                          entity_id: media_player.sigtagyeop
              - homeassistant.service:
                  service: tts.google_say
                  data:
                    entity_id: media_player.sigtagyeop
                    message: !lambda 'return id(EV_TEXT).state;'

  # 엘리베이터 방향(UP/DOWN/도착) 정보
  - platform: template
    name: Elevator Direction
    icon: "mdi:elevator"
    id: EV_DIRECTION
    on_value:
      - if:
          condition:
            text_sensor.state:
              id: EV_DIRECTION
              state: '도착'
          then:
            # 방향 정보가 업데이트 될 경우 엘리베이터 호출에 성공한 것으로 판단
            - globals.set:
                id: EV_CALLING
                value: 'false'
            - delay: 5s
            - homeassistant.service:
                service: media_player.turn_off
                data:
                  entity_id: media_player.sigtagyeop


switch:
    
  # 안방1 콘센트
  # 켜기
  #  0xf7 0x0b 0x01 0x1f 0x02 0x40 0x21 0x01 0x00 0x80 0xee
  #  0xf7 0x0b 0x01 0x1f 0x04 0x40 0x21 0x01 0x01 0x87 0xee (ack)
  # 끄기
  #  0xf7 0x0b 0x01 0x1f 0x02 0x40 0x21 0x02 0x00 0x83 0xee
  #  0xf7 0x0b 0x01 0x1f 0x04 0x40 0x21 0x02 0x02 0x87 0xee (ack)
  # 켜기상태-> 0xF7 0x12 0x01 0x1F 0x04 0x40 0x21 0x00 0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x9E 0xEE
  # 끄기상태-> 0xF7 0x12 0x01 0x1F 0x04 0x40 0x21 0x00 0x02 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x9D 0xEE

  - platform: template
    name: Elevator Call
    icon: "mdi:elevator"
    turn_on_action:
      # 엘리베이터 호출 cmd는 최대 30번
      # 점검 등의 사유로 호출이 안될 경우 중단을 위해 최대 카운트 설정
      - globals.set:
          id: EV_CALL_COUNT
          value: '25'
      # 엘리베이터 호출에 성공할 경우 cmd 보내는 것을 중지하기 위한 변수
      # 층수 정보(EV_TEXT)가 업데이트 될 경우 엘리베이터 호출에 성공한 것으로 판단
      - globals.set:
          id: EV_CALLING
          value: 'true'
      # TTS로 엘리베이터 호출 방송
      - homeassistant.service:
          service: media_player.turn_on
          data:
            entity_id: media_player.sigtagyeop
      - homeassistant.service:
          service: tts.google_say
          data:
            entity_id: media_player.sigtagyeop
            message: 엘리베이터를 호출합니다.
      # TTS 방송이 완료될 때 까지 대기
      # 대기하지 않을 경우 층수 정보(EV_TEXT) 방송에 의해 호출 방송이 중단 됨
      - delay: 2s
      # 반복문
      - while:
          # 엘리베이터 호출에 성공하거나, 최대 30번까지만 cmd를 전송
          condition:
            lambda: |-
              return ( 0 < id(EV_CALL_COUNT) ) && ( true == id(EV_CALLING) );
          # 1초마다 한번씩 cmd를 전송
          # cmd를 전송할 때 마다 카운트 변수를 1씩 차감
          then:
            - rs485.write: [0x0B, 0x01, 0x34, 0x04, 0x41, 0x10, 0x00, 0x06]
            #- rs485.write: [0x0B, 0x01, 0x34, 0x04, 0x41, 0x10, 0x00, 0x06]  kks 
            - lambda: |-
                id(EV_CALL_COUNT) -= 1;
            - delay: 1s
      # 엘리베이터 호출에 실패할 경우 TTS로 호출 실패 방송
      - if:
          condition:
            lambda: |-
              return ( 0 == id(EV_CALL_COUNT) );
          then:
            - homeassistant.service:
                service: tts.google_say
                data:
                  entity_id: media_player.sigtagyeop
                  message: 엘리베이터 호출에 실패했습니다.
            - delay: 3s
            - homeassistant.service:
                service: media_player.turn_off
                data:
                  entity_id: media_player.sigtagyeop
 
  - platform: rs485
    name: "Bedroom Power Socket 1"
    icon: "mdi:power-socket-eu"
    device: [0x25, 0x01, 0x1F, 0x04, 0x40, 0x20, 0x00]
    state_on:
      offset: 8
      data: [0x01]
    state_off:
      offset: 8
      data: [0x02]
    command_on:
      data: [0x0b, 0x01, 0x1f, 0x02, 0x40, 0x21, 0x01, 0x00]
      ack: [0x0b, 0x01, 0x1f, 0x04, 0x40, 0x21, 0x01, 0x01]
    command_off:
      data: [0x0b, 0x01, 0x1f, 0x02, 0x40, 0x21, 0x02, 0x00]
      ack: [0x0b, 0x01, 0x1f, 0x04, 0x40, 0x21, 0x02, 0x02]
    #command_state: [0x0B, 0x01, 0x1f, 0x01, 0x40, 0x20, 0x00, 0x00] #Option
    #update_interval: 997s #Option(default: 60s)
    
  # 안방2 콘센트
  - platform: rs485
    name: "Bedroom Power Socket 2"
    icon: "mdi:power-socket-eu"
    device: [0x25, 0x01, 0x1F, 0x04, 0x40, 0x20, 0x00]
    state_on:
      offset: 17
      data: [0x01]
    state_off:
      offset: 17
      data: [0x02]
    command_on:
      data: [0x0b, 0x01, 0x1f, 0x02, 0x40, 0x22, 0x01, 0x00]
      ack: [0x0b, 0x01, 0x1f, 0x04, 0x40, 0x22, 0x01, 0x01]
    command_off:
      data: [0x0b, 0x01, 0x1f, 0x02, 0x40, 0x22, 0x02, 0x00]
      ack: [0x0b, 0x01, 0x1f, 0x04, 0x40, 0x22, 0x02, 0x02]

  # 안방3 콘센트
  - platform: rs485
    name: "Bedroom Power Socket 3"
    icon: "mdi:power-socket-eu"
    device: [0x25, 0x01, 0x1F, 0x04, 0x40, 0x20, 0x00]
    state_on:
      offset: 26
      data: [0x01]
    state_off:
      offset: 26
      data: [0x02]
    command_on:
      data: [0x0b, 0x01, 0x1f, 0x02, 0x40, 0x23, 0x01, 0x00]
      ack: [0x0b, 0x01, 0x1f, 0x04, 0x40, 0x23, 0x01, 0x01]
    command_off:
      data: [0x0b, 0x01, 0x1f, 0x02, 0x40, 0x23, 0x02, 0x00]
      ack: [0x0b, 0x01, 0x1f, 0x04, 0x40, 0x23, 0x02, 0x02]
      
  # 거실1 콘센트
  - platform: rs485
    name: "Livingroom Power Socket 1"
    icon: "mdi:power-socket-eu"
    device: [0x1C, 0x01, 0x1F, 0x04, 0x40, 0x10]
    state_on:
      offset: 8
      data: [0x01]
    state_off:
      offset: 8
      data: [0x02]
    command_on:
      data: [0x0b, 0x01, 0x1f, 0x02, 0x40, 0x11, 0x01, 0x00]
      ack: [0x0b, 0x01, 0x1f, 0x04, 0x40, 0x11, 0x01, 0x01]
    command_off:
      data: [0x0b, 0x01, 0x1f, 0x02, 0x40, 0x11, 0x02, 0x00]
      ack: [0x0b, 0x01, 0x1f, 0x04, 0x40, 0x11, 0x02, 0x02]
    #command_state: [0x0B, 0x01, 0x1f, 0x01, 0x40, 0x10, 0x00, 0x00] #Option
    #update_interval: 991s #Option(default: 60s)


  # 거실2 콘센트
  - platform: rs485
    name: "Livingroom Power Socket 2"
    icon: "mdi:power-socket-eu"
    device: [0x1C, 0x01, 0x1F, 0x04, 0x40, 0x10]
    state_on:
      offset: 17
      data: [0x01]
    state_off:
      offset: 17
      data: [0x02]
    command_on:
      data: [0x0b, 0x01, 0x1f, 0x02, 0x40, 0x12, 0x01, 0x00]
      ack: [0x0b, 0x01, 0x1f, 0x04, 0x40, 0x12, 0x01, 0x01]
    command_off:
      data: [0x0b, 0x01, 0x1f, 0x02, 0x40, 0x12, 0x02, 0x00]
      ack: [0x0b, 0x01, 0x1f, 0x04, 0x40, 0x12, 0x02, 0x02]


  # 컴퓨터방 콘센트1
  # 켜기
  #, 0xF7, 0x0B, 0x01, 0x1F, 0x02, 0x40, 0x41, 0x01, 0x00, 0xE0, 0xEE
  #, 0xF7, 0x0B, 0x01, 0x1F, 0x04, 0x40, 0x41, 0x01, 0x01, 0xE7, 0xEE  ack
  # 끄기
  #, 0xF7, 0x0B, 0x01, 0x1F, 0x02, 0x40, 0x41, 0x02, 0x00, 0xE3, 0xEE
  #, 0xF7, 0x0B, 0x01, 0x1F, 0x04, 0x40, 0x41, 0x02, 0x02, 0xE7, 0xEE
  
  - platform: rs485
    name: "Computer Room Power Socket 1"
    icon: "mdi:power-socket-eu"
    device: [0x1C, 0x01, 0x1F, 0x04, 0x40, 0x40, 0x00]
    state_on:
      offset: 8
      data: [0x01]
    state_off:
      offset: 8
      data: [0x02]
    command_on:
      data: [0x0B, 0x01, 0x1F, 0x02, 0x40, 0x41, 0x01, 0x00]
      ack: [0x0B, 0x01, 0x1F, 0x04, 0x40, 0x41, 0x01, 0x01]
    command_off:
      data: [0x0B, 0x01, 0x1F, 0x02, 0x40, 0x41, 0x02, 0x00]
      ack: [0x0B, 0x01, 0x1F, 0x04, 0x40, 0x41, 0x02, 0x02]
    #command_state: [0x0B, 0x01, 0x1f, 0x01, 0x40, 0x40, 0x00, 0x00] #Option
    #update_interval: 983s #Option(default: 60s)

  # 컴퓨터방 콘센트2
  # 켜기
  #, 0xF7, 0x0B, 0x01, 0x1F, 0x02, 0x40, 0x42, 0x01, 0x00, 0xE3, 0xEE
  #, 0xF7, 0x0B, 0x01, 0x1F, 0x04, 0x40, 0x42, 0x01, 0x01, 0xE4, 0xEE  ack
  # 끄기
  #, 0xF7, 0x0B, 0x01, 0x1F, 0x02, 0x40, 0x42, 0x02, 0x00, 0xE0, 0xEE
  #, 0xF7, 0x0B, 0x01, 0x1F, 0x04, 0x40, 0x42, 0x02, 0x02, 0xE4, 0xEE


  - platform: rs485
    name: "Computer Room Power Socket 2"
    icon: "mdi:power-socket-eu"
    device: [0x1C, 0x01, 0x1F, 0x04, 0x40, 0x40, 0x00]
    state_on:
      offset: 17
      data: [0x01]
    state_off:
      offset: 17
      data: [0x02]
    command_on:
      data: [0x0B, 0x01, 0x1F, 0x02, 0x40, 0x42, 0x01, 0x00]
      ack: [0x0B, 0x01, 0x1F, 0x04, 0x40, 0x42, 0x01, 0x01]
    command_off:
      data: [0x0B, 0x01, 0x1F, 0x02, 0x40, 0x42, 0x02, 0x00]
      ack: [0x0B, 0x01, 0x1F, 0x04, 0x40, 0x42, 0x02, 0x02]

  # 작은방 콘센트1

  - platform: rs485
    name: "Room3 Power Socket 1"
    icon: "mdi:power-socket-eu"
    device: [0x1C, 0x01, 0x1F, 0x04, 0x40, 0x30, 0x00]
    state_on:
      offset: 8
      data: [0x01]
    state_off:
      offset: 8
      data: [0x02]
    command_on:
      data: [0x0B, 0x01, 0x1F, 0x02, 0x40, 0x31, 0x01, 0x00]
      ack: [0x0B, 0x01, 0x1F, 0x04, 0x40, 0x31, 0x01, 0x01]
    command_off:
      data: [0x0B, 0x01, 0x1F, 0x02, 0x40, 0x31, 0x02, 0x00]
      ack: [0x0B, 0x01, 0x1F, 0x04, 0x40, 0x31, 0x02, 0x02]
    #command_state: [0x0B, 0x01, 0x1f, 0x01, 0x40, 0x30, 0x00, 0x00] #Option
    #update_interval: 977s #Option(default: 60s)
    
    
  # 작은방 콘센트2

  - platform: rs485
    name: "Room3 Power Socket 2"
    icon: "mdi:power-socket-eu"
    device: [0x1C, 0x01, 0x1F, 0x04, 0x40, 0x30, 0x00]
    state_on:
      offset: 17
      data: [0x01]
    state_off:
      offset: 17
      data: [0x02]
    command_on:
      data: [0x0B, 0x01, 0x1F, 0x02, 0x40, 0x32, 0x01, 0x00]
      ack: [0x0B, 0x01, 0x1F, 0x04, 0x40, 0x32, 0x01, 0x01]
    command_off:
      data: [0x0B, 0x01, 0x1F, 0x02, 0x40, 0x32, 0x02, 0x00]
      ack: [0x0B, 0x01, 0x1F, 0x04, 0x40, 0x32, 0x02, 0x02]

  # 주방 콘센트1

  - platform: rs485
    name: "Kitchen Power Socket 1"
    icon: "mdi:power-socket-eu"
    device: [0x1C, 0x01, 0x1F, 0x04, 0x40, 0x50, 0x00]
    state_on:
      offset: 8
      data: [0x01]
    state_off:
      offset: 8
      data: [0x02]
    command_on:
      data: [0x0B, 0x01, 0x1F, 0x02, 0x40, 0x51, 0x01, 0x00]
      ack: [0x0B, 0x01, 0x1F, 0x04, 0x40, 0x51, 0x01, 0x01]
    command_off:
      data: [0x0B, 0x01, 0x1F, 0x02, 0x40, 0x51, 0x02, 0x00]
      ack: [0x0B, 0x01, 0x1F, 0x04, 0x40, 0x51, 0x02, 0x02]
    #command_state: [0x0B, 0x01, 0x1f, 0x01, 0x40, 0x50, 0x00, 0x00] #Option
    #update_interval: 971s #Option(default: 60s)
    
    
  # 주방 콘센트2
  - platform: rs485
    name: "Kitchen Power Socket 2"
    icon: "mdi:power-socket-eu"
    device: [0x1C, 0x01, 0x1F, 0x04, 0x40, 0x50, 0x00]
    state_on:
      offset: 24
      data: [0x01]
    state_off:
      offset: 24
      data: [0x02]
    command_on:
      data: [0x0B, 0x01, 0x1F, 0x02, 0x40, 0x52, 0x01, 0x00]
      ack: [0x0B, 0x01, 0x1F, 0x04, 0x40, 0x52, 0x01, 0x01]
    command_off:
      data: [0x0B, 0x01, 0x1F, 0x02, 0x40, 0x52, 0x02, 0x00]
      ack: [0x0B, 0x01, 0x1F, 0x04, 0x40, 0x52, 0x02, 0x02]


# RS485 Light(like Binary Light)
light:
  # [안방1]
  # 켜짐 상태-> 0xf7, 0x0b, 0x01, 0x19, 0x04, 0x40, 0x21, 0x00, 0x01, 0x80, 0xee
  # 꺼짐 상태-> 0xf7, 0x0b, 0x01, 0x19, 0x04, 0x40, 0x21, 0x00, 0x02, 0x83, 0xee
  # 켜짐 명령-> 0xf7, 0x0b, 0x01, 0x19, 0x02, 0x40, 0x21, 0x01, 0x00, 0x86, 0xee
  # 꺼짐 명령-> 0xf7, 0x0b, 0x01, 0x19, 0x02, 0x40, 0x21, 0x02, 0x00, 0x85, 0xee
  - platform: rs485
    name: "Bedroom 1"
    device: [0x0c, 0x01, 0x19, 0x04, 0x40, 0x20, 0x00]
    state_on:
      offset: 7
      data: [0x01]
    state_off:
      offset: 7
      data: [0x02]
    command_on:
      data: [0x0b, 0x01, 0x19, 0x02, 0x40, 0x21, 0x01, 0x00]
      ack: [0x0b, 0x01, 0x19, 0x04, 0x40, 0x21, 0x01, 0x01]
    command_off:
      data: [0x0b, 0x01, 0x19, 0x02, 0x40, 0x21, 0x02, 0x00]
      ack: [0x0b, 0x01, 0x19, 0x04, 0x40, 0x21, 0x02, 0x02]
#    command_state: [0x0B, 0x01, 0x19, 0x01, 0x40, 0x20, 0x00, 0x00] #Option
#    update_interval: 101s #Option(default: 60s)
    
  # [안방2]
  # 켜짐 상태-> 0xf7, 0x0b, 0x01, 0x19, 0x04, 0x40, 0x22, 0x00, 0x01, 0x83, 0xee
  # 꺼짐 상태-> 0xf7, 0x0b, 0x01, 0x19, 0x04, 0x40, 0x22, 0x00, 0x02, 0x80, 0xee
  # 켜짐 명령-> 0xf7, 0x0b, 0x01, 0x19, 0x02, 0x40, 0x22, 0x01, 0x00, 0x85, 0xee
  # 꺼짐 명령-> 0xf7, 0x0b, 0x01, 0x19, 0x02, 0x40, 0x22, 0x02, 0x00, 0x86, 0xee
  - platform: rs485
    name: "Bedroom 2"
    device: [0x0c, 0x01, 0x19, 0x04, 0x40, 0x20, 0x00]
    state_on:
      offset: 8
      data: [0x01]
    state_off:
      offset: 8
      data: [0x02]
    command_on:
      data: [0x0b, 0x01, 0x19, 0x02, 0x40, 0x22, 0x01, 0x00]
      ack: [0x0b, 0x01, 0x19, 0x04, 0x40, 0x22, 0x01, 0x01]
    command_off: 
      data: [0x0b, 0x01, 0x19, 0x02, 0x40, 0x22, 0x02, 0x00]
      ack: [0x0b, 0x01, 0x19, 0x04, 0x40, 0x22, 0x02, 0x02]


  # [거실1]
  # 켜짐 상태-> 0xf7, 0x0b, 0x01, 0x19, 0x04, 0x40, 0x11, 0x00, 0x01, 0xb0, 0xee
  # 꺼짐 상태-> 0xf7, 0x0b, 0x01, 0x19, 0x04, 0x40, 0x11, 0x00, 0x02, 0xb3, 0xee
  # 켜짐 명령-> 0xf7, 0x0b, 0x01, 0x19, 0x02, 0x40, 0x11, 0x01, 0x00, 0xb6, 0xee
  # 꺼짐 명령-> 0xf7, 0x0b, 0x01, 0x19, 0x02, 0x40, 0x11, 0x02, 0x00, 0xb5, 0xee
  - platform: rs485
    name: "Livingroom 1"
    device: [0x0D, 0x01, 0x19, 0x04, 0x40, 0x10, 0x00]
    state_on:
      offset: 7
      data: [0x01]
    state_off:
      offset: 7
      data: [0x02]
    command_on:
      data: [0x0b, 0x01, 0x19, 0x02, 0x40, 0x11, 0x01, 0x00]
      ack: [0x0b, 0x01, 0x19, 0x04, 0x40, 0x11, 0x01, 0x01]
    command_off:
      data: [0x0b, 0x01, 0x19, 0x02, 0x40, 0x11, 0x02, 0x00]
      ack: [0x0b, 0x01, 0x19, 0x04, 0x40, 0x11, 0x02, 0x02]
#    command_state: [0x0B, 0x01, 0x19, 0x01, 0x40, 0x10, 0x00, 0x00] #Option
#    update_interval: 103s #Option(default: 60s)
 

  # [거실2]
  # 켜짐 상태-> 0xf7, 0x0b, 0x01, 0x19, 0x04, 0x40, 0x12, 0x00, 0x01, 0xb3, 0xee
  # 꺼짐 상태-> 0xf7, 0x0b, 0x01, 0x19, 0x04, 0x40, 0x12, 0x00, 0x02, 0xb0, 0xee
  # 켜짐 명령-> 0xf7, 0x0b, 0x01, 0x19, 0x02, 0x40, 0x12, 0x01, 0x00, 0xb5, 0xee
  # 꺼짐 명령-> 0xf7, 0x0b, 0x01, 0x19, 0x02, 0x40, 0x12, 0x02, 0x00, 0xb6, 0xee
  - platform: rs485
    name: "Livingroom 2"
    device: [0x0D, 0x01, 0x19, 0x04, 0x40, 0x10, 0x00]
    state_on:
      offset: 8
      data: [0x01]
    state_off:
      offset: 8
      data: [0x02]
    command_on:
      data: [0x0b, 0x01, 0x19, 0x02, 0x40, 0x12, 0x01, 0x00]
      ack: [0x0b, 0x01, 0x19, 0x04, 0x40, 0x12, 0x01, 0x01]
    command_off:
      data: [0x0b, 0x01, 0x19, 0x02, 0x40, 0x12, 0x02, 0x00]
      ack: [0x0b, 0x01, 0x19, 0x04, 0x40, 0x12, 0x02, 0x02]



  # [발코니]
  # 켜짐 상태-> 0xf7, 0x0b, 0x01, 0x19, 0x04, 0x40, 0x13, 0x00, 0x01, 0xb2, 0xee
  # 꺼짐 상태-> 0xf7, 0x0b, 0x01, 0x19, 0x04, 0x40, 0x13, 0x00, 0x02, 0xb1, 0xee
  # 켜짐 명령-> 0xf7, 0x0b, 0x01, 0x19, 0x02, 0x40, 0x13, 0x01, 0x00, 0xb4, 0xee
  # 꺼짐 명령-> 0xf7, 0x0b, 0x01, 0x19, 0x02, 0x40, 0x13, 0x02, 0x00, 0xb7, 0xee
  - platform: rs485
    name: "Livingroom 3"
    device: [0x0D, 0x01, 0x19, 0x04, 0x40, 0x10, 0x00]
    state_on:
      offset: 9
      data: [0x01]
    state_off:
      offset: 9
      data: [0x02]
    command_on:
      data: [0x0b, 0x01, 0x19, 0x02, 0x40, 0x13, 0x01, 0x00]
      ack: [0x0b, 0x01, 0x19, 0x04, 0x40, 0x13, 0x01, 0x01]
    command_off:
      data: [0x0b, 0x01, 0x19, 0x02, 0x40, 0x13, 0x02, 0x00]
      ack: [0x0b, 0x01, 0x19, 0x04, 0x40, 0x13, 0x02, 0x02]


  # [작은방]
  # 켜짐 상태-> 0xf7, 0x0b, 0x01, 0x19, 0x04, 0x40, 0x31, 0x01, 0x01, 0x91, 0xee
  # 꺼짐 상태-> 0xf7, 0x0b, 0x01, 0x19, 0x04, 0x40, 0x31, 0x02, 0x02, 0x91, 0xee
  # 켜짐 명령-> 0xf7, 0x0b, 0x01, 0x19, 0x02, 0x40, 0x31, 0x01, 0x00, 0x96, 0xee
  # 꺼짐 명령-> 0xf7, 0x0b, 0x01, 0x19, 0x02, 0x40, 0x31, 0x02, 0x00, 0x95, 0xee
  - platform: rs485
    name: "Room 3"
    device: [0x0b, 0x01, 0x19, 0x04, 0x40, 0x30, 0x00]
    state_on:
      offset: 7
      data: [0x01]
    state_off:
      offset: 7
      data: [0x02]
    command_on:
      data: [0x0b, 0x01, 0x19, 0x02, 0x40, 0x31, 0x01, 0x00]
      ack: [0x0b, 0x01, 0x19, 0x04, 0x40, 0x31, 0x01, 0x01]
    command_off:
      data: [0x0b, 0x01, 0x19, 0x02, 0x40, 0x31, 0x02, 0x00]
      ack: [0x0b, 0x01, 0x19, 0x04, 0x40, 0x31, 0x02, 0x02]
#    command_state: [0x0B, 0x01, 0x19, 0x01, 0x40, 0x30, 0x00, 0x00] #Option
#    update_interval: 107s #Option(default: 60s)
    
      
  # [컴퓨터방]
  # 켜짐 상태-> 0xf7, 0x0b, 0x01, 0x19, 0x04, 0x40, 0x41, 0x01, 0x01, 0xe1, 0xee
  # 꺼짐 상태-> 0xf7, 0x0b, 0x01, 0x19, 0x04, 0x40, 0x41, 0x02, 0x02, 0xe1, 0xee
  # 켜짐 명령-> 0xf7, 0x0b, 0x01, 0x19, 0x02, 0x40, 0x41, 0x01, 0x00, 0xe6, 0xee
  # 꺼짐 명령-> 0xf7, 0x0b, 0x01, 0x19, 0x02, 0x40, 0x41, 0x02, 0x00, 0xe5, 0xee
  - platform: rs485
    name: "Computer Room"
    device: [0x0b, 0x01, 0x19, 0x04, 0x40, 0x40, 0x00]
    state_on:
      offset: 7
      data: [0x01]
    state_off:
      offset: 7
      data: [0x02]
    command_on:
      data: [0x0b, 0x01, 0x19, 0x02, 0x40, 0x41, 0x01, 0x00]
      ack: [0x0b, 0x01, 0x19, 0x04, 0x40, 0x41, 0x01, 0x01]
    command_off:
      data: [0x0b, 0x01, 0x19, 0x02, 0x40, 0x41, 0x02, 0x00]
      ack: [0x0b, 0x01, 0x19, 0x04, 0x40, 0x41, 0x02, 0x02]
#    command_state: [0x0B, 0x01, 0x19, 0x01, 0x40, 0x40, 0x00, 0x00] #Option
#    update_interval: 109s #Option(default: 60s)

      
  # [주방]
  # 켜짐 상태-> 0xf7, 0x0b, 0x01, 0x19, 0x04, 0x40, 0x51, 0x01, 0x01, 0xf1, 0xee
  # 꺼짐 상태-> 0xf7, 0x0b, 0x01, 0x19, 0x04, 0x40, 0x51, 0x02, 0x02, 0xf1, 0xee
  # 켜짐 명령-> 0xf7, 0x0b, 0x01, 0x19, 0x02, 0x40, 0x51, 0x01, 0x00, 0xf6, 0xee
  # 꺼짐 명령-> 0xf7, 0x0b, 0x01, 0x19, 0x02, 0x40, 0x51, 0x02, 0x00, 0xf5, 0xee
  - platform: rs485
    name: "Kitchen"
    device: [0x0C, 0x01, 0x19, 0x04, 0x40, 0x50, 0x00]
    state_on:
      offset: 7
      data: [0x01]
    state_off:
      offset: 7
      data: [0x02]
    command_on:
      data: [0x0b, 0x01, 0x19, 0x02, 0x40, 0x51, 0x01, 0x00]
      ack: [0x0b, 0x01, 0x19, 0x04, 0x40, 0x51, 0x01, 0x01]
    command_off:
      data: [0x0b, 0x01, 0x19, 0x02, 0x40, 0x51, 0x02, 0x00]
      ack: [0x0b, 0x01, 0x19, 0x04, 0x40, 0x51, 0x02, 0x02]
#    command_state: [0x0B, 0x01, 0x19, 0x01, 0x40, 0x50, 0x00, 0x00] #Option
#    update_interval: 113s #Option(default: 60s)
      
      
  # [식탁]
  # 켜짐 상태-> 0xf7, 0x0b, 0x01, 0x19, 0x04, 0x40, 0x52, 0x01, 0x01, 0xf2, 0xee
  # 꺼짐 상태-> 0xf7, 0x0b, 0x01, 0x19, 0x04, 0x40, 0x52, 0x02, 0x02, 0xf2, 0xee
  # 켜짐 명령-> 0xf7, 0x0b, 0x01, 0x19, 0x02, 0x40, 0x52, 0x01, 0x00, 0xf5, 0xee
  # 꺼짐 명령-> 0xf7, 0x0b, 0x01, 0x19, 0x02, 0x40, 0x52, 0x02, 0x00, 0xf6, 0xee
  - platform: rs485
    name: "Table"
    device: [0x0C, 0x01, 0x19, 0x04, 0x40, 0x50, 0x00]
    state_on:
      offset: 8
      data: [0x01]
    state_off:
      offset: 8
      data: [0x02]
    command_on:
      data: [0x0b, 0x01, 0x19, 0x02, 0x40, 0x52, 0x01, 0x00]
      ack: [0x0b, 0x01, 0x19, 0x04, 0x40, 0x52, 0x01, 0x01]
    command_off:
      data: [0x0b, 0x01, 0x19, 0x02, 0x40, 0x52, 0x02, 0x00]
      ack: [0x0b, 0x01, 0x19, 0x04, 0x40, 0x52, 0x02, 0x02]


# RS485 Fan
fan:
  # [환기]
  # 켜짐(강) 상태-> 0xf7, 0x0c, 0x01, 0x2b, 0x04, 0x42, 0x11, 0x07, 0x01, 0x07, 0x87, 0xee
  # 켜짐(중) 상태-> 0xf7, 0x0c, 0x01, 0x2b, 0x04, 0x42, 0x11, 0x03, 0x01, 0x03, 0x87, 0xee
  # 켜짐(약) 상태-> 0xf7, 0x0c, 0x01, 0x2b, 0x04, 0x42, 0x11, 0x01, 0x01, 0x01, 0x87, 0xee
  # 꺼짐     상태-> 0xf7, 0x0c, 0x01, 0x2b, 0x04, 0x40, 0x11, 0x02, 0x02, 0x01, 0x85, 0xee
  # 켜짐(강) 명령-> 0xf7, 0x0b, 0x01, 0x2b, 0x02, 0x42, 0x11, 0x07, 0x00, 0x80, 0xee
  # 켜짐(중) 명령-> 0xf7, 0x0b, 0x01, 0x2b, 0x02, 0x42, 0x11, 0x03, 0x00, 0x84, 0xee
  # 켜짐(약) 명령-> 0xf7, 0x0b, 0x01, 0x2b, 0x02, 0x42, 0x11, 0x01, 0x00, 0x86, 0xee
  # 꺼짐     명령-> 0xf7, 0x0b, 0x01, 0x2b, 0x02, 0x40, 0x11, 0x02, 0x00, 0x87, 0xee
  - platform: rs485
    name: "Ventilation"
    device: [0x0c, 0x01, 0x2b, 0x04, 0x40, 0x11, 0x00]
    state_on:
      offset: 7
      data: [0x01]
    state_off:
      offset: 7
      data: [0x02]
    command_on:
      data: [0x0b, 0x01, 0x2b, 0x02, 0x40, 0x11, 0x01, 0x00]
#      ack: [0x0c, 0x01, 0x2b, 0x04, 0x41, 0x2b, 0x04, 0x40, 0x11, 0x00, 0x01]
      ack: [0x0c, 0x01, 0x2b, 0x04, 0x40, 0x11, 0x01, 0x01, 0x01]
    command_off:
      data: [0x0b, 0x01, 0x2b, 0x02, 0x40, 0x11, 0x02, 0x00]
      ack: [0x0c, 0x01, 0x2b, 0x04, 0x40, 0x11, 0x02, 0x02, 0x01]
    speed: #Option(high, medium, low) -> 없으면 Binary Fan
      high:
        state:
          offset: 7
          data: [0x01, 0x07]
#          data: [0x07, 0x01, 0x07]
        command:
          data: [0x0b, 0x01, 0x2b, 0x02, 0x42, 0x11, 0x07, 0x00]
  #        data: [0x0c, 0x01, 0x2b, 0x04, 0x42, 0x11, 0x07, 0x01, 0X07 ]
          ack: [0x0c, 0x01, 0x2b, 0x04, 0x40, 0x11, 0x00, 0x01, 0x07]
      medium:
        state:
          offset: 7
          data: [0x01, 0x03]
        command:
#          data: [0x0b, 0x01, 0x2b, 0x02, 0x42, 0x11, 0x03, 0x00, 0x84
          data: [0x0b, 0x01, 0x2b, 0x02, 0x42, 0x11, 0x03, 0x00]
          ack: [0x0c, 0x01, 0x2b, 0x04, 0x40, 0x11, 0x00, 0x01, 0x03]
      low:
        state:
          offset: 7
          data: [0x01, 0x01, 0x01]
        command:
          data: [0x0b, 0x01, 0x2b, 0x02, 0x42, 0x11, 0x01, 0x00]
          ack: [0x0c, 0x01, 0x2b, 0x04, 0x40, 0x11, 0x00, 0x01, 0x01]
 #   command_state: [0x0B, 0x01, 0x2b, 0x01, 0x40, 0x11, 0x00, 0x00] #Option
#    update_interval: 107s #Option(default: 60s)


# RS485 Climate
climate:
  # [거실 난방] 0x11
  # 상태 요청: 0xF7, 0x0B, 0x01, 0x18, 0x01, 0x45, 0x11, 0x00, 0x00, 0xB0, 0xEE
  # 켜짐 상태: 0xF7, 0x0D, 0x01, 0x18, 0x04, 0x45, 0x11, 0x00, (0x01, 0x1B, 0x17), 0xBE, 0xEE (상태, 현재온도, 설정온도)
  # 꺼짐 상태: 0xF7, 0x0D, 0x01, 0x18, 0x04, 0x45, 0x11, 0x00, (0x04, 0x1B, 0x17), 0xBB, 0xEE (상태, 현재온도, 설정온도)
  # 외출 상태: 0xF7, 0x0D, 0x01, 0x18, 0x04, 0x45, 0x11, 0x00, (0x07, 0x1B, 0x17), 0xB9, 0xEE
  # 켜짐 명령: 0xF7, 0x0B, 0x01, 0x18, 0x02, 0x46, 0x11, 0x01, 0x00, 0xB1, 0xEE
  #      ACK: 0xF7, 0x0D, 0x01, 0x18, 0x04, 0x46, 0x11, 0x01, 0x01, 0x1B, 0x17, 0xBC, 0xEE
  # 꺼짐 명령: 0xF7, 0x0B, 0x01, 0x18, 0x02, 0x46, 0x11, 0x04, 0x00, 0xB4, 0xEE
  #      ACK: 0xF7, 0x0D, 0x01, 0x18, 0x04, 0x46, 0x11, 0x04, 0x04, 0x1B, 0x17, 0xBC, 0xEE
  # 온도 조절: 0xF7, 0x0B, 0x01, 0x18, 0x02, 0x45, 0x11, (0x18), 0x00, 0xA7, 0xEE (온도 24도 설정)
  #      ACK: 0xF7, 0x0D, 0x01, 0x18, 0x04, 0x45, 0x11, (0x18), 0x01, (0x1A, 0x18), 0xA8, 0xEE
  - platform: rs485
    name: "Livingroom Heater"
    visual:
      min_temperature: 10 °C
      max_temperature: 40 °C
      temperature_step: 1 °C
    device: [0x22, 0x01, 0x18, 0x04, 0x46, 0x10, 0x00]
    state_current: #Required (현재온도 State, RS485 Sensor 설정 참고, sensor:로 대체 가능)
      offset: 8
      length: 1
      precision: 0
    state_target: #Required (설정온도 State)
      offset: 9
      length: 1
      precision: 0
    state_off: #Required (끄기 상태)
      offset: 7
      data: [0x04]
    state_heat: #Option (난방모드, 냉방모드: state_cool, 자동모드: state_auto)
      offset: 7
      data: [0x01]
    state_away: #Option (외출모드)
      offset: 7
      data: [0x07]
    command_off: #Required (끄기 명령)
      data: [0x0B, 0x01, 0x18, 0x02, 0x46, 0x11, 0x04, 0x00]
      ack: [0x0D, 0x01, 0x18, 0x04, 0x46, 0x11, 0x04, 0x04]
    command_heat: #Option (난방모드 켜기)
      data: [0x0B, 0x01, 0x18, 0x02, 0x46, 0x11, 0x01, 0x00]
      ack: [0x0D, 0x01, 0x18, 0x04, 0x46, 0x11, 0x01, 0x01]
    command_away: #Option (외출 켜기)
      data: [0x0B, 0x01, 0x18, 0x02, 0x46, 0x11, 0x07, 0x00]
      ack: [0x0D, 0x01, 0x18, 0x04, 0x46, 0x11, 0x07, 0x07]
    command_temperature: !lambda |-  #Required (온도 조절)
      // @param: const float x
      return {
                {0x0B, 0x01, 0x18, 0x02, 0x46, 0x11, (uint8_t)x, 0x00},
                {0x0D, 0x01, 0x18, 0x04, 0x46, 0x11, (uint8_t)x, 0x01}
             };
             
#    command_state: [0x0B, 0x01, 0x18, 0x01, 0x46, 0x11, 0x00, 0x00] #Option
#    update_interval: 701s #Option(default: 60s)
 #0xF7, 0x0B, 0x01, 0x18, 0x01, 0x46, 0x10, 0x00, 0x00, 0xB2, 0xEE
 #0xF7, 0x22, 0x01, 0x18, 0x04, 0x46, 0x10, 0x00, 0x01, 0x15, 0x15, 0x01, 0x15, 0x16, 0x04, 0x13, 0x17, 0x04, 0x16, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0


  # [안방] 0x12
  # (현재온도 외부 센서 사용 샘플)
  - platform: rs485
    name: "Bedroom Heater"
    visual:
      min_temperature: 10 °C
      max_temperature: 40 °C
      temperature_step: 1 °C
    device: [0x22, 0x01, 0x18, 0x04, 0x46, 0x10, 0x00]
    state_current: #Required (현재온도 State, RS485 Sensor 설정 참고, sensor:로 대체 가능)
      offset: 11
      length: 1
      precision: 0
    state_target:
      offset: 12
      length: 1
      precision: 0
    state_off:
      offset: 10
      data: [0x04]
    state_heat:
      offset: 10
      data: [0x01]
    state_away:
      offset: 10
      data: [0x07]
    command_off: #Required (끄기 명령)
      data: [0x0B, 0x01, 0x18, 0x02, 0x46, 0x12, 0x04, 0x00]
      ack: [0x0D, 0x01, 0x18, 0x04, 0x46, 0x12, 0x04, 0x04]
    command_heat: #Option (난방모드 켜기)
      data: [0x0B, 0x01, 0x18, 0x02, 0x46, 0x12, 0x01, 0x00]
      ack: [0x0D, 0x01, 0x18, 0x04, 0x46, 0x12, 0x01, 0x01]
    command_away: #Option (외출 켜기)
      data: [0x0B, 0x01, 0x18, 0x02, 0x46, 0x12, 0x07, 0x00]
      ack: [0x0D, 0x01, 0x18, 0x04, 0x46, 0x12, 0x07, 0x07]
    command_temperature: !lambda |-  #Required (온도 조절)
      // @param: const float x
      return {
                {0x0B, 0x01, 0x18, 0x02, 0x46, 0x12, (uint8_t)x, 0x00},
                {0x0D, 0x01, 0x18, 0x04, 0x46, 0x12, (uint8_t)x, 0x01}
             };
#    command_state: [0x0B, 0x01, 0x18, 0x01, 0x46, 0x12, 0x00, 0x00] #Option
#    update_interval: 709s #Option(default: 60s)

  # [작은방] 0x14
  - platform: rs485
    name: "Room3 Heater"
    visual:
      min_temperature: 10 °C
      max_temperature: 40 °C
      temperature_step: 1 °C
    device: [0x22, 0x01, 0x18, 0x04, 0x46, 0x10, 0x00]
    state_current: #Required (현재온도 State, RS485 Sensor 설정 참고, sensor:로 대체 가능)
      offset: 14
      length: 1
      precision: 0
    state_target:
      offset: 15
      length: 1
      precision: 0
    state_off:
      offset: 13
      data: [0x04]
    state_heat:
      offset: 13
      data: [0x01]
    state_away:
      offset: 13
      data: [0x07]
    command_off: #Required (끄기 명령)
      data: [0x0B, 0x01, 0x18, 0x02, 0x46, 0x13, 0x04, 0x00]
      ack: [0x0D, 0x01, 0x18, 0x04, 0x46, 0x13, 0x04, 0x04]
    command_heat: #Option (난방모드 켜기)
      data: [0x0B, 0x01, 0x18, 0x02, 0x46, 0x13, 0x01, 0x00]
      ack: [0x0D, 0x01, 0x18, 0x04, 0x46, 0x13, 0x01, 0x01]
    command_away: #Option (외출 켜기)
      data: [0x0B, 0x01, 0x18, 0x02, 0x46, 0x13, 0x07, 0x00]
      ack: [0x0D, 0x01, 0x18, 0x04, 0x46, 0x13, 0x07, 0x07]
    command_temperature: !lambda |-  #Required (온도 조절)
      // @param: const float x
      return {
                {0x0B, 0x01, 0x18, 0x02, 0x46, 0x13, (uint8_t)x, 0x00},
                {0x0D, 0x01, 0x18, 0x04, 0x46, 0x13, (uint8_t)x, 0x01}
             };
#    command_state: [0x0B, 0x01, 0x18, 0x01, 0x46, 0x13, 0x00, 0x00] #Option
#    update_interval: 719s #Option(default: 60s)

  # [컴퓨터방] 0x13
  - platform: rs485
    name: "Computer Room Heater"
    visual:
      min_temperature: 10 °C
      max_temperature: 40 °C
      temperature_step: 1 °C
    device: [0x22, 0x01, 0x18, 0x04, 0x46, 0x10, 0x00]
    state_current:
      offset: 17
      length: 1
      precision: 0
    state_target:
      offset: 18
      length: 1
      precision: 0
    state_off:
      offset: 16
      data: [0x04]
    state_heat:
      offset: 16
      data: [0x01]
    state_away:
      offset: 16
      data: [0x07]
    command_off: #Required (끄기 명령)
      data: [0x0B, 0x01, 0x18, 0x02, 0x46, 0x14, 0x04, 0x00]
      ack: [0x0D, 0x01, 0x18, 0x04, 0x46, 0x14, 0x04, 0x04]
    command_heat: #Option (난방모드 켜기)
      data: [0x0B, 0x01, 0x18, 0x02, 0x46, 0x14, 0x01, 0x00]
      ack: [0x0D, 0x01, 0x18, 0x04, 0x46, 0x14, 0x01, 0x01]
    command_away: #Option (외출 켜기)
      data: [0x0B, 0x01, 0x18, 0x02, 0x46, 0x14, 0x07, 0x00]
      ack: [0x0D, 0x01, 0x18, 0x04, 0x46, 0x14, 0x07, 0x07]
    command_temperature: !lambda |-  #Required (온도 조절)
      // @param: const float x
      return {
                {0x0B, 0x01, 0x18, 0x02, 0x45, 0x14, (uint8_t)x, 0x00},
                {0x0D, 0x01, 0x18, 0x04, 0x45, 0x14, (uint8_t)x, 0x01}
             };
#    command_state: [0x0B, 0x01, 0x18, 0x01, 0x46, 0x14, 0x00, 0x00] #Option
#    update_interval: 727s #Option(default: 60s)
반응형

+ Recent posts