mirror of
https://github.com/esphome/esphome.git
synced 2026-05-28 21:59:59 +08:00
[sensor] Fix delta filter percentage mode regression (#14302)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
committed by
Jesse Hills
parent
5a1d6428b2
commit
8479664df1
@@ -603,7 +603,7 @@ DELTA_SCHEMA = cv.Any(
|
|||||||
def _get_delta(value):
|
def _get_delta(value):
|
||||||
if isinstance(value, str):
|
if isinstance(value, str):
|
||||||
assert value.endswith("%")
|
assert value.endswith("%")
|
||||||
return 0.0, float(value[:-1])
|
return 0.0, float(value[:-1]) / 100.0
|
||||||
return value, 0.0
|
return value, 0.0
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -28,6 +28,11 @@ sensor:
|
|||||||
id: source_sensor_4
|
id: source_sensor_4
|
||||||
accuracy_decimals: 1
|
accuracy_decimals: 1
|
||||||
|
|
||||||
|
- platform: template
|
||||||
|
name: "Source Sensor 5"
|
||||||
|
id: source_sensor_5
|
||||||
|
accuracy_decimals: 1
|
||||||
|
|
||||||
- platform: copy
|
- platform: copy
|
||||||
source_id: source_sensor_1
|
source_id: source_sensor_1
|
||||||
name: "Filter Min"
|
name: "Filter Min"
|
||||||
@@ -69,6 +74,13 @@ sensor:
|
|||||||
filters:
|
filters:
|
||||||
- delta: 0
|
- delta: 0
|
||||||
|
|
||||||
|
- platform: copy
|
||||||
|
source_id: source_sensor_5
|
||||||
|
name: "Filter Percentage"
|
||||||
|
id: filter_percentage
|
||||||
|
filters:
|
||||||
|
- delta: 50%
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- id: test_filter_min
|
- id: test_filter_min
|
||||||
then:
|
then:
|
||||||
@@ -154,6 +166,28 @@ script:
|
|||||||
id: source_sensor_4
|
id: source_sensor_4
|
||||||
state: 2.0
|
state: 2.0
|
||||||
|
|
||||||
|
- id: test_filter_percentage
|
||||||
|
then:
|
||||||
|
- sensor.template.publish:
|
||||||
|
id: source_sensor_5
|
||||||
|
state: 100.0
|
||||||
|
- delay: 20ms
|
||||||
|
- sensor.template.publish:
|
||||||
|
id: source_sensor_5
|
||||||
|
state: 120.0 # Filtered out (delta=20, need >50)
|
||||||
|
- delay: 20ms
|
||||||
|
- sensor.template.publish:
|
||||||
|
id: source_sensor_5
|
||||||
|
state: 160.0 # Passes (delta=60 > 50% of 100=50)
|
||||||
|
- delay: 20ms
|
||||||
|
- sensor.template.publish:
|
||||||
|
id: source_sensor_5
|
||||||
|
state: 200.0 # Filtered out (delta=40, need >50% of 160=80)
|
||||||
|
- delay: 20ms
|
||||||
|
- sensor.template.publish:
|
||||||
|
id: source_sensor_5
|
||||||
|
state: 250.0 # Passes (delta=90 > 80)
|
||||||
|
|
||||||
button:
|
button:
|
||||||
- platform: template
|
- platform: template
|
||||||
name: "Test Filter Min"
|
name: "Test Filter Min"
|
||||||
@@ -178,3 +212,9 @@ button:
|
|||||||
id: btn_filter_zero_delta
|
id: btn_filter_zero_delta
|
||||||
on_press:
|
on_press:
|
||||||
- script.execute: test_filter_zero_delta
|
- script.execute: test_filter_zero_delta
|
||||||
|
|
||||||
|
- platform: template
|
||||||
|
name: "Test Filter Percentage"
|
||||||
|
id: btn_filter_percentage
|
||||||
|
on_press:
|
||||||
|
- script.execute: test_filter_percentage
|
||||||
|
|||||||
@@ -24,12 +24,14 @@ async def test_sensor_filters_delta(
|
|||||||
"filter_max": [],
|
"filter_max": [],
|
||||||
"filter_baseline_max": [],
|
"filter_baseline_max": [],
|
||||||
"filter_zero_delta": [],
|
"filter_zero_delta": [],
|
||||||
|
"filter_percentage": [],
|
||||||
}
|
}
|
||||||
|
|
||||||
filter_min_done = loop.create_future()
|
filter_min_done = loop.create_future()
|
||||||
filter_max_done = loop.create_future()
|
filter_max_done = loop.create_future()
|
||||||
filter_baseline_max_done = loop.create_future()
|
filter_baseline_max_done = loop.create_future()
|
||||||
filter_zero_delta_done = loop.create_future()
|
filter_zero_delta_done = loop.create_future()
|
||||||
|
filter_percentage_done = loop.create_future()
|
||||||
|
|
||||||
def on_state(state: EntityState) -> None:
|
def on_state(state: EntityState) -> None:
|
||||||
if not isinstance(state, SensorState) or state.missing_state:
|
if not isinstance(state, SensorState) or state.missing_state:
|
||||||
@@ -66,6 +68,12 @@ async def test_sensor_filters_delta(
|
|||||||
and not filter_zero_delta_done.done()
|
and not filter_zero_delta_done.done()
|
||||||
):
|
):
|
||||||
filter_zero_delta_done.set_result(True)
|
filter_zero_delta_done.set_result(True)
|
||||||
|
elif (
|
||||||
|
sensor_name == "filter_percentage"
|
||||||
|
and len(sensor_values[sensor_name]) == 3
|
||||||
|
and not filter_percentage_done.done()
|
||||||
|
):
|
||||||
|
filter_percentage_done.set_result(True)
|
||||||
|
|
||||||
async with (
|
async with (
|
||||||
run_compiled(yaml_config),
|
run_compiled(yaml_config),
|
||||||
@@ -80,6 +88,7 @@ async def test_sensor_filters_delta(
|
|||||||
"filter_max": "Filter Max",
|
"filter_max": "Filter Max",
|
||||||
"filter_baseline_max": "Filter Baseline Max",
|
"filter_baseline_max": "Filter Baseline Max",
|
||||||
"filter_zero_delta": "Filter Zero Delta",
|
"filter_zero_delta": "Filter Zero Delta",
|
||||||
|
"filter_percentage": "Filter Percentage",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -98,13 +107,14 @@ async def test_sensor_filters_delta(
|
|||||||
"Test Filter Max": "filter_max",
|
"Test Filter Max": "filter_max",
|
||||||
"Test Filter Baseline Max": "filter_baseline_max",
|
"Test Filter Baseline Max": "filter_baseline_max",
|
||||||
"Test Filter Zero Delta": "filter_zero_delta",
|
"Test Filter Zero Delta": "filter_zero_delta",
|
||||||
|
"Test Filter Percentage": "filter_percentage",
|
||||||
}
|
}
|
||||||
buttons = {}
|
buttons = {}
|
||||||
for entity in entities:
|
for entity in entities:
|
||||||
if isinstance(entity, ButtonInfo) and entity.name in button_name_map:
|
if isinstance(entity, ButtonInfo) and entity.name in button_name_map:
|
||||||
buttons[button_name_map[entity.name]] = entity.key
|
buttons[button_name_map[entity.name]] = entity.key
|
||||||
|
|
||||||
assert len(buttons) == 4, f"Expected 3 buttons, found {len(buttons)}"
|
assert len(buttons) == 5, f"Expected 5 buttons, found {len(buttons)}"
|
||||||
|
|
||||||
# Test 1: Min
|
# Test 1: Min
|
||||||
sensor_values["filter_min"].clear()
|
sensor_values["filter_min"].clear()
|
||||||
@@ -161,3 +171,18 @@ async def test_sensor_filters_delta(
|
|||||||
assert sensor_values["filter_zero_delta"] == pytest.approx(expected), (
|
assert sensor_values["filter_zero_delta"] == pytest.approx(expected), (
|
||||||
f"Test 4 failed: expected {expected}, got {sensor_values['filter_zero_delta']}"
|
f"Test 4 failed: expected {expected}, got {sensor_values['filter_zero_delta']}"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Test 5: Percentage (delta: 50%)
|
||||||
|
sensor_values["filter_percentage"].clear()
|
||||||
|
client.button_command(buttons["filter_percentage"])
|
||||||
|
try:
|
||||||
|
await asyncio.wait_for(filter_percentage_done, timeout=2.0)
|
||||||
|
except TimeoutError:
|
||||||
|
pytest.fail(
|
||||||
|
f"Test 5 timed out. Values: {sensor_values['filter_percentage']}"
|
||||||
|
)
|
||||||
|
|
||||||
|
expected = [100.0, 160.0, 250.0]
|
||||||
|
assert sensor_values["filter_percentage"] == pytest.approx(expected), (
|
||||||
|
f"Test 5 failed: expected {expected}, got {sensor_values['filter_percentage']}"
|
||||||
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user