laundry: add Table_00 cycle labels for WF45R6300 washer and DVE45R6300 dryer
Adds washer_cycle_table_00 and dryer_cycle_table_00 translation catalog entries, confirmed by the issue #357 reporter selecting each cycle on a WF45R6300AW/US washer and DVE45R6300W/A3 dryer and reading back the raw course code. Table_00 is a separate, older course-code family from the existing Table_02/Table_03 catalogs -- laundry.cycle_select's table_href scoping already keeps them apart, so this is a translations-only change. Table_00 was previously used only as an example of an unconfirmed table in tests; those now use Table_99 for that role, and new tests assert the confirmed codes translate and that the resolved key routes to the new table-scoped catalog entries. Mirrored to all shipped languages (cs/de/es/it/ko/nl) to keep tests/test_translations.py's key-for-key invariant.
This commit is contained in:
@@ -46,6 +46,13 @@ DRYER_SETTINGS = Capability(
|
||||
# (issue #244). /st/dryercourse/vs/0 re-encodes the same selected course
|
||||
# and is ignored (ignored.py), mirroring /st/washercourse/vs/0 for washers.
|
||||
#
|
||||
# dryer_cycle_table_00 is a separate, older course-code family reported by
|
||||
# a DVE45R6300W/A3 (issue #357), confirmed the same way: the reporter
|
||||
# selected each cycle on the appliance and read back the resulting raw
|
||||
# code. It shares no codes with Table_03 above -- 'a5' Bedding here and
|
||||
# '01' Normal are both table-scoped, so a Table_03 dryer never picks up a
|
||||
# Table_00 label or vice versa (see laundry.cycle_select's table_href).
|
||||
#
|
||||
# Drum Clean+ maintenance tracking (issue #258) reuses washer.py's
|
||||
# DrumCleanProposal_/WashingTimes_/DrumCleanLog_ tokens on this same
|
||||
# options[] array -- see laundry.drum_clean_cycles_remaining/
|
||||
|
||||
@@ -58,6 +58,15 @@ from .laundry import (
|
||||
# the owner or device metadata falls back to washer_cycle_fallback, which
|
||||
# surfaces a personal-course name only -- no invented English label for an
|
||||
# unrecognized standard code (PR #251 review).
|
||||
#
|
||||
# washer_cycle_table_00 (issue #357) is a separate, older course-code family
|
||||
# reported by a WF45R6300AW/US -- confirmed by the reporter selecting each
|
||||
# cycle on the appliance and reading back the raw code, the same method used
|
||||
# for Table_02's WF50A8600AV/US codes above. A device reporting Table_00 with
|
||||
# an unconfirmed code (FlexWash's washer_flexwash_device fixture, for
|
||||
# instance) still renders that code raw rather than borrowing a Table_02
|
||||
# label -- the two tables are unrelated code spaces despite a handful of
|
||||
# overlapping hex values.
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
# /washer/vs/0 -- wash temperature, spin speed, rinse cycle count.
|
||||
|
||||
@@ -324,6 +324,22 @@
|
||||
"4": "Alarm 4"
|
||||
}
|
||||
},
|
||||
"dryer_cycle_table_00": {
|
||||
"name": "Cyklus",
|
||||
"state": {
|
||||
"01": "Normální",
|
||||
"9c": "Intenzivní",
|
||||
"a5": "Ložní prádlo",
|
||||
"9e": "Nežehlivé prádlo",
|
||||
"9b": "Parní dezinfekce+",
|
||||
"27": "Osvěžení",
|
||||
"a0": "Provětrání",
|
||||
"a4": "Časové sušení",
|
||||
"a6": "Rychlé sušení",
|
||||
"a3": "Sportovní oblečení",
|
||||
"a2": "Jemné prádlo"
|
||||
}
|
||||
},
|
||||
"dryer_cycle_table_03": {
|
||||
"name": "Cyklus",
|
||||
"state": {
|
||||
@@ -604,6 +620,22 @@
|
||||
"extra_hot": "Extra horká"
|
||||
}
|
||||
},
|
||||
"washer_cycle_table_00": {
|
||||
"name": "Cyklus",
|
||||
"state": {
|
||||
"01": "Normální",
|
||||
"70": "Intenzivní",
|
||||
"55": "Bílé prádlo",
|
||||
"71": "Ložní prádlo",
|
||||
"72": "Dezinfekce",
|
||||
"77": "Nežehlivé prádlo",
|
||||
"57": "Samočištění+",
|
||||
"73": "Máchání + odstřeďování",
|
||||
"74": "Sportovní oblečení",
|
||||
"75": "Jemné prádlo",
|
||||
"78": "Rychlé praní"
|
||||
}
|
||||
},
|
||||
"washer_cycle_table_02": {
|
||||
"name": "Cyklus",
|
||||
"state": {
|
||||
|
||||
@@ -324,6 +324,22 @@
|
||||
"4": "Alarm 4"
|
||||
}
|
||||
},
|
||||
"dryer_cycle_table_00": {
|
||||
"name": "Programm",
|
||||
"state": {
|
||||
"01": "Normal",
|
||||
"9c": "Intensiv",
|
||||
"a5": "Bettwäsche",
|
||||
"9e": "Pflegeleicht",
|
||||
"9b": "Dampf-Hygiene+",
|
||||
"27": "Auffrischen",
|
||||
"a0": "Lüften",
|
||||
"a4": "Zeittrocknen",
|
||||
"a6": "Schnelltrocknen",
|
||||
"a3": "Sportkleidung",
|
||||
"a2": "Feinwäsche"
|
||||
}
|
||||
},
|
||||
"dryer_cycle_table_03": {
|
||||
"name": "Programm",
|
||||
"state": {
|
||||
@@ -567,6 +583,22 @@
|
||||
"extra_hot": "Extra heiß"
|
||||
}
|
||||
},
|
||||
"washer_cycle_table_00": {
|
||||
"name": "Programm",
|
||||
"state": {
|
||||
"01": "Normal",
|
||||
"70": "Intensiv",
|
||||
"55": "Weißwäsche",
|
||||
"71": "Bettwäsche",
|
||||
"72": "Hygienespülung",
|
||||
"77": "Pflegeleicht",
|
||||
"57": "Selbstreinigung+",
|
||||
"73": "Spülen + Schleudern",
|
||||
"74": "Sportkleidung",
|
||||
"75": "Feinwäsche",
|
||||
"78": "Schnellwäsche"
|
||||
}
|
||||
},
|
||||
"washer_cycle_table_02": {
|
||||
"name": "Programm",
|
||||
"state": {
|
||||
|
||||
@@ -324,6 +324,22 @@
|
||||
"4": "Alarm 4"
|
||||
}
|
||||
},
|
||||
"dryer_cycle_table_00": {
|
||||
"name": "Cycle",
|
||||
"state": {
|
||||
"01": "Normal",
|
||||
"9c": "Heavy Duty",
|
||||
"a5": "Bedding",
|
||||
"9e": "Perm Press",
|
||||
"9b": "Steam Sanitize+",
|
||||
"27": "Refresh",
|
||||
"a0": "Air Fluff",
|
||||
"a4": "Time Dry",
|
||||
"a6": "Quick Dry",
|
||||
"a3": "Active Wear",
|
||||
"a2": "Delicates"
|
||||
}
|
||||
},
|
||||
"dryer_cycle_table_03": {
|
||||
"name": "Cycle",
|
||||
"state": {
|
||||
@@ -604,6 +620,22 @@
|
||||
"extra_hot": "Extra hot"
|
||||
}
|
||||
},
|
||||
"washer_cycle_table_00": {
|
||||
"name": "Cycle",
|
||||
"state": {
|
||||
"01": "Normal",
|
||||
"70": "Heavy Duty",
|
||||
"55": "Whites",
|
||||
"71": "Bedding",
|
||||
"72": "Sanitize",
|
||||
"77": "Perm Press",
|
||||
"57": "Self Clean+",
|
||||
"73": "Rinse + Spin",
|
||||
"74": "Active Wear",
|
||||
"75": "Delicates",
|
||||
"78": "Quick Wash"
|
||||
}
|
||||
},
|
||||
"washer_cycle_table_02": {
|
||||
"name": "Cycle",
|
||||
"state": {
|
||||
|
||||
@@ -517,6 +517,22 @@
|
||||
"4": "Alarma 4"
|
||||
}
|
||||
},
|
||||
"dryer_cycle_table_00": {
|
||||
"name": "Ciclo",
|
||||
"state": {
|
||||
"01": "Normal",
|
||||
"9c": "Servicio intensivo",
|
||||
"a5": "Ropa de cama",
|
||||
"9e": "Planchado fácil",
|
||||
"9b": "Desinfección por vapor+",
|
||||
"27": "Renovar",
|
||||
"a0": "Aireación",
|
||||
"a4": "Secado por tiempo",
|
||||
"a6": "Secado rápido",
|
||||
"a3": "Ropa deportiva",
|
||||
"a2": "Delicados"
|
||||
}
|
||||
},
|
||||
"dryer_cycle_table_03": {
|
||||
"name": "Ciclo",
|
||||
"state": {
|
||||
@@ -797,6 +813,22 @@
|
||||
"extra_hot": "Muy caliente"
|
||||
}
|
||||
},
|
||||
"washer_cycle_table_00": {
|
||||
"name": "Ciclo",
|
||||
"state": {
|
||||
"01": "Normal",
|
||||
"70": "Servicio intensivo",
|
||||
"55": "Blancos",
|
||||
"71": "Ropa de cama",
|
||||
"72": "Desinfección",
|
||||
"77": "Planchado fácil",
|
||||
"57": "Autolimpieza+",
|
||||
"73": "Aclarar + Centrifugar",
|
||||
"74": "Ropa deportiva",
|
||||
"75": "Delicados",
|
||||
"78": "Lavado rápido"
|
||||
}
|
||||
},
|
||||
"washer_cycle_table_02": {
|
||||
"name": "Ciclo",
|
||||
"state": {
|
||||
|
||||
@@ -324,6 +324,22 @@
|
||||
"4": "Allarme 4"
|
||||
}
|
||||
},
|
||||
"dryer_cycle_table_00": {
|
||||
"name": "Ciclo",
|
||||
"state": {
|
||||
"01": "Normale",
|
||||
"9c": "Intenso",
|
||||
"a5": "Biancheria da letto",
|
||||
"9e": "Pronto da stirare",
|
||||
"9b": "Igienizzante a vapore+",
|
||||
"27": "Rinfresca",
|
||||
"a0": "Arieggiatura",
|
||||
"a4": "Asciugatura a tempo",
|
||||
"a6": "Asciugatura rapida",
|
||||
"a3": "Abbigliamento sportivo",
|
||||
"a2": "Delicati"
|
||||
}
|
||||
},
|
||||
"dryer_cycle_table_03": {
|
||||
"name": "Ciclo",
|
||||
"state": {
|
||||
@@ -604,6 +620,22 @@
|
||||
"extra_hot": "Extra caldo"
|
||||
}
|
||||
},
|
||||
"washer_cycle_table_00": {
|
||||
"name": "Ciclo",
|
||||
"state": {
|
||||
"01": "Normale",
|
||||
"70": "Intenso",
|
||||
"55": "Bianchi",
|
||||
"71": "Biancheria da letto",
|
||||
"72": "Igienizzante",
|
||||
"77": "Pronto da stirare",
|
||||
"57": "Self Clean+",
|
||||
"73": "Risciacquo+Centrifuga",
|
||||
"74": "Abbigliamento sportivo",
|
||||
"75": "Delicati",
|
||||
"78": "Lavaggio rapido"
|
||||
}
|
||||
},
|
||||
"washer_cycle_table_02": {
|
||||
"name": "Ciclo",
|
||||
"state": {
|
||||
|
||||
@@ -324,6 +324,22 @@
|
||||
"4": "알림음 4"
|
||||
}
|
||||
},
|
||||
"dryer_cycle_table_00": {
|
||||
"name": "코스",
|
||||
"state": {
|
||||
"01": "표준건조",
|
||||
"9c": "강력건조",
|
||||
"a5": "이불",
|
||||
"9e": "구김방지",
|
||||
"9b": "스팀살균+",
|
||||
"27": "리프레시",
|
||||
"a0": "송풍",
|
||||
"a4": "시간건조",
|
||||
"a6": "쾌속건조",
|
||||
"a3": "운동복",
|
||||
"a2": "섬세의류"
|
||||
}
|
||||
},
|
||||
"dryer_cycle_table_03": {
|
||||
"name": "코스",
|
||||
"state": {
|
||||
@@ -604,6 +620,22 @@
|
||||
"extra_hot": "고온수"
|
||||
}
|
||||
},
|
||||
"washer_cycle_table_00": {
|
||||
"name": "코스",
|
||||
"state": {
|
||||
"01": "표준세탁",
|
||||
"70": "강력세탁",
|
||||
"55": "흰옷",
|
||||
"71": "이불",
|
||||
"72": "살균",
|
||||
"77": "구김방지",
|
||||
"57": "통세척+",
|
||||
"73": "헹굼+탈수",
|
||||
"74": "운동복",
|
||||
"75": "섬세의류",
|
||||
"78": "쾌속세탁"
|
||||
}
|
||||
},
|
||||
"washer_cycle_table_02": {
|
||||
"name": "코스",
|
||||
"state": {
|
||||
|
||||
@@ -324,6 +324,22 @@
|
||||
"4": "Alarm 4"
|
||||
}
|
||||
},
|
||||
"dryer_cycle_table_00": {
|
||||
"name": "Programma",
|
||||
"state": {
|
||||
"01": "Normaal",
|
||||
"9c": "Intensief",
|
||||
"a5": "Beddengoed",
|
||||
"9e": "Strijkvrij",
|
||||
"9b": "Stoomhygiëne+",
|
||||
"27": "Opfrissen",
|
||||
"a0": "Luchtdrogen",
|
||||
"a4": "Tijdprogramma",
|
||||
"a6": "Snel drogen",
|
||||
"a3": "Sportkleding",
|
||||
"a2": "Fijne was"
|
||||
}
|
||||
},
|
||||
"dryer_cycle_table_03": {
|
||||
"name": "Programma",
|
||||
"state": {
|
||||
@@ -604,6 +620,22 @@
|
||||
"extra_hot": "Extra heet"
|
||||
}
|
||||
},
|
||||
"washer_cycle_table_00": {
|
||||
"name": "Programma",
|
||||
"state": {
|
||||
"01": "Normaal",
|
||||
"70": "Intensief",
|
||||
"55": "Witte was",
|
||||
"71": "Beddengoed",
|
||||
"72": "Hygiëne",
|
||||
"77": "Strijkvrij",
|
||||
"57": "Self Clean+",
|
||||
"73": "Spoelen + centrifugeren",
|
||||
"74": "Sportkleding",
|
||||
"75": "Fijne was",
|
||||
"78": "Snelle was"
|
||||
}
|
||||
},
|
||||
"washer_cycle_table_02": {
|
||||
"name": "Programma",
|
||||
"state": {
|
||||
|
||||
@@ -89,6 +89,20 @@ def test_course_bound_to_shared_course_vs_0():
|
||||
assert desc.rep_fn(rep) == "16"
|
||||
|
||||
|
||||
def test_reported_table_00_course_codes_are_translated():
|
||||
"""The reporter confirmed these codes on a DVE45R6300W/A3 by selecting
|
||||
each cycle and reading back the raw course code (issue #357)."""
|
||||
from custom_components.localthings.catalog import translated_states
|
||||
|
||||
desc = next(
|
||||
e for e in dryer.DRYER_COURSE.entities if e.key == "cycle" and isinstance(e, SelectDesc)
|
||||
)
|
||||
table_00 = {"/st/dryercourse/vs/0": {"x.com.samsung.da.st.courseTable": "Table_00"}}
|
||||
assert desc.translation_key(table_00) == "dryer_cycle_table_00"
|
||||
confirmed = {"01", "9c", "a5", "9e", "9b", "27", "a0", "a4", "a6", "a3", "a2"}
|
||||
assert confirmed <= translated_states("select", "dryer_cycle_table_00")
|
||||
|
||||
|
||||
def test_st_dryercourse_is_ignored():
|
||||
"""/st/dryercourse/vs/0 re-encodes the course exposed via /course/vs/0 and
|
||||
is globally ignored -- the mirror of /st/washercourse/vs/0."""
|
||||
|
||||
@@ -369,7 +369,7 @@ class TestCycleSelectTableGating:
|
||||
def test_untranslated_table_uses_generic_cycle_key(self):
|
||||
"""An unknown table does not claim another board's state labels."""
|
||||
desc = self._desc()
|
||||
resources = {"/st/washercourse/vs/0": {"x.com.samsung.da.st.courseTable": "Table_00"}}
|
||||
resources = {"/st/washercourse/vs/0": {"x.com.samsung.da.st.courseTable": "Table_99"}}
|
||||
assert desc.translation_key(resources) == "cycle"
|
||||
|
||||
def test_resolves_to_generic_cycle_when_table_id_is_unknown(self):
|
||||
|
||||
@@ -99,16 +99,18 @@ class TestWasherCourse:
|
||||
|
||||
def test_translation_key(self):
|
||||
"""Table-scoped (issue: course codes aren't guaranteed consistent
|
||||
across board generations sharing /course/vs/0 -- FlexWash's older
|
||||
board reports Table_00, not the Table_02 every washer_cycle_table_02
|
||||
name was confirmed against) -- see laundry.cycle_select. Only a
|
||||
verified table gets table-specific state translations."""
|
||||
across board generations sharing /course/vs/0 -- a device reporting
|
||||
an unrecognized table id must not borrow another board generation's
|
||||
labels) -- see laundry.cycle_select. Only a verified table gets
|
||||
table-specific state translations."""
|
||||
desc = next(e for e in washer.WASHER_COURSE.entities if e.key == "cycle")
|
||||
assert callable(desc.translation_key)
|
||||
table_02 = {"/st/washercourse/vs/0": {"x.com.samsung.da.st.courseTable": "Table_02"}}
|
||||
assert desc.translation_key(table_02) == "washer_cycle_table_02"
|
||||
table_00 = {"/st/washercourse/vs/0": {"x.com.samsung.da.st.courseTable": "Table_00"}}
|
||||
assert desc.translation_key(table_00) == "cycle"
|
||||
assert desc.translation_key(table_00) == "washer_cycle_table_00"
|
||||
unrecognized = {"/st/washercourse/vs/0": {"x.com.samsung.da.st.courseTable": "Table_99"}}
|
||||
assert desc.translation_key(unrecognized) == "cycle"
|
||||
assert desc.translation_key({}) == "cycle"
|
||||
|
||||
def test_reads_raw_course_code_from_options_array(self):
|
||||
@@ -146,6 +148,15 @@ class TestWasherCourse:
|
||||
}
|
||||
assert confirmed <= translated_states("select", "washer_cycle_table_02")
|
||||
|
||||
def test_reported_table_00_course_codes_are_translated(self):
|
||||
"""The reporter confirmed these codes on a WF45R6300AW/US by
|
||||
selecting each cycle and reading back the raw course code
|
||||
(issue #357)."""
|
||||
from custom_components.localthings.catalog import translated_states
|
||||
|
||||
confirmed = {"01", "70", "55", "71", "72", "77", "57", "73", "74", "75", "78"}
|
||||
assert confirmed <= translated_states("select", "washer_cycle_table_00")
|
||||
|
||||
def test_missing_course_option_returns_none(self):
|
||||
desc = next(e for e in washer.WASHER_COURSE.entities if e.key == "cycle")
|
||||
assert desc.rep_fn is not None
|
||||
|
||||
Reference in New Issue
Block a user