mirror of
https://github.com/esphome/esphome.git
synced 2026-10-04 02:05:59 +00:00
Merge branch 'dev' into multi_device
This commit is contained in:
@@ -26,3 +26,17 @@ binary_sensor:
|
||||
threshold: 100
|
||||
filters:
|
||||
- invert:
|
||||
- platform: analog_threshold
|
||||
name: Analog Threshold 3
|
||||
sensor_id: template_sensor
|
||||
threshold: !lambda return 100;
|
||||
filters:
|
||||
- invert:
|
||||
- platform: analog_threshold
|
||||
name: Analog Threshold 4
|
||||
sensor_id: template_sensor
|
||||
threshold:
|
||||
upper: !lambda return 110;
|
||||
lower: !lambda return 90;
|
||||
filters:
|
||||
- invert:
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
packages:
|
||||
common: !include common.yaml
|
||||
|
||||
wifi:
|
||||
ssid: MySSID
|
||||
password: password1
|
||||
|
||||
api:
|
||||
encryption:
|
||||
key: !remove
|
||||
@@ -0,0 +1,71 @@
|
||||
image:
|
||||
grayscale:
|
||||
alpha_channel:
|
||||
- file: ../../pnglogo.png
|
||||
id: image_1
|
||||
resize: 50x50
|
||||
- file: ../../pnglogo.png
|
||||
id: image_2
|
||||
resize: 50x50
|
||||
|
||||
mapping:
|
||||
- id: weather_map
|
||||
from: string
|
||||
to: "image::Image"
|
||||
entries:
|
||||
clear-night: image_1
|
||||
sunny: image_2
|
||||
- id: weather_map_1
|
||||
from: string
|
||||
to: esphome::image::Image
|
||||
entries:
|
||||
clear-night: image_1
|
||||
sunny: image_2
|
||||
- id: weather_map_2
|
||||
from: string
|
||||
to: image
|
||||
entries:
|
||||
clear-night: image_1
|
||||
sunny: image_2
|
||||
- id: int_map
|
||||
from: int
|
||||
to: string
|
||||
entries:
|
||||
1: "one"
|
||||
2: "two"
|
||||
3: "three"
|
||||
77: "seventy-seven"
|
||||
- id: string_map
|
||||
from: string
|
||||
to: int
|
||||
entries:
|
||||
one: 1
|
||||
two: 2
|
||||
three: 3
|
||||
seventy-seven: 77
|
||||
- id: color_map
|
||||
from: string
|
||||
to: color
|
||||
entries:
|
||||
red: red_id
|
||||
blue: blue_id
|
||||
green: green_id
|
||||
|
||||
color:
|
||||
- id: red_id
|
||||
red: 1.0
|
||||
green: 0.0
|
||||
blue: 0.0
|
||||
- id: green_id
|
||||
red: 0.0
|
||||
green: 1.0
|
||||
blue: 0.0
|
||||
- id: blue_id
|
||||
red: 0.0
|
||||
green: 0.0
|
||||
blue: 1.0
|
||||
|
||||
display:
|
||||
lambda: |-
|
||||
it.image(0, 0, id(weather_map)[0]);
|
||||
it.image(0, 100, id(weather_map)[1]);
|
||||
@@ -0,0 +1,17 @@
|
||||
spi:
|
||||
- id: spi_main_lcd
|
||||
clk_pin: 16
|
||||
mosi_pin: 17
|
||||
miso_pin: 15
|
||||
|
||||
display:
|
||||
- platform: ili9xxx
|
||||
id: main_lcd
|
||||
model: ili9342
|
||||
cs_pin: 12
|
||||
dc_pin: 13
|
||||
reset_pin: 21
|
||||
invert_colors: false
|
||||
|
||||
packages:
|
||||
map: !include common.yaml
|
||||
@@ -0,0 +1,17 @@
|
||||
spi:
|
||||
- id: spi_main_lcd
|
||||
clk_pin: 6
|
||||
mosi_pin: 7
|
||||
miso_pin: 5
|
||||
|
||||
display:
|
||||
- platform: ili9xxx
|
||||
id: main_lcd
|
||||
model: ili9342
|
||||
cs_pin: 8
|
||||
dc_pin: 9
|
||||
reset_pin: 10
|
||||
invert_colors: false
|
||||
|
||||
packages:
|
||||
map: !include common.yaml
|
||||
@@ -0,0 +1,17 @@
|
||||
spi:
|
||||
- id: spi_main_lcd
|
||||
clk_pin: 6
|
||||
mosi_pin: 7
|
||||
miso_pin: 5
|
||||
|
||||
display:
|
||||
- platform: ili9xxx
|
||||
id: main_lcd
|
||||
model: ili9342
|
||||
cs_pin: 8
|
||||
dc_pin: 9
|
||||
reset_pin: 10
|
||||
invert_colors: false
|
||||
|
||||
packages:
|
||||
map: !include common.yaml
|
||||
@@ -0,0 +1,17 @@
|
||||
spi:
|
||||
- id: spi_main_lcd
|
||||
clk_pin: 16
|
||||
mosi_pin: 17
|
||||
miso_pin: 15
|
||||
|
||||
display:
|
||||
- platform: ili9xxx
|
||||
id: main_lcd
|
||||
model: ili9342
|
||||
cs_pin: 12
|
||||
dc_pin: 13
|
||||
reset_pin: 21
|
||||
invert_colors: false
|
||||
|
||||
packages:
|
||||
map: !include common.yaml
|
||||
@@ -0,0 +1,17 @@
|
||||
spi:
|
||||
- id: spi_main_lcd
|
||||
clk_pin: 14
|
||||
mosi_pin: 13
|
||||
miso_pin: 12
|
||||
|
||||
display:
|
||||
- platform: ili9xxx
|
||||
id: main_lcd
|
||||
model: ili9342
|
||||
cs_pin: 5
|
||||
dc_pin: 15
|
||||
reset_pin: 16
|
||||
invert_colors: false
|
||||
|
||||
packages:
|
||||
map: !include common.yaml
|
||||
@@ -0,0 +1,12 @@
|
||||
display:
|
||||
- platform: sdl
|
||||
id: sdl_display
|
||||
update_interval: 1s
|
||||
auto_clear_enabled: false
|
||||
show_test_card: true
|
||||
dimensions:
|
||||
width: 450
|
||||
height: 600
|
||||
|
||||
packages:
|
||||
map: !include common.yaml
|
||||
@@ -0,0 +1,17 @@
|
||||
spi:
|
||||
- id: spi_main_lcd
|
||||
clk_pin: 2
|
||||
mosi_pin: 3
|
||||
miso_pin: 4
|
||||
|
||||
display:
|
||||
- platform: ili9xxx
|
||||
id: main_lcd
|
||||
model: ili9342
|
||||
cs_pin: 20
|
||||
dc_pin: 21
|
||||
reset_pin: 22
|
||||
invert_colors: false
|
||||
|
||||
packages:
|
||||
map: !include common.yaml
|
||||
@@ -0,0 +1,13 @@
|
||||
i2c:
|
||||
- id: i2c_pm2005
|
||||
scl: ${scl_pin}
|
||||
sda: ${sda_pin}
|
||||
|
||||
sensor:
|
||||
- platform: pm2005
|
||||
pm_1_0:
|
||||
name: PM1.0
|
||||
pm_2_5:
|
||||
name: PM2.5
|
||||
pm_10_0:
|
||||
name: PM10.0
|
||||
@@ -0,0 +1,5 @@
|
||||
substitutions:
|
||||
scl_pin: GPIO16
|
||||
sda_pin: GPIO17
|
||||
|
||||
<<: !include common.yaml
|
||||
@@ -0,0 +1,5 @@
|
||||
substitutions:
|
||||
scl_pin: GPIO5
|
||||
sda_pin: GPIO4
|
||||
|
||||
<<: !include common.yaml
|
||||
@@ -0,0 +1,5 @@
|
||||
substitutions:
|
||||
scl_pin: GPIO5
|
||||
sda_pin: GPIO4
|
||||
|
||||
<<: !include common.yaml
|
||||
@@ -0,0 +1,5 @@
|
||||
substitutions:
|
||||
scl_pin: GPIO16
|
||||
sda_pin: GPIO17
|
||||
|
||||
<<: !include common.yaml
|
||||
@@ -0,0 +1,5 @@
|
||||
substitutions:
|
||||
scl_pin: GPIO5
|
||||
sda_pin: GPIO4
|
||||
|
||||
<<: !include common.yaml
|
||||
@@ -0,0 +1,5 @@
|
||||
substitutions:
|
||||
scl_pin: GPIO5
|
||||
sda_pin: GPIO4
|
||||
|
||||
<<: !include common.yaml
|
||||
@@ -1,6 +1,3 @@
|
||||
substitutions:
|
||||
verify_ssl: "false"
|
||||
|
||||
esphome:
|
||||
name: livingroomdevice
|
||||
friendly_name: Living Room Device
|
||||
@@ -129,6 +126,14 @@ valve:
|
||||
optimistic: true
|
||||
has_position: true
|
||||
|
||||
remote_transmitter:
|
||||
pin: ${pin}
|
||||
carrier_duty_percent: 50%
|
||||
|
||||
climate:
|
||||
- platform: climate_ir_lg
|
||||
name: LG Climate
|
||||
|
||||
prometheus:
|
||||
include_internal: true
|
||||
relabel:
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
substitutions:
|
||||
verify_ssl: "false"
|
||||
pin: GPIO5
|
||||
|
||||
<<: !include common.yaml
|
||||
|
||||
i2s_audio:
|
||||
|
||||
@@ -1 +1,5 @@
|
||||
substitutions:
|
||||
verify_ssl: "false"
|
||||
pin: GPIO2
|
||||
|
||||
<<: !include common.yaml
|
||||
|
||||
@@ -1 +1,5 @@
|
||||
substitutions:
|
||||
verify_ssl: "false"
|
||||
pin: GPIO2
|
||||
|
||||
<<: !include common.yaml
|
||||
|
||||
@@ -1 +1,5 @@
|
||||
substitutions:
|
||||
verify_ssl: "false"
|
||||
pin: GPIO2
|
||||
|
||||
<<: !include common.yaml
|
||||
|
||||
@@ -1 +1,5 @@
|
||||
substitutions:
|
||||
verify_ssl: "false"
|
||||
pin: GPIO5
|
||||
|
||||
<<: !include common.yaml
|
||||
|
||||
@@ -17,3 +17,13 @@ sensor:
|
||||
text_sensor:
|
||||
- platform: uptime
|
||||
name: Uptime Text
|
||||
- platform: uptime
|
||||
name: Uptime Text With Separator
|
||||
format:
|
||||
separator: "-"
|
||||
expand: true
|
||||
days: "Days"
|
||||
hours: "H"
|
||||
minutes: "M"
|
||||
seconds: "S"
|
||||
update_interval: 10s
|
||||
|
||||
@@ -267,3 +267,13 @@ def test_sanitize(text, expected):
|
||||
actual = helpers.sanitize(text)
|
||||
|
||||
assert actual == expected
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"text, expected",
|
||||
((["127.0.0.1", "fe80::1", "2001::2"], ["2001::2", "127.0.0.1", "fe80::1"]),),
|
||||
)
|
||||
def test_sort_ip_addresses(text: list[str], expected: list[str]) -> None:
|
||||
actual = helpers.sort_ip_addresses(text)
|
||||
|
||||
assert actual == expected
|
||||
|
||||
@@ -0,0 +1,125 @@
|
||||
import json
|
||||
import os
|
||||
from unittest.mock import Mock, patch
|
||||
|
||||
from esphome import vscode
|
||||
|
||||
|
||||
def _run_repl_test(input_data):
|
||||
"""Reusable test function for different input scenarios."""
|
||||
input_data.append(_exit())
|
||||
with (
|
||||
patch("builtins.input", side_effect=input_data),
|
||||
patch("sys.stdout") as mock_stdout,
|
||||
):
|
||||
args = Mock([])
|
||||
args.ace = False
|
||||
args.substitution = None
|
||||
vscode.read_config(args)
|
||||
|
||||
# Capture printed output
|
||||
full_output = "".join(call[0][0] for call in mock_stdout.write.call_args_list)
|
||||
return full_output.strip().split("\n")
|
||||
|
||||
|
||||
def _validate(file_path: str):
|
||||
return json.dumps({"type": "validate", "file": file_path})
|
||||
|
||||
|
||||
def _file_response(data: str):
|
||||
return json.dumps({"type": "file_response", "content": data})
|
||||
|
||||
|
||||
def _read_file(file_path: str):
|
||||
return json.dumps({"type": "read_file", "path": file_path})
|
||||
|
||||
|
||||
def _exit():
|
||||
return json.dumps({"type": "exit"})
|
||||
|
||||
|
||||
RESULT_NO_ERROR = '{"type": "result", "yaml_errors": [], "validation_errors": []}'
|
||||
|
||||
|
||||
def test_multi_file():
|
||||
source_path = os.path.join("dir_path", "x.yaml")
|
||||
output_lines = _run_repl_test(
|
||||
[
|
||||
_validate(source_path),
|
||||
# read_file x.yaml
|
||||
_file_response("""esphome:
|
||||
name: test1
|
||||
esp8266:
|
||||
board: !secret my_secret_board
|
||||
"""),
|
||||
# read_file secrets.yaml
|
||||
_file_response("""my_secret_board: esp1f"""),
|
||||
]
|
||||
)
|
||||
|
||||
expected_lines = [
|
||||
_read_file(source_path),
|
||||
_read_file(os.path.join("dir_path", "secrets.yaml")),
|
||||
RESULT_NO_ERROR,
|
||||
]
|
||||
|
||||
assert output_lines == expected_lines
|
||||
|
||||
|
||||
def test_shows_correct_range_error():
|
||||
source_path = os.path.join("dir_path", "x.yaml")
|
||||
output_lines = _run_repl_test(
|
||||
[
|
||||
_validate(source_path),
|
||||
# read_file x.yaml
|
||||
_file_response("""esphome:
|
||||
name: test1
|
||||
esp8266:
|
||||
broad: !secret my_secret_board # typo here
|
||||
"""),
|
||||
# read_file secrets.yaml
|
||||
_file_response("""my_secret_board: esp1f"""),
|
||||
]
|
||||
)
|
||||
|
||||
assert len(output_lines) == 3
|
||||
error = json.loads(output_lines[2])
|
||||
validation_error = error["validation_errors"][0]
|
||||
assert validation_error["message"].startswith("[broad] is an invalid option for")
|
||||
range = validation_error["range"]
|
||||
assert range["document"] == source_path
|
||||
assert range["start_line"] == 3
|
||||
assert range["start_col"] == 2
|
||||
assert range["end_line"] == 3
|
||||
assert range["end_col"] == 7
|
||||
|
||||
|
||||
def test_shows_correct_loaded_file_error():
|
||||
source_path = os.path.join("dir_path", "x.yaml")
|
||||
output_lines = _run_repl_test(
|
||||
[
|
||||
_validate(source_path),
|
||||
# read_file x.yaml
|
||||
_file_response("""esphome:
|
||||
name: test1
|
||||
|
||||
packages:
|
||||
board: !include .pkg.esp8266.yaml
|
||||
"""),
|
||||
# read_file .pkg.esp8266.yaml
|
||||
_file_response("""esp8266:
|
||||
broad: esp1f # typo here
|
||||
"""),
|
||||
]
|
||||
)
|
||||
|
||||
assert len(output_lines) == 3
|
||||
error = json.loads(output_lines[2])
|
||||
validation_error = error["validation_errors"][0]
|
||||
assert validation_error["message"].startswith("[broad] is an invalid option for")
|
||||
range = validation_error["range"]
|
||||
assert range["document"] == os.path.join("dir_path", ".pkg.esp8266.yaml")
|
||||
assert range["start_line"] == 1
|
||||
assert range["start_col"] == 2
|
||||
assert range["end_line"] == 1
|
||||
assert range["end_col"] == 7
|
||||
@@ -42,3 +42,23 @@ def test_loading_a_missing_file(fixture_path):
|
||||
yaml_util.load_yaml(yaml_file)
|
||||
except EsphomeError as err:
|
||||
assert "missing.yaml" in str(err)
|
||||
|
||||
|
||||
def test_parsing_with_custom_loader(fixture_path):
|
||||
"""Test custom loader used for vscode connection
|
||||
Default loader is tested in test_include_with_vars
|
||||
"""
|
||||
yaml_file = fixture_path / "yaml_util" / "includetest.yaml"
|
||||
|
||||
loader_calls = []
|
||||
|
||||
def custom_loader(fname):
|
||||
loader_calls.append(fname)
|
||||
|
||||
with open(yaml_file, encoding="utf-8") as f_handle:
|
||||
yaml_util.parse_yaml(yaml_file, f_handle, custom_loader)
|
||||
|
||||
assert len(loader_calls) == 3
|
||||
assert loader_calls[0].endswith("includes/included.yaml")
|
||||
assert loader_calls[1].endswith("includes/list.yaml")
|
||||
assert loader_calls[2].endswith("includes/scalar.yaml")
|
||||
|
||||
Reference in New Issue
Block a user