Replace the fixed time.sleep(GRACE_PERIOD_S) in try_enter_observe_mode
with a threading.Condition.wait_for(predicate, timeout=grace_period_s)
that returns as soon as success_fraction of subscribed hrefs have
notified. Production data (fridge TP2X_REF_20K): all 13 hrefs notify
within ~0.34s of subscribe, so every successful first-refresh / observe
retry was waiting ~14.6s of dead time. AC retry cycles showed the same
16s-fetches-that-transition pattern.
No behavior change on the fallback path (fraction not reached → wait
the full ceiling → MODE_POLL, identical to today). GRACE_PERIOD_S and
SUCCESS_FRACTION unchanged. No smartthings_local library change.
mbillow's follow-up review: exposing read-only Software/Firmware (and
Outdoor/Touch IC) version strings is "data for the sake of exposing it" --
no user control, just clutter, and every other registry leaves
/information/vs/0 in the global ignore as identity plumbing. Conforming to
that stance rather than expanding the entity surface for no user story.
- by_type/airconditioner.py: revert to *ignored.IGNORED (no _IGNORED_LESS_INFO
filter); drop airconditioner.INFO from the registry.
- capabilities/airconditioner.py: remove the INFO capability, the _info_version
/_info_items_of_type /_has_info_version helpers, and HREF_INFORMATION.
- translations/{en,nl}.json: drop software_version, firmware_version,
firmware_version_2/3, outdoor_unit_version, touch_ic_version.
- tests: drop the six INFO tests; golden regenerated for 8 AC + dehumidifier.
625 tests pass.
Conflicts resolved:
- capabilities/airconditioner.py: keep my NumberDesc/SelectDesc imports +
upstream's hoist of _filter_usage_percent -> common.filter_usage_percent
(local def removed by upstream's auto-merge; AIR_FILTER.air_filter_usage
now references the common helper). Upstream's ANOMALY_LOAD, HREF_WIND_OSCILLATION
and oscillation climate-write kind kept; my beep/tropical/INFO/AIR_QUALITY/
threshold-Select/filter-hours kept. Both change sets coexist.
- translations/{en,nl}.json: switch section -- keep both my 'beep' and
upstream's display/pet_filter_activation/auto_empty/dustbin_auto_close/
uvc_intensive_mode entries.
Regenerated the 8 AC + dehumidifier goldens (+ the 2 new upstream AC fixtures
ara_ww_tp1_22, windfree_oscillation) against the merged code. 631 tests pass.
Per mbillow's review on PR #129 (CHANGES_REQUESTED). Items 1-7 + smaller.
1. INFO: expose each /information/vs/0 version item per (type, ordinal) instead
of collapsing to a single first-Firmware value. Boards carry 1-3 Firmware
items (separate MCUs) plus an Outdoor unit and (window AC) a Touch IC item;
each is a distinct version string. _info_version(items, type_, ordinal)
+ _has_info_version exists_fn gate, so an item with no number (tp2x_rac_20k's
second Firmware) suppresses the entity rather than binding unknown.
2. air_filter_threshold is locally writable, not cloud-only -- confirmed live
on ARTIK051_PRAC: POST filterDesiredUsage=700 to /filter/airdustfilter/vs/0
-> 2.04, read-back 700, persists; restored to 500. Converted from a
read-only sensor to a SelectDesc keyed to the device's
supportedFilterDesiredUsage enum (options_field), with a write_fn that
POSTs the scalar field. Only binds where the enum is advertised; boards
without it leave this writable field unexposed rather than guess the valid
set (don't-guess).
3. air_filter_usage_hours uses unit_fn reading filterCapacityUnit ('Hour'->'h')
instead of a hardcoded unit, so a board advertising a different unit doesn't
mislabel a duration statistic.
4. air_filter_usage_hours state_class is total_increasing, not measurement --
filterUsage is a lifetime hour counter that resets on filter replacement.
5. INFO and air_filter_threshold now carry exists_fn (AIR_QUALITY already did),
so they don't bind a permanently-unknown entity when their item/field is
absent. Also fixes the caww_tp2 golden nuance (filterDesiredUsage absent
-> no threshold key, matching what HA would actually create).
6. AIR_QUALITY: CleanLevel is corroborated as numeric by a top-level
x.com.samsung.da.cleanLevel scalar (tp1x_da_ac_rac_01011 reports both as
'1'), so clean_level is now an int measurement; odor/dust/fine_dust stay
string diagnostics. Reinstated the 2-element-array ambiguity note (Dust/
FineDust/SuperFineDust report ['0','0']; v[1] meaning unconfirmed, v[0]
taken as the reading). SuperFineDust is now modeled for consistency with
Dust/FineDust (same shape), rather than skipped without reason.
7. _beep_write restores the last non-Mute Volume level on 'On' instead of
forcing Volume_100, so an intermediate setting (e.g. Volume_50 set via
the cloud) survives an off/on cycle; falls back to 100 when no prior level.
Smaller: test_air_quality now asserts the tp1x_da_ac_rac_01011 clean_level==1
non-zero reading (the one value_fn-regression catch in the corpus); renamed
by_type's _AC_IGNORED -> _IGNORED_LESS_INFO to resolve the two-meaning
collision with the capabilities module's _AC_IGNORED (href strings); golden
regenerated for the 8 AC fixtures + dehumidifier.
612 tests pass.
Layer the ARTIK051_PRAC additive entities onto the upstream registry on a
fresh branch (additive-only; the round-1 display-light/mute-once/WindFree
work was independently shipped upstream and is not redone here).
New entities, all driven by single-token option_write or item reads:
- beep (switch): Volume_Mute/Volume_100 option token; single-token merge --
a full options RMW reverts on ARTIK051_PRAC. Cloud counterpart:
samsungce.airConditionerAudioFeedback (on/off only; level is cloud-only).
- tropical_night_mode (number 0-16): Sleep_<N> option token. Cloud:
custom.airConditionerTropicalNightMode.
- air_filter_usage_hours / air_filter_threshold (duration sensors, h):
raw filterUsage count and filterDesiredUsage alarm threshold. Threshold
SET is cloud-only (samsungce.dustFilterAlarm); local read-only.
- clean_level / odor / dust / fine_dust (diagnostic sensors): /sensors/vs/0
items[]. No unit advertised on the resource, so no device_class until a
populated reading + unit is observed (don't-guess rule). SuperFineDust
intentionally not modeled.
- software_version / firmware_version (diagnostic sensors):
/information/vs/0 items[]. The href is globally ignored as identity
plumbing; the AC registry drops that ignore so INFO is the sole cap on it.
Translations: en.json + nl.json (every-language-mirrors-english invariant).
Golden regression: regenerated the 8 AC fixtures + dehumidifier (reuses
AIR_FILTER) for the new state keys.
608 tests pass.