diff --git a/README.md b/README.md index 3afe99f..8d7b1e1 100644 --- a/README.md +++ b/README.md @@ -194,6 +194,8 @@ Samsung's firmware occasionally drops the DTLS session briefly — this is norma If reconnects become persistent (more than a handful per minute), something's actually wrong. Check the appliance's Wi-Fi link first, then look for a competing DTLS client on the LAN — only one active session per appliance is allowed at a time. +Deregistering a device in SmartThings causes a reset of its network settings as soon as it accesses Samsung's servers, dropping it off Wi-Fi until it's re-onboarded through the SmartThings app. As such, consider keeping devices registered even if egress-blocked, to avoid them resetting upon brief internet access. + ### Multi-subdevice ("2-in-1") air conditioner systems Some Samsung installs run more than one indoor subdevice off a single outdoor unit, all reachable over the *one* IP/DTLS session your config entry connects to (a floor-standing + wall-mounted 2-in-1 is a common shape). The integration discovers any sibling subdevices automatically, once, right after the first successful poll — there's nothing to configure. Each discovered subdevice gets its own HA device (linked to the main one via "via device") and its own `climate` card, so it lands in its own room in the dashboard instead of being invisible or mixed into the master's state. diff --git a/custom_components/localthings/registry/capabilities/airconditioner.py b/custom_components/localthings/registry/capabilities/airconditioner.py index edf61cc..2bc5cce 100644 --- a/custom_components/localthings/registry/capabilities/airconditioner.py +++ b/custom_components/localthings/registry/capabilities/airconditioner.py @@ -14,6 +14,7 @@ from dataclasses import replace from ..capability import Capability from ..entities import ( BinarySensorDesc, + ButtonDesc, ClimateDesc, NumberDesc, SelectDesc, @@ -480,6 +481,45 @@ CLIMATE = Capability( icon="mdi:fan-auto", entity_category="config", ), + # A drying cycle the unit runs after cooling, to keep the coil from going + # mouldy. Three tokens describe it and the switch above only covered the + # first: Autoclean_ is the setting, AutocleanProgress_ is how far a + # running cycle has got, and StopAutoClean_ is a channel for ending one + # early -- its presence is what says the appliance takes that at all + # (the app gates its own stop button on exactly that), and the value it + # reports while nothing is running is Idle. + # + # The percentage scale is the app's own: `` with the + # token rendered as "{{value}}%" beside it. An idle unit here reports 1 + # rather than 0, the same floor the laundry firmware's progressPercentage + # sits at when Ready, so 0-vs-1 is not a reliable "is it running" test -- + # which is why the button below is not gated on it. + # + # The sensor shares AUTO_CLEAN's catalog entry, like auto_clean_legacy + # above: same figure, different board generation. Distinct key, so + # nothing collides if a board ever reported both. + SensorDesc( + key="auto_clean_progress_legacy", + translation_key="auto_clean_progress", + rep_fn=_option_token_num("AutocleanProgress"), + exists_fn=_has_option_token("AutocleanProgress"), + unit="%", + state_class="measurement", + icon="mdi:progress-check", + entity_category="diagnostic", + ), + ButtonDesc( + key="auto_clean_stop", + field="", + payload="StopAutoClean_Set", + icon="mdi:fan-off", + entity_category="config", + exists_fn=_has_option_token("StopAutoClean"), + write_fn=lambda p, rep, href=None: ( + ["mode", "vs", "0"], + {"x.com.samsung.da.options": [p]}, + ), + ), SwitchDesc( key="air_monitoring", rep_fn=_option_token_on("AirMonitoring"), diff --git a/custom_components/localthings/translations/cs.json b/custom_components/localthings/translations/cs.json index dc3fcbd..aeece88 100644 --- a/custom_components/localthings/translations/cs.json +++ b/custom_components/localthings/translations/cs.json @@ -117,6 +117,9 @@ "diagnosis_start": { "name": "Spustit diagnostiku" }, + "auto_clean_stop": { + "name": "Zastavit samočištění" + }, "pause": { "name": "Pozastavit" }, diff --git a/custom_components/localthings/translations/en.json b/custom_components/localthings/translations/en.json index 591019d..545e8c0 100644 --- a/custom_components/localthings/translations/en.json +++ b/custom_components/localthings/translations/en.json @@ -117,6 +117,9 @@ "diagnosis_start": { "name": "Start diagnosis" }, + "auto_clean_stop": { + "name": "Stop auto clean" + }, "pause": { "name": "Pause" }, diff --git a/custom_components/localthings/translations/es.json b/custom_components/localthings/translations/es.json index b7728e3..729b853 100644 --- a/custom_components/localthings/translations/es.json +++ b/custom_components/localthings/translations/es.json @@ -239,6 +239,9 @@ "diagnosis_start": { "name": "Iniciar diagnóstico" }, + "auto_clean_stop": { + "name": "Detener la autolimpieza" + }, "pause": { "name": "Pausar" }, diff --git a/custom_components/localthings/translations/it.json b/custom_components/localthings/translations/it.json index e904333..f9e66a6 100644 --- a/custom_components/localthings/translations/it.json +++ b/custom_components/localthings/translations/it.json @@ -117,6 +117,9 @@ "diagnosis_start": { "name": "Avvia diagnosi" }, + "auto_clean_stop": { + "name": "Arresta autopulizia" + }, "pause": { "name": "Pausa" }, diff --git a/custom_components/localthings/translations/ko.json b/custom_components/localthings/translations/ko.json new file mode 100644 index 0000000..b3c7ab4 --- /dev/null +++ b/custom_components/localthings/translations/ko.json @@ -0,0 +1,1332 @@ +{ + "entity": { + "binary_sensor": { + "auto_clean_running": { + "name": "자동 청소 작동 중" + }, + "after_run_active": { + "name": "후속 운전 작동 중" + }, + "any_burner_active": { + "name": "화구 작동 중" + }, + "automatic_operation": { + "name": "자동 운전" + }, + "battery_charging": { + "name": "충전 중" + }, + "burner_hot_surface": { + "name": "{number}번 화구 표면 고온" + }, + "burner_pan_detected": { + "name": "{number}번 화구 용기 감지" + }, + "child_lock": { + "name": "어린이 보호 잠금" + }, + "cloud_connected": { + "name": "클라우드 연결됨" + }, + "dustbag_full": { + "name": "먼지 봉투 가득 참" + }, + "cooktop_power": { + "name": "쿡탑 전원" + }, + "cooktop_safety_shutoff_enabled": { + "name": "고온 표면 자동 차단 활성화" + }, + "current_limit_enabled": { + "name": "전류 제한 활성화" + }, + "overload_protection_active": { + "name": "과부하 보호 작동 중" + }, + "odor_controller_active": { + "name": "탈취 기능 작동 중" + }, + "cycle_active": { + "name": "작동 중" + }, + "defrost_active": { + "name": "제상 작동 중" + }, + "detergent_low": { + "name": "세제 부족" + }, + "device_active": { + "name": "기기 작동 중" + }, + "door_open": { + "name": "문" + }, + "filter_door_status": { + "name": "필터 도어" + }, + "firmware_update": { + "name": "펌웨어 업데이트 가능" + }, + "instance_open": { + "name": "{instance_name} 열림" + }, + "paired_hood_connected": { + "name": "연동 후드 연결됨" + }, + "paired_hood_light": { + "name": "연동 후드 조명" + }, + "paired_hood_power": { + "name": "연동 후드 전원" + }, + "periodic_air_sensing": { + "name": "주기적 공기 감지" + }, + "pouring": { + "name": "출수 중" + }, + "alarm_in_mute": { + "name": "알림 음소거 중" + }, + "power_state": { + "name": "전원 상태" + }, + "probe_connected": { + "name": "탐침 온도계 연결됨" + }, + "power_switch": { + "name": "전원" + }, + "rapid_freezing": { + "name": "급속 냉동" + }, + "rapid_fridge": { + "name": "급속 냉장" + }, + "remote_control": { + "name": "스마트 컨트롤" + }, + "softener_low": { + "name": "섬유유연제 부족" + } + }, + "button": { + "after_run_cancel": { + "name": "후속 운전 취소" + }, + "diagnosis_start": { + "name": "진단 시작" + }, + "pause": { + "name": "일시정지" + }, + "selfcheck_start": { + "name": "자가 점검 시작" + }, + "start": { + "name": "시작" + }, + "stop": { + "name": "정지" + } + }, + "climate": { + "airconditioner": { + "state_attributes": { + "fan_mode": { + "state": { + "turbo": "터보", + "max": "최대" + } + }, + "preset_mode": { + "state": { + "ai_comfort": "AI 쾌적", + "quiet": "저소음", + "smart": "스마트", + "speed": "스피드", + "nano": "무풍", + "nanosleep": "무풍 수면", + "longwind": "롱바람", + "motionindirect": "간접풍", + "motiondirect": "직접풍", + "drycomfort": "쾌적 제습", + "2step": "2단계" + } + } + } + } + }, + "fan": { + "air_purifier_fan": { + "state_attributes": { + "preset_mode": { + "state": { + "smart": "스마트", + "max": "최대", + "mid": "중간", + "windfree": "무풍", + "sleep": "수면" + } + } + } + } + }, + "number": { + "cook_time": { + "name": "조리 시간" + }, + "delay_start_hours": { + "name": "예약 시작" + }, + "dispense_capacity": { + "name": "출수량" + }, + "good_sleep": { + "name": "쾌면 시간" + }, + "instance_setpoint": { + "name": "{instance_name} 설정값" + }, + "oven_setpoint": { + "name": "설정 온도" + }, + "setpoint": { + "name": "설정값" + }, + "sound_volume": { + "name": "음량" + }, + "target_humidity": { + "name": "목표 습도" + }, + "tropical_night_mode": { + "name": "열대야 모드" + }, + "zone_target_temperature": { + "name": "구역 목표 온도" + } + }, + "select": { + "ai_energy_level": { + "name": "AI 절약 모드 단계" + }, + "air_filter_threshold": { + "name": "필터 알림 기준" + }, + "beverage_zone_mode": { + "name": "음료 보관 모드", + "state": { + "sp_ttype_beer_drinks": "음료", + "sp_ttype_wine_dessert": "와인 및 디저트" + } + }, + "brightness_level": { + "name": "야간 밝기", + "state": { + "33": "낮음", + "66": "중간", + "100": "높음" + } + }, + "cooler_temperature_setpoint": { + "name": "냉각실 온도" + }, + "day_brightness": { + "name": "수납장 밝기", + "state": { + "33": "낮음", + "66": "중간", + "100": "높음" + } + }, + "buzzer_sound": { + "name": "부저음", + "state": { + "off": "끄기", + "on": "켜기" + } + }, + "discharging_time": { + "name": "먼지 비움 시간", + "state": { + "1": "1분", + "3": "3분" + } + }, + "cycle": { + "name": "코스" + }, + "detergent_quantity": { + "name": "세제 투입량", + "state": { + "00": "없음", + "01": "적게", + "02": "보통", + "03": "많이" + } + }, + "detergent_water_hardness": { + "name": "물 경도", + "state": { + "01": "연수", + "02": "보통", + "03": "경수" + } + }, + "dishwasher_cycle": { + "name": "코스", + "state": { + "80": "섬세", + "83": "표준", + "84": "강력", + "86": "급속 60분", + "90": "내부 세척", + "0e": "AI 맞춤 세척", + "07": "애벌 세척", + "8d": "냄비 및 팬", + "8e": "플라스틱", + "8f": "젖병 살균" + } + }, + "dispense_type": { + "name": "출수 종류" + }, + "door_alert": { + "name": "문 열림 알림", + "state": { + "1": "알림음 1", + "2": "알림음 2", + "3": "알림음 3", + "4": "알림음 4" + } + }, + "dryer_cycle_table_03": { + "name": "코스", + "state": { + "01": "표준건조", + "06": "시간건조", + "16": "면의류", + "17": "쾌속건조", + "18": "합성섬유", + "19": "섬세의류", + "20": "다림질건조", + "21": "살균건조", + "22": "조용히 건조", + "23": "쾌속건조 35분", + "24": "송풍건조", + "25": "온풍건조", + "27": "시간건조", + "29": "AI 맞춤건조", + "1a": "울", + "1b": "이불", + "1c": "셔츠", + "1d": "타월", + "1e": "아웃도어", + "1f": "혼합", + "2b": "통 건조", + "4c": "에어 리프레시", + "51": "에코 면", + "53": "AI 맞춤건조+", + "4e": "자체 건조" + } + }, + "favorite_capacity": { + "name": "즐겨찾기 출수량" + }, + "favorite_hotwater_temperature": { + "name": "즐겨찾는 온수 온도" + }, + "filter_alarm_time": { + "name": "필터 알림 간격", + "state": { + "180": "180시간", + "300": "300시간", + "500": "500시간", + "700": "700시간" + } + }, + "finish_sound": { + "name": "종료음", + "state": { + "off": "끄기", + "on": "켜기" + } + }, + "flex_zone_mode": { + "name": "맞춤 보관실 모드", + "state": { + "cv_ttype_rf9000a_freeze": "냉동", + "cv_ttype_rf9000a_softfreeze": "소프트 냉동", + "cv_ttype_rf9000a_meat_fish": "육류/생선", + "cv_ttype_rf9000a_fruit_veggies": "과일 및 채소", + "cv_ttype_rf9000a_beverage": "음료", + "cv_fdr_wine": "와인", + "cv_fdr_deli": "델리", + "cv_fdr_beverage": "음료", + "cv_fdr_meat": "육류", + "cv_fdr_soft_freezer": "소프트 냉동" + } + }, + "heated_dry": { + "name": "스마트 건조", + "state": { + "off": "끄기", + "low": "낮음", + "high": "높음", + "extra_high": "매우 높음" + } + }, + "hot_water_temperature": { + "name": "온수 온도" + }, + "ice_type": { + "name": "{instance_name} 종류", + "state": { + "off": "끄기", + "whiskey_iceball_3": "하루 3개", + "whiskey_iceball_6": "하루 6개", + "whiskey_iceball_9": "하루 9개" + } + }, + "led_brightness": { + "name": "도어 LED 밝기", + "state": { + "low": "낮음", + "high": "높음" + } + }, + "led_night_brightness": { + "name": "도어 LED 야간 밝기", + "state": { + "low": "낮음", + "high": "높음" + } + }, + "cooking_mode": { + "name": "조리 모드", + "state": { + "no_operation": "작동 안 함", + "micro_wave": "전자레인지", + "micro_wave_grill": "전자레인지 + 그릴", + "micro_wave_convection": "전자레인지 + 컨벡션", + "convection": "컨벡션", + "air_fryer": "에어프라이", + "grill": "그릴", + "autocook": "자동 조리", + "autocook_custom": "자동 조리(사용자 설정)", + "deodorization": "탈취", + "keep_warm": "보온" + } + }, + "oven_mode": { + "name": "조리 모드", + "state": { + "no_operation": "작동 안 함", + "bake": "베이크", + "broil": "브로일", + "convection": "컨벡션", + "convection_bake": "컨벡션 베이크", + "convection_broil": "컨벡션 브로일", + "frozen_pizza_plus": "냉동 피자+", + "slow_cook": "저온 조리", + "plate_warm": "접시 데우기", + "air_fry": "에어프라이" + } + }, + "operating_mode": { + "name": "운전 모드" + }, + "kimchi_zone_mode": { + "name": "{instance_name} 보관 모드", + "state": { + "off": "끄기", + "kimchi_storage_normal": "김치", + "kimchi_storage_cold": "김치 강", + "kimchi_storage_warm": "김치 약", + "kimchi_storage_low_salt_normal": "저염 김치", + "kimchi_storage_low_salt_cold": "저염 김치 강", + "kimchi_storage_low_salt_warm": "저염 김치 약", + "kimchi_storage_crunfch": "아삭 김치", + "kimchi_storage_buy": "구입 김치", + "storage_fridge_normal": "냉장", + "storage_fridge_cold": "냉장 강", + "storage_fridge_warm": "냉장 약", + "storage_freezer_normal": "냉동", + "storage_freezer_cold": "냉동 강", + "storage_freezer_warm": "냉동 약", + "kimchi_ripe_low_temp": "김치 저온 숙성", + "kimchi_ripe_normal_temp": "김치 상온 숙성", + "kimchi_ripe_kkakdugi": "깍두기 숙성", + "kimchi_ripe_dongchimi": "동치미 숙성", + "meat_ripe_normal": "육류 숙성", + "storage_meat": "육류 및 생선", + "storage_fridge_vegetables_fruit": "과일 및 채소", + "storage_fresh_cereal": "곡류", + "storage_fridge_drink": "음료", + "storage_fresh_wine": "와인", + "storage_fresh_potato_banana": "감자 및 바나나" + } + }, + "pantry_zone_mode": { + "name": "팬트리실 모드", + "state": { + "fdr_wine": "와인", + "fdr_deli": "델리", + "fdr_drinks": "음료" + } + }, + "range_burner_power_level": { + "name": "{number}번 화구 화력", + "state": { + "0": "끄기", + "boost": "부스트", + "simmer": "약불" + } + }, + "range_hood_lamp_brightness": { + "name": "램프 밝기", + "state": { + "1": "1단계", + "2": "2단계" + } + }, + "rinse_cycles": { + "name": "헹굼 횟수" + }, + "softener_concentration": { + "name": "섬유유연제 농축도", + "state": { + "01": "1배", + "02": "2배", + "03": "3배" + } + }, + "softener_quantity": { + "name": "섬유유연제 투입량", + "state": { + "00": "없음", + "01": "적게", + "02": "보통", + "03": "많이" + } + }, + "sound_mode": { + "name": "소리 모드", + "state": { + "voice": "음성", + "tone": "알림음", + "mute": "음소거" + } + }, + "air_purifier_sound_mode": { + "name": "소리 모드", + "state": { + "mute": "음소거", + "buzzer": "부저" + } + }, + "water_purifier_sound_mode": { + "name": "소리 모드", + "state": { + "voice": "음성", + "fixedtone": "고정 알림음", + "mute": "음소거" + } + }, + "spin_speed": { + "name": "탈수 세기", + "state": { + "rinse_hold": "헹굼 후 대기", + "no_spin": "탈수 안 함", + "low": "약", + "medium": "중", + "high": "강" + } + }, + "wash_temperature": { + "name": "세탁 온도", + "state": { + "none": "설정 안 함", + "cold": "냉수", + "cool": "찬물", + "warm": "미온수", + "hot": "온수", + "extra_hot": "고온수" + } + }, + "washer_cycle_table_02": { + "name": "코스", + "state": { + "01": "표준세탁", + "04": "쾌속세탁", + "17": "다운로드 코스", + "1b": "면", + "1c": "에코 40-60", + "1d": "쾌속세탁", + "1e": "15분 쾌속세탁", + "1f": "강력 냉수 세탁", + "20": "살균세탁", + "21": "컬러 의류", + "22": "울", + "23": "아웃도어", + "24": "타월", + "25": "합성섬유", + "26": "섬세의류", + "27": "헹굼+탈수", + "28": "배수/탈수", + "29": "무세제통세척+", + "2a": "청바지", + "2b": "AI 맞춤세탁", + "2d": "조용히 세탁", + "2e": "아기옷", + "2f": "피트니스", + "30": "흐린 날", + "32": "셔츠", + "33": "이불", + "34": "혼합", + "36": "세탁+건조", + "37": "에어워시", + "38": "면 건조", + "39": "합성섬유 건조", + "3a": "무세제통세척", + "52": "에코 냉수 세탁", + "53": "강력세탁", + "54": "타월", + "55": "피트니스", + "57": "섬세의류", + "5e": "헹굼+탈수", + "60": "통세척+", + "65": "컬러 의류", + "66": "데님", + "7c": "흰옷", + "7d": "이불/방수 의류", + "7e": "통세척", + "7f": "울/섬세", + "86": "찌든 때 세탁", + "87": "다운로드", + "8f": "강력 냉수 세탁", + "96": "미세플라스틱저감" + } + }, + "washer_dry_level": { + "name": "건조 단계", + "state": { + "30": "30분", + "60": "1시간", + "90": "1시간 30분", + "120": "2시간", + "180": "3시간", + "240": "4시간", + "none": "끄기", + "cupboard": "옷장 보관" + } + }, + "zone_mode": { + "name": "구역 모드" + }, + "watertank_light_color": { + "name": "물탱크 조명 색상", + "state": { + "warmwhite": "전구색", + "naturalwhite": "주백색", + "coolwhite": "주광색", + "green": "초록색", + "purple": "보라색", + "blue": "파란색", + "orange": "주황색", + "pink": "분홍색" + } + }, + "watertank_light_brightness": { + "name": "물탱크 조명 밝기" + }, + "air_filter_pm1_threshold": { + "name": "PM1 필터 알림 기준" + }, + "freezer_temperature_setpoint": { + "name": "냉동실 온도" + } + }, + "sensor": { + "auto_clean_progress": { + "name": "자동 청소 진행률" + }, + "after_run_progress": { + "name": "후속 운전 진행률" + }, + "air_filter_usage": { + "name": "필터 사용량" + }, + "air_filter_usage_hours": { + "name": "필터 사용 시간" + }, + "air_quality_standard": { + "name": "공기질 기준" + }, + "air_sensing_state": { + "name": "공기질 감지 상태" + }, + "alarm_code": { + "name": "알람 코드" + }, + "auto_ventilation_action": { + "name": "자동 환기 동작" + }, + "automatic_ventilation_state": { + "name": "자동 환기 상태" + }, + "battery": { + "name": "배터리" + }, + "burner_state": { + "name": "{number}번 화구 상태" + }, + "clean_level": { + "name": "청정도" + }, + "co2": { + "name": "이산화탄소" + }, + "coffee_brew_status": { + "name": "커피 추출 상태" + }, + "connection_mode": { + "name": "연결 모드", + "state": { + "observe": "푸시(OBSERVE)", + "poll": "폴링" + } + }, + "cooktop_running_state": { + "name": "쿡탑 작동 상태" + }, + "cooktop_state": { + "name": "쿡탑 상태" + }, + "current_limit_level": { + "name": "전류 제한 단계" + }, + "filter_time": { + "name": "필터 사용 시간" + }, + "hepa_filter_usage": { + "name": "HEPA 필터 사용량" + }, + "outdoor_temperature": { + "name": "실외 온도" + }, + "odor_controller_progress": { + "name": "탈취 진행률" + }, + "panel_status": { + "name": "패널 상태" + }, + "sound_output": { + "name": "소리 출력" + }, + "dustbag_usage": { + "name": "먼지봉투 사용량" + }, + "cleanstation_status": { + "name": "청정스테이션 상태" + }, + "stick_status": { + "name": "스틱 청소기 상태" + }, + "uvc_operation_time": { + "name": "UV-C 작동 시간" + }, + "uvc_total_operation_time": { + "name": "UV-C 누적 작동 시간" + }, + "uvc_finished_time": { + "name": "UV-C 완료 시각" + }, + "uvc_emitted_time": { + "name": "UV-C 조사 시간" + }, + "overload_protection_mode": { + "name": "과부하 보호 모드", + "state": { + "alarm": "경보", + "powersaving": "절전" + } + }, + "absence_power_saving_mode": { + "name": "부재 절전 모드", + "state": { + "eco": "에코", + "normal": "일반", + "comfort": "쾌적" + } + }, + "motion_detect_wind_mode": { + "name": "모션 감지 바람 모드", + "state": { + "direct": "직접풍", + "indirect": "간접풍" + } + }, + "current_temp_c": { + "name": "온도" + }, + "current_temperature_c": { + "name": "온도" + }, + "diagnosis": { + "name": "진단" + }, + "diagnosis_status": { + "name": "진단 상태" + }, + "drum_clean_cycles_remaining": { + "name": "통세척까지 남은 횟수" + }, + "drum_clean_last_cleaned": { + "name": "마지막 통세척" + }, + "dry_level": { + "name": "건조 단계" + }, + "dry_time": { + "name": "건조 시간" + }, + "dryer_type": { + "name": "건조기 유형" + }, + "dust": { + "name": "미세먼지" + }, + "energy_kwh": { + "name": "에너지" + }, + "energy_last_month_kwh": { + "name": "지난달 에너지" + }, + "energy_saved_kwh": { + "name": "절감 에너지" + }, + "energy_this_month_kwh": { + "name": "이번 달 에너지" + }, + "fan_direction": { + "name": "바람 방향" + }, + "fan_speed_level": { + "name": "바람 세기 단계" + }, + "filter_clean_remain_time": { + "name": "필터 청소까지 남은 시간" + }, + "filter_progress": { + "name": "필터 사용률" + }, + "filter_usage": { + "name": "필터 사용량" + }, + "fine_dust": { + "name": "초미세먼지" + }, + "finish_time": { + "name": "예상 완료 시각" + }, + "completion_minutes": { + "name": "완료까지 남은 시간" + }, + "freezer_temperature": { + "name": "냉동실 온도" + }, + "fridge_temperature": { + "name": "냉장실 온도" + }, + "kimchi_ripening_status": { + "name": "{instance_name} 숙성 상태" + }, + "kimchi_ripening_remaining": { + "name": "{instance_name} 숙성 남은 시간" + }, + "kimchi_rack_count": { + "name": "{instance_name} 선반 수" + }, + "hood_filter_capacity": { + "name": "후드 필터 용량" + }, + "humidity": { + "name": "습도" + }, + "hood_filter_usage": { + "name": "후드 필터 사용량" + }, + "instance_temperature": { + "name": "{instance_name} 온도" + }, + "job_beginning_status": { + "name": "작업 시작 상태" + }, + "last_air_sensing_level": { + "name": "마지막 공기질 감지 단계" + }, + "last_air_sensing_time": { + "name": "마지막 공기질 감지 시각" + }, + "main_timer_current": { + "name": "타이머 현재 값" + }, + "main_timer_state": { + "name": "타이머 상태" + }, + "odor": { + "name": "냄새" + }, + "operating_mode": { + "name": "운전 모드" + }, + "operation_origin": { + "name": "마지막 작동 출처" + }, + "operation_time_minutes": { + "name": "운전 시간" + }, + "oven_state": { + "name": "조리실 상태" + }, + "cavity_state": { + "name": "조리실 상태" + }, + "power_level": { + "name": "출력 단계" + }, + "paired_hood_fan_speed": { + "name": "연동 후드 풍량" + }, + "paired_hood_firmware": { + "name": "연동 후드 펌웨어" + }, + "paired_hood_model": { + "name": "연동 후드 모델" + }, + "power_energy_kwh": { + "name": "소비 에너지" + }, + "power_watts": { + "name": "소비 전력" + }, + "probe_battery": { + "name": "탐침 온도계 배터리" + }, + "probe_target_temperature": { + "name": "탐침 온도계 목표 온도" + }, + "probe_temperature": { + "name": "탐침 온도계 현재 온도" + }, + "progress": { + "name": "진행률" + }, + "progress_percentage": { + "name": "진행률" + }, + "selfcheck_error": { + "name": "자가 점검 오류" + }, + "selfcheck_result": { + "name": "자가 점검 결과" + }, + "selfcheck_status": { + "name": "자가 점검 상태" + }, + "sterilize_last_time": { + "name": "마지막 살균 시각" + }, + "sterilize_period": { + "name": "살균 주기" + }, + "sterilize_plan_time": { + "name": "살균 예약 시각" + }, + "sterilize_run_time": { + "name": "살균 작동 시간" + }, + "super_fine_dust": { + "name": "극초미세먼지" + }, + "warming_center_state": { + "name": "보온 화구 상태" + }, + "water_liters": { + "name": "물 사용량" + }, + "waterpurifier_status": { + "name": "상태" + }, + "cup_state": { + "name": "컵 상태" + }, + "last_pour_type": { + "name": "마지막 출수 유형" + }, + "last_pour_capacity": { + "name": "마지막 출수량" + }, + "machine_state": { + "name": "기기 상태", + "state": { + "idle": "대기", + "active": "작동 중", + "pause": "일시 정지" + } + }, + "filter_status": { + "name": "필터 상태", + "state": { + "normal": "정상", + "wash": "세척 필요", + "replace": "교체 필요" + } + }, + "ice_making_status": { + "name": "{instance_name} 제빙 상태", + "state": { + "icestatus_stop": "대기", + "icestatus_run": "제빙 중" + } + }, + "zone_temperature": { + "name": "구역 온도" + }, + "watertank_full_alarm_status": { + "name": "물통 가득 참 알림 상태" + }, + "air_filter_pm1_usage": { + "name": "PM1 필터 사용량" + }, + "air_filter_pm1_usage_hours": { + "name": "PM1 필터 사용 시간" + } + }, + "switch": { + "ai_energy_level": { + "name": "AI 절약 모드" + }, + "air_monitoring": { + "name": "공기질 모니터링" + }, + "air_purify": { + "name": "공기 청정" + }, + "auto_clean": { + "name": "자동 청소" + }, + "absence_power_saving_active": { + "name": "부재 절전 작동" + }, + "motion_detect_wind_active": { + "name": "모션 감지 바람 회피 작동" + }, + "beep": { + "name": "비프음" + }, + "display": { + "name": "디스플레이" + }, + "pet_filter_activation": { + "name": "펫 필터 작동" + }, + "auto_empty": { + "name": "자동 먼지 비움" + }, + "dustbin_auto_close": { + "name": "먼지통 자동 닫힘" + }, + "spi": { + "name": "청정 이온" + }, + "uvc_intensive_mode": { + "name": "UV-C 집중 모드" + }, + "auto_door_opener": { + "name": "오토 오픈 도어" + }, + "auto_release_dry": { + "name": "자동 문 열림 건조" + }, + "autofill": { + "name": "오토필 정수기" + }, + "bubble_soak": { + "name": "버블 불림" + }, + "buzz_lock": { + "name": "알림음 잠금" + }, + "cabinet_light_dim": { + "name": "서서히 밝아짐" + }, + "cabinet_light_switch": { + "name": "내부 조명" + }, + "child_lock": { + "name": "어린이 보호 잠금" + }, + "coldwater_lock": { + "name": "냉수 잠금" + }, + "cooktop_child_lock": { + "name": "어린이 보호 잠금" + }, + "defrost_delay": { + "name": "제상 지연" + }, + "display_light": { + "name": "디스플레이 조명" + }, + "dnd": { + "name": "방해 금지 모드" + }, + "fast_preheat": { + "name": "빠른 예열" + }, + "favorite_capacity_enabled": { + "name": "즐겨찾기 출수량 사용" + }, + "favorite_coffee_enabled": { + "name": "즐겨찾기 커피" + }, + "filter_remind": { + "name": "필터 알림" + }, + "fridge_sound": { + "name": "소리" + }, + "hotwater_lock": { + "name": "온수 잠금" + }, + "ice_maker_enabled": { + "name": "제빙기" + }, + "ice_night_mode": { + "name": "야간 제빙 저소음 모드" + }, + "instance_enabled": { + "name": "{instance_name} 사용" + }, + "intensive": { + "name": "강력" + }, + "lamp": { + "name": "램프" + }, + "led_night_light": { + "name": "도어 LED 야간 조명" + }, + "mute_once": { + "name": "한 번 음소거" + }, + "natural_steam": { + "name": "내추럴 스팀" + }, + "energy_saving": { + "name": "절전" + }, + "cooktop_on_alert": { + "name": "쿡탑 켜짐 알림" + }, + "power_switch": { + "name": "전원" + }, + "pre_wash": { + "name": "예비 세탁" + }, + "rapid_freezing": { + "name": "급속 냉동" + }, + "rapid_fridge": { + "name": "급속 냉장" + }, + "remind_beep": { + "name": "종료 알림음" + }, + "sabbath_mode": { + "name": "사바스 모드" + }, + "sanitize": { + "name": "살균" + }, + "sound": { + "name": "소리" + }, + "storm_wash": { + "name": "스톰 워시+" + }, + "welcome_lighting": { + "name": "웰컴 라이팅" + }, + "wrinkle_prevent": { + "name": "구김 방지" + }, + "zone_power": { + "name": "구역 전원" + }, + "away_mode": { + "name": "외출 모드" + }, + "watertank_light": { + "name": "물통 조명" + }, + "uv_led": { + "name": "자외선 LED" + }, + "ventilation_alarm": { + "name": "환기 알림" + } + }, + "time": { + "dnd_end": { + "name": "방해 금지 종료" + }, + "dnd_start": { + "name": "방해 금지 시작" + }, + "led_night_end": { + "name": "도어 LED 야간 종료" + }, + "led_night_start": { + "name": "도어 LED 야간 시작" + }, + "night_end": { + "name": "야간 조명 종료" + }, + "night_start": { + "name": "야간 조명 시작" + } + }, + "water_heater": { + "dhw": { + "name": "온수" + } + } + }, + "config": { + "step": { + "user": { + "title": "삼성 가전제품 추가", + "description": "삼성 가전제품의 IP 주소와 기기 인증서 발급에 사용할 AC14K_M CA 인증 정보를 입력하세요.", + "data": { + "host": "IP 주소", + "ca_cert_pem": "CA 인증서(PEM)", + "ca_key_pem": "CA 개인 키(PEM)" + }, + "data_description": { + "host": "삼성 가전제품의 로컬 IP 주소입니다(예: 192.168.1.50).", + "ca_cert_pem": "PEM으로 인코딩된 AC14K_M CA 인증서 체인입니다. 모든 BEGIN/END CERTIFICATE 블록을 포함한 전체 인증서 체인 PEM 내용을 붙여 넣으세요.", + "ca_key_pem": "PEM으로 인코딩된 AC14K_M 개인 키입니다. BEGIN/END PRIVATE KEY 머리글과 바닥글을 포함한 전체 내용을 붙여 넣으세요." + } + }, + "user_reuse": { + "title": "삼성 가전제품 추가", + "description": "삼성 가전제품의 IP 주소를 입력하세요. 기존 LocalThings 가전제품의 CA 인증 정보를 다시 사용합니다.", + "data": { + "host": "IP 주소" + }, + "data_description": { + "host": "삼성 가전제품의 로컬 IP 주소입니다(예: 192.168.1.50)." + } + }, + "confirm_unknown_type": { + "title": "가전제품 유형을 인식할 수 없음", + "description": "이 가전제품이 보고한 모델은 \"{model}\"이며, 아직 LocalThings에서 인식하는 유형이 아닙니다. 그래도 추가할 수 있지만, 해당 제품군의 전체 기능 대신 공통 기능(전원, 알림 등 기기에서 제공하는 기능)만 사용할 수 있습니다. 나중에 이 기기의 진단 정보를 다운로드(설정 > 기기 및 서비스 > 이 기기 > 메뉴 > 진단 정보 다운로드)하여 새 이슈에 첨부하면 전체 기능 지원을 추가하는 데 도움을 줄 수 있습니다. 그래도 추가하려면 제출을 선택하세요." + } + }, + "error": { + "no_response": "해당 IP 주소에서 응답이 없습니다. 가전제품의 로컬 API 포트 범위(UDP 49152-49160)에 있는 어떤 포트에서도 응답하지 않았습니다. IP 주소가 올바른지, 가전제품의 전원이 켜져 있고 Home Assistant와 같은 네트워크에 연결되어 있는지, 방화벽이 가전제품으로 향하는 UDP 트래픽을 차단하고 있지 않은지 확인하세요.", + "ports_closed": "해당 IP 주소에는 연결할 수 있지만, 로컬 API 포트 범위(UDP 49152-49160)의 모든 포트가 연결을 거부했습니다. 삼성 가전제품이 아니거나, 이 통합 구성요소에서 사용할 수 없는 TCP 8888을 통해 삼성 클라우드와만 통신하는 구형 펌웨어를 사용하고 있을 수 있습니다.", + "no_dtls_server": "해당 주소의 로컬 API 포트 범위에는 연결할 수 있지만, DTLS 핸드셰이크에 응답하는 서버가 없습니다. IP 주소가 네트워크의 다른 기기가 아닌 해당 가전제품의 주소인지 확인하세요.", + "handshake_timeout": "가전제품이 로컬 API 포트에서 응답했지만 DTLS 핸드셰이크를 완료하지 않았습니다. 이전 연결 시도의 세션이 아직 유지되고 있을 가능성이 큽니다. 약 1분 후 다시 시도하세요.", + "cert_rejected": "가전제품이 인증서를 거부했습니다. CA 인증서와 키가 이 가전제품에서 신뢰하는 AC14K_M CA의 것이 아니거나 서로 일치하지 않을 가능성이 큽니다. 가전제품이 보낸 정확한 경고는 Home Assistant 로그에 기록됩니다.", + "handshake_failed": "인증서와 관련 없는 이유로 가전제품이 DTLS 핸드셰이크를 거부했습니다. 프로토콜이나 암호화 방식이 일치하지 않을 가능성이 큽니다. 가전제품이 보낸 정확한 경고는 Home Assistant 로그에 기록됩니다.", + "cloud_unreachable": "이 기기의 인증서 발급에 필요한 UUID를 가져오기 위해 삼성 클라우드 게이트웨이에 연결할 수 없습니다. Home Assistant의 인터넷 연결을 확인한 후 다시 시도하세요.", + "unexpected_response": "기기에 연결했지만 사용할 수 있는 기기 설명을 반환하지 않았습니다. 이 통합 구성요소에서 지원하는 가전제품이 아닐 수 있습니다. 기기가 보낸 내용은 Home Assistant 로그에 기록됩니다.", + "cannot_connect": "기기에 연결할 수 없습니다. IP 주소에 연결할 수 있는지와 CA 인증 정보가 올바른지 확인하세요.", + "invalid_ca": "CA 인증서 또는 개인 키를 불러올 수 없습니다. PEM 내용이 올바르고 키가 인증서와 일치하는지 확인하세요.", + "unknown": "예기치 않은 오류가 발생했습니다. 자세한 내용은 Home Assistant 로그에서 확인하세요." + }, + "abort": { + "already_configured": "기기가 이미 구성되어 있습니다" + } + }, + "options": { + "step": { + "init": { + "title": "LocalThings 옵션", + "menu_options": { + "settings": "기기 설정", + "debug_write": "디버그: 리소스에 쓰기" + } + }, + "settings": { + "title": "기기 설정", + "description": "일부 기기는 스마트 컨트롤이 꺼져 있다고 보고하는 동안에도 특정 쓰기 요청(예: 세탁기의 기본 세제/섬유유연제 투입량)을 받아들입니다. 기본적으로 LocalThings는 기기가 스마트 컨트롤 꺼짐을 보고하면 기기가 쓰기 요청을 조용히 거부하도록 두지 않고, 명확한 오류와 함께 모든 쓰기를 차단합니다. 스마트 컨트롤이 꺼진 상태에서도 이 기기에 쓰기가 실제로 동작하는 것을 확인한 경우에만 이 옵션을 활성화하세요. 그렇지 않으면 명확한 오류 대신 아무 표시 없이 쓰기에 실패할 수 있습니다.\n\n예상 완료 시각은 기기가 보고하는 남은 시간 추정치를 사용하여 상태를 확인할 때마다 다시 계산합니다. 이 추정치는 업데이트 사이에 1~2분 정도 변하거나 수정될 수 있습니다. 아래의 최소 변경량을 늘리면 추정치가 설정한 시간(분) 이상 변할 때까지 센서가 마지막으로 보고된 값을 유지하므로 기록과 로그북에 불필요한 항목이 쌓이는 것을 줄일 수 있습니다. 계산된 모든 변경 사항을 보고하려면 0으로 설정하세요.", + "data": { + "bypass_remote_control_lock": "스마트 컨트롤이 꺼진 것으로 보고되어도 쓰기 허용", + "finish_time_hysteresis_minutes": "예상 완료 시각 - 최소 변경량(분)" + } + }, + "debug_write": { + "title": "디버그: 리소스에 쓰기", + "description": "기기별 쓰기 동작을 파악하기 위한 고급 사용자용 도구입니다. 쓰려는 리소스(href)를 선택하거나 목록에 없는 값을 직접 입력하세요. 이 기능은 스마트 컨트롤 꺼짐 차단을 우회하고 입력한 필드를 그대로 전송합니다. 가전제품이 잘못 설정될 수 있으므로 신중하게 사용하세요.", + "data": { + "href": "리소스 href" + } + }, + "debug_edit": { + "title": "디버그 쓰기: {href}", + "description": "`{href}`의 현재 값:\n```\n{current_value}\n```\n아래에는 변경하려는 필드만 입력하세요. 입력한 내용은 부분 업데이트로 기기에 그대로 전송되며, 위에 표시된 필드와 병합되지 않으므로 전체 값을 다시 붙여 넣지 마세요. 자료형에 주의하세요. \"1\"과 같은 숫자 문자열은 반드시 따옴표로 감싸야 합니다. 따옴표가 없는 1은 정수로 전송되며 일부 기기에서 거부할 수 있습니다.", + "data": { + "payload": "쓰기 페이로드" + } + }, + "debug_result": { + "title": "디버그 쓰기 결과", + "description": "기기가 반환한 CoAP 코드는 {code}입니다. 2.xx 계열은 쓰기 요청이 수락되었음을, 4.xx/5.xx 계열은 거부되었음을 뜻합니다. 현재 리소스 값은 다음과 같습니다.\n```\n{new_value}\n```\n값이 변경되지 않았다면 기기가 쓰기 요청을 무시했을 가능성이 큽니다. 다음 작업을 선택하세요.", + "menu_options": { + "debug_write": "다른 리소스에 쓰기", + "finish": "완료" + } + } + }, + "error": { + "empty_payload": "쓸 필드를 하나 이상 입력하세요.", + "write_failed": "쓰기에 실패했습니다. 자세한 내용은 Home Assistant 로그에서 확인하세요." + }, + "abort": { + "not_loaded": "이 기기는 아직 연결되지 않았습니다. 기기를 불러온 후 다시 시도하세요." + } + }, + "issues": { + "device_gap": { + "title": "{device_name}의 기능 지원이 완전하지 않음", + "description": "이 기기의 일부 기능이 아직 완전히 지원되지 않습니다. 가전제품 유형이 인식되지 않았거나, 기기가 제공하는 일부 리소스가 아직 구현되지 않았습니다. 현재 지원되는 기능은 계속 사용할 수 있습니다. 설정 > 기기 및 서비스 > {device_name} > 오른쪽 위 메뉴 > 진단 정보 다운로드로 이동하여 진단 정보를 내려받은 뒤, 연결된 이슈 양식에 첨부하면 지원 범위를 넓히는 데 도움을 줄 수 있습니다." + } + }, + "exceptions": { + "remote_control_disabled": { + "message": "이 기기의 스마트 컨트롤이 꺼져 있습니다. Home Assistant에서 기기를 제어하려면 가전제품 설명서에서 스마트 컨트롤을 활성화하는 방법을 확인하세요." + }, + "debug_payload_empty": { + "message": "디버그 쓰기 페이로드는 비어 있지 않은 객체여야 합니다." + }, + "resource_href_required": { + "message": "리소스 href가 필요합니다." + }, + "bubble_soak_unavailable_for_cycle": { + "message": "선택한 코스에서는 버블 불림을 사용할 수 없습니다." + }, + "pre_wash_unavailable_for_cycle": { + "message": "선택한 코스에서는 예비 세탁을 사용할 수 없습니다." + }, + "intensive_unavailable_for_cycle": { + "message": "선택한 코스에서는 강력 세탁을 사용할 수 없습니다." + } + } +} diff --git a/custom_components/localthings/translations/nl.json b/custom_components/localthings/translations/nl.json index 45e1a68..e6658e9 100644 --- a/custom_components/localthings/translations/nl.json +++ b/custom_components/localthings/translations/nl.json @@ -117,6 +117,9 @@ "diagnosis_start": { "name": "Diagnose starten" }, + "auto_clean_stop": { + "name": "Zelfreiniging stoppen" + }, "pause": { "name": "Pauzeren" }, diff --git a/tests/fixtures/golden/airconditioner_artik051_dongle_fac_18k.json b/tests/fixtures/golden/airconditioner_artik051_dongle_fac_18k.json index 379fcbb..22b6c37 100644 --- a/tests/fixtures/golden/airconditioner_artik051_dongle_fac_18k.json +++ b/tests/fixtures/golden/airconditioner_artik051_dongle_fac_18k.json @@ -2,6 +2,7 @@ "state_keys": [ "alarm_code", "auto_clean_legacy", + "auto_clean_progress_legacy", "beep", "clean_level", "climate", @@ -18,6 +19,7 @@ "super_fine_dust", "subdevice1_alarm_code", "subdevice1_auto_clean_legacy", + "subdevice1_auto_clean_progress_legacy", "subdevice1_beep", "subdevice1_climate", "subdevice1_current_temperature_c", diff --git a/tests/fixtures/golden/airconditioner_artik051_krac_18k.json b/tests/fixtures/golden/airconditioner_artik051_krac_18k.json index 4008747..9bb4c7c 100644 --- a/tests/fixtures/golden/airconditioner_artik051_krac_18k.json +++ b/tests/fixtures/golden/airconditioner_artik051_krac_18k.json @@ -3,6 +3,7 @@ "air_monitoring", "alarm_code", "auto_clean_legacy", + "auto_clean_progress_legacy", "beep", "climate", "current_temperature_c", diff --git a/tests/fixtures/golden/airconditioner_artik051_krac_18k_slot.json b/tests/fixtures/golden/airconditioner_artik051_krac_18k_slot.json index 3008f12..cf236cd 100644 --- a/tests/fixtures/golden/airconditioner_artik051_krac_18k_slot.json +++ b/tests/fixtures/golden/airconditioner_artik051_krac_18k_slot.json @@ -3,6 +3,7 @@ "air_monitoring", "alarm_code", "auto_clean_legacy", + "auto_clean_progress_legacy", "beep", "climate", "current_temperature_c", diff --git a/tests/fixtures/golden/airconditioner_artik051_krac_energy.json b/tests/fixtures/golden/airconditioner_artik051_krac_energy.json index 4008747..9bb4c7c 100644 --- a/tests/fixtures/golden/airconditioner_artik051_krac_energy.json +++ b/tests/fixtures/golden/airconditioner_artik051_krac_energy.json @@ -3,6 +3,7 @@ "air_monitoring", "alarm_code", "auto_clean_legacy", + "auto_clean_progress_legacy", "beep", "climate", "current_temperature_c", diff --git a/tests/test_airconditioner_artik051_krac.py b/tests/test_airconditioner_artik051_krac.py index 6081e78..1034c94 100644 --- a/tests/test_airconditioner_artik051_krac.py +++ b/tests/test_airconditioner_artik051_krac.py @@ -235,6 +235,32 @@ def test_filter_alarm_time_reads_the_threshold_and_writes_one_token(): ) +def test_auto_clean_progress_and_stop_come_off_their_own_tokens(): + """Three tokens describe the drying cycle and the switch only covered the + first. AutocleanProgress_ is a percentage -- the app renders it into a + `` beside a "{{value}}%" label -- and StopAutoClean_ is + the channel for ending a cycle early, whose presence is what says the + appliance accepts that at all (the fixture reports Idle, this unit's + resting value).""" + assert _state()["auto_clean_progress_legacy"] == 1.0 # the fixture's own value + + desc = _desc(_load_device(FIXTURE), "auto_clean_stop") + assert desc is not None + assert desc.write_fn(desc.payload, {}) == ( + ["mode", "vs", "0"], + {"x.com.samsung.da.options": ["StopAutoClean_Set"]}, + ) + + +def test_auto_clean_stop_stays_off_boards_without_the_token(): + """Newer boards run the same cycle off /option/autoclean/vs/0 and say + nothing about stopping it, so writing a legacy token there would be a + guess.""" + newer = _load_device("airconditioner_tp1x_rac") + assert _desc(newer, "auto_clean_stop") is None + assert "auto_clean_progress_legacy" not in _state("airconditioner_tp1x_rac") + + def test_filter_alarm_time_stays_off_boards_with_a_real_threshold_resource(): """Newer boards carry air_filter_threshold off supportedFilterDesiredUsage; two thresholds on one device would be a coin flip for the user.