Repository navigation
Conversation
select.py의 current_option/async_select_option은 s2h_state_mapping만 읽었는데, climate/fan 쪽 mode/preset_mode 필드는 관례상 s2h_mode_mapping을 쓴다. 이 이름 불일치 때문에 select에 s2h_mode_mapping을 쓴 설정은 매핑이 통째로 무시되어 상태가 unknown으로 뜨고 커맨드도 잘못된 값으로 전송됐다 (예: samsungce.hoodFanSpeed 14~18을 smart/normal/.../max로 매핑하는 후드 팬속도 select). - select.py: s2h_state_mapping이 없으면 s2h_mode_mapping을 fallback으로 사용 - common.py get_mapping_value/get_mapping_key: 매핑 키가 숫자 SmartThings 값과 문자열로 따옴표 붙여 적힌 YAML 키 사이에서도 매칭되도록 하고, 커맨드로 되돌려 보낼 때도 숫자로 캐스팅해서 SmartThings API 타입 검증을 통과하도록 함 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CmJTDppSN12JBjtZJzFWza
async_set_hvac_mode 가 꺼진 상태에서 다른 모드로 바꾸면 switch on 커맨드와 setAirConditionerMode 커맨드를 지연 없이 연속으로 보내는데, 클라우드로 실행되는 일부 에어컨(특히 삼성 벽걸이형)은 전원이 켜진 걸 인지하기 전에 모드 변경 커맨드가 도착하면 다시 꺼짐 상태로 튕겨나가는 것으로 보인다 (asyncio 가 import만 되어있고 안 쓰이던 것도 이 타이밍 처리가 미완성으로 남아있던 흔적으로 보임). 전원 on 이후 1초 지연을 추가해 완화. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CmJTDppSN12JBjtZJzFWza
직전 커밋에서 넣은 "매핑 키가 숫자면 int로 캐스팅" 처리가 for 루프
바깥에 있어서, 매핑 테이블이 아예 없거나(s2h_*_mapping 미설정) 값이
안 걸린 경우에도 무조건 적용되고 있었다. 그 결과 climate의 fan_mode
처럼 매핑 없이 그대로 전송해야 하는 값("3", "auto", "max" 등)까지
숫자로 캐스팅되어 SmartThings API가 "integer found, string expected"로
거부 — 실사용 중 팬속도 수동 조절이 막히는 회귀가 발생했다
(실기기 테스트로 재현/확인됨).
캐스팅을 실제로 매핑에서 매치를 찾은 분기 안으로 옮겨서, 매핑이 없는
pass-through 값은 원래 타입 그대로 전송되도록 수정.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CmJTDppSN12JBjtZJzFWza
일부 에어컨(예: 삼성 무풍)은 팬속도(fan_mode)와 별개 캐패빌리티로 켜고 끄지만 기기 자체가 "팬속도를 바꾸면 무풍 해제, 무풍을 켜면 팬속도 auto로 리셋"하는 식으로 상호 배타적으로 동작한다 (실기기 테스트로 확인). 이런 경우 정확한 캐패빌리티/커맨드가 다르다는 이유로 별도 select 엔티티로 분리해야 했는데, 사용자 입장에서는 같은 climate 카드의 fan_mode 드롭다운 하나에서 고르는 게 자연스럽다. fan_mode 서브캐패빌리티에 선택적으로 `alt_mode`(단일 대체 모드) 설정을 추가할 수 있게 했다: - 옵션 목록(fan_modes)에 alt_mode.name이 추가로 붙는다 - fan_mode 읽기: alt_mode에 설정된 상태(state)가 on_state에 해당하면 alt_mode.name을 우선 반환한다 (기기가 fanMode를 auto로 리셋해도 정확히 표시됨) - fan_mode 쓰기: alt_mode.name이 선택되면 alt_mode에 설정된 capability/command/argument로 커맨드를 보낸다 (기존 fan_mode 커맨드 대신) alt_mode를 설정하지 않은 기존 구성에는 전혀 영향 없음 (완전히 opt-in). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CmJTDppSN12JBjtZJzFWza
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
배경
에어컨(airConditionerMode)/후드(samsungce.hoodFanSpeed) 실사용 중 발견한 이슈 3건을 고쳤습니다.
이후 실사용 중 추가로 발견한 회귀 수정 1건과 편의 기능 1건도 같은 PR에 포함했습니다 (아래 4, 5번).
1) select 엔티티가
s2h_mode_mapping을 인식하지 못함select.py의current_option/async_select_option은s2h_state_mapping만 읽습니다. 그런데 climate/fan 쪽의mode/preset_mode필드는 관례상s2h_mode_mapping을 씁니다. 이 이름 불일치 때문에 select에s2h_mode_mapping을 쓴 설정(예:samsungce.hoodFanSpeed의 14~18 값을 smart/normal/.../max로 매핑하는 후드 팬속도 select)은 매핑이 통째로 무시되어:current_option이 되어options에 없는 값이라 HA가unknown으로 표시수정:
s2h_state_mapping이 없으면s2h_mode_mapping을 fallback으로 사용하도록 변경 (기존s2h_state_mapping설정에는 영향 없음).2) 매핑 키의 숫자/문자열 타입 불일치
YAML에서
"14": "smart"처럼 따옴표 붙은 숫자 키를 쓰면 문자열이 되어, SmartThings가 정수로 주는 실제 속성값(14)과 매칭이 안 됩니다.get_mapping_value/get_mapping_key가 문자열↔숫자 양쪽으로 매칭을 시도하고, 커맨드로 값을 되돌려 보낼 때도 숫자로 캐스팅하도록 해서 SmartThings API의 타입 검증을 통과하게 했습니다.3) climate 전원 on + 모드 변경을 동시에 하면 다시 꺼짐으로 되튕기는 문제
async_set_hvac_mode가 꺼진 상태에서 다른 모드로 바꾸며 켤 때switch on커맨드와setAirConditionerMode커맨드를 지연 없이 바로 연달아 보냅니다. 클라우드로 실행되는 일부 에어컨(테스트한 삼성 벽걸이형 에어컨)은 전원이 켜진 걸 미처 인지하기 전에 모드 변경 커맨드가 도착하면 다시 꺼짐 상태로 튕겨나가는 것으로 보입니다.async_turn_on()직후 1초 지연을 추가했습니다.테스트
실제 삼성 에어컨(스탠드형/벽걸이형) + 삼성 후드로 검증:
select.hood_fan_mode:unknown→ 정상적으로smart/normal/... 표시 및 실제 팬속도 변경 확인climate.wall_air: 꺼짐 → 다른 모드로 켜기를 3회 반복, 3회 모두 안정적으로 유지되고 꺼짐으로 되튕기는 현상 재현 안 됨climate.stand_air: 기존 동작 회귀 없음 확인4) (회귀 수정) 매핑이 없는 값까지 숫자로 캐스팅되던 문제
2번 수정에서 넣은 "매핑 키가 숫자 문자열이면 int로 캐스팅" 처리가 원래 for 루프 바깥에 있어서,
s2h_*_mapping이 아예 설정 안 된 값(예: climatefan_mode의"3"처럼 그대로 전송해야 하는 pass-through 값)까지 무조건 int로 바뀌고 있었습니다. 실기기 테스트로 재현: SmartThings API가"integer found, string expected"로 거부하면서 팬속도 수동 조절이 막혔습니다. 캐스팅을 실제로 매핑에서 매치를 찾은 분기 안으로 옮겨서, 매핑이 없는 값은 원래 타입 그대로 유지되도록 수정했습니다.5) climate fan_mode에 상호 배타적인 대체 모드(예: 무풍)를 같은 드롭다운으로 통합하는
alt_mode옵션 추가삼성 무풍처럼 팬속도와는 별개 캐패빌리티(
custom.airConditionerOptionalMode)로 켜고 끄지만, 기기 자체가 "팬속도를 바꾸면 무풍 해제, 무풍을 켜면 팬속도 auto로 리셋"하는 식으로 상호 배타적으로 동작하는 기능을 실기기로 확인했습니다. 이런 경우를 위해fan_mode서브캐패빌리티에 선택적alt_mode설정을 추가할 수 있게 했습니다:alt_mode.name이 추가됩니다alt_mode에 설정된 별도 capability/command로 커맨드를 보냅니다alt_mode의on_state에 해당하면 (기기가 원래 캐패빌리티 값을 다른 값으로 리셋해도)alt_mode.name을 우선 표시합니다alt_mode를 설정하지 않은 기존 구성에는 전혀 영향 없는 opt-in 기능입니다. 실기기(삼성 스탠드형 에어컨)로 옵션 목록 노출/선택 시 실제 전환/상태 표시/상호 자동 해제까지 전부 검증했습니다.참고: s2h_action_mapping은 HVACAction enum 값을 써야 합니다
이번 PR 범위는 아니지만,
hvac_action(s2h_action_mapping으로 매핑)은 HA의HVACActionenum(off/heating/cooling/drying/idle/fan/preheating/defrosting)이어야 프론트엔드가 인식합니다. 한글 텍스트("냉방 청정" 등)를 넣으면 상태창에 정상 표시되지 않습니다 — README/예제에 이 제약을 명시하면 다른 사용자들의 혼동을 줄일 수 있을 것 같습니다.🤖 Generated with Claude Code
https://claude.ai/code/session_01CmJTDppSN12JBjtZJzFWza