fan: - platform: template id: test_fan name: "Test Fan" preset_modes: - Eco - Sleep - Turbo 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 binary_sensor: - platform: template id: fan_has_preset name: "Fan Has Preset" lambda: |- // Migration guide: Checking if preset mode is set // Use empty() or has_preset_mode() if (!id(test_fan).get_preset_mode().empty()) { // preset is set } if (id(test_fan).has_preset_mode()) { // preset is set } // Migration guide: Comparing preset mode // Use == operator directly (safe, works even when empty) if (id(test_fan).get_preset_mode() == "Eco") { return true; } // Migration guide: Checking for no preset if (id(test_fan).get_preset_mode().empty()) { // no preset } if (!id(test_fan).has_preset_mode()) { // no preset } // Migration guide: Getting as std::string std::string preset = std::string(id(test_fan).get_preset_mode()); // Migration guide: Logging option 1 // Use .c_str() - works because StringRef points to null-terminated string in traits ESP_LOGD("test", "Preset: %s", id(test_fan).get_preset_mode().c_str()); // Migration guide: Logging option 2 // Use %.*s format (safer, no null-termination assumption) auto preset_ref = id(test_fan).get_preset_mode(); ESP_LOGD("test", "Preset: %.*s", (int)preset_ref.size(), preset_ref.c_str()); // Test != comparison if (id(test_fan).get_preset_mode() != "Sleep") { 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;"