mirror of
https://github.com/esphome/esphome.git
synced 2026-02-18 15:35:59 -07:00
Merge branch 'dev' into jesserockz-2025-457
This commit is contained in:
194
tests/component_tests/psram/test_psram.py
Normal file
194
tests/component_tests/psram/test_psram.py
Normal file
@@ -0,0 +1,194 @@
|
||||
"""Tests for PSRAM component."""
|
||||
|
||||
from typing import Any
|
||||
|
||||
import pytest
|
||||
|
||||
from esphome.components.esp32.const import (
|
||||
KEY_VARIANT,
|
||||
VARIANT_ESP32,
|
||||
VARIANT_ESP32C2,
|
||||
VARIANT_ESP32C3,
|
||||
VARIANT_ESP32C5,
|
||||
VARIANT_ESP32C6,
|
||||
VARIANT_ESP32H2,
|
||||
VARIANT_ESP32P4,
|
||||
VARIANT_ESP32S2,
|
||||
VARIANT_ESP32S3,
|
||||
)
|
||||
import esphome.config_validation as cv
|
||||
from esphome.const import CONF_ESPHOME, PlatformFramework
|
||||
from tests.component_tests.types import SetCoreConfigCallable
|
||||
|
||||
UNSUPPORTED_PSRAM_VARIANTS = [
|
||||
VARIANT_ESP32C2,
|
||||
VARIANT_ESP32C3,
|
||||
VARIANT_ESP32C5,
|
||||
VARIANT_ESP32C6,
|
||||
VARIANT_ESP32H2,
|
||||
]
|
||||
|
||||
SUPPORTED_PSRAM_VARIANTS = [
|
||||
VARIANT_ESP32,
|
||||
VARIANT_ESP32S2,
|
||||
VARIANT_ESP32S3,
|
||||
VARIANT_ESP32P4,
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("config", "error_match"),
|
||||
[
|
||||
pytest.param(
|
||||
{},
|
||||
r"PSRAM is not supported on this chip",
|
||||
id="psram_not_supported",
|
||||
),
|
||||
],
|
||||
)
|
||||
@pytest.mark.parametrize("variant", UNSUPPORTED_PSRAM_VARIANTS)
|
||||
def test_psram_configuration_errors_unsupported_variants(
|
||||
config: Any,
|
||||
error_match: str,
|
||||
variant: str,
|
||||
set_core_config: SetCoreConfigCallable,
|
||||
) -> None:
|
||||
set_core_config(
|
||||
PlatformFramework.ESP32_IDF,
|
||||
platform_data={KEY_VARIANT: variant},
|
||||
full_config={CONF_ESPHOME: {}},
|
||||
)
|
||||
"""Test detection of invalid PSRAM configuration on unsupported variants."""
|
||||
from esphome.components.psram import CONFIG_SCHEMA
|
||||
|
||||
with pytest.raises(cv.Invalid, match=error_match):
|
||||
CONFIG_SCHEMA(config)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("variant", SUPPORTED_PSRAM_VARIANTS)
|
||||
def test_psram_configuration_valid_supported_variants(
|
||||
variant: str,
|
||||
set_core_config: SetCoreConfigCallable,
|
||||
) -> None:
|
||||
set_core_config(
|
||||
PlatformFramework.ESP32_IDF,
|
||||
platform_data={KEY_VARIANT: variant},
|
||||
full_config={
|
||||
CONF_ESPHOME: {},
|
||||
"esp32": {
|
||||
"variant": variant,
|
||||
"cpu_frequency": "160MHz",
|
||||
"framework": {"type": "esp-idf"},
|
||||
},
|
||||
},
|
||||
)
|
||||
"""Test that PSRAM configuration is valid on supported variants."""
|
||||
from esphome.components.psram import CONFIG_SCHEMA, FINAL_VALIDATE_SCHEMA
|
||||
|
||||
# This should not raise an exception
|
||||
config = CONFIG_SCHEMA({})
|
||||
FINAL_VALIDATE_SCHEMA(config)
|
||||
|
||||
|
||||
def _setup_psram_final_validation_test(
|
||||
esp32_config: dict,
|
||||
set_core_config: SetCoreConfigCallable,
|
||||
set_component_config: Any,
|
||||
) -> str:
|
||||
"""Helper function to set up ESP32 configuration for PSRAM final validation tests."""
|
||||
# Use ESP32S3 for schema validation to allow all options, then override for final validation
|
||||
schema_variant = "ESP32S3"
|
||||
final_variant = esp32_config.get("variant", "ESP32S3")
|
||||
full_esp32_config = {
|
||||
"variant": final_variant,
|
||||
"cpu_frequency": esp32_config.get("cpu_frequency", "240MHz"),
|
||||
"framework": {"type": "esp-idf"},
|
||||
}
|
||||
|
||||
set_core_config(
|
||||
PlatformFramework.ESP32_IDF,
|
||||
platform_data={KEY_VARIANT: schema_variant},
|
||||
full_config={
|
||||
CONF_ESPHOME: {},
|
||||
"esp32": full_esp32_config,
|
||||
},
|
||||
)
|
||||
set_component_config("esp32", full_esp32_config)
|
||||
|
||||
return final_variant
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("config", "esp32_config", "expect_error", "error_match"),
|
||||
[
|
||||
pytest.param(
|
||||
{"speed": "120MHz"},
|
||||
{"cpu_frequency": "160MHz"},
|
||||
True,
|
||||
r"PSRAM 120MHz requires 240MHz CPU frequency",
|
||||
id="120mhz_requires_240mhz_cpu",
|
||||
),
|
||||
pytest.param(
|
||||
{"mode": "octal"},
|
||||
{"variant": "ESP32"},
|
||||
True,
|
||||
r"Octal PSRAM is only supported on ESP32-S3",
|
||||
id="octal_mode_only_esp32s3",
|
||||
),
|
||||
pytest.param(
|
||||
{"mode": "quad", "enable_ecc": True},
|
||||
{},
|
||||
True,
|
||||
r"ECC is only available in octal mode",
|
||||
id="ecc_only_in_octal_mode",
|
||||
),
|
||||
pytest.param(
|
||||
{"speed": "120MHZ"},
|
||||
{"cpu_frequency": "240MHZ"},
|
||||
False,
|
||||
None,
|
||||
id="120mhz_with_240mhz_cpu",
|
||||
),
|
||||
pytest.param(
|
||||
{"mode": "octal"},
|
||||
{"variant": "ESP32S3"},
|
||||
False,
|
||||
None,
|
||||
id="octal_mode_on_esp32s3",
|
||||
),
|
||||
pytest.param(
|
||||
{"mode": "octal", "enable_ecc": True},
|
||||
{"variant": "ESP32S3"},
|
||||
False,
|
||||
None,
|
||||
id="ecc_in_octal_mode",
|
||||
),
|
||||
],
|
||||
)
|
||||
def test_psram_final_validation(
|
||||
config: Any,
|
||||
esp32_config: dict,
|
||||
expect_error: bool,
|
||||
error_match: str | None,
|
||||
set_core_config: SetCoreConfigCallable,
|
||||
set_component_config: Any,
|
||||
) -> None:
|
||||
"""Test PSRAM final validation for both error and valid cases."""
|
||||
from esphome.components.psram import CONFIG_SCHEMA, FINAL_VALIDATE_SCHEMA
|
||||
from esphome.core import CORE
|
||||
|
||||
final_variant = _setup_psram_final_validation_test(
|
||||
esp32_config, set_core_config, set_component_config
|
||||
)
|
||||
|
||||
validated_config = CONFIG_SCHEMA(config)
|
||||
|
||||
# Update CORE variant for final validation
|
||||
CORE.data["esp32"][KEY_VARIANT] = final_variant
|
||||
|
||||
if expect_error:
|
||||
with pytest.raises(cv.Invalid, match=error_match):
|
||||
FINAL_VALIDATE_SCHEMA(validated_config)
|
||||
else:
|
||||
# This should not raise an exception
|
||||
FINAL_VALIDATE_SCHEMA(validated_config)
|
||||
89
tests/components/esp32_can/test.esp32-c6-idf.yaml
Normal file
89
tests/components/esp32_can/test.esp32-c6-idf.yaml
Normal file
@@ -0,0 +1,89 @@
|
||||
esphome:
|
||||
on_boot:
|
||||
then:
|
||||
- canbus.send:
|
||||
# Extended ID explicit
|
||||
canbus_id: esp32_internal_can
|
||||
use_extended_id: true
|
||||
can_id: 0x100
|
||||
data: [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08]
|
||||
- canbus.send:
|
||||
# Standard ID by default
|
||||
canbus_id: esp32_internal_can
|
||||
can_id: 0x100
|
||||
data: [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08]
|
||||
- canbus.send:
|
||||
# Extended ID explicit
|
||||
canbus_id: esp32_internal_can_2
|
||||
use_extended_id: true
|
||||
can_id: 0x100
|
||||
data: [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08]
|
||||
- canbus.send:
|
||||
# Standard ID by default
|
||||
canbus_id: esp32_internal_can_2
|
||||
can_id: 0x100
|
||||
data: [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08]
|
||||
|
||||
canbus:
|
||||
- platform: esp32_can
|
||||
id: esp32_internal_can
|
||||
rx_pin: GPIO8
|
||||
tx_pin: GPIO7
|
||||
can_id: 4
|
||||
bit_rate: 50kbps
|
||||
on_frame:
|
||||
- can_id: 500
|
||||
then:
|
||||
- lambda: |-
|
||||
std::string b(x.begin(), x.end());
|
||||
ESP_LOGD("canbus1", "canid 500 %s", b.c_str() );
|
||||
- can_id: 0b00000000000000000000001000000
|
||||
can_id_mask: 0b11111000000000011111111000000
|
||||
use_extended_id: true
|
||||
then:
|
||||
- lambda: |-
|
||||
auto pdo_id = can_id >> 14;
|
||||
switch (pdo_id)
|
||||
{
|
||||
case 117:
|
||||
ESP_LOGD("canbus1", "exhaust_fan_duty");
|
||||
break;
|
||||
case 118:
|
||||
ESP_LOGD("canbus1", "supply_fan_duty");
|
||||
break;
|
||||
case 119:
|
||||
ESP_LOGD("canbus1", "supply_fan_flow");
|
||||
break;
|
||||
// to be continued...
|
||||
}
|
||||
- platform: esp32_can
|
||||
id: esp32_internal_can_2
|
||||
rx_pin: GPIO10
|
||||
tx_pin: GPIO9
|
||||
can_id: 4
|
||||
bit_rate: 50kbps
|
||||
on_frame:
|
||||
- can_id: 500
|
||||
then:
|
||||
- lambda: |-
|
||||
std::string b(x.begin(), x.end());
|
||||
ESP_LOGD("canbus2", "canid 500 %s", b.c_str() );
|
||||
- can_id: 0b00000000000000000000001000000
|
||||
can_id_mask: 0b11111000000000011111111000000
|
||||
use_extended_id: true
|
||||
then:
|
||||
- lambda: |-
|
||||
auto pdo_id = can_id >> 14;
|
||||
switch (pdo_id)
|
||||
{
|
||||
case 117:
|
||||
ESP_LOGD("canbus2", "exhaust_fan_duty");
|
||||
break;
|
||||
case 118:
|
||||
ESP_LOGD("canbus2", "supply_fan_duty");
|
||||
break;
|
||||
case 119:
|
||||
ESP_LOGD("canbus2", "supply_fan_flow");
|
||||
break;
|
||||
// to be continued...
|
||||
}
|
||||
9
tests/components/lm75b/common.yaml
Normal file
9
tests/components/lm75b/common.yaml
Normal file
@@ -0,0 +1,9 @@
|
||||
i2c:
|
||||
- id: i2c_lm75b
|
||||
scl: ${scl_pin}
|
||||
sda: ${sda_pin}
|
||||
|
||||
sensor:
|
||||
- platform: lm75b
|
||||
name: LM75B Temperature
|
||||
update_interval: 30s
|
||||
5
tests/components/lm75b/test.esp32-ard.yaml
Normal file
5
tests/components/lm75b/test.esp32-ard.yaml
Normal file
@@ -0,0 +1,5 @@
|
||||
substitutions:
|
||||
scl_pin: GPIO15
|
||||
sda_pin: GPIO13
|
||||
|
||||
<<: !include common.yaml
|
||||
5
tests/components/lm75b/test.esp32-c3-ard.yaml
Normal file
5
tests/components/lm75b/test.esp32-c3-ard.yaml
Normal file
@@ -0,0 +1,5 @@
|
||||
substitutions:
|
||||
scl_pin: GPIO5
|
||||
sda_pin: GPIO4
|
||||
|
||||
<<: !include common.yaml
|
||||
5
tests/components/lm75b/test.esp32-c3-idf.yaml
Normal file
5
tests/components/lm75b/test.esp32-c3-idf.yaml
Normal file
@@ -0,0 +1,5 @@
|
||||
substitutions:
|
||||
scl_pin: GPIO5
|
||||
sda_pin: GPIO4
|
||||
|
||||
<<: !include common.yaml
|
||||
5
tests/components/lm75b/test.esp32-idf.yaml
Normal file
5
tests/components/lm75b/test.esp32-idf.yaml
Normal file
@@ -0,0 +1,5 @@
|
||||
substitutions:
|
||||
scl_pin: GPIO15
|
||||
sda_pin: GPIO13
|
||||
|
||||
<<: !include common.yaml
|
||||
5
tests/components/lm75b/test.esp8266-ard.yaml
Normal file
5
tests/components/lm75b/test.esp8266-ard.yaml
Normal file
@@ -0,0 +1,5 @@
|
||||
substitutions:
|
||||
scl_pin: GPIO5
|
||||
sda_pin: GPIO4
|
||||
|
||||
<<: !include common.yaml
|
||||
5
tests/components/lm75b/test.rp2040-ard.yaml
Normal file
5
tests/components/lm75b/test.rp2040-ard.yaml
Normal file
@@ -0,0 +1,5 @@
|
||||
substitutions:
|
||||
scl_pin: GPIO5
|
||||
sda_pin: GPIO4
|
||||
|
||||
<<: !include common.yaml
|
||||
@@ -6,11 +6,16 @@ esphome:
|
||||
format: "Warning: Logger level is %d"
|
||||
args: [id(logger_id).get_log_level()]
|
||||
- logger.set_level: WARN
|
||||
- logger.set_level:
|
||||
level: ERROR
|
||||
tag: mqtt.client
|
||||
|
||||
logger:
|
||||
id: logger_id
|
||||
level: DEBUG
|
||||
initial_level: INFO
|
||||
logs:
|
||||
mqtt.component: WARN
|
||||
|
||||
select:
|
||||
- platform: logger
|
||||
|
||||
@@ -17,5 +17,7 @@ sensor:
|
||||
temperature:
|
||||
name: QMC5883L Temperature
|
||||
range: 800uT
|
||||
data_rate: 200Hz
|
||||
oversampling: 256x
|
||||
update_interval: 15s
|
||||
drdy_pin: ${drdy_pin}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
substitutions:
|
||||
scl_pin: GPIO16
|
||||
sda_pin: GPIO17
|
||||
drdy_pin: GPIO18
|
||||
|
||||
<<: !include common.yaml
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
substitutions:
|
||||
scl_pin: GPIO5
|
||||
sda_pin: GPIO4
|
||||
drdy_pin: GPIO6
|
||||
|
||||
<<: !include common.yaml
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
substitutions:
|
||||
scl_pin: GPIO5
|
||||
sda_pin: GPIO4
|
||||
drdy_pin: GPIO6
|
||||
|
||||
<<: !include common.yaml
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
substitutions:
|
||||
scl_pin: GPIO16
|
||||
sda_pin: GPIO17
|
||||
drdy_pin: GPIO18
|
||||
|
||||
<<: !include common.yaml
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
substitutions:
|
||||
scl_pin: GPIO5
|
||||
sda_pin: GPIO4
|
||||
drdy_pin: GPIO2
|
||||
|
||||
<<: !include common.yaml
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
substitutions:
|
||||
scl_pin: GPIO5
|
||||
sda_pin: GPIO4
|
||||
drdy_pin: GPIO2
|
||||
|
||||
<<: !include common.yaml
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
substitutions:
|
||||
pin: GPIO2
|
||||
clock_resolution: "2000000"
|
||||
carrier_duty_percent: "25"
|
||||
carrier_frequency: "30000"
|
||||
filter_symbols: "2"
|
||||
receive_symbols: "4"
|
||||
rmt_symbols: "64"
|
||||
|
||||
@@ -5,6 +5,9 @@ substitutions:
|
||||
var21: '79'
|
||||
value: 33
|
||||
values: 44
|
||||
position:
|
||||
x: 79
|
||||
y: 82
|
||||
|
||||
esphome:
|
||||
name: test
|
||||
@@ -26,3 +29,7 @@ test_list:
|
||||
- Literal $values ${are not substituted}
|
||||
- ["list $value", "${is not}", "${substituted}"]
|
||||
- {"$dictionary": "$value", "${is not}": "${substituted}"}
|
||||
- |-
|
||||
{{{ "x", "79"}, { "y", "82"}}}
|
||||
- '{{{"AA"}}}'
|
||||
- '"HELLO"'
|
||||
|
||||
@@ -8,6 +8,9 @@ substitutions:
|
||||
var21: "79"
|
||||
value: 33
|
||||
values: 44
|
||||
position:
|
||||
x: 79
|
||||
y: 82
|
||||
|
||||
test_list:
|
||||
- "$var1"
|
||||
@@ -27,3 +30,7 @@ test_list:
|
||||
- !literal Literal $values ${are not substituted}
|
||||
- !literal ["list $value", "${is not}", "${substituted}"]
|
||||
- !literal {"$dictionary": "$value", "${is not}": "${substituted}"}
|
||||
- |- # Test parsing things that look like a python set of sets when rendered:
|
||||
{{{ "x", "${ position.x }"}, { "y", "${ position.y }"}}}
|
||||
- ${ '{{{"AA"}}}' }
|
||||
- ${ '"HELLO"' }
|
||||
|
||||
Reference in New Issue
Block a user