mirror of
https://github.com/esphome/esphome.git
synced 2026-10-01 17:00:21 +00:00
Merge branch 'dev' into sendspin-artwork
This commit is contained in:
@@ -91,6 +91,24 @@ api:
|
||||
- float_arr.size()
|
||||
- string_arr[0].c_str()
|
||||
- string_arr.size()
|
||||
# Test array + string args used after a non-synchronous action (delay).
|
||||
# The default non-owning types (StringRef, const FixedVector&) would
|
||||
# dangle once rx_buf_ is reused, and FixedVector is non-copyable so
|
||||
# DelayAction's lambda capture would fail to compile. The api codegen
|
||||
# must fall back to owning std::string / std::vector here.
|
||||
- action: array_with_delay
|
||||
variables:
|
||||
name: string
|
||||
int_arr: int[]
|
||||
string_arr: string[]
|
||||
then:
|
||||
- delay: 20ms
|
||||
- logger.log:
|
||||
format: "Delayed: %s (%u ints, %u strings)"
|
||||
args:
|
||||
- name.c_str()
|
||||
- int_arr.size()
|
||||
- string_arr.size()
|
||||
# Test ContinuationAction (IfAction with then/else branches)
|
||||
- action: test_if_action
|
||||
variables:
|
||||
|
||||
@@ -0,0 +1,123 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <ios>
|
||||
#include <random>
|
||||
|
||||
#include "esphome/components/api/api_buffer.h"
|
||||
#include "esphome/components/api/proto.h"
|
||||
|
||||
namespace esphome::api::testing {
|
||||
|
||||
// Generic varint decoder, used to verify the encoded bytes round-trip back to
|
||||
// the original 48-bit MAC value, independent of the specialized encoder under
|
||||
// test.
|
||||
static uint64_t decode_varint(const uint8_t *buf, size_t len, size_t *consumed) {
|
||||
uint64_t value = 0;
|
||||
int shift = 0;
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
value |= static_cast<uint64_t>(buf[i] & 0x7F) << shift;
|
||||
if ((buf[i] & 0x80) == 0) {
|
||||
*consumed = i + 1;
|
||||
return value;
|
||||
}
|
||||
shift += 7;
|
||||
}
|
||||
*consumed = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Reference encoder mirroring ProtoEncode::encode_varint_raw_64.
|
||||
static size_t reference_encode(uint64_t value, uint8_t *out) {
|
||||
uint8_t *p = out;
|
||||
if (value < 128) {
|
||||
*p++ = static_cast<uint8_t>(value);
|
||||
return p - out;
|
||||
}
|
||||
do {
|
||||
*p++ = static_cast<uint8_t>(value | 0x80);
|
||||
value >>= 7;
|
||||
} while (value > 0x7F);
|
||||
*p++ = static_cast<uint8_t>(value);
|
||||
return p - out;
|
||||
}
|
||||
|
||||
// Encode `mac` via the 48-bit fast path and verify:
|
||||
// - byte-identical output to the reference loop
|
||||
// - encoded byte length matches `expected_bytes`
|
||||
// - calc_uint64_48bit_force agrees on the size
|
||||
// - the bytes round-trip through a generic varint decoder
|
||||
static void verify_mac(uint64_t mac, size_t expected_bytes) {
|
||||
ASSERT_LT(mac, 1ULL << 48) << "test fixture mac exceeds 48 bits";
|
||||
|
||||
uint8_t ref_buf[16] = {0};
|
||||
size_t ref_len = reference_encode(mac, ref_buf);
|
||||
|
||||
APIBuffer api_buf;
|
||||
api_buf.resize(16);
|
||||
uint8_t *pos = api_buf.data();
|
||||
#ifdef ESPHOME_DEBUG_API
|
||||
uint8_t *proto_debug_end_ = api_buf.data() + api_buf.size();
|
||||
#endif
|
||||
ProtoEncode::encode_varint_raw_48bit(pos PROTO_ENCODE_DEBUG_ARG, mac);
|
||||
size_t new_len = pos - api_buf.data();
|
||||
|
||||
EXPECT_EQ(new_len, expected_bytes) << "mac=0x" << std::hex << mac << std::dec;
|
||||
EXPECT_EQ(ref_len, expected_bytes) << "reference disagrees on length for mac=0x" << std::hex << mac << std::dec;
|
||||
|
||||
for (size_t i = 0; i < new_len; i++) {
|
||||
EXPECT_EQ(api_buf.data()[i], ref_buf[i])
|
||||
<< "byte " << i << " differs for mac=0x" << std::hex << mac << " (got 0x" << static_cast<int>(api_buf.data()[i])
|
||||
<< ", expected 0x" << static_cast<int>(ref_buf[i]) << ")" << std::dec;
|
||||
}
|
||||
|
||||
size_t consumed = 0;
|
||||
uint64_t decoded = decode_varint(api_buf.data(), new_len, &consumed);
|
||||
EXPECT_EQ(consumed, new_len) << "decoder did not consume all bytes for mac=0x" << std::hex << mac << std::dec;
|
||||
EXPECT_EQ(decoded, mac) << "round-trip mismatch for mac=0x" << std::hex << mac << std::dec;
|
||||
|
||||
// Verify the size helper agrees. field_id_size = 1 (typical 1-byte tag).
|
||||
uint32_t calc_size = ProtoSize::calc_uint64_48bit_force(1, mac);
|
||||
EXPECT_EQ(calc_size, 1 + expected_bytes)
|
||||
<< "calc_uint64_48bit_force size mismatch for mac=0x" << std::hex << mac << std::dec;
|
||||
}
|
||||
|
||||
// Compute the canonical varint byte length for a value < 1<<48.
|
||||
static size_t expected_varint_len(uint64_t v) {
|
||||
if (v < (1ULL << 7))
|
||||
return 1;
|
||||
if (v < (1ULL << 14))
|
||||
return 2;
|
||||
if (v < (1ULL << 21))
|
||||
return 3;
|
||||
if (v < (1ULL << 28))
|
||||
return 4;
|
||||
if (v < (1ULL << 35))
|
||||
return 5;
|
||||
if (v < (1ULL << 42))
|
||||
return 6;
|
||||
return 7;
|
||||
}
|
||||
|
||||
// --- Specific MACs requested for verification ---
|
||||
|
||||
TEST(ProtoMacVarint, AllZeros) { verify_mac(0x000000000000ULL, 1); } // 00:00:00:00:00:00
|
||||
TEST(ProtoMacVarint, FirstByteOnly) { verify_mac(0x110000000000ULL, 7); } // 11:00:00:00:00:00
|
||||
TEST(ProtoMacVarint, SecondByteOnly) { verify_mac(0x00AA00000000ULL, 6); } // 00:AA:00:00:00:00
|
||||
TEST(ProtoMacVarint, ThirdByteOnly) { verify_mac(0x0000BB000000ULL, 5); } // 00:00:BB:00:00:00
|
||||
TEST(ProtoMacVarint, FourthByteOnly) { verify_mac(0x000000CC0000ULL, 4); } // 00:00:00:CC:00:00
|
||||
TEST(ProtoMacVarint, FifthByteOnly) { verify_mac(0x00000000DD00ULL, 3); } // 00:00:00:00:DD:00
|
||||
TEST(ProtoMacVarint, SixthByteOnly) { verify_mac(0x0000000000EEULL, 2); } // 00:00:00:00:00:EE
|
||||
TEST(ProtoMacVarint, AllOnes) { verify_mac(0xFFFFFFFFFFFFULL, 7); } // FF:FF:FF:FF:FF:FF
|
||||
|
||||
// 100 deterministic-random 48-bit MACs to catch regressions across the space.
|
||||
TEST(ProtoMacVarint, RandomSample) {
|
||||
// NOLINTNEXTLINE(cert-msc32-c,cert-msc51-cpp,bugprone-random-generator-seed) -- fixed seed for reproducibility
|
||||
std::mt19937_64 rng(0xC0FFEE);
|
||||
for (int i = 0; i < 100; i++) {
|
||||
uint64_t mac = rng() & 0xFFFFFFFFFFFFULL;
|
||||
verify_mac(mac, expected_varint_len(mac));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace esphome::api::testing
|
||||
@@ -0,0 +1,14 @@
|
||||
audio:
|
||||
codecs:
|
||||
flac:
|
||||
buffer_memory: internal
|
||||
mp3:
|
||||
buffer_memory: psram
|
||||
opus:
|
||||
floating_point: false
|
||||
state_memory: psram
|
||||
pseudostack:
|
||||
threadsafe: false
|
||||
buffer_memory: internal
|
||||
size: 80000
|
||||
wav:
|
||||
@@ -0,0 +1 @@
|
||||
<<: !include common.yaml
|
||||
@@ -29,3 +29,74 @@ climate:
|
||||
heat_action:
|
||||
- switch.turn_on: climate_heater_switch
|
||||
- switch.turn_off: climate_cooler_switch
|
||||
# Thermostat-based climate so climate.control: action variants get build
|
||||
# coverage (bang_bang doesn't support fan modes, presets, etc.). Climate
|
||||
# has no template platform, so thermostat is the right vehicle.
|
||||
- platform: thermostat
|
||||
id: climate_test_thermostat
|
||||
name: Test Thermostat
|
||||
sensor: climate_temperature_sensor
|
||||
min_idle_time: 30s
|
||||
min_heating_off_time: 300s
|
||||
min_heating_run_time: 300s
|
||||
min_cooling_off_time: 300s
|
||||
min_cooling_run_time: 300s
|
||||
heat_action:
|
||||
- logger.log: heating
|
||||
idle_action:
|
||||
- logger.log: idle
|
||||
cool_action:
|
||||
- logger.log: cooling
|
||||
auto_mode:
|
||||
- logger.log: auto
|
||||
heat_cool_mode:
|
||||
- logger.log: heat_cool
|
||||
preset:
|
||||
- name: Default
|
||||
default_target_temperature_low: 18°C
|
||||
default_target_temperature_high: 22°C
|
||||
|
||||
button:
|
||||
# Exercise the climate.control: action so ControlAction templates get
|
||||
# build coverage. Various field combinations are tested.
|
||||
- platform: template
|
||||
name: "Climate Control Mode"
|
||||
on_press:
|
||||
- climate.control:
|
||||
id: climate_test_thermostat
|
||||
mode: HEAT
|
||||
- platform: template
|
||||
name: "Climate Control Mode And Temps"
|
||||
on_press:
|
||||
- climate.control:
|
||||
id: climate_test_thermostat
|
||||
mode: HEAT_COOL
|
||||
target_temperature_low: 19.0°C
|
||||
target_temperature_high: 23.0°C
|
||||
- platform: template
|
||||
name: "Climate Control Lambda Temp"
|
||||
on_press:
|
||||
- climate.control:
|
||||
id: climate_test_thermostat
|
||||
target_temperature_high: !lambda "return 21.5;"
|
||||
- platform: template
|
||||
name: "Climate Control Off"
|
||||
on_press:
|
||||
- climate.control:
|
||||
id: climate_test_thermostat
|
||||
mode: "OFF"
|
||||
|
||||
# Exercise climate.control inside a trigger with non-empty Ts (number on_value
|
||||
# passes float).
|
||||
number:
|
||||
- platform: template
|
||||
id: climate_target_temp_number
|
||||
optimistic: true
|
||||
min_value: 16
|
||||
max_value: 28
|
||||
step: 0.5
|
||||
on_value:
|
||||
then:
|
||||
- climate.control:
|
||||
id: climate_test_thermostat
|
||||
target_temperature_high: !lambda "return x;"
|
||||
|
||||
@@ -9,6 +9,14 @@ fan:
|
||||
has_oscillating: true
|
||||
has_direction: true
|
||||
speed_count: 3
|
||||
# Exercise fan.turn_on inside a trigger whose Ts pack is non-empty
|
||||
# (StringRef from on_preset_set) so the apply-lambda + inner-lambda
|
||||
# codegen runs through the cvref-normalized path.
|
||||
on_preset_set:
|
||||
then:
|
||||
- fan.turn_on:
|
||||
id: test_fan
|
||||
speed: !lambda "return x.empty() ? 1 : 3;"
|
||||
|
||||
# Test lambdas using get_preset_mode() which returns StringRef
|
||||
# These examples match the migration guide in the PR description
|
||||
@@ -57,3 +65,52 @@ binary_sensor:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
# Exercise fan.turn_on with various field combinations so the
|
||||
# TurnOnAction codegen paths get build coverage.
|
||||
button:
|
||||
- platform: template
|
||||
name: "Fan Speed Only"
|
||||
on_press:
|
||||
- fan.turn_on:
|
||||
id: test_fan
|
||||
speed: 2
|
||||
- platform: template
|
||||
name: "Fan Oscillating + Direction"
|
||||
on_press:
|
||||
- fan.turn_on:
|
||||
id: test_fan
|
||||
oscillating: true
|
||||
direction: REVERSE
|
||||
- platform: template
|
||||
name: "Fan All Fields"
|
||||
on_press:
|
||||
- fan.turn_on:
|
||||
id: test_fan
|
||||
oscillating: false
|
||||
speed: 3
|
||||
direction: FORWARD
|
||||
- platform: template
|
||||
name: "Fan Lambda Speed"
|
||||
on_press:
|
||||
- fan.turn_on:
|
||||
id: test_fan
|
||||
speed: !lambda 'return 1;'
|
||||
|
||||
# Exercise fan.turn_on inside triggers with non-empty Ts:
|
||||
# - number.on_value: Ts = float (Python value type; previously raised
|
||||
# AttributeError on .operator("const"))
|
||||
# - fan.on_preset_set: Ts = StringRef (already a value-type wrapper around
|
||||
# a const char * + size; tests the cvref-normalized inner-lambda path)
|
||||
number:
|
||||
- platform: template
|
||||
id: fan_speed_number
|
||||
optimistic: true
|
||||
min_value: 1
|
||||
max_value: 3
|
||||
step: 1
|
||||
on_value:
|
||||
then:
|
||||
- fan.turn_on:
|
||||
id: test_fan
|
||||
speed: !lambda "return (int) x;"
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
from tests.testing_helpers import ComponentManifestOverride
|
||||
|
||||
|
||||
def override_manifest(manifest: ComponentManifestOverride) -> None:
|
||||
# json's to_code calls cg.add_library("bblanchon/ArduinoJson", ...). C++
|
||||
# unit test builds that pull json in transitively (e.g. api) need that
|
||||
# library registration to happen, otherwise json_util.cpp fails to find
|
||||
# ArduinoJson.h.
|
||||
manifest.enable_codegen()
|
||||
@@ -108,6 +108,10 @@ esphome:
|
||||
relative_brightness: 5%
|
||||
brightness_limits:
|
||||
max_brightness: 90%
|
||||
- light.dim_relative:
|
||||
id: test_monochromatic_light
|
||||
relative_brightness: -5%
|
||||
transition_length: 250ms
|
||||
- light.turn_on:
|
||||
id: test_addressable_transition
|
||||
brightness: 50%
|
||||
@@ -123,6 +127,21 @@ esphome:
|
||||
blue: 0%
|
||||
transition_length: 1s
|
||||
|
||||
# Exercise light actions inside a trigger with non-empty Ts (number on_value
|
||||
# passes float).
|
||||
number:
|
||||
- platform: template
|
||||
id: test_number_brightness
|
||||
optimistic: true
|
||||
min_value: 0
|
||||
max_value: 100
|
||||
step: 1
|
||||
on_value:
|
||||
then:
|
||||
- light.turn_on:
|
||||
id: test_monochromatic_light
|
||||
brightness: !lambda "return x / 100.0;"
|
||||
|
||||
light:
|
||||
- platform: binary
|
||||
id: test_binary_light
|
||||
|
||||
@@ -16,10 +16,19 @@ binary_sensor:
|
||||
platform: template
|
||||
- id: left_sensor
|
||||
platform: template
|
||||
- platform: lvgl
|
||||
name: Button A pressed
|
||||
widget: button_a
|
||||
state: pressed
|
||||
- platform: lvgl
|
||||
name: Button A checked
|
||||
widget: button_a
|
||||
state: checked
|
||||
- platform: lvgl
|
||||
id: button_checker
|
||||
name: LVGL button
|
||||
widget: button_button
|
||||
state: checked
|
||||
on_state:
|
||||
then:
|
||||
- lvgl.checkbox.update:
|
||||
@@ -29,6 +38,12 @@ binary_sensor:
|
||||
auto y = x; // block inlining of one line return
|
||||
return y;
|
||||
|
||||
- platform: lvgl
|
||||
id: button_presser
|
||||
name: Button pressed
|
||||
widget: button_button
|
||||
state: pressed
|
||||
|
||||
lvgl:
|
||||
id: lvgl_id
|
||||
rotation: 90
|
||||
@@ -1098,6 +1113,8 @@ lvgl:
|
||||
pad_row: 6px
|
||||
pad_column: 0
|
||||
multiple_widgets_per_cell: true
|
||||
grid_cell_x_align: center
|
||||
grid_cell_y_align: center
|
||||
widgets:
|
||||
- image:
|
||||
grid_cell_row_pos: 0
|
||||
@@ -1290,6 +1307,87 @@ lvgl:
|
||||
hidden: true
|
||||
mode: text_lower
|
||||
|
||||
# Grid shorthand "<rows>x": 3 rows specified, columns derived
|
||||
# from widget count (4 widgets / 3 rows -> 2 columns)
|
||||
- obj:
|
||||
id: grid_rows_only_shorthand
|
||||
layout: 3x
|
||||
widgets:
|
||||
- label:
|
||||
text: "r1"
|
||||
- label:
|
||||
text: "r2"
|
||||
- label:
|
||||
text: "r3"
|
||||
- label:
|
||||
text: "r4"
|
||||
|
||||
# Grid shorthand "x<cols>": 4 columns specified, rows derived
|
||||
# from widget count (5 widgets / 4 cols -> 2 rows)
|
||||
- obj:
|
||||
id: grid_cols_only_shorthand
|
||||
layout: x4
|
||||
widgets:
|
||||
- label:
|
||||
text: "a"
|
||||
- label:
|
||||
text: "b"
|
||||
- label:
|
||||
text: "c"
|
||||
- label:
|
||||
text: "d"
|
||||
- label:
|
||||
text: "e"
|
||||
|
||||
# Grid dict form with grid_rows as a plain integer; columns derived
|
||||
- obj:
|
||||
id: grid_rows_int
|
||||
layout:
|
||||
type: grid
|
||||
grid_rows: 2
|
||||
widgets:
|
||||
- label:
|
||||
text: "1"
|
||||
- label:
|
||||
text: "2"
|
||||
- label:
|
||||
text: "3"
|
||||
|
||||
# Grid dict form with grid_columns as a plain integer; rows derived
|
||||
- obj:
|
||||
id: grid_cols_int
|
||||
layout:
|
||||
type: grid
|
||||
grid_columns: 3
|
||||
widgets:
|
||||
- label:
|
||||
text: "x"
|
||||
- label:
|
||||
text: "y"
|
||||
- label:
|
||||
text: "z"
|
||||
- label:
|
||||
text: "w"
|
||||
- label:
|
||||
text: "v"
|
||||
|
||||
# Grid dict form with both grid_rows and grid_columns as plain integers
|
||||
- obj:
|
||||
id: grid_both_int
|
||||
layout:
|
||||
type: grid
|
||||
grid_rows: 2
|
||||
grid_columns: 2
|
||||
widgets:
|
||||
- label:
|
||||
text: "1,1"
|
||||
- label:
|
||||
text: "1,2"
|
||||
- label:
|
||||
text: "2,1"
|
||||
- label:
|
||||
text: "2,2"
|
||||
|
||||
font:
|
||||
- file: "gfonts://Roboto"
|
||||
id: space16
|
||||
|
||||
@@ -21,6 +21,7 @@ mapping:
|
||||
entries:
|
||||
clear-night: image_1
|
||||
sunny: image_2
|
||||
default_value: image_1
|
||||
- id: weather_map_2
|
||||
from: string
|
||||
to: image
|
||||
@@ -35,6 +36,7 @@ mapping:
|
||||
2: "two"
|
||||
3: "three"
|
||||
77: "seventy-seven"
|
||||
default_value: unknown
|
||||
- id: string_map
|
||||
from: string
|
||||
to: int
|
||||
|
||||
@@ -4,7 +4,7 @@ packages:
|
||||
|
||||
display:
|
||||
spi_id: spi_bus
|
||||
platform: ili9xxx
|
||||
platform: mipi_spi
|
||||
id: main_lcd
|
||||
model: ili9342
|
||||
cs_pin: 12
|
||||
|
||||
@@ -4,7 +4,7 @@ packages:
|
||||
|
||||
display:
|
||||
spi_id: spi_bus
|
||||
platform: ili9xxx
|
||||
platform: mipi_spi
|
||||
id: main_lcd
|
||||
model: ili9342
|
||||
cs_pin: 5
|
||||
|
||||
@@ -4,7 +4,7 @@ packages:
|
||||
|
||||
display:
|
||||
spi_id: spi_bus
|
||||
platform: ili9xxx
|
||||
platform: mipi_spi
|
||||
id: main_lcd
|
||||
model: ili9342
|
||||
data_rate: 31.25MHz
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
ethernet:
|
||||
type: W5500
|
||||
clk_pin: 18
|
||||
mosi_pin: 19
|
||||
miso_pin: 16
|
||||
cs_pin: 17
|
||||
interrupt_pin: 21
|
||||
reset_pin: 20
|
||||
manual_ip:
|
||||
static_ip: 192.168.178.56
|
||||
gateway: 192.168.178.1
|
||||
subnet: 255.255.255.0
|
||||
domain: .local
|
||||
mac_address: "02:AA:BB:CC:DD:01"
|
||||
|
||||
mdns:
|
||||
disabled: false
|
||||
services:
|
||||
- service: _test_service
|
||||
protocol: _tcp
|
||||
port: 8888
|
||||
txt:
|
||||
static_string: Anything
|
||||
@@ -0,0 +1 @@
|
||||
<<: !include common-enabled-ethernet.yaml
|
||||
@@ -1,53 +1,11 @@
|
||||
modbus:
|
||||
- id: mod_bus2
|
||||
uart_id: uart_bus
|
||||
role: server
|
||||
|
||||
modbus_controller:
|
||||
- id: modbus_controller1
|
||||
address: 0x2
|
||||
modbus_id: modbus_bus
|
||||
allow_duplicate_commands: false
|
||||
on_online:
|
||||
then:
|
||||
logger.log: "Module Online"
|
||||
- id: modbus_controller2
|
||||
address: 0x2
|
||||
modbus_id: mod_bus2
|
||||
server_registers:
|
||||
- address: 0x0000
|
||||
value_type: S_DWORD_R
|
||||
read_lambda: |-
|
||||
return 42.3;
|
||||
max_cmd_retries: 0
|
||||
- id: modbus_controller3
|
||||
address: 0x3
|
||||
modbus_id: mod_bus2
|
||||
server_registers:
|
||||
- address: 0x0009
|
||||
value_type: S_DWORD
|
||||
read_lambda: |-
|
||||
return 31;
|
||||
write_lambda: |-
|
||||
printf("address=%d, value=%d", x);
|
||||
return true;
|
||||
max_cmd_retries: 0
|
||||
- id: modbus_controller4
|
||||
modbus_id: mod_bus2
|
||||
address: 0x4
|
||||
server_courtesy_response:
|
||||
enabled: true
|
||||
register_last_address: 100
|
||||
register_value: 0
|
||||
server_registers:
|
||||
- address: 0x0001
|
||||
value_type: U_WORD
|
||||
read_lambda: |-
|
||||
return 0x8;
|
||||
- address: 0x0005
|
||||
value_type: U_WORD
|
||||
read_lambda: |-
|
||||
return (random_uint32() % 100);
|
||||
|
||||
binary_sensor:
|
||||
- platform: modbus_controller
|
||||
modbus_controller_id: modbus_controller1
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
modbus:
|
||||
- id: mod_bus2
|
||||
uart_id: uart_bus
|
||||
role: server
|
||||
|
||||
modbus_server:
|
||||
- id: modbus_server2
|
||||
address: 0x2
|
||||
modbus_id: mod_bus2
|
||||
registers:
|
||||
- address: 0x0
|
||||
value_type: S_DWORD_R
|
||||
read_lambda: |-
|
||||
return 42.3;
|
||||
- id: modbus_server3
|
||||
address: 0x3
|
||||
modbus_id: mod_bus2
|
||||
registers:
|
||||
- address: 0x9
|
||||
value_type: S_DWORD
|
||||
read_lambda: |-
|
||||
return 31;
|
||||
write_lambda: |-
|
||||
printf("address=%d, value=%d", x);
|
||||
return true;
|
||||
- id: modbus_server4
|
||||
modbus_id: mod_bus2
|
||||
address: 0x4
|
||||
courtesy_response:
|
||||
enabled: true
|
||||
register_last_address: 100
|
||||
register_value: 0
|
||||
registers:
|
||||
- address: 0x1
|
||||
value_type: U_WORD
|
||||
read_lambda: |-
|
||||
return 0x8;
|
||||
- address: 0x5
|
||||
value_type: U_WORD
|
||||
read_lambda: |-
|
||||
return (random_uint32() % 100);
|
||||
@@ -0,0 +1,4 @@
|
||||
packages:
|
||||
modbus: !include ../../test_build_components/common/modbus/esp32-idf.yaml
|
||||
|
||||
<<: !include common.yaml
|
||||
@@ -0,0 +1,4 @@
|
||||
packages:
|
||||
modbus: !include ../../test_build_components/common/modbus/esp8266-ard.yaml
|
||||
|
||||
<<: !include common.yaml
|
||||
@@ -0,0 +1,4 @@
|
||||
packages:
|
||||
modbus: !include ../../test_build_components/common/modbus/rp2040-ard.yaml
|
||||
|
||||
<<: !include common.yaml
|
||||
@@ -0,0 +1,9 @@
|
||||
nrf52:
|
||||
dfu:
|
||||
reset_pin:
|
||||
number: 14
|
||||
inverted: true
|
||||
mode:
|
||||
output: true
|
||||
reg0:
|
||||
voltage: 1.8V
|
||||
@@ -1,9 +1,4 @@
|
||||
nrf52:
|
||||
dfu:
|
||||
reset_pin:
|
||||
number: 14
|
||||
inverted: true
|
||||
mode:
|
||||
output: true
|
||||
dfu: true
|
||||
reg0:
|
||||
voltage: 1.8V
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
ota:
|
||||
- platform: esphome
|
||||
allow_partition_access: true
|
||||
|
||||
<<: !include common.yaml
|
||||
@@ -7,3 +7,4 @@ media_source:
|
||||
initial_static_delay: 5ms
|
||||
static_delay_adjustable: true
|
||||
fixed_delay: 480us
|
||||
decode_memory: internal
|
||||
|
||||
@@ -293,6 +293,60 @@ cover:
|
||||
cover.is_closed: template_cover_with_triggers
|
||||
then:
|
||||
logger.log: Cover is closed
|
||||
# Exercise cover.control / cover.template.publish action variants so they
|
||||
# get build coverage in CI (and so memory-impact analysis on PRs that
|
||||
# touch ControlAction / CoverPublishAction sees real instances).
|
||||
- platform: template
|
||||
name: "Template Cover Actions"
|
||||
id: template_cover_actions
|
||||
has_position: true
|
||||
optimistic: true
|
||||
open_action:
|
||||
# CONF_STATE alias for the position bit
|
||||
- cover.template.publish:
|
||||
id: template_cover_actions
|
||||
state: OPEN
|
||||
- cover.template.publish:
|
||||
id: template_cover_actions
|
||||
position: 1.0
|
||||
- cover.template.publish:
|
||||
id: template_cover_actions
|
||||
current_operation: IDLE
|
||||
close_action:
|
||||
- cover.template.publish:
|
||||
id: template_cover_actions
|
||||
position: 0.0
|
||||
tilt: 0.0
|
||||
stop_action:
|
||||
- cover.template.publish:
|
||||
id: template_cover_actions
|
||||
current_operation: IDLE
|
||||
tilt_action:
|
||||
- lambda: |-
|
||||
id(template_cover_actions).tilt = tilt;
|
||||
id(template_cover_actions).publish_state();
|
||||
on_idle:
|
||||
# position only
|
||||
- cover.control:
|
||||
id: template_cover_actions
|
||||
position: 50%
|
||||
# tilt only
|
||||
- cover.control:
|
||||
id: template_cover_actions
|
||||
tilt: 75%
|
||||
# position + tilt
|
||||
- cover.control:
|
||||
id: template_cover_actions
|
||||
position: 25%
|
||||
tilt: 30%
|
||||
# stop
|
||||
- cover.control:
|
||||
id: template_cover_actions
|
||||
stop: true
|
||||
# CONF_STATE alias for position
|
||||
- cover.control:
|
||||
id: template_cover_actions
|
||||
state: OPEN
|
||||
|
||||
number:
|
||||
- platform: template
|
||||
@@ -302,6 +356,19 @@ number:
|
||||
min_value: 0
|
||||
max_value: 100
|
||||
step: 1
|
||||
# Exercise valve.control inside a trigger with non-empty Ts (number on_value
|
||||
# passes float).
|
||||
- platform: template
|
||||
id: template_valve_position_number
|
||||
optimistic: true
|
||||
min_value: 0
|
||||
max_value: 100
|
||||
step: 1
|
||||
on_value:
|
||||
then:
|
||||
- valve.control:
|
||||
id: template_valve
|
||||
position: !lambda "return x / 100.0f;"
|
||||
|
||||
select:
|
||||
- platform: template
|
||||
@@ -388,6 +455,20 @@ valve:
|
||||
state: CLOSED
|
||||
stop_action:
|
||||
- logger.log: stop_action
|
||||
# Exercise valve.control with various field combinations so the
|
||||
# ControlAction codegen paths get build coverage.
|
||||
- valve.control:
|
||||
id: template_valve
|
||||
stop: true
|
||||
- valve.control:
|
||||
id: template_valve
|
||||
position: 50%
|
||||
- valve.control:
|
||||
id: template_valve
|
||||
state: OPEN
|
||||
- valve.control:
|
||||
id: template_valve
|
||||
position: !lambda 'return 0.25f;'
|
||||
optimistic: true
|
||||
|
||||
text:
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
wifi:
|
||||
min_auth_mode: WPA2
|
||||
post_connect_roaming: true
|
||||
phy_mode: 11G
|
||||
|
||||
packages:
|
||||
- !include common.yaml
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
esphome:
|
||||
on_boot:
|
||||
- lambda: |-
|
||||
ESP_LOGD("test", "millis=%u micros=%u cycles=%u",
|
||||
(unsigned) millis(), (unsigned) micros(),
|
||||
(unsigned) arch_get_cpu_cycle_count());
|
||||
delay(1);
|
||||
delayMicroseconds(1);
|
||||
@@ -0,0 +1 @@
|
||||
<<: !include common.yaml
|
||||
Reference in New Issue
Block a user